Loops/Increment loop index within loop body: Difference between revisions
(Added Algol 68) |
|||
Line 63: | Line 63: | ||
ELSE |
ELSE |
||
LONG INT d := 5; |
LONG INT d := 5; |
||
BOOL |
BOOL result := TRUE; |
||
BOOL result := TRUE; |
|||
WHILE IF d * d > n THEN FALSE |
WHILE IF d * d > n THEN FALSE |
||
ELIF n MOD d = 0 THEN result := FALSE |
ELIF n MOD d = 0 THEN result := FALSE |
||
Line 91: | Line 90: | ||
i +:= 1 |
i +:= 1 |
||
OD |
OD |
||
END |
END</lang> |
||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
Revision as of 20:05, 19 February 2018
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
- Loop over multiple arrays simultaneously
- Loops/Break
- Loops/Continue
- Loops/Do-while
- Loops/Downward for
- Loops/For
- Loops/For with a specified step
- Loops/Foreach
- Loops/Infinite
- Loops/N plus one half
- Loops/Nested
- Loops/While
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>
- include <locale.h>
- 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} … *);
- 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