Loops/With multiple ranges: Difference between revisions
Thundergnat (talk | contribs) (→{{header|Perl 6}}: Add a Perl 6 example) |
(Add Factor example) |
||
Line 61: | Line 61: | ||
* [[Loops/with multiple ranges]] |
* [[Loops/with multiple ranges]] |
||
<br><br> |
<br><br> |
||
=={{header|Factor}}== |
|||
Factor doesn't have any special support for this sort of thing, but we can store iterable <code>range</code> 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> |
|||
{{out}} |
|||
<pre> |
|||
sum= 348,173 |
|||
prod= -793,618,560 |
|||
</pre> |
|||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |
Revision as of 12:17, 14 September 2018
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
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
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
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