Loops/With multiple ranges: Difference between revisions
Flagged for clarification. |
Flagged for clarification. |
||
Line 4: | Line 4: | ||
{{draft task|Iteration}} |
{{draft task|Iteration}} |
||
{{Category:Clarify task}} |
|||
Some languages allow multiple '''loop''' ranges, such as the '''PL/I''' example (snippet) below. |
Some languages allow multiple '''loop''' ranges, such as the '''PL/I''' example (snippet) below. |
Revision as of 19:20, 15 September 2018
Maintenance
These tasks require clarification. Please participate in their talk pages, or implement the consensus found therein.
Some languages allow multiple loop ranges, such as the PL/I example (snippet) below.
<lang pli> /* all variables are DECLARED as integers. */
prod= 1; /*start with a product of unity. */ sum= 0; /* " " " sum " zero. */ x= +5; y= -5; z= -2; one= 1; three= 3; seven= 7; /*(below) ** is exponentiation: 4**3=64 */ do j= -three to 3**3 by three , -seven to +seven by x , 555 to 550 - y , 22 to -28 by -three , 1927 to 1939 , x to y by z , 11**x to 11**x + one; /* ABS(n) = absolute value*/ sum= sum + abs(j); /*add absolute value of J.*/ if abs(prod)<2**27 & j¬=0 then prod=prod*j; /*PROD is small enough & J*/ end; /*not 0, then multiply it.*/ /*SUM and PROD are used for verification of J incrementation.*/ display (' sum= ' || sum); /*display strings to term.*/ display ('prod= ' || prod); /* " " " " */</lang>
- Task
Simulate/translate the above PL/I program snippet as best as possible in your language, with particular emphasis on the do loop construct.
The do index must be incremented/decremented in the same order shown.
If possible, add commas to the two output numbers.
Show all output here.
- 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/Increment loop index within loop body
- Loops/Infinite
- Loops/N plus one half
- Loops/Nested
- Loops/While
- Loops/with multiple ranges
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <locale.h>
long prod = 1L, sum = 0L;
void process(int j) {
sum += abs(j); if (labs(prod) < (1 << 27) && j) prod *= j;
}
long ipow(int n, uint e) {
long pr = n; int i; if (e == 0) return 1L; for (i = 2; i <= e; ++i) pr *= n; return pr;
}
int main() {
int j; const int x = 5, y = -5, z = -2; const int one = 1, three = 3, seven = 7; long p = ipow(11, x); for (j = -three; j <= ipow(3, 3); j += three) process(j); for (j = -seven; j <= seven; j += x) process(j); for (j = 555; j <= 550 - y; ++j) process(j); for (j = 22; j >= -28; j -= three) process(j); for (j = 1927; j <= 1939; ++j) process(j); for (j = x; j >= y; j -= -z) process(j); for (j = p; j <= p + one; ++j) process(j); setlocale(LC_NUMERIC, ""); printf("sum = % 'ld\n", sum); printf("prod = % 'ld\n", prod); return 0;
}</lang>
- Output:
sum = 348,173 prod = -793,618,560
Factor
Factor doesn't have any special support for this sort of thing, but we can store iterable range
objects in a collection and loop over them.
<lang factor>USING: formatting kernel locals math math.functions math.ranges
sequences sequences.generalizations tools.memory.private ;
[let ! Allow lexical variables.
1 :> prod! ! Start with a product of unity. 0 :> sum! ! " " " sum " zero. 5 :> x -5 :> y -2 :> z 1 :> one 3 :> three 7 :> seven
three neg 3 3 ^ three <range> ! Create array seven neg seven x <range> ! of 7 ranges. 555 550 y - [a,b] 22 -28 three neg <range> 1927 1939 [a,b] x y z <range> 11 x ^ 11 x ^ 1 + [a,b] 7 narray
[ [ :> j j abs sum + sum! prod abs 2 27 ^ < j zero? not and [ prod j * prod! ] when ] each ! Loop over range. ] each ! Loop over array of ranges. ! SUM and PROD are used for verification of J incrementation. sum prod [ commas ] bi@ " sum= %s\nprod= %s\n" printf
]</lang>
- Output:
sum= 348,173 prod= -793,618,560
Go
Nothing fancy from Go here (is there ever?), just a series of individual for loops. <lang go>package main
import "fmt"
func pow(n int, e uint) int {
if e == 0 { return 1 } prod := n for i := uint(2); i <= e; i++ { prod *= n } return prod
}
func abs(n int) int {
if n >= 0 { return n } return -n
}
func commatize(n int) string {
s := fmt.Sprintf("%d", n) if n < 0 { s = s[1:] } le := len(s) for i := le - 3; i >= 1; i -= 3 { s = s[0:i] + "," + s[i:] } if n >= 0 { return " " + s } return "-" + s
}
func main() {
prod := 1 sum := 0 const ( x = 5 y = -5 z = -2 one = 1 three = 3 seven = 7 ) p := pow(11, x) var j int
process := func() { sum += abs(j) if abs(prod) < (1<<27) && j != 0 { prod *= j } }
for j = -three; j <= pow(3, 3); j += three { process() } for j = -seven; j <= seven; j += x { process() } for j = 555; j <= 550-y; j++ { process() } for j = 22; j >= -28; j -= three { process() } for j = 1927; j <= 1939; j++ { process() } for j = x; j >= y; j -= -z { process() } for j = p; j <= p+one; j++ { process() } fmt.Println("sum = ", commatize(sum)) fmt.Println("prod = ", commatize(prod))
}</lang>
- Output:
sum = 348,173 prod = -793,618,560
Kotlin
Nothing special here, just a series of individual for loops. <lang scala>// Version 1.2.70
import kotlin.math.abs
infix fun Int.pow(e: Int): Int {
if (e == 0) return 1 var prod = this for (i in 2..e) { prod *= this } return prod
}
fun main(args: Array<String>) {
var prod = 1 var sum = 0 val x = 5 val y = -5 val z = -2 val one = 1 val three = 3 val seven = 7 val p = 11 pow x fun process(j: Int) { sum += abs(j) if (abs(prod) < (1 shl 27) && j != 0) prod *= j }
for (j in -three..(3 pow 3) step three) process(j) for (j in -seven..seven step x) process(j) for (j in 555..550-y) process(j) for (j in 22 downTo -28 step three) process(j) for (j in 1927..1939) process(j) for (j in x downTo y step -z) process(j) for (j in p..p + one) process(j) System.out.printf("sum = % ,d\n", sum) System.out.printf("prod = % ,d\n", prod)
}</lang>
- Output:
sum = 348,173 prod = -793,618,560
Perl 6
Also displaying the j sequence since it isn't very large.
<lang perl6>sub comma ($i) {
my $sign = $i < 0 ?? '-' !! ; $sign ~ $i.abs.flip.comb(3).join(',').flip
}
my \x = 5; my \y = -5; my \z = -2; my \one = 1; my \three = 3; my \seven = 7;
my $j = flat
(-three, *+three … 3³), (-seven, *+x …^ * > seven), (555 .. 550 - y), (22, *-three …^ * < -28), (1927 .. 1939), (x, *+z …^ * < y), (11**x .. 11**x + one);
put 'j sequence: ', $j; put ' Sum: ', comma [+] $j».abs; put ' Product: ', comma ([\*] $j.grep: so *).first: *.abs > 2²⁷;</lang>
- Output:
j sequence: -3 0 3 6 9 12 15 18 21 24 27 -7 -2 3 555 22 19 16 13 10 7 4 1 -2 -5 -8 -11 -14 -17 -20 -23 -26 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 5 3 1 -1 -3 -5 161051 161052 Sum: 348,173 Product: -793,618,560
Literal-minded variation
An alternate method for generating the 'j' sequence, employing user-defined operators to preserve the 'X to Y by Z' layout of the example code. <lang perl6>sub infix:<to> { $^a...$^b } sub infix:<by> { ($^a.split(' '))[0,$^b.abs ... *] }
$j = flat
-three to 3**3 by three , -seven to seven by x , 555 to (550 - y) , 22 to -28 by -three , 1927 to 1939 by one , x to y by z , 11**x to (11**x+one);</lang>
REXX
Programming note: the (sympathetic) trailing semicolons (;) after each REXX statement are optional, they are only there to mimic what the PL/I language requires after each statement.
The technique used by this REXX version is to "break up" the various do iterating clauses (ranges) into separate do loops, and have them invoke a subroutine to perform the actual computations. <lang rexx>/*REXX program emulates a multiple─range DO loop (all variables can be any numbers). */
prod= 1; sum= 0; x= +5; y= -5; z= -2; one= 1;
three= 3; seven= 7;
do j= -three to 3**3 by three ; call meat; end; do j= -seven to seven by x ; call meat; end; do j= 555 to 550 - y ; call meat; end; do j= 22 to -28 by -three ; call meat; end; do j= 1927 to 1939 ; call meat; end; do j= x to y by z ; call meat; end; do j= 11**x to 11**x + one ; call meat; end;
say ' sum= ' || commas( sum); /*display SUM with commas. */ say 'prod= ' || commas(prod); /* " PROD " " */ exit; /*stick a fork in it, we're done.*/ /*──────────────────────────────────────────────────────────────────────────────────────*/ commas: procedure; parse arg _; n= _'.9'; #= 123456789; b= verify(n, #, "M")
e= verify(n, #'0', , verify(n, #"0.", 'M') ) - 4 do j=e to b by -3; _= insert(',', _, j); end; return _
/*──────────────────────────────────────────────────────────────────────────────────────*/ meat: sum= sum + abs(j);
if abs(prod)<2**27 & j\==0 then prod= prod * j; return;</lang>
- output when using the same variable values:
sum= 348,173 prod= -793,618,560
zkl
<lang zkl>prod,sum := 1,0; /* start with a product of unity, sum of 0 */ x,y,z := 5, -5, -2; one,three,seven := 1,3,7; foreach j in (Walker.chain([-three..(3).pow(3),three],
[-seven..seven,x], [555..550 - y], [22..-28,-three], [1927..1939], [x..y,z], [(11).pow(x)..(11).pow(x) + one])){ sum+=j.abs(); /* add absolute value of J */ if(prod.abs()<(2).pow(27) and j!=0) prod*=j; /* PROD is small enough & J */
} /* SUM and PROD are used for verification of J incrementation */ println("sum = %,d\nprod = %,d".fmt(sum,prod));</lang>
- Output:
sum = 348,173 prod = -793,618,560