Loops/With multiple ranges

From Rosetta Code


Task
Loops/With multiple ranges
You are encouraged to solve this task according to the task description, using any language you may know.

Some languages allow multiple loop ranges, such as the PL/I example (snippet) below.

                                       /* 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);                    /*   "       "     "   "  */


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 feasible, add commas to the two output numbers (being displayed).

Show all output here.

      A simple PL/I   DO  loop  (incrementing or decrementing)  has the construct of:

            DO variable = start_expression    {TO ending_expression]       {BY increment_expression} ;
                 ---or---
            DO variable = start_expression    {BY increment_expression}    {TO ending_expression]    ;  

      where it is understood that all expressions will have a value.  The  variable  is normally a 
      scaler variable,  but need not be  (but for this task, all variables and expressions are declared
      to be scaler integers).   If the   BY   expression is omitted,  a   BY   value of unity is used.
      All expressions are evaluated before the   DO   loop is executed,  and those values are used
      throughout the   DO   loop execution   (even though, for instance,  the value of   Z   may be
      changed within the   DO   loop.    This isn't the case here for this task.  

      A multiple-range   DO   loop can be constructed by using a comma (,) to separate additional ranges
      (the use of multiple   TO   and/or   BY   keywords).     This is the construct used in this task.
 
      There are other forms of   DO   loops in PL/I involving the  WHILE  clause,  but those won't be 
      needed here.    DO  loops without a   TO   clause might need a   WHILE   clause  or some other 
      means of exiting the loop  (such as  LEAVE,  RETURN,  SIGNAL,  GOTO,  or  STOP),  or some other 
      (possible error) condition that causes transfer of control outside the  DO  loop.
 
      Also, in PL/I, the check if the   DO   loop index value is outside the range is made at the 
      "head"  (start)  of the   DO  loop,  so it's possible that the   DO   loop isn't executed,  but 
      that isn't the case for any of the ranges used in this task. 

      In the example above, the clause:                    x    to y       by z     
      will cause the variable   J   to have to following values  (in this order):  5  3  1  -1  -3  -5

      In the example above, the clause:                 -seven  to +seven  by x  
      will cause the variable   J   to have to following values  (in this order):  -7  -2   3


Related tasks



11l[edit]

Translation of: Nim
V prod = 1
V s = 0

-V
   x = +5
   y = -5
   z = -2
   one = 1
   three = 3
   seven = 7

F body(j)
   :s += abs(j)
   I abs(:prod) < 2 ^ 27 & j != 0
      :prod *= j

L(j) (-three .. 3 ^ 3).step(three) {body(j)}
L(j) (-seven .. seven).step(x)     {body(j)}
L(j) 555 .. 550 - y                {body(j)}
L(j) (22 .. -28).step(-three)      {body(j)}
L(j) 1927 .. 1939                  {body(j)}
L(j) (x .. y).step(z)              {body(j)}
L(j) 11 ^ x .. 11 ^ x + one        {body(j)}

V ss = String(s)
V ps = String(prod)
V m = max(ss.len, ps.len)
print(‘ sum = ’ss.rjust(m))
print(‘prod = ’ps.rjust(m))
Output:
 sum =     348173
prod = -793618560

AArch64 Assembly[edit]

Works with: as version Raspberry Pi 3B version Buster 64 bits
/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program loopnrange64.s   */

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResult:      .asciz "@ \n"                    // message result
szCarriageReturn:  .asciz "\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss 
qSum:                      .skip 8         // this program store sum and product in memory
qProd:                     .skip 8         // it is possible to use registers x22 and x28
sZoneConv:                 .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                       // entry of program
    ldr x0,qAdrqProd
    mov x1,1
    str x1,[x0]                             // init product
    ldr x0,qAdrqSum
    mov x1,0
    str x1,[x0]                             // init sum

    mov x25,5                               // x
    mov x24,-5                              // y
    mov x26,-2                              // z
    mov x21,1                               // one
    mov x23,3                               // three
    mov x27,7                               // seven

                                            // loop one
    mov x0,3
    mov x1,3
    bl computePow                           // compute 3 pow 3
    mov x20,x0                              // save result
    mvn x9,x23                              // x9 = - three
    add x9,x9,1
1: 
    mov x0,x9
    bl computeSumProd
    add x9,x9,x23                           // increment with three
    cmp x9,x20
    ble 1b
                                            // loop two
    mvn x9,x27                              // x9 = - seven
    add x9,x9,1
2: 
    mov x0,x9
    bl computeSumProd
    add x9,x9,x25                           // increment with x
    cmp x9,x27                              // compare to seven
    ble 2b

                                            // loop three
    mov x9,#550
    sub x20,x9,x24                          // x20 = 550 - y
    mov x9,#555
3: 
    mov x0,x9
    bl computeSumProd
    add x9,x9,#1
    cmp x9,x20
    ble 3b
                                            // loop four
    mov x9,#22
4: 
    mov x0,x9
    bl computeSumProd
    sub x9,x9,x23                           // decrement with three
    cmp x9,#-28
    bge 4b
                                            // loop five
    mov x9,1927
    mov x20,1939
5: 
    mov x0,x9
    bl computeSumProd
    add x9,x9,1
    cmp x9,x20
    ble 5b
                                            // loop six
    mov x9,x25                              // x9 = x
    mvn x20,x26                             // x20 = - z
    add x20,x20,1
6: 
    mov x0,x9
    bl computeSumProd
    sub x9,x9,x20
    cmp x9,x24
    bge 6b
                                            // loop seven
    mov x0,x25
    mov x1,11
    bl computePow                           // compute 11 pow x
    add x20,x0,x21                          // + one
    mov x9,x0
7: 
    mov x0,x9
    bl computeSumProd
    add x9,x9,1
    cmp x9,x20
    ble 7b
                                            // display result
    ldr x0,qAdrqSum
    ldr x0,[x0]
    ldr x1,qAdrsZoneConv                    // signed conversion value
    bl conversion10S                        // decimal conversion
    ldr x0,qAdrszMessResult
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc                   // insert result at @ character
    bl affichageMess                        // display message
    ldr x0,qAdrszCarriageReturn
    bl affichageMess                        // display return line
    ldr x0,qAdrqProd
    ldr x0,[x0]
    ldr x1,qAdrsZoneConv                    // conversion value
    bl conversion10S                        // signed decimal conversion
    ldr x0,qAdrszMessResult
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc                   // insert result at  @ character
    bl affichageMess                        // display message
    ldr x0,qAdrszCarriageReturn
    bl affichageMess                        // display return line
 
 
100:                                        // standard end of the program 
    mov x0,0                                // return code
    mov x8,EXIT                             // request to exit program
    svc 0                                   // perform the system call
 
qAdrsZoneConv:            .quad sZoneConv
qAdrszMessResult:         .quad szMessResult
qAdrszCarriageReturn:     .quad szCarriageReturn
/******************************************************************/
/*     compute the sum and prod                         */ 
/******************************************************************/
/* x0 contains the number  */
computeSumProd:
    stp x1,lr,[sp,-16]!          // save  registers
    asr x10,x0,#63
    eor x12,x10,x0
    sub x12,x12,x10             // compute absolue value
    ldr x13,qAdrqSum            // load sum
    ldr x11,[x13]
    add x11,x11,x12             // add sum
    str x11,[x13]               // store sum
    cmp x0,#0                   // j = 0 ?
    beq 100f                    // yes
    ldr x13,qAdrqProd
    ldr x11,[x13]
    asr x12,x11,#63             // compute absolute value of prod
    eor x14,x11,x12
    sub x12,x14,x12
    ldr x10,qVal2P27
    cmp x12,x10                 // compare 2 puissance 27
    bgt 100f
    mul x11,x0,x11
    str x11,[x13]               // store prod
100:
    ldp x1,lr,[sp],16           // restaur  2 registers
    ret                         // return to address lr x230
qAdrqSum:                .quad qSum
qAdrqProd:               .quad qProd
qVal2P27:                .quad 1<<27
/******************************************************************/
/*     compute pow                         */ 
/******************************************************************/
/* x0 contains pow  */
/* x1 contains number */
computePow:
    stp x1,lr,[sp,-16]!          // save  registers
    mov x12,x0
    mov x0,#1
1:
    cmp x12,#0
    ble 100f
    mul x0,x1,x0
    sub x12,x12,#1
    b 1b
100:
    ldp x1,lr,[sp],16           // restaur  2 registers
    ret                         // return to address lr x230
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
Output:
+348173
-793618560

Ada[edit]

Ada does not support multiple ranges in a single loop.

Translation of: C++
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;

procedure Main is
   package int_vector is new Ada.Containers.Vectors
     (Index_Type => Natural, Element_Type => Integer);
   use int_vector;

   summing_values : Vector := Empty_Vector;

   prod : Integer := 1;
   sum  : Integer := 0;
   x    : Integer := 5;
   y    : Integer := -5;
   z    : Integer := -2;
   N    : Integer;
begin
   N := -3;
   while N <= 3**3 loop
      summing_values.Append (N);
      N := N + 3;
   end loop;

   N := -7;
   while N <= 7 loop
      summing_values.Append (N);
      N := N + x;
   end loop;

   for I in 555 .. 550 - y loop
      summing_values.Append (I);
   end loop;

   N := 22;
   while N >= -28 loop
      summing_values.Append (N);
      N := N - 3;
   end loop;

   for I in 1_927 .. 1_939 loop
      summing_values.Append (I);
   end loop;

   N := x;
   while N >= y loop
      summing_values.Append (N);
      N := N + z;
   end loop;

   for I in 11**x .. 11**x + 1 loop
      summing_values.Append (I);
   end loop;

   for value of summing_values loop
      sum := sum + abs (value);
      if abs (prod) < 2**27 and then value /= 0 then
         prod := prod * value;
      end if;
   end loop;

   Put_Line ("sum = " & sum'Image);
   Put_Line ("prod = " & prod'Image);

end Main;
Output:
sum =  348173
prod = -793618560

ALGOL 60[edit]

Works with: MARST
begin
  integer prod, sum, x, y, z, one, three, seven;
  integer j;
  prod := 1;
  sum := 0;
  x := 5; y := -5; z := -2;
  one := 1;
  three := 3;
  seven := 7;

  for j := -three  step  three  until 3^3    ,
           -seven  step      x  until seven  ,
              555  step      1  until 550 - y,
               22  step -three  until -28    ,
             1927  step      1  until 1939   ,
                x  step      z  until y      ,
             11^x  step      1  until 11^x + one
  do begin
    sum := sum + iabs(j);
    if iabs(prod) < 2^27 & j != 0 then prod := prod*j
  end;

  outstring(1, " sum= "); outinteger(1, sum);  outstring(1, "\n");
  outstring(1, "prod= "); outinteger(1, prod); outstring(1, "\n")
end
Output:
 sum= 348173 
prod= -793618560 

ALGOL 68[edit]

Translation of: ALGOL W

As with most of the other languages, Algol 68 doesn't support multiple loop ranges, so a sequence pf loops is used instead.

BEGIN
    # translation of task PL/1 code, with minimal changes, semicolons required by      #
    # PL/1 but not allowed in Algol 68 removed, unecessary rounding removed            #
    # Note that in Algol 68, the loop counter is a local variable to the loop and      #
    # the value of j is not available outside the loops                                #
    PROC loop body = ( INT j )VOID:          #(below)  **  is exponentiation:  4**3=64 #
    BEGIN sum +:= ABS j;                                      #add absolute value of J.#
          IF ABS prod<2**27 AND j /= 0 THEN prod *:= j FI     #PROD is small enough & J#
                                                              # ABS(n) = absolute value#
          END;                                                #not 0, then multiply it.#
                           #SUM and PROD are used for verification of J incrementation.#
     INT  prod :=  1;                        #start with a product of unity.           #
     INT   sum :=  0;                        #  "     "  "   sum    " zero.            #
     INT     x := +5;
     INT     y := -5;
     INT     z := -2;
     INT   one :=  1;
     INT three :=  3;
     INT seven :=  7;
         FOR j FROM -three  BY  three TO      ( 3**3 )        DO loop body( j ) OD;
         FOR j FROM -seven  BY  x     TO    +seven            DO loop body( j ) OD;
         FOR j FROM    555            TO    550 - y           DO loop body( j ) OD;
         FOR j FROM     22  BY -three TO   -28                DO loop body( j ) OD;
         FOR j FROM   1927            TO  1939                DO loop body( j ) OD;
         FOR j FROM      x  BY  z     TO     y                DO loop body( j ) OD;
         FOR j FROM      ( 11**x )    TO      ( 11**x ) + one DO loop body( j ) OD;
         print((" sum= ", whole( sum,0), newline));           #display strings to term.#
         print(("prod= ", whole(prod,0), newline))            #   "       "     "   "  #
END
Output:
 sum= 348173
prod= -793618560

ALGOL W[edit]

As with most of the other languages, Algol W doesn't support multiple loop ranges, so a sequence pf loops is used instead.

begin
    % translation of task PL/1 code, with minimal changes, semicolons required by      %
    % PL/1 but redundant in Algol W retained ( technically they introduce empty        %
    % statements after the "if" in the loop body and before the final "end" )          %
    % Note that in Algol W, the loop counter is a local variable to the loop and       %
    % the value of j is not available outside the loops                                %
    procedure loopBody ( integer value j );  %(below)  **  is exponentiation:  4**3=64 %
    begin sum := sum + abs(j);                                %add absolute value of J.%
          if abs(prod)<2**27 and j not = 0 then prod := prod*j; %PROD is small enough & J%
                                                              % ABS(n) = absolute value%
          end;                                                %not 0, then multiply it.%
                           %SUM and PROD are used for verification of J incrementation.%
      integer prod, sum, x, y, z, one, three, seven;
          prod :=  1;                        %start with a product of unity.           %
           sum :=  0;                        %  "     "  "   sum    " zero.            %
             x := +5;
             y := -5;
             z := -2;
           one :=  1;
         three :=  3;
         seven :=  7;
         for j :=   -three  step  three until round( 3**3 )        do loopBody( j );
         for j :=   -seven  step  x     until    +seven            do loopBody( j );
         for j :=      555              until    550 - y           do loopBody( j );
         for j :=       22  step -three until   -28                do loopBody( j );
         for j :=     1927              until  1939                do loopBody( j );
         for j :=        x  step  z     until     y                do loopBody( j );
         for j := round( 11**x )        until round( 11**x ) + one do loopBody( j );
         write(s_w := 0, " sum= ",  sum);                    %display strings to term.%
         write(s_w := 0, "prod= ", prod);                    %   "       "     "   "  %
end.
Output:
 sum=         348173
prod=     -793618560

Applesoft BASIC[edit]

All of the numeric variables are Floating Point but get displayed as integers. The variable ONE is named UNO because ON is a keyword.

100    ::::::::: REMALL VARIABLES ARE DECLARED AS INTEGERS.
110   PROD=  1 : REMSTART WITH A PRODUCT OF UNITY.
120    SUM=  0:: REM  "     "  "   SUM    " ZERO.
130      X= +5
140      Y= -5
150      Z= -2
160    UNO=  1
170  THREE=  3
180  SEVEN=  7
190 REM(BELOW)  ^  IS EXPONENTIATION:  4^3=64
200 DO(0) = -THREE : T0(0) = 3^3          : BY(0) = THREE
210 DO(1) = -SEVEN : T0(1) = +SEVEN       : BY(1) = X
220 DO(2) =    555 : T0(2) =    550 - Y
230 DO(3) =     22 : T0(3) =    -28       : BY(3) = -THREE
240 DO(4) =   1927 : T0(4) =   1939
250 DO(5) =      X : T0(5) =      Y       : BY(5) = Z
260 DO(6) =   11^X : T0(6) =   11^X + UNO
270 FOR I = 0 TO 6 : FINISH= T0(I)        : BY = BY(I)
280  START = DO(I) :         IF NOT BY THEN BY = 1
290  FOR J = START TO FINISH STEP BY
300      REM ABS(N) = ABSOLUTE VALUE
310      SUM= SUM + ABS(J) : REMADD ABSOLUTE VALUE OF J.
320      IF ABS(PROD)<2^27 AND J<>0  THEN PROD=PROD*J:REMPROD IS SMALL ENOUGH AND J NOT 0, THEN MULTIPLY IT.
330 NEXT J, I
340 REMSUM AND PROD ARE USED FOR VERIFICATION OF J INCREMENTATION.
350 PRINT " SUM= ";:N=SUM :GOSUB400:REMDISPLAY STRINGS TO TERM.
360 PRINT "PROD= ";:N=PROD:GOSUB400:REM   "        "    "   "
370 END
400 N$ =  STR$ ( ABS ( INT (N))):O$ = "":D = -1: FOR I =  LEN (N$) TO 1 STEP  - 1:C$ =  MID$ (N$,I,1) : O$ = MID$ (",",1 + (D  < 2)) + O$ : D = (D + 1) * (D < 2) : O$ = C$ + O$: NEXT I: PRINT  MID$ ("-",1 + (N >  = 0))O$: RETURN

ARM Assembly[edit]

Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program loopnrange.s   */

/* REMARK 1 : this program use routines in a include file 
   see task Include a file language arm assembly 
   for the routine affichageMess conversion10 
   see at end of this program the instruction include */
/*********************************/
/* Constantes                    */
/*********************************/
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
 
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResult:      .ascii ""                    @ message result
sMessValeur:       .fill 11, 1, ' '
szCarriageReturn:  .asciz "\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss 
iSum:                      .skip 4         @ this program store sum and product in memory
iProd:                     .skip 4         @ it is possible to use registers r2 and r11
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                       @ entry of program
    ldr r0,iAdriProd
    mov r1,#1
    str r1,[r0]                             @ init product
    ldr r0,iAdriSum
    mov r1,#0
    str r1,[r0]                             @ init sum

    mov r5,#5                               @ x
    mov r4,#-5                              @ y
    mov r6,#-2                              @ z
    mov r8,#1                               @ one
    mov r3,#3                               @ three
    mov r7,#7                               @ seven

                                            @ loop one
    mov r0,#3
    mov r1,#3
    bl computePow                           @ compute 3 pow 3
    mov r10,r0                              @ save result
    mvn r9,r3                               @ r9 = - three
    add r9,#1
1: 
    mov r0,r9
    bl computeSumProd
    add r9,r3                               @ increment with three
    cmp r9,r10
    ble 1b
                                            @ loop two
    mvn r9,r7                               @ r9 = - seven
    add r9,#1
2: 
    mov r0,r9
    bl computeSumProd
    add r9,r5                               @ increment with x
    cmp r9,r7                               @ compare to seven
    ble 2b

                                            @ loop three
    mov r9,#550
    sub r10,r9,r4                           @ r10 = 550 - y
    mov r9,#555
3: 
    mov r0,r9
    bl computeSumProd
    add r9,#1
    cmp r9,r10
    ble 3b
                                            @ loop four
    mov r9,#22
4: 
    mov r0,r9
    bl computeSumProd
    sub r9,r3                               @ decrement with three
    cmp r9,#-28
    bge 4b
                                            @ loop five
    mov r9,#1927
    ldr r10,iVal1939
5: 
    mov r0,r9
    bl computeSumProd
    add r9,#1
    cmp r9,r10
    ble 5b
                                            @ loop six
    mov r9,r5                               @ r9 = x
    mvn r10,r6                              @ r10 = - z
    add r10,#1
6: 
    mov r0,r9
    bl computeSumProd
    sub r9,r10
    cmp r9,r4
    bge 6b
                                            @ loop seven
    mov r0,r5
    mov r1,#11
    bl computePow                           @ compute 11 pow x
    add r10,r0,r8                           @ + one
    mov r9,r0
7: 
    mov r0,r9
    bl computeSumProd
    add r9,#1
    cmp r9,r10
    ble 7b
                                            @ display result
    ldr r0,iAdriSum
    ldr r0,[r0]
    ldr r1,iAdrsMessValeur                  @ signed conversion value
    bl conversion10S                        @ decimal conversion
    ldr r0,iAdrszMessResult
    bl affichageMess                        @ display message
    ldr r0,iAdrszCarriageReturn
    bl affichageMess                        @ display return line
    ldr r0,iAdriProd
    ldr r0,[r0]
    ldr r1,iAdrsMessValeur                  @ conversion value
    bl conversion10S                        @ signed decimal conversion
    ldr r0,iAdrszMessResult
    bl affichageMess                        @ display message
    ldr r0,iAdrszCarriageReturn
    bl affichageMess                        @ display return line
 
 
100:                                        @ standard end of the program 
    mov r0, #0                              @ return code
    mov r7, #EXIT                           @ request to exit program
    svc #0                                  @ perform the system call
 
iAdrsMessValeur:          .int sMessValeur
iAdrszMessResult:         .int szMessResult
iAdrszCarriageReturn:     .int szCarriageReturn
iVal1939:                 .int 1939
/******************************************************************/
/*     compute the sum and prod                         */ 
/******************************************************************/
/* r0 contains the number  */
computeSumProd:
    push {r1-r4,lr}             @ save  registers 
    asr r1,r0,#31
    eor r2,r0,r1
    sub r2,r2,r1                @ compute absolue value
    //vidregtit somme
    ldr r3,iAdriSum             @ load sum
    ldr r1,[r3]
    add r1,r2                   @ add sum
    str r1,[r3]                 @ store sum
    cmp r0,#0                   @ j = 0 ?
    beq 100f                    @ yes
    ldr r3,iAdriProd
    ldr r1,[r3]
    asr r2,r1,#31               @ compute absolute value of prod
    eor r4,r1,r2
    sub r2,r4,r2
    cmp r2,#1<<27               @ compare 2 puissance 27
    bgt 100f
    mul r1,r0,r1
    str r1,[r3]                 @ store prod
100:
    pop {r1-r4,lr}              @ restaur registers
    bx lr                       @ return
iAdriSum:                .int iSum
iAdriProd:               .int iProd
/******************************************************************/
/*     compute pow                         */ 
/******************************************************************/
/* r0 contains pow  */
/* r1 contains number */
computePow:
    push {r1-r2,lr}             @ save  registers 
    mov r2,r0
    mov r0,#1
1:
    cmp r2,#0
    ble 100f
    mul r0,r1,r0
    sub r2,#1
    b 1b
100:
    pop {r1-r2,lr}              @ restaur registers
    bx lr                       @ return
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
Output:
    +348173

 -793618560

AutoHotkey[edit]

As with most of the other languages, AutoHotkey doesn't support multiple loop ranges, so a workaround function is used instead.

for_J(doFunction, start, stop, step:=1){
	j := start
	while (j<=stop) && (start<=stop) && (step>0)
		%doFunction%(j),		j+=step
	while (j>=stop) && (start>stop) && (step<0)
		%doFunction%(j),		j+=step
}
Examples:
prod := 1
sum := 0
x := +5
y := -5
z := -2
one :=  1
three :=  3
seven :=  7

for_J("doTHis", -three, 3**3, three)
for_J("doTHis", -seven, +seven, x)
for_J("doTHis", 555, 550-y)
for_J("doTHis", 22, -28, -three)
for_J("doTHis", 1927, 1939)
for_J("doTHis", x, y, z)
for_J("doTHis", 11**x, 11**x+one)

MsgBox % "sum = " RegExReplace(sum, "\B(?=(\d{3})+$)", ",") 
. "`nprod = "  RegExReplace(prod, "\B(?=(\d{3})+$)", ",") 
return
;----------------------------------------------
doThis(j){
	global sum, prod
	sum += Abs(j)
	if (Abs(prod) < 2**27) && (j != 0)
		prod *= j
}
return
Output:
sum = 348,173
prod = -793,618,560

AWK[edit]

# syntax: GAWK -f LOOPS_WITH_MULTIPLE_RANGES.AWK
BEGIN {
    prod = 1
    sum = 0
    x = 5
    y = -5
    z = -2
    one = 1
    three = 3
    seven = 7
    for (j=-three; j<=(3^3); j+=three) { main(j) }
    for (j=-seven; j<=seven; j+=x) { main(j) }
    for (j=555; j<=550-y; j++) { main(j) }
    for (j=22; j>=-28; j+=-three) { main(j) }
    for (j=1927; j<=1939; j++) { main(j) }
    for (j=x; j>=y; j+=z) { main(j) }
    for (j=(11^x); j<=(11^x)+1; j++) { main(j) }
    printf("sum = %d\n",sum)
    printf("prod = %d\n",prod)
    exit(0)
}
function main(x) {
    sum += abs(x)
    if (abs(prod) < (2^27) && x != 0) {
      prod *= x
    }
}
function abs(x) { if (x >= 0) { return x } else { return -x } }
Output:
sum = 348173
prod = -793618560

BASIC256[edit]

Translation of: FreeBASIC
global sum, prod

subroutine process(x)
	sum += abs(x)
	if abs(prod) < (2 ^ 27) and x <> 0 then prod *= x
end subroutine

prod = 1
sum = 0
x = 5   : y = -5    : z = -2
one = 1 : three = 3 : seven = 7

for j = -three to (3 ^ 3) step three: call process(j): next j
for j = -seven to seven step x: call process(j): next j
for j = 555 to 550 - y: call process(j): next j
for j = 22 to -28 step -three: call process(j): next j
for j = 1927 to 1939: call process(j): next j
for j = x to y step z: call process(j): next j
for j = (11 ^ x) to (11 ^ x) + one: call process(j): next j

print " sum= "; int(sum)
print "prod= "; int(prod)
end


C[edit]

#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;
}
Output:
sum  =  348,173
prod = -793,618,560

C#[edit]

Multiple ranges don't exist in C# out-of-the-box but it is easy to make something.

using System;
using System.Collections.Generic;
using System.Linq;

public static class LoopsWithMultipleRanges
{
    public static void Main() {
        int prod = 1;
        int sum = 0;
        int x = 5;
        int y = -5;
        int z = -2;
        int one = 1;
        int three = 3;
        int seven = 7; 

        foreach (int j in Concat(
            For(-three, 3.Pow(3), three),
            For(-seven, seven, x),
            For(555, 550 - y),
            For(22, -28, -three),
            For(1927, 1939),
            For(x, y, z),
            For(11.Pow(x), 11.Pow(x) + one)
        )) {
            sum += Math.Abs(j);
            if (Math.Abs(prod) < (1 << 27) && j != 0) prod *= j;
        }
        Console.WriteLine($" sum = {sum:N0}");
        Console.WriteLine($"prod = {prod:N0}");
    }

    static IEnumerable<int> For(int start, int end, int by = 1) {
        for (int i = start; by > 0 ? (i <= end) : (i >= end); i += by) yield return i;
    }

    static IEnumerable<int> Concat(params IEnumerable<int>[] ranges) => ranges.Aggregate((acc, r) => acc.Concat(r));
    static int Pow(this int b, int e) => (int)Math.Pow(b, e);
}
Output:
 sum = 348,173
prod = -793,618,560

C++[edit]

Works with: C++11

C++ doesn't natively support multiple ranges, but we can simulate that using a list and then iterating over the values in that list.

#include <iostream>
#include <cmath>
#include <vector>

using std::abs;
using std::cout;
using std::pow;
using std::vector;


int main()
{
    int prod  = 1,
        sum   = 0,
        x     = 5,
        y     = -5,
        z     = -2,
        one   = 1,
        three = 3,
        seven = 7;

    auto summingValues = vector<int>{};

    for(int n = -three; n <= pow(3, 3); n += three)
        summingValues.push_back(n);
    for(int n = -seven; n <= seven; n += x)
        summingValues.push_back(n);
    for(int n = 555; n <= 550 - y; ++n)
        summingValues.push_back(n);
    for(int n = 22; n >= -28; n -= three)
        summingValues.push_back(n);
    for(int n = 1927; n <= 1939; ++n)
        summingValues.push_back(n);
    for(int n = x; n >= y; n += z)
        summingValues.push_back(n);
    for(int n = pow(11, x); n <= pow(11, x) + one; ++n)
        summingValues.push_back(n);

    for(auto j : summingValues)
    {
        sum += abs(j);
        if(abs(prod) < pow(2, 27) && j != 0)
            prod *= j;
    }

    cout << "sum = " << sum << "\n";
    cout << "prod = " << prod << "\n";
}
Output:
sum = 348173
prod = -793618560

Common Lisp[edit]

Using raw code and DO iterator

(let ((prod 1)				; Initialize aggregator
      (sum 0)
      (x 5)				; Initialize variables
      (y -5)
      (z -2)
      (one 1)
      (three 3)
      (seven 7))

  (flet ((loop-body (j)			; Set the loop function
	    (incf sum (abs j))
	    (if (and (< (abs prod) (expt 2 27))
		     (/= j 0))
		(setf prod (* prod j)))))

    (do ((i (- three) (incf i three)))	; Just a serie of individual loops
	((> i (expt 3 3)))
      (loop-body i))
    (do ((i (- seven) (incf i x)))
	((> i seven))
      (loop-body i))
    (do ((i 555 (incf i -1)))
	((< i (- 550 y)))
      (loop-body i))
    (do ((i 22 (incf i (- three))))
	((< i -28))
      (loop-body i))
    (do ((i 1927 (incf i)))
	((> i 1939))
      (loop-body i))
    (do ((i x (incf i z)))
	((< i y))
      (loop-body i))
    (do ((i (expt 11 x) (incf i)))
	((> i (+ (expt 11 x) one)))
      (loop-body i)))

  (format t "~&sum  = ~14<~:d~>" sum)
  (format t "~&prod = ~14<~:d~>" prod))

or with loop ranges and increments as list to dolist

(let ((prod 1)
      (sum 0)
      (x 5)
      (y -5)
      (z -2)
      (one 1)
      (three 3)
      (seven 7))

  (flet ((loop-body (j)			; Set the loop function
	   (incf sum (abs j))
	   (if (and (< (abs prod) (expt 2 27))
		    (/= j 0))
	       (setf prod (* prod j)))))

    (dolist (lst `((,(- three) ,(expt 3 3) ,three)
		   (,(- seven) ,seven ,x)
		   (555 ,(- 550 y) -1)
		   (22 -28 ,(- three))
		   (1927 1939 1)
		   (,x ,y ,z)
		   (,(expt 11 x) ,(+ (expt 11 x) one) 1)))
      (do ((i (car lst) (incf i (caddr lst))))
	  ((if (plusp (caddr lst))
	       (> i (cadr lst))
	       (< i (cadr lst))))
	(loop-body i))))

  (format t "~&sum  = ~14<~:d~>" sum)
  (format t "~&prod = ~14<~:d~>" prod))
Output:
sum  =        348,173
prod =   -793,618,560

Delphi[edit]

Translation of: C

Delphi don't have for with multiples ranges and for with different increments (except +1 and -1). The workaround is using while loop.

program with_multiple_ranges;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

var
  prod: Int64 = 1;
  sum: Int64 = 0;

function labs(value: Int64): Int64;
begin
  Result := value;
  if value < 0 then
    Result := -Result;
end;

procedure process(j: Int64);
begin
  sum := sum + (abs(j));
  if (labs(prod) < (1 shl 27)) and (j <> 0) then
    prod := prod * j;
end;

function ipow(n: Integer; e: Cardinal): Int64;
var
  pr: Int64;
  max, i: Cardinal;
begin
  result := n;
  if e = 0 then
    Exit(1);
  max := e;
  for i := 2 to max do
    result := result * n;
end;

var
  j: Int64;
  p: Int64;

const
  x = 5;
  y = -5;
  z = -2;
  one = 1;
  three = 3;
  seven = 7;

begin
  p := ipow(11, x);

  j := -three;
  while j <= ipow(3, 3) do
  begin
    process(j);
    inc(j, three);
  end;

  j := -seven;
  while j <= seven do
  begin
    process(j);
    inc(j, x);
  end;

  j := 555;
  while j <= (550 - y) do
  begin
    process(j);
    inc(j, x);
  end;

  j := 22;
  while j >= -28 do
  begin
    process(j);
    dec(j, three);
  end;

  j := 1927;
  while j <= 1939 do
  begin
    process(j);
    inc(j);
  end;

  j := x;
  while j >= y do
  begin
    process(j);
    dec(j, -z);
  end;

  j := p;
  while j <= p + one do
  begin
    process(j);
    inc(j);
  end;

  writeln(format('sum  =  %d  ', [sum]));
  writeln(format('prod =  %d  ', [prod]));
  Readln;
end.
Output:
sum  =  348173
prod =  -793618560

EasyLang[edit]

prod = 1
sum = 0
x = 5
y = -5
z = -2
one = 1
three = 3
seven = 7
ranges[][] = [ [ -three (pow 3 3) three ] [ -seven seven x ] [ 555 (550 - y) ] [ 22 -28 (-three) ] [ 1927 1939 ] [ x y z ] [ (pow 11 x) (pow 11 x + one) ] ]
# 
for i range len ranges[][]
  j = ranges[i][0]
  to = ranges[i][1]
  inc = 1
  if len ranges[i][] = 3
    inc = ranges[i][2]
  .
  repeat
    until inc > 0 and j > to or inc < 0 and j < to
    sum += abs j
    if abs prod < pow 2 27 and j <> 0
      prod *= j
    .
    j += inc
  .
.
print sum
print prod

Eiffel[edit]

Eiffel does not support multiple ranges in the same fashion as PL/I. However, it does have an across loop, which does the trick, together with an inline agent (lambda function).

class
	APPLICATION

create
	make

feature

	prod, sum, x, y, z, one, three, seven: INTEGER

	make
		local
			process: PROCEDURE
		do
			prod := 1; x := 5; y := -5; z := -2; one := 1; three := 3; seven := 7
			process := (agent (j: INTEGER)
								do
									print (j.out + ", ")
									sum := sum + j.abs
									if prod.abs < 2^27 and j /= 0 then
										prod := prod * j
									end
								end)

			across (-three |..| (3^3).truncated_to_integer).new_cursor + (three - 1)  as ic loop process.call (ic.item) end
			across (-seven |..| seven).new_cursor + (x - 1)	as ic loop process.call (ic.item) end
			across 555 |..| (550 - y) as ic loop process.call (ic.item) end
			across (-26 |..| 22).new_cursor + (three - 1) as ic loop process.call (ic.item) end
			across 1927 |..| 1939 as ic loop process.call (ic.item) end
			across (y |..| x).new_cursor + (-z - 1)	as ic loop process.call (ic.item) end
			across (11^x).truncated_to_integer |..| ((11^x).truncated_to_integer + 1) as ic loop process.call (ic.item) end

			print ("%N")
			print ("sum = " + sum.out + "%N") 		-- sum = 348,173
			print ("prod = " + prod.out + "%N")		-- prod = -793,618,560
		end

end

Alternatively, there is the "symbolic form" of the across loop, which modifies the code as follows:

class
	APPLICATION

create
	make

feature

	prod, sum, x, y, z, one, three, seven: INTEGER

	make
		local
			process: PROCEDURE
		do
			prod := 1; x := 5; y := -5; z := -2; one := 1; three := 3; seven := 7
			process := (agent (j: INTEGER)
								do
									print (j.out + ", ")
									sum := sum + j.abs
									if prod.abs < 2^27 and j /= 0 then
										prod := prod * j
									end
								end)

			 ic: (-three |..| (3^3).truncated_to_integer).new_cursor + (three - 1) ¦ process.call (ic) 
			 ic: (-seven |..| seven).new_cursor + (x - 1) ¦ process.call (ic) 
			 ic:555 |..| (550 - y) ¦ process.call (ic) 
			 ic: (-26 |..| 22).new_cursor + (three - 1) ¦ process.call (ic) 
			 ic: 1927 |..| 1939 ¦ process.call (ic) 
			 ic: (y |..| x).new_cursor + (-z - 1) ¦ process.call (ic) 
			 ic: (11^x).truncated_to_integer |..| ((11^x).truncated_to_integer + 1) ¦ process.call (ic) 

			print ("%N")
			print ("sum = " + sum.out + "%N") 		-- sum = 348,173
			print ("prod = " + prod.out + "%N")		-- prod = -793,618,560
		end

end
Output:
 sum=  348,173
prod= -793,618,560

F#[edit]

// Loops/With multiple ranges. Nigel Galloway: June 13th., 2022
let x,y,z,one,three,seven=5,-5,-2,1,3,7
let Range=[-three..three..pown 3 3]@[-7..x..seven]@[555..550-y]@[22..-three.. -28]@[1927..1939]@[x..z..y]@[pown 11 x..(pown 11 x)+1]
printfn "Sum=%d Product=%d" (Range|>Seq.sumBy(abs)) (Range|>Seq.filter((<>)0)|>Seq.fold(fun n g->if abs n<pown 2 27 then n*g else n) 1)
Output:
Sum=348173 Product=-793618560

Factor[edit]

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.

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
]
Output:
 sum=  348,173
prod= -793,618,560

FreeBASIC[edit]

Translation of: VBA
Dim Shared As Long prod, sum

Sub process(x As Long)
    sum += Abs(x)
    If Abs(prod) < (2 ^ 27) And x <> 0 Then prod *= x
End Sub

Dim j As Long
prod = 1
sum = 0
Dim As Integer x = 5, y = -5, z = -2
Dim As Integer one = 1, three = 3, seven = 7

For j = -three To (3 ^ 3) Step three: process(j): Next j
For j = -seven To seven Step x: process(j): Next j
For j = 555 To 550 - y: process(j): Next j
For j = 22 To -28 Step -three: process(j): Next j
For j = 1927 To 1939: process(j): Next j
For j = x To y Step z: process(j): Next j
For j = (11 ^ x) To (11 ^ x) + one: process(j): Next j

Print Using " sum= ###,###"; sum
Print Using "prod= ####,###,###"; prod
Sleep

FutureBasic[edit]

Note: This code uses NSInteger variables instead of int because NSInteger automatically adjusts to 32-bit or 64-bit Macintosh architecture. Also, since FB's abs() function takes either a legacy int or a float, this code uses a float for the abs() parameter to avoid a warning,

window 1, @"Loops with Ranges", ( 0, 0, 400, 400 )

begin globals
NSInteger sum  = 0
float     prod = 1
end globals

local fn process( x as float )
sum += abs(x)
if abs(prod) < (2 ^ 27) and x <> 0 then prod = prod * x
end fn

NSInteger j
NSInteger x = 5, y = -5, z = -2
NSInteger one = 1, three = 3, seven = 7

for j = -three to (3 ^ 3) step three: fn process(j): next j
for j = -seven to seven step x: fn process(j): next j
for j = 555 to 550 - y: fn process(j): next j
for j = 22 to -28 step -three: fn process(j): next j
for j = 1927 to 1939: fn process(j): next j
for j = x to y step z: fn process(j): next j
for j = (11 ^ x) to (11 ^ x) + one: fn process(j): next j

print using " sum = ###,###"; sum
print using "prod =-####,###,###"; prod

HandleEvents
Output:
sum  = 348,173
prod = -793,618,560

Go[edit]

Nothing fancy from Go here (is there ever?), just a series of individual for loops.

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))
}
Output:
sum  =   348,173
prod =  -793,618,560

Groovy[edit]

Solution:

def (prod, sum, x, y, z, one, three, seven) = [1, 0, +5, -5, -2, 1, 3, 7]

for (
    j in (
        ((-three) .. (3**3)       ).step(three)
      + ((-seven) .. (+seven)     ).step(x)
      + (555      .. (550-y)      )
      + (22       .. (-28)        ).step(three)    // This is correct!
      // Groovy interprets positive step size as stride through the LIST ELEMENTS as ordered
      // and negative step size as stride through the REVERSED LIST ELEMENTS as ordered
      //   so step(-3) gives:   -28, -25, -22, ... ,  20
      //   while step(3) gives:  22,  19,  16, ... , -26
      + (1927     .. 1939         )
      + (x        .. y            ).step(z)
      + (11**x    .. (11**x + one))
    )
) {

    sum = sum + j.abs()
    if ( prod.abs() < 2**27 && j != 0) prod *= j
}

println " sum= ${sum}"
println "prod= ${prod}"

Output:

 sum= 348177
prod= -793618560

Haskell[edit]

Haskell does not have loops. Programmers use either explicit recursion or recursive schemes (folds or unfolds) for looping. The following code mimics the PL/1 example using composition of left folds in order to handle multiple ranges:

loop :: (b -> a -> b) -> b -> [[a]] -> b
loop = foldl . foldl

example = let
  x = 5
  y = -5
  z = -2
  one = 1
  three = 3
  seven = 7
  in
    loop
    -- body
    (
      \(sum, prod) j ->
        (
          sum + abs j,
          if abs prod < 2^27 && j /= 0
          then prod * j else prod
        )
    )
    -- initial state
    (0, 1)
    -- ranges
    [ [-three, -three + three .. 3^3]
      , [-seven, -seven + x .. seven]
      , [555 .. 550 - y]
      , [22, 22 - three .. -28]
      , [1927 .. 1939]
      , [x, x + z .. y]
      , [11^x ..  11^x + one] ]

J[edit]

J uses the names x, y, m, n, u, v to pass arguments into explicit definitions. Treating these as reserved names is reasonable practice. Originally these had been x. , y. etceteras however the dots must have been deemed "noisy".

We've passed the range list argument literally for evaluation in local scope. Verb f evaluates and concatenates the ranges, then perhaps the ensuing for. loop looks somewhat like familiar code.

NB. http://rosettacode.org/wiki/Loops/Wrong_ranges#J
NB. define range as a linear polynomial
start =: 0&{
stop =: 1&{
increment =: 2&{ :: 1:  NB. on error use 1
range =: (start , increment) p. [: i. [: >: [: <. (stop - start) % increment

f =: 3 :0
 input =. y
 'prod sum x y z one three seven' =. 1 0 5 _5 _2 1 3 7
 J =. ([: ; range&.>) ". input
 for_j. J do.
  sum =. sum + | j
  if. ((|prod)<2^27) *. (0 ~: j) do.
   prod =. prod * j
  end.
 end.
 sum , prod
)
   ] A =: f '((-three), (3^3), three); ((-seven),seven,x); (555 , 550-y); (22 _28, -three); 1927 1939; (x,y,z); (0 1 + 11^x)'
348173 _7.93619e8
   
   20j0 ": A
              348173          _793618560

Java[edit]

Java does not support multiple ranges. Use list to simulate multiple ranges. Accumulate values in a list, then iterate over the list.

With Java 8, streams are available. Streams can be concatenated. However, the Java 9 feature takeWhile is important to this task to specify the iteration limit.

Maintain formatting similar to the original code.

import java.util.ArrayList;
import java.util.List;

public class LoopsWithMultipleRanges {

    private static long sum = 0;
    private static long prod = 1;
    
    public static void main(String[] args) {
        long x = 5;
        long y = -5;
        long z = -2;
        long one = 1;
        long three = 3;
        long seven = 7;
        
        List<Long> jList = new ArrayList<>();
        for ( long j = -three     ; j <= pow(3, 3)        ; j += three )  jList.add(j);
        for ( long j = -seven     ; j <= seven            ; j += x )      jList.add(j);
        for ( long j = 555        ; j <= 550-y            ; j += 1 )      jList.add(j);
        for ( long j = 22         ; j >= -28              ; j += -three ) jList.add(j);
        for ( long j = 1927       ; j <= 1939             ; j += 1 )      jList.add(j);
        for ( long j = x          ; j >= y                ; j += z )      jList.add(j);
        for ( long j = pow(11, x) ; j <= pow(11, x) + one ; j += 1 )      jList.add(j);

        List<Long> prodList = new ArrayList<>();
        for ( long j : jList ) {
            sum += Math.abs(j);
            if ( Math.abs(prod) < pow(2, 27) && j != 0 ) {
                prodList.add(j);
                prod *= j;
            }            
        }
        
        System.out.printf(" sum        = %,d%n", sum);
        System.out.printf("prod        = %,d%n", prod);
        System.out.printf("j values    = %s%n", jList);
        System.out.printf("prod values = %s%n", prodList);
    }
    
    private static long pow(long base, long exponent) {
        return (long) Math.pow(base, exponent);
    }
    
}
Output:
 sum        = 348,173
prod        = -793,618,560
j values    = [-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]
prod values = [-3, 3, 6, 9, 12, 15, 18, 21, 24]

jq[edit]

Works with: jq

Works with gojq, the Go implementation of jq

jq is stream-oriented, and so the "multiple ranges" feature comes for free, that is, it just involves stream concatenation with the "," operator.

The only wrinkle is that jq's `range` filters exclude the "right-hand" limit; to facilitate comparison with the PL/I code, the adjustment (e.g. "1 + ...") has been made explicit.

Since the only variables that are updated within the body of the loop are "sum" and "prod", the others could be defined as constants (i.e. as $-variables), but again to facilitate comparison with the PL/I code, this has not been done.

# If using gojq, one may want to preserve integer precision, so:
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);

{ prod: 1,                             #  start with a product of unity.
  sum:  0,                             #  henceforth skip redundant comments.
    x:  5,
    y: -5,
    z: -2,
  one:  1,
  three: 3,
  seven: 7 }
| .x as $x  
| reduce (range(-.three; 1 + 3|power(3); .three),
          range(-.seven; 1 + .seven;     .x),
          range(    555; 1 +  550 - .y),
          range(     22; -1 -28;          -.three),
          range(1927   ; 1 + 1939),
          range(.x     ; .y;              .z),
          range(11|power($x); 1 + ( 11 | power($x)) + .one)) as $j (.;
             .sum += ($j|length)                         # add absolute value of $j (!)
             | if (.prod|length) < (2|power(27)) and $j != 0
	       then .prod *= $j
	       else .
	       end )
| "sum=  \(.sum)",
  "prod= \(.prod)"
Output:
sum=  348726
prod= -793618560

Julia[edit]

Julia allows concatenation of iterators with the ; iterator within a vector. An attempt was made to preserve the shape of the PL/1 code.

using Formatting

function PL1example()

                                    # 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
    for j in [           -three   :  three :  3^3           ;
                         -seven   :   x    :  +seven        ;
                            555            :  550 - y       ;
                             22   : -three :  -28           ;
                           1927            :  1939          ;
                              x   :  z     :  y             ;
                           11^x            :   11^x + one   ]
                                                        # ABS(n) = absolute value
        sum = sum + abs(j);                             # add absolute value of J.
        if abs(prod) < 2^27 && j !=0 prod = prod*j      # PROD is small enough & J
        end;                                            # not 0, then multiply it.
    end             # SUM and PROD are used for verification of J incrementation.
    println(" sum = $(format(sum, commas=true))");      # display strings to term.
    println("prod = $(format(prod, commas=true))");     #   "       "     "   "
end

PL1example()
Output:

    sum = 348,173      
   prod = -793,618,560 

Kotlin[edit]

Nothing special here, just a series of individual for loops.

// 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)
}
Output:
sum  =  348,173
prod = -793,618,560

Lua[edit]

Not directly supported, i.e. no true multi-range loops, but.. all that's really needed is a helper function to populate the list of values, aiming to specify the ranges with a syntax as-close-as-manageable to mimic that given in task description (iteration is then trivial):

-- support:
function T(t) return setmetatable(t, {__index=table}) end
table.range = function(t,a,b,c) local s=T{} for i=a,b,c or 1 do s[#s+1]=i end return s end
table.clone = function(t) local s=T{} for k,v in ipairs(t) do s[k]=v end return s end
table.chain = function(t,u) local s=t:clone() for i=1,#u do s[#s+1]=u[i] end return s end
unpack = unpack or table.unpack -- polyfill 5.2 vs 5.3

-- impl:
-- Multi-Range-Loop
-- param: table of tables of range specs
-- return: iterator over the chain of all ranges
function mrl(tt)
  local s=T{}
  for _,t in ipairs(tt) do s=s:chain(T{}:range(unpack(t))) end
  return ipairs(s)
end

-- demo:
prod,sum,x,y,z,one,three,seven = 1,0,5,-5,-2,1,3,7
for _,j in mrl{
  { -three,    3^3,  three },
  { -seven,  seven,      x },
  {    555,  550-y         },
  {     22,    -28, -three },
  {   1927,   1939         },
  {      x,      y,      z },
  {   11^x, 11^x+1         }} do
  sum = sum + math.abs(j)
  if math.abs(prod) < 2^27 and j~=0 then prod = prod * j end
end
print(" sum= " .. sum)
print("prod= " .. prod)
Output:
 sum= 348173
prod= -793618560

M2000 Interpreter[edit]

Using lambda functions and a final While End While to perform a multiple range.

Values by default are double, but we can make them Long (32 bit integer), or Decimal or Currency or single (prod for single has less accuracy here), but not integer (16 bit) because we get overflow.

In M2000 expressions can change numeric type to hold the produced value. Variables take once the type, so we get overflow if we pass a value frome an expression which can't convert to variable's type.

Module MultipleLoop {
	def long prod=1, sum=0, x=+5,y=-5, z=-2, one=1, three=3, seven=7, j
	Range=lambda (a, b, c=1) ->{
		=lambda a, b, c (&f)-> {
			if compare(a,b)=sgn(c) then =false else =true: f=a: a+=c
		}
	}
	MultipleRange=Lambda -> {
		a=array([])  '  convert stack items in current stack [] to an array of items
		=lambda  a, k=0 (&f) ->{
			do : if k<len(a) Else exit
			if a#eval(k, &f) then =true: exit
			k++ : always
		}
	}
	Exec=MultipleRange(Range(-three, 3**3, three), Range(-seven, +seven, x), Range(555, 550-y), Range(22, -28, -three), Range(1927, 1939), Range(x,y,z), Range(11**x, 11**x+one))
	j=0
	while Exec(&j)
		sum+=abs(j)
		if abs(prod) < 2^27 And j <> 0 then prod*=j
	End While
	
	Print "sum=";sum
	Print "prod=";prod
}
MultipleLoop
Output:
sum=348173
prod=-793618560

Mathematica / Wolfram Language[edit]

prod = 1;
sum = 0;
x = 5;
y = -5;
z = -2;
one = 1;
three = 3;
seven = 7;
Do[
 sum += Abs[j];
 If[Abs[prod] < 2^27 \[And] j != 0, prod *= j];
 ,
 {j,
  Join[
   Range[-three, 3^3, three],
   Range[-seven, seven, x],
   Range[555, 550 - y],
   Range[22, -28, -three],
   Range[1927, 1939],
   Range[x, y, z],
   Range[11^x, 11^x + one]
   ]
  }
 ]
sum
prod
Output:
348173
-793618560

Nim[edit]

Nim doesn’t provide loops with multiple ranges. There are several ways to translate the PL/1 program: using a sequence of for loops, using a sequence of while loops, using an iterator and, probably, too, some way using macros.

Using a sequence of loops[edit]

This solution is the obvious one, but it supposes that the direction of the loop is known (i.e. the sign of the step is known) as we have to choose between iterators “countup” and “countdown”. Using this method, the PL/1 example can be translated the following way:

import math, strutils

var
  prod = 1
  sum = 0

let
  x = +5
  y = -5
  z = -2
  one = 1
  three = 3
  seven = 7

proc body(j: int) =
  sum += abs(j)
  if abs(prod) < 2^27 and j != 0: prod *= j


for j in countup(-three, 3^3, three): body(j)
for j in countup(-seven, seven, x): body(j)
for j in countup(555, 550 - y): body(j)
for j in countdown(22, -28, three): body(j)
for j in countup(1927, 1939): body(j)
for j in countdown(x, y, -z): body(j)
for j in countup(11^x, 11^x + one): body(j)

let s = ($sum).insertSep(',')
let p = ($prod).insertSep(',')
let m = max(s.len, p.len)
echo " sum = ", s.align(m)
echo "prod = ", p.align(m)

Note that for “countdown” we must change the sign of the step to insure that it is positive.

Output:
 sum =      348,173
prod = -793,618,560

Using an iterator[edit]

If the sign of the step is not known (or may vary), it is no longer possible to use the previous method. One could use a while loop but it seems better to use an iterator.

import math, strutils

var
  prod = 1
  sum = 0

let
  x = +5
  y = -5
  z = -2
  one = 1
  three = 3
  seven = 7

type Range = tuple[first, last, step: int]

func initRange(first, last, step = 1): Range = (first, last, step)

iterator loop(ranges: varargs[Range]): int =
  for r in ranges:
    if r.step > 0:
      for i in countup(r.first, r.last, r.step):
        yield i
    elif r.step < 0:
      for i in countdown(r.first, r.last, -r.step):
        yield i
    else:
      raise newException(ValueError, "step cannot be zero")

for j in loop(initRange(-three, 3^3, three),
              initRange(-seven, seven, x),
              initRange(555, 550 - y),
              initRange(22, -28, three),
              initRange(1927, 1939),
              initRange(x, y, -z),
              initRange(11^x, 11^x + one)):
  sum += abs(j)
  if abs(prod) < 2^27 and j != 0: prod *= j

let s = ($sum).insertSep(',')
let p = ($prod).insertSep(',')
let m = max(s.len, p.len)
echo " sum = ", s.align(m)
echo "prod = ", p.align(m)

Note that we have defined a function “initRange” to create the ranges. This is needed to make the step optional. If we suppressed this requirement (i.e. we required the step to be always specified), we could get ride of “initRange” and write the loop this way:

for j in loop((-three, 3^3, three),
              (-seven, seven, x),
              (555, 550 - y),
              (22, -28, three),
              (1927, 1939, 1),
              (x, y, -z),
              (11^x, 11^x + one)):
  sum += abs(j)
  if abs(prod) < 2^27 and j != 0: prod *= j

Perl[edit]

use constant   one =>  1;
use constant three =>  3;
use constant seven =>  7;
use constant     x =>  5;
use constant    yy => -5; # 'y' conflicts with use as equivalent to 'tr' operator (a carry-over from 'sed')
use constant     z => -2;

my $prod = 1;

sub from_to_by {
    my($begin,$end,$skip) = @_;
    my $n = 0;
    grep{ !($n++ % abs $skip) } $begin <= $end ? $begin..$end : reverse $end..$begin;
}

sub commatize {
    (my $s = reverse shift) =~ s/(.{3})/$1,/g;
    $s =~ s/,(-?)$/$1/;
    $s = reverse $s;
}

for my $j (
    from_to_by(-three,3**3,three),
    from_to_by(-seven,seven,x),
    555 .. 550 - yy,
    from_to_by(22,-28,-three),
    1927 .. 1939,
    from_to_by(x,yy,z),
    11**x .. 11**x+one,
   ) {
     $sum  += abs($j);
     $prod *= $j if $j and abs($prod) < 2**27;
}

printf "%-8s %12s\n", 'Sum:',     commatize $sum;
printf "%-8s %12s\n", 'Product:', commatize $prod;
Output:
Sum:          348,173
Product: -793,618,560

Phix[edit]

integer prod =  1,
       total =  0,  -- (renamed as sum is a Phix builtin)
           x = +5,
           y = -5,
           z = -2,
         one =  1,
       three =  3,
       seven =  7
 
sequence loopset = {{     -three,        power(3,3), three },
                    {     -seven,            +seven,   x   },
                    {        555,           550 - y,   1   },
                    {         22,               -28, -three},
                    {       1927,              1939,   1   },
                    {          x,                 y,   z   },
                    {power(11,x), power(11,x) + one,   1   }}
 
for i=1 to length(loopset) do
    integer {f,t,s} = loopset[i]
    for j=f to t by s do
        total += abs(j)
        if abs(prod)<power(2,27) and j!=0 then
            prod *= j
        end if
    end for
end for
printf(1," sum = %,d\n",total)
printf(1,"prod = %,d\n",prod)
Output:
 sum = 348,173
prod = -793,618,560

Picat[edit]

Picat has support for multiple loop variables, but the index variables for each range must be different:

foreach(I in 1..3, J in 4..6, K in 7..9)
  % ...
end

Here's a variant using the single loop variable J.

go =>
   Prod=  1,
    Sum=  0,
      X= +5,
      Y= -5,
      Z= -2,
    One=  1,
  Three=  3,
  Seven=  7,
  Ranges = [-Three..Three..3**3,
            -Seven..X.. +Seven,
            555..550-Y,
            22..-Three..-28,
            1927..1939,
            X..Z..Y,
            11**X..11**X + One
           ], 
  foreach(Range in Ranges, J in Range)
    Sum := Sum + abs(J),
    if abs(Prod) < 2**27, J != 0 then
      Prod := Prod * J
    end
  end,                                        
  println(sum=Sum),
  println(prod=Prod),
  nl.
Output:
sum = 348173
prod = -793618560

Another approach is to first concatenate the ranges and then flatten to a single list:

  % ...
  foreach(J in [-Three..Three..3**3,
                -Seven..X.. +Seven,
                555..550-Y,
                22..-Three..-28,
                1927..1939,
                X..Z..Y,
                11**X..11**X + One
                ].flatten
    )
    Sum := Sum + abs(J),
    if abs(Prod) < 2**27, J != 0 then
      Prod := Prod * J
    end
  end,                                        
  % ...


Prolog[edit]

Prolog does not have the richness of some other languages where it comes to loops, variables and the like, but does have some rather interesting features such as difference lists and backtracking for generating solutions.

for(Lo,Hi,Step,Lo)  :- Step>0, Lo=<Hi.
for(Lo,Hi,Step,Val) :- Step>0, plus(Lo,Step,V), V=<Hi, !, for(V,Hi,Step,Val).
for(Hi,Lo,Step,Hi)  :- Step<0, Lo=<Hi.
for(Hi,Lo,Step,Val) :- Step<0, plus(Hi,Step,V), Lo=<V, !, for(V,Lo,Step,Val).

sym(x,5).                 % symbolic lookups for values
sym(y,-5).
sym(z,-2).
sym(one,1).
sym(three,3).
sym(seven,7).

range(-three,3^3,three).  % as close as we can syntactically get
range(-seven,seven,x).
range(555,550-y,1).
range(22,-28, -three).
range(1927,1939,1).
range(x,y,z).
range(11^x,11^x+one,1).

translate(V, V)   :- number(V), !.    % difference list based parser
translate(S, V)   :- sym(S,V), !.
translate(-S, V)  :- translate(S,V0), !, V is -V0.
translate(A+B, V) :- translate(A,A0), translate(B, B0), !, V is A0+B0.
translate(A-B, V) :- translate(A,A0), translate(B, B0), !, V is A0-B0.
translate(A^B, V) :- translate(A,A0), translate(B, B0), !, V is A0^B0.

range_value(Val) :-             % enumerate values for all ranges in order
	range(From,To,Step), 
	translate(From,F), translate(To,T), translate(Step,S), 
	for(F,T,S,Val).

calc_values([], S, P, S, P).    % calculate all values in generated order
calc_values([J|Js], S, P, Sum, Product) :-
  S0 is S + abs(J), ((abs(P)< 2^27, J \= 0) -> P0 is P * J; P0=P),
  !, calc_values(Js, S0, P0, Sum, Product).

calc_values(Sum, Product) :-    % Find the sum and product
	findall(V, range_value(V), Values),
	calc_values(Values, 0, 1, Sum, Product).
?- calc_values(Sum, Product).
Sum = 348173,
Product = -793618560.

PureBasic[edit]

#X = 5 : #Y = -5 : #Z = -2
#ONE   = 1 : #THREE = 3 : #SEVEN = 7
Define j.i
Global prod.i = 1, sum.i = 0

Macro ipow(n, e)
  Int(Pow(n, e))
EndMacro

Macro ifn(x)
  FormatNumber(x,0,".",",")
EndMacro

Macro loop_for(start, stop, step_for=1)
  For j = start To stop Step step_for
    proc(j)
  Next
EndMacro

Procedure proc(j.i)
  sum + Abs(j)
  If (Abs(prod) < ipow(2 , 27)) And (j<>0)
    prod * j
  EndIf
EndProcedure

loop_for(-#THREE, ipow(3, 3), #THREE)
loop_for(-#SEVEN, #SEVEN, #X)
loop_for(555, 550 - #Y)
loop_for(22, -28, -#THREE)
loop_for(1927, 1939)
loop_for(#X, #Y, #Z)
loop_for(ipow(11, #X), ipow(11, #X) + 1)

If OpenConsole("Loops/with multiple ranges")
  PrintN("sum  = " + ifn(sum))
  PrintN("prod = " + ifn(prod))
  Input()
EndIf
Output:
sum  = 348,173
prod = -793,618,560

Python[edit]

Pythons range function does not include the second argument hence the definition of _range()

from itertools import chain

prod, sum_, x, y, z, one,three,seven = 1, 0, 5, -5, -2, 1, 3, 7

def _range(x, y, z=1):
    return range(x, y + (1 if z > 0 else -1), z)

print(f'list(_range(x, y, z)) = {list(_range(x, y, z))}')
print(f'list(_range(-seven, seven, x)) = {list(_range(-seven, seven, x))}')

for j in chain(_range(-three, 3**3, three), _range(-seven, seven, x), 
               _range(555, 550 - y), _range(22, -28, -three),
               _range(1927, 1939), _range(x, y, z),
               _range(11**x, 11**x + 1)):
    sum_ += abs(j)
    if abs(prod) < 2**27 and (j != 0):
        prod *= j
print(f' sum= {sum_}\nprod= {prod}')
Output:
list(_range(x, y, z)) = [5, 3, 1, -1, -3, -5]
list(_range(-seven, seven, x)) = [-7, -2, 3]
 sum= 348173
prod= -793618560

QB64[edit]

'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 feasible, add commas to the two output numbers (being displayed).
'Show all output here.

'Unknown DO multiple conditions behaviour:
' this code implements a sequential/serial set of ranges mode for DO condition

Dim As Integer prod, sum, x, y, z, one, three, seven
Dim As _Integer64 Count(1 To 7)
Dim As Integer Index, IndexCondition

prod = 1
sum = 0
x = 5
y = -5
z = -2
one = 1
three = 3
seven = 7
Count(1) = -three
Count(2) = -seven
Count(3) = 555
Count(4) = 22
Count(5) = 1927
Count(6) = x
Count(7) = 11 ^ x
IndexCondition = 1
Do
    If IndexCondition = 1 Then
        If Count(1) + three < 3 ^ 3 Then Count(1) = Count(1) + three Else IndexCondition = 2
    ElseIf IndexCondition = 2 Then
        If Count(2) + x < seven Then Count(2) = Count(2) + x Else IndexCondition = 3
    ElseIf IndexCondition = 3 Then
        If Count(3) - 1 > 550 - y Then Count(3) = Count(3) - 1 Else IndexCondition = 4
    ElseIf IndexCondition = 4 Then
        If Count(4) - three > -28 Then Count(4) = Count(4) - three Else IndexCondition = 5
    ElseIf IndexCondition = 5 Then
        If Count(5) + 1 < 1939 Then Count(5) = Count(5) + 1 Else IndexCondition = 6
    ElseIf IndexCondition = 6 Then
        If Count(6) + z < y Then Count(6) = Count(6) + z Else IndexCondition = 7
    ElseIf IndexCondition = 7 Then
        If Count(7) + 1 < 11 ^ (x + one) Then Count(7) = Count(7) + 1 Else Exit Do
    End If

    sum = sum + Abs(Count(IndexCondition))
    If Abs(prod) < 2 ^ 27 And (j <> 0) Then prod = prod * Count(IndexCondition)
    Print sum
    Print prod

Loop

Raku[edit]

(formerly Perl 6)

This task is really conflating two separate things, (at least in Raku). Sequences and loops are two different concepts and may be considered / implemented separately from each other.

Yes, you can generate a sequence with a loop, and a loop can use a sequence for an iteration value, but the two are somewhat orthogonal and don't necessarily overlap.

Sequences are first class objects in Raku. You can (and typically do) generate a sequence using the (appropriately enough) sequence operator and can assign it to a variable and/or pass it as a parameter; the entire sequence, not just it's individual values. It may be used in a looping construct, but it is not necessary to do so.

Various looping constructs often do use sequences as their iterator but not exclusively, possibly not even in the majority.


Displaying the j sequence as well since it isn't very large.

sub comma { ($^i < 0 ?? '-' !! '') ~ $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, *+three3³         ),
  ( -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²⁷;

# Or, 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.
# Note that these operators will only work for monotonic sequences.

sub infix:<to> { $^a ... $^b }
sub infix:<by> { $^a[0, $^b.abs ... *] }

$j = cache 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)            ;

put "\nLiteral minded variant:";
put '       Sum: ', comma [+] $j».abs;
put '   Product: ', comma ([\*] $j.grep: so +*).first: *.abs > 2²⁷;
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 variant:
       Sum: 348,173
   Product: -793,618,560

Red[edit]

As "to" has another meaning in Red, we name "->" the range operator.

Red ["For loop with multiple ranges"]

->: make op! function [start end][
    res: copy []
    repeat n 1 + absolute to-integer end - start [
        append res start + either start > end [1 - n][n - 1]
    ]
]
by: make op! function [s w] [extract s absolute w]

for: function ['word ranges body][
    inp: copy [] 
    foreach c reduce ranges [append inp c]
    foreach i inp [set word i do body]
]

 prod:  1                   
  sum:  0            
    x: +5
    y: -5
    z: -2
  one:  1
three:  3
seven:  7

for j [
    0 - three -> (3 ** 3)   by three
    0 - seven -> seven      by x
        555   -> (550 - y)            
        22    -> -28        by (0 - three)
        1927  -> 1939                  
        x     -> y          by z    
    11 ** x   -> (11 ** x + one)
] [
    sum: sum + absolute j;                          
    if all [(absolute prod) < power 2 27 j <> 0] [prod: prod * j]
]
print ["sum: " sum "^/prod:" prod]
Output:
sum:  348173 
prod: -793618560

REXX[edit]

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.

/*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;
output   when using the same variable values:
 sum= 348,173
prod= -793,618,560

Ring[edit]

Translation of: Phix
prod =  1
total =  0
x = 5
y = -5
z = -2
one =  1
three =  3
seven =  7
 
loopset = [[-three,pow(3,3),three],
           [-seven,seven,x],
           [555,550 - y,1],
           [22,-28,-three],
           [1927,1939,1],
           [x,y,z],
           [pow(11,x),pow(11,x) + one,1]]
 
for i=1 to len(loopset) 
    f = loopset[i][1]
    t = loopset[i][2]
    s = loopset[i][3]
    for j=f to t step s
        total += fabs(j)
        if fabs(prod)<pow(2,27) and j!=0 
           prod *= j
        ok
    next
next

see "total = " + total + nl
see "product = " + prod + nl
Output:
total = 348173
product = -793618560

Ruby[edit]

Uses chaining of enumerables, which was introduced with Ruby 2.6

x, y, z, one, three, seven = 5, -5, -2, 1, 3, 7

enums = (-three).step(3**3, three) +
        (-seven).step(seven, x) +
        555     .step(550-y, -1) +
        22      .step(-28, -three) +
        (1927..1939) +                # just toying, 1927.step(1939) is fine too
        x       .step(y, z) +
        (11**x) .step(11**x + one)
# enums is an enumerator, consisting of a bunch of chained enumerators,
# none of which has actually produced a value.

puts "Sum of absolute numbers:  #{enums.sum(&:abs)}"
prod = enums.inject(1){|prod, j| ((prod.abs < 2**27) && j!=0) ? prod*j : prod}
puts "Product (but not really): #{prod}"
Output:
Sum of absolute numbers:  348173
Product (but not really): -793618560

Smalltalk[edit]

Ranges (called Interval in Smalltalk) are collections, which - like all collections - can be concatenated with the , (comma) message. Intervals are created by sending a to: or to:by: message to a magnitude-like thingy (i.e. other than numbers are possible):

prod := 1.        
sum := 0.
x := 5.
y := -5.
z := -2.
one := 1.
three := 3.
seven := 7.

(three negated to: 3**3  by: three       ) ,
(seven negated to: seven by: x           ) ,
(555           to: 550-y                 ) ,
(22            to: -28  by: three negated) ,
(1927          to: 1939                  ) ,
(x             to: y    by:z             ) ,
(11**x         to: 11**x + one           )
    do:[:j |
        sum := sum + j abs.
        ((prod abs < (2**27)) and:[ j ~= 0 ]) ifTrue:[
            prod := prod*j
        ].
    ].
Transcript show:' sum = '; showCR:sum.
Transcript show:'prod = '; showCR:prod

The above creates a temporary "collection of ranges" and enumerates that, which might be inconvenient, if the collections are huge.
One alternative is to loop over each individually.

Of course, we definitely don't want to retype the loop body and we usually don't want to the code to be non-local (i.e. define another method for it).
That's what blocks (aka lambdas or anonymous functions) are perfect for:

prod := 1.        
sum := 0.
x := 5.
y := -5.
z := -2.
one := 1.
three := 3.
seven := 7.

action := 
    [:j |
       sum := sum + j abs.
        ((prod abs < (2**27)) and:[ j ~= 0 ]) ifTrue:[
            prod := prod*j
        ].
    ].

(three negated to: 3**3  by: three       ) do:action.
(seven negated to: seven by: x           ) do:action.
(555           to: 550-y                 ) do:action.
(22            to: -28  by: three negated) do:action.
(1927          to: 1939                  ) do:action.
(x             to: y    by:z             ) do:action.
(11**x         to: 11**x + one           ) do:action.
Transcript show:' sum = '; showCR:sum.
Transcript show:'prod = '; showCR:prod

As another alternative to the first solution above, we can loop over the ranges. This avoids the concatenations and generation of the intermediate big collection (which does not really make a difference here, but would, if each collection consisted of millions of objects):

Works with: Smalltalk/X
...
{
    (three negated to: 3**3  by: three       ) .
    (seven negated to: seven by: x           ) .
    (555           to: 550-y                 ) .
    (22            to: -28  by: three negated) .
    (1927          to: 1939                  ) .
    (x             to: y    by:z             ) .
    (11**x         to: 11**x + one           ) .
} do:[:eachRange |
    eachRange 
        select:[:j | ((prod abs < (2**27)) and:[ j ~= 0 ]) ]
        thenDo:[:j | prod := prod*j ].
    ]
].
...

Notice: this creates only 8 objects and also demonstrates an alternative element selection scheme, which may be more readable.

Output:
  sum = 348173
 prod = -793618560

Note) Dialects with no **-method should use raisedTo:, or else define an alias for it in Number as:

** arg
    ^ self raisedTo: arg


True BASIC[edit]

Translation of: FreeBASIC
SUB process(x)
    LET sum = sum + abs(x)
    IF abs(prod) < (2 ^ 27) and x <> 0 then LET prod = prod * x
END SUB

LET prod = 1
LET sum = 0
LET x = 5
LET y = -5
LET z = -2
LET one = 1
LET three = 3
LET seven = 7

FOR j = -three to (3 ^ 3) step three
    CALL process(j)
NEXT j
FOR j = -seven To seven Step x
    CALL process(j)
NEXT j
FOR j = 555 to 550 - y
    CALL process(j)
NEXT j
FOR j = 22 to -28 step -three
    CALL process(j)
NEXT j
FOR j = 1927 to 1939
    CALL process(j)
NEXT j
FOR j = x to y step z
    CALL process(j)
NEXT j
FOR j = (11 ^ x) to (11 ^ x) + one
    CALL process(j)
NEXT j
PRINT " sum= "; sum
PRINT "prod= "; prod
END


uBasic/4tH[edit]

Translation of: FreeBASIC
p =  1                                 ' product
s =  0                                 ' sum

x =  5
y = -5
z = -2

o =  1                                 ' one
t =  3                                 ' three
v =  7                                 ' seVen
 
For j =   -t To (3 ^ 3) Step t:   Proc _Process(j) : Next
For j =   -v To v       Step x:   Proc _Process(j) : Next
For j =  555 To 550 - y:          Proc _Process(j) : Next
For j =   22 To -28     Step -t:  Proc _Process(j) : Next
For j = 1927 To 1939:             Proc _Process(j) : Next
For j =    x To y       Step z:   Proc _Process(j) : Next
For j = (11 ^ x) To (11 ^ x) + o: Proc _Process(j) : Next
 
Print Using " sum= +###,###"; s
Print Using "prod= +###,###,###"; p
End

_Process
  Param (1)
  
  s = s + Abs(a@)
  If (Abs(p) < (2 ^ 27)) * (a@ # 0) Then p = p * a@
Return
Output:
 sum= 348,173
prod= -793,618,560

0 OK, 0:537

Vala[edit]

const int CHARBIT = 8;
long prod = 1;
long sum = 0;

long labs(long n) {
  long mask = n >> ((long)sizeof(long) * CHARBIT - 1);
  return ((n + mask) ^ mask);
}

long lpow(long base_num, long exp)
{
  long result = 1;
  while (true)
  {
    if ((exp & 1) != 0) result *= base_num;
    exp >>= 1;
    if (exp == 0) break;
    base_num *= base_num;
  }
  return result;
}

void process(long j) {
  sum += labs(j);
  if (labs(prod) < (1 << 27) && j != 0) prod *= j;
}

void main() {
  const int x = 5;
  const int y = -5;
  const int z = -2;
  const int one = 1;
  const int three = 3;
  const int seven = 11;
  long p = lpow(11, x);
  
  for (int j = -three; j <= lpow(3, 3); j += three ) process(j);
  for (int j = -seven; j <= seven; j += x) process(j);
  for (int j = 555; j <= 550 - y; ++j) process(j);
  for (int j = 22; j >= -28; j -= three) process(j);
  for (int j = 1928; j <= 1939; ++j) process(j);
  for (int j = x; j >= y; j -= -z) process(j);
  for (long j = p; j <= p + one; ++j) process(j);
  stdout.printf("sum  = %10ld\n", sum);
  stdout.printf("prod = %10ld\n", prod);
}
Output:
sum  =     346265
prod = -793618560

VBA[edit]

Dim prod As Long, sum As Long
Public Sub LoopsWithMultipleRanges()
    Dim x As Integer, y As Integer, z As Integer, one As Integer, three As Integer, seven As Integer, j As Long
    prod = 1
    sum = 0
    x = 5
    y = -5
    z = -2
    one = 1
    three = 3
    seven = 7
    For j = -three To pow(3, 3) Step three: Call process(j): Next j
    For j = -seven To seven Step x: Call process(j): Next j
    For j = 555 To 550 - y: Call process(j): Next j
    For j = 22 To -28 Step -three: Call process(j): Next j
    For j = 1927 To 1939: Call process(j): Next j
    For j = x To y Step z: Call process(j): Next j
    For j = pow(11, x) To pow(11, x) + one: Call process(j): Next j
    Debug.Print " sum= " & Format(sum, "#,##0")
    Debug.Print "prod= " & Format(prod, "#,##0")
End Sub
Private Function pow(x As Long, y As Integer) As Long
    pow = WorksheetFunction.Power(x, y)
End Function
Private Sub process(x As Long)
    sum = sum + Abs(x)
    If Abs(prod) < pow(2, 27) And x <> 0 Then prod = prod * x
End Sub
Output:
 sum= 348.173
prod= -793.618.560

Visual Basic .NET[edit]

VB.NET loops can't have multiple ranges, so this implementation will use the For Each loop and demonstrate various functions that produce concatenated ranges.

Composite formatting is used to add digit separators.

Using the following to provide the functionality of the For loop as a function,

Partial Module Program
    ' Stop and Step are language keywords and must be escaped with brackets.
    Iterator Function Range(start As Integer, [stop] As Integer, Optional [step] As Integer = 1) As IEnumerable(Of Integer)
        For i = start To [stop] Step [step]
            Yield i
        Next
    End Function
End Module

and Enumerable.Concat (along with extension method syntax) to splice the ranges, the program ends up looking like this:

Imports System.Globalization

Partial Module Program
    Sub Main()
        ' All variables are inferred to be of type Integer.
        Dim prod = 1,
            sum = 0,
            x = +5,
            y = -5,
            z = -2,
            one = 1,
            three = 3,
            seven = 7

        ' The exponent operator compiles to a call to Math.Pow, which returns Double, and so must be converted back to Integer.
        For Each j In Range(-three,       CInt(3 ^ 3),        3     ).
               Concat(Range(-seven,       +seven,             x     )).
               Concat(Range(555,          550 - y                   )).
               Concat(Range(22,           -28,                -three)).
               Concat(Range(1927,         1939                      )).
               Concat(Range(x,            y,                  z     )).
               Concat(Range(CInt(11 ^ x), CInt(11 ^ x) + one        ))

            sum = sum + Math.Abs(j)
            If Math.Abs(prod) < 2 ^ 27 AndAlso j <> 0 Then prod = prod * j
        Next

        ' The invariant format info by default has two decimal places.
        Dim format As New NumberFormatInfo() With {
            .NumberDecimalDigits = 0
        }

        Console.WriteLine(String.Format(format, " sum= {0:N}", sum))
        Console.WriteLine(String.Format(format, "prod= {0:N}", prod))
    End Sub
End Module

To improve the program's appearance, a ConcatRange method can be defined to combine the two method calls,

    <Runtime.CompilerServices.Extension>
    Function ConcatRange(source As IEnumerable(Of Integer), start As Integer, [stop] As Integer, Optional [step] As Integer = 1) As IEnumerable(Of Integer)
        Return source.Concat(Range(start, [stop], [step]))
    End Function

which results in a loop that looks like this:

        For Each j In Range(-three,       CInt(3 ^ 3),        3     ).
                ConcatRange(-seven,       +seven,             x     ).
                ConcatRange(555,          550 - y                   ).
                ConcatRange(22,           -28,                -three).
                ConcatRange(1927,         1939                      ).
                ConcatRange(x, y,         z                         ).
                ConcatRange(CInt(11 ^ x), CInt(11 ^ x) + one        )
        Next

An alternative to avoid the repeated method calls would be to make a Range function that accepts multiple ranges, in this case as a parameter array of tuples.

    Function Range(ParamArray ranges() As (start As Integer, [stop] As Integer, [step] As Integer)) As IEnumerable(Of Integer)
        ' Note: SelectMany is equivalent to bind, flatMap, etc.
        Return ranges.SelectMany(Function(r) Range(r.start, r.stop, r.step))
    End Function

resulting in:

        For Each j In Range((-three,       CInt(3 ^ 3),        3        ),
                            (-seven,       +seven,             x        ),
                            (555,          550 - y,            1        ),
                            (22,           -28,                -three   ),
                            (1927,         1939,               1        ),
                            (x,            y,                  z        ),
                            (CInt(11 ^ x), CInt(11 ^ x) + one, 1        ))
        Next

Note, however, that the inability to have a heterogenous array means that specifying the step is now mandatory. Using a parameter array of arrays is slightly less clear but results in the tersest loop.

    Function Range(ParamArray ranges As Integer()()) As IEnumerable(Of Integer)
        Return ranges.SelectMany(Function(r) Range(r(0), r(1), If(r.Length < 3, 1, r(2))))
    End Function
        For Each j In Range({-three,       CInt(3 ^ 3),        3        },
                            {-seven,       +seven,             x        },
                            {555,          550 - y                      },
                            {22,           -28,                -three   },
                            {1927,         1939                         },
                            {x,            y,                  z        },
                            {CInt(11 ^ x), CInt(11 ^ x) + one           })
        Next
Output (for all variations):
 sum= 348,173
prod= -793,618,560

Wren[edit]

Translation of: Go
import "/fmt" for Fmt

var prod = 1
var sum = 0
var x = 5
var y = -5
var z = -2
var one = 1
var three = 3
var seven = 7
var p = 11.pow(x)
var j = 0

var process = Fn.new {
    sum = sum + j.abs
    if (prod.abs < (1 << 27) && j != 0) prod = prod * j
}
    
j = -three
while (j <= 3.pow(3)) {
    process.call()
    j = j + three
}

j = -seven
while (j <= seven) {
    process.call()
    j = j + x
}

j = 555
while (j <= 550 - y) {
    process.call()
    j = j + 1
}

j = 22
while (j >= -28) {
    process.call()
    j = j - three
}

j = 1927
while (j <= 1939) {
    process.call()
    j = j + 1
}

j = x
while (j >= y) {
    process.call()
    j = j - (-z)
}

j = p
while (j <= p + one) {
    process.call()
    j = j + 1
}

System.print("sum  =  %(Fmt.dc(sum))")
System.print("prod = %(Fmt.dc(prod))")
Output:
sum  =  348,173
prod = -793,618,560

XPL0[edit]

func IPow(A, B);        \Return A**B
int  A, B;
return fix(Pow(float(A), float(B)));

int Prod, Sum, X, Y, Z, One, Three, Seven, J;

           proc Block;
           begin                                        \ABS(n) = absolute value
           Sum:= Sum + abs(J);                          \add absolute value of J.
           if abs(Prod)<1<<27 & J#0  then Prod:=Prod*J; \PROD is small enough & J
           end;                                         \not 0, then multiply it.

begin                                  \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;

           for J:= -Three  to     3*3*3          do [Block;  J:= J+Three-1];
           for J:= -Seven  to   +Seven           do [Block;  J:= J+X-1];
           for J:=    555  to      550 - Y       do  Block;
           for J:=     22  downto  -28           do [Block;  J:= J-Three+1];
           for J:=   1927  to     1939           do  Block;
           for J:=      X  downto    Y           do [Block;  J:= J+Z+1];
           for J:=  IPow(11,X) to IPow(11,X)+One do  Block;

                     \SUM and PROD are used for verification of J incrementation.
Text(0, " Sum= ");  IntOut(0, Sum);   CrLf(0);          \display strings to term.
Text(0, "Prod= ");  IntOut(0, Prod);  CrLf(0);          \  "       "     "   " 
end
Output:
 Sum= 348173
Prod= -793618560

Yabasic[edit]

Translation of: FreeBASIC
sub process(x)
	sum = sum + abs(x)
	if abs(prod) < (2 ^ 27) and x <> 0 then prod = prod * x : fi
end sub

prod = 1
sum = 0
x = 5   : y = -5    : z = -2
one = 1 : three = 3 : seven = 7

for j = -three to (3 ^ 3) step three: process(j): next j
for j = -seven to seven step x: process(j): next j
for j = 555 to 550 - y: process(j): next j
for j = 22 to -28 step -three: process(j): next j
for j = 1927 to 1939: process(j): next j
for j = x to y step z: process(j): next j
for j = (11 ^ x) to (11 ^ x) + one: process(j): next j

print " sum= ", sum using "###,###"
print "prod= ", prod using "####,###,###"
end


zkl[edit]

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], // do these sequentially
               [-seven..seven,x], [555..550 - y], [22..-28,-three], #[start..last,step]
               [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));
Output:
sum  = 348,173
prod = -793,618,560