Loops/Increment loop index within loop body: Difference between revisions

From Rosetta Code
Content added Content deleted
m (removed the __TOC__ (forced table of contents), no longer needed.)
Line 51: Line 51:
*   [[Loops/While]]
*   [[Loops/While]]
<br><br>
<br><br>

__TOC__


=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==

Revision as of 23:13, 19 February 2018

Loops/Increment loop index within loop body is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Sometimes, one may need   (or want)   a loop which its   iterator   (the index variable)   is modified within the loop body.


Goal

Demonstrate the best way to accomplish this.


Task

Write a loop which:

  •   starts the index (variable) at   42
  •   (at iteration time)   increments the index by unity
  •   if the index is prime:
  •   displays the index and the prime (to the terminal)
  •   increments the index such that the new index is now that prime
  •   terminates the loop when   42   primes are shown


Extra credit:   because of the primes get rather large, use commas within the displayed primes to ease comprehension.


Show all output here.


Note

Not all programming languages allow the modification of a loop's index.   If that is the case, then use whatever method that is appropriate or idiomatic for that language.   Please add a note if the loop's index isn't modifiable.


Related tasks



ALGOL 68

In Algol 68, the FOR loop counter cannot be modified in the loop. This uses a WHILE loop testing at the top but is otherwise largely a translation of the Kotlin entry. <lang algol68>BEGIN

   # returns TRUE if n is prime, FALSE otherwise #
   PROC is prime = ( LONG INT n )BOOL:
        IF   n MOD 2 = 0 THEN n = 2
        ELIF n MOD 3 = 0 THEN n = 3
        ELSE
           LONG INT d := 5;
           BOOL result := TRUE;
           WHILE IF   d * d > n   THEN FALSE
                 ELIF n MOD d = 0 THEN result := FALSE
                 ELIF d +:= 2;
                      n MOD d = 0 THEN result := FALSE
                 ELSE d +:= 4; TRUE
                 FI
           DO SKIP OD;
           result
        FI # is prime # ;
   LONG INT i := 42;
   LONG INT n := 0;
   WHILE n < 42 DO
       IF is prime( i ) THEN
           n +:= 1;
           print( ( "n = "
                  , whole( n,  -2 )
                  , "  "
                  , whole( i, -19 )
                  , newline
                  )
                );
           i +:= i - 1
       FI;
       i +:= 1
   OD

END</lang>

Output:
n =  1                   43
n =  2                   89
n =  3                  179
n =  4                  359
n =  5                  719
n =  6                 1439
n =  7                 2879
n =  8                 5779
n =  9                11579
n = 10                23159
n = 11                46327
n = 12                92657
n = 13               185323
n = 14               370661
n = 15               741337
n = 16              1482707
n = 17              2965421
n = 18              5930887
n = 19             11861791
n = 20             23723597
n = 21             47447201
n = 22             94894427
n = 23            189788857
n = 24            379577741
n = 25            759155483
n = 26           1518310967
n = 27           3036621941
n = 28           6073243889
n = 29          12146487779
n = 30          24292975649
n = 31          48585951311
n = 32          97171902629
n = 33         194343805267
n = 34         388687610539
n = 35         777375221081
n = 36        1554750442183
n = 37        3109500884389
n = 38        6219001768781
n = 39       12438003537571
n = 40       24876007075181
n = 41       49752014150467
n = 42       99504028301131

C

The following uses a 'for' rather than a 'do/while' loop but otherwise is similar to the Kotlin entry.

The 'thousands separator' aspect (using the ' flag in printf and setting the locale appropriately) works fine when compiled with gcc on Ubuntu 14.04 but may not work on some other systems as this is not a standard flag. <lang c>#include <stdio.h>

  1. include <locale.h>
  1. define LIMIT 42

int is_prime(long long n) {

   if (n % 2 == 0) return n == 2;
   if (n % 3 == 0) return n == 3;
   long long d = 5;
   while (d * d <= n) {
       if (n % d == 0) return 0;
       d += 2;
       if (n % d == 0) return 0;
       d += 4;
   }
   return 1;

}

int main() {

   long long i;
   int n;
   setlocale(LC_NUMERIC, "");
   for (i = LIMIT, n = 0; n < LIMIT; i++)
       if (is_prime(i)) {
           n++;
           printf("n = %-2d  %'19lld\n", n, i);
           i += i - 1;
       }
   return 0;

}</lang>

Output:
Same as Kotlin entry

Java

The following uses a 'for' rather than a 'do/while' loop but otherwise is similar to the Kotlin entry. <lang java>public class LoopIncrementWithinBody {

   static final int LIMIT = 42;
   static boolean isPrime(long n) {
       if (n % 2 == 0) return n == 2;
       if (n % 3 == 0) return n == 3;
       long d = 5;
       while (d * d <= n) {
           if (n % d == 0) return false;
           d += 2;
           if (n % d == 0) return false;
           d += 4;
       }
       return true;
   }
   public static void main(String[] args) {
       long i;
       int n;
       for (i = LIMIT, n = 0; n < LIMIT; i++)
           if (isPrime(i)) {
               n++;
               System.out.printf("n = %-2d  %,19d\n", n, i);
               i += i - 1;
           }
   }

}</lang>

Output:
Same as Kotlin entry

Kotlin

Unlike most other 'curly brace' languages, Kotlin's 'for' statement is quite limited and doesn't allow either the iteration variable or the step to be modified within the loop body.

So instead we use a do/while loop here which has no such restrictions. <lang scala>// version 1.2.21

fun isPrime(n: Long): Boolean {

   if (n % 2L == 0L) return n == 2L
   if (n % 3L == 0L) return n == 3L
   var d = 5L
   while (d * d <= n) {
       if (n % d == 0L) return false
       d += 2L
       if (n % d == 0L) return false
       d += 4L
   }
   return true

}

fun main(args: Array<String>) {

   var i = 42L
   var n = 0
   do {
       if (isPrime(i)) {
           n++
           System.out.printf("n = %-2d  %,19d\n", n, i)
           i += i - 1
       }
       i++
   }
   while (n < 42)

}</lang>

Output:
n = 1                    43
n = 2                    89
n = 3                   179
n = 4                   359
n = 5                   719
n = 6                 1,439
n = 7                 2,879
n = 8                 5,779
n = 9                11,579
n = 10               23,159
n = 11               46,327
n = 12               92,657
n = 13              185,323
n = 14              370,661
n = 15              741,337
n = 16            1,482,707
n = 17            2,965,421
n = 18            5,930,887
n = 19           11,861,791
n = 20           23,723,597
n = 21           47,447,201
n = 22           94,894,427
n = 23          189,788,857
n = 24          379,577,741
n = 25          759,155,483
n = 26        1,518,310,967
n = 27        3,036,621,941
n = 28        6,073,243,889
n = 29       12,146,487,779
n = 30       24,292,975,649
n = 31       48,585,951,311
n = 32       97,171,902,629
n = 33      194,343,805,267
n = 34      388,687,610,539
n = 35      777,375,221,081
n = 36    1,554,750,442,183
n = 37    3,109,500,884,389
n = 38    6,219,001,768,781
n = 39   12,438,003,537,571
n = 40   24,876,007,075,181
n = 41   49,752,014,150,467
n = 42   99,504,028,301,131

Perl 6

Hmm.

Demonstrate the best way to accomplish this.

The best way is to not bother to use an explicit loop. Just calculate the sequence directly.

<lang perl6># the actual sequence logic my @seq = grep *.is-prime, (42, {.is-prime ?? $_+<1 !! $_+1} … *);

  1. display code

say ++$ .fmt("%2d"), .flip.comb(3).join(',').flip.fmt("%20s") for @seq[^42];</lang>

Output:
 1                  43
 2                  89
 3                 179
 4                 359
 5                 719
 6               1,439
 7               2,879
 8               5,779
 9              11,579
10              23,159
11              46,327
12              92,657
13             185,323
14             370,661
15             741,337
16           1,482,707
17           2,965,421
18           5,930,887
19          11,861,791
20          23,723,597
21          47,447,201
22          94,894,427
23         189,788,857
24         379,577,741
25         759,155,483
26       1,518,310,967
27       3,036,621,941
28       6,073,243,889
29      12,146,487,779
30      24,292,975,649
31      48,585,951,311
32      97,171,902,629
33     194,343,805,267
34     388,687,610,539
35     777,375,221,081
36   1,554,750,442,183
37   3,109,500,884,389
38   6,219,001,768,781
39  12,438,003,537,571
40  24,876,007,075,181
41  49,752,014,150,467
42  99,504,028,301,131

REXX

<lang rexx>/*REXX pgm displays primes found: starting Z at 42, if Z is a prime, add Z, else add 1.*/ numeric digits 20; d=digits() /*ensure enough decimal digits for Z. */ parse arg limit . /*obtain optional arguments from the CL*/ if limit== | limit=="," then limit=42 /*Not specified? Then use the default.*/ n=0 /*the count of number of primes found. */

    do z=42  until n==limit                     /* ◄──this DO loop's index is modified.*/
    if isPrime(z)  then do;  n=n + 1            /*Z  a prime?  Them bump prime counter.*/
                             say right('n='n, 9)     right(commas(z), d)
                             z=z + z - 1        /*also, bump the  DO  loop index  Z.   */
                        end
    end   /*z*/                                 /* [↑] a small tribute to Douglas Adams*/

exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ commas: parse arg _; do j=length(_)-3 to 1 by -3; _=insert(',', _, j); end; return _ /*──────────────────────────────────────────────────────────────────────────────────────*/ isPrime: procedure; parse arg #; if wordpos(#, '2 3 5 7')\==0 then return 1

                                        if # // 2==0 | # // 3    ==0  then return 0
          do j=5  by 6  until j*j>#;    if # // j==0 | # // (J+2)==0  then return 0
          end   /*j*/                           /*           ___                       */
        return 1                                /*Exceeded  √ #  ?    Then # is prime. */</lang>
output:
      n=1                   43
      n=2                   89
      n=3                  179
      n=4                  359
      n=5                  719
      n=6                1,439
      n=7                2,879
      n=8                5,779
      n=9               11,579
     n=10               23,159
     n=11               46,327
     n=12               92,657
     n=13              185,323
     n=14              370,661
     n=15              741,337
     n=16            1,482,707
     n=17            2,965,421
     n=18            5,930,887
     n=19           11,861,791
     n=20           23,723,597
     n=21           47,447,201
     n=22           94,894,427
     n=23          189,788,857
     n=24          379,577,741
     n=25          759,155,483
     n=26        1,518,310,967
     n=27        3,036,621,941
     n=28        6,073,243,889
     n=29       12,146,487,779
     n=30       24,292,975,649
     n=31       48,585,951,311
     n=32       97,171,902,629
     n=33      194,343,805,267
     n=34      388,687,610,539
     n=35      777,375,221,081
     n=36    1,554,750,442,183
     n=37    3,109,500,884,389
     n=38    6,219,001,768,781
     n=39   12,438,003,537,571
     n=40   24,876,007,075,181
     n=41   49,752,014,150,467
     n=42   99,504,028,301,131

zkl

Uses libGMP (GNU MP Bignum Library) for easy prime detection rather than write that bit of code and pollute this solution. <lang zkl>var [const] BN=Import("zklBigNum"); // libGMP n,p := 1,BN(42); do{

  if(p.probablyPrime()){ println("n = %2d %,20d".fmt(n,p)); p.add(p); n+=1; }
  p.add(1); 

}while(n<=42);</lang> zkl loop variables are iterators that don't allow direct manipulation of their underlying source. The compiler names these iterators __<index>Walker. However, by using the look ahead stack, we can keep the iterator from advancing through the source. <lang zkl>p:=BN(42); foreach n in ([1..42]){

  if(p.probablyPrime()){ println("n = %2d %,20d".fmt(n,p)); p.add(p); }
  else{ p.add(1); __nWalker.push(n); }  // p not prime, don't advance n

}</lang>

Output:
n =  1                   43
n =  2                   89
n =  3                  179
n =  4                  359
n =  5                  719
n =  6                1,439
n =  7                2,879
n =  8                5,779
n =  9               11,579
n = 10               23,159
n = 11               46,327
n = 12               92,657
n = 13              185,323
n = 14              370,661
n = 15              741,337
n = 16            1,482,707
n = 17            2,965,421
n = 18            5,930,887
n = 19           11,861,791
n = 20           23,723,597
n = 21           47,447,201
n = 22           94,894,427
n = 23          189,788,857
n = 24          379,577,741
n = 25          759,155,483
n = 26        1,518,310,967
n = 27        3,036,621,941
n = 28        6,073,243,889
n = 29       12,146,487,779
n = 30       24,292,975,649
n = 31       48,585,951,311
n = 32       97,171,902,629
n = 33      194,343,805,267
n = 34      388,687,610,539
n = 35      777,375,221,081
n = 36    1,554,750,442,183
n = 37    3,109,500,884,389
n = 38    6,219,001,768,781
n = 39   12,438,003,537,571
n = 40   24,876,007,075,181
n = 41   49,752,014,150,467
n = 42   99,504,028,301,131