Loops/Wrong ranges
You are encouraged to solve this task according to the task description, using any language you may know.
Some languages have syntax or function(s) to generate a range of numeric values from a start value, a stop value, and an increment.
The purpose of this task is to select the range syntax/function that would generate at least two increasing numbers when given a stop value more than the start value and a positive increment of less than half the difference. You are then to use that same syntax/function but with different parameters; and show, here, what would happen.
Use these values if possible:
start stop increment Comment -2 2 1 Normal -2 2 0 Zero increment -2 2 -1 Increments away from stop value -2 2 10 First increment is beyond stop value 2 -2 1 Start more than stop: positive increment 2 2 1 Start equal stop: positive increment 2 2 -1 Start equal stop: negative increment 2 2 0 Start equal stop: zero increment 0 0 0 Start equal stop equal zero: zero increment
- 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
- Loops/Wrong ranges
11l
F displayRange(first, last, step)
print(‘(#2, #2, #2): ’.format(first, last, step), end' ‘’)
I step == 0
print(‘not allowed.’)
E
print(Array((first..last).step(step)))
L(f, l, s) [(-2, 2, 1), (-2, 2, 0), (-2, 2, -1),
(-2, 2, 10), (2, -2, 1), ( 2, 2, 1),
( 2, 2, -1), (2, 2, 0), ( 0, 0, 0)]
displayRange(f, l, s)
- Output:
(-2, 2, 1): [-2, -1, 0, 1, 2] (-2, 2, 0): not allowed. (-2, 2, -1): [] (-2, 2, 10): [-2] ( 2, -2, 1): [] ( 2, 2, 1): [2] ( 2, 2, -1): [2] ( 2, 2, 0): not allowed. ( 0, 0, 0): not allowed.
Ada
Ada uses the concept of a range extensively, both in the definition of programmer-defined scalar types and subtypes and also in the iteration of arrays. In Ada a range is defined in the Ada 2012 Language Reference Manual as
A range has a lower bound and an upper bound and specifies a subset of the values of some scalar type (the type of the range). A range with lower bound L and upper bound R is described by “L .. R”. If R is less than L, then the range is a null range, and specifies an empty set of values. Otherwise, the range specifies the values of the type from the lower bound to the upper bound, inclusive.
The following solution follows the logic of a range as specified in the task description.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;
procedure Main is
procedure print_range(start : integer; stop : integer; step : integer) is
Num : Integer := start;
begin
Put("Range(" & start'Image & ", " & stop'image &
", " & step'image & ") => ");
if stop < start then
Put_Line("Error: stop must be no less than start!");
elsif step not in positive then
Put_Line("Error: increment must be greater than 0!");
elsif start = stop then
Put_Line(start'image);
else
while num <= stop loop
Put(num'Image);
num := num + step;
end loop;
New_Line;
end if;
end print_range;
type test_record is record
start : integer;
stop : integer;
step : integer;
comment : unbounded_string := null_unbounded_string;
end record;
tests : array(1..9) of test_record :=
( 1 => (-2, 2, 1, To_Unbounded_String("Normal")),
2 => (-2, 2, 0, To_Unbounded_String("Zero increment")),
3 => (-2, 2, -1, To_Unbounded_String("Increments away from stop value")),
4 => (-2, 2, 10, To_Unbounded_String("First increment is beyond stop value")),
5 => (2, -1, 1, To_Unbounded_String("Start more than stop: positive increment")),
6 => (2, 2, 1, To_Unbounded_String("Start equal stop: positive increment")),
7 => (2, 2, -1, To_Unbounded_String("Start equal stop: negative increment")),
8 => (2, 2, 0, To_Unbounded_String("Start equal stop: zero increment")),
9 => (0, 0, 0, To_Unbounded_String("Start equal stop equal zero: zero increment")));
begin
for test of tests loop
Put(Test.Comment); Put(" : ");
print_range(test.start, test.stop, test.step);
New_line;
end loop;
end Main;
- Output:
Normal : Range(-2, 2, 1) => -2-1 0 1 2 Zero increment : Range(-2, 2, 0) => Error: increment must be greater than 0! Increments away from stop value : Range(-2, 2, -1) => Error: increment must be greater than 0! First increment is beyond stop value : Range(-2, 2, 10) => -2 Start more than stop: positive increment : Range( 2, -1, 1) => Error: stop must be no less than start! Start equal stop: positive increment : Range( 2, 2, 1) => 2 Start equal stop: negative increment : Range( 2, 2, -1) => Error: increment must be greater than 0! Start equal stop: zero increment : Range( 2, 2, 0) => Error: increment must be greater than 0! Start equal stop equal zero: zero increment : Range( 0, 0, 0) => Error: increment must be greater than 0!
ALGOL 68
BEGIN
# returns the first n elements of the sequences of values specified by s sstart, s stop and increment #
PROC sequence = ( INT n, s start, s stop, increment )[]INT:
BEGIN
[ 1 : n ]INT s;
FOR j FROM LWB s TO UPB s DO s[ j ] := 0 OD;
INT s pos := LWB s - 1;
FOR j FROM s start BY increment TO s stop WHILE s pos < n DO
s[ s pos +:= 1 ] := j
OD;
s[ LWB s : s pos ]
END # sequence # ;
# tests the sequence procedure #
PROC test sequence = ( INT s start, s stop, increment, STRING legend )VOID:
BEGIN
[]INT s = sequence( 10, s start, s stop, increment );
print( ( legend, ": " ) );
FOR i FROM LWB s TO UPB s DO print( ( " ", whole( s[ i ], -4 ) ) ) OD;
print( ( newline ) )
END # test sequence # ;
# task trest cases #
test sequence( -2, 2, 1, "Normal " );
test sequence( -2, 2, 0, "Zero increment " );
test sequence( -2, 2, -1, "Increments away from stop value " );
test sequence( -2, 2, 10, "First increment is beyond stop value " );
test sequence( 2, -2, 1, "Start more than stop: positive increment " );
test sequence( 2, 2, 1, "Start equal stop: positive increment " );
test sequence( 2, 2, -1, "Start equal stop: negative increment " );
test sequence( 2, 2, 0, "Start equal stop: zero increment " );
test sequence( 0, 0, 0, "Start equal stop equal zero: zero increment" )
END
- Output:
Normal : -2 -1 0 1 2 Zero increment : -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value : First increment is beyond stop value : -2 Start more than stop: positive increment : Start equal stop: positive increment : 2 Start equal stop: negative increment : 2 Start equal stop: zero increment : 2 2 2 2 2 2 2 2 2 2 Start equal stop equal zero: zero increment: 0 0 0 0 0 0 0 0 0 0
ALGOL W
Using the Algol W for loop and limiting the sequence to 10 values. The Algol W for loop considers the sign of the increment value when deciding whether to terminate when the loop counter exceeds the stop value (positive increment) or is smaller than the stop value (negative increment).
begin
% sets the first n elements of s to the sequences of values specified by start, stop and increment %
% s( 0 ) is set to the number of elements of s that have been set, in case the sequence ends before n %
procedure sequence ( integer array s ( * )
; integer value n, start, stop, increment
) ;
begin
integer sPos;
for j := 0 until n do s( j ) := 0;
sPos := 1;
for j := start step increment until stop do begin
if sPos > n then goto done;
s( sPos ) := j;
s( 0 ) := s( 0 ) + 1;
sPos := sPos + 1;
end for_j ;
done:
end sequence ;
% tests the sequence procedure %
procedure testSequence( integer value start, stop, increment
; string(48) value legend
) ;
begin
integer array s ( 0 :: 10 );
sequence( s, 10, start, stop, increment );
s_w := 0; % set output formating %
i_w := 4;
write( legend, ": " );
for i := 1 until s( 0 ) do writeon( s( i ) )
end testSequence ;
% task trest cases %
testSequence( -2, 2, 1, "Normal" );
testSequence( -2, 2, 0, "Zero increment" );
testSequence( -2, 2, -1, "Increments away from stop value" );
testSequence( -2, 2, 10, "First increment is beyond stop value" );
testSequence( 2, -2, 1, "Start more than stop: positive increment" );
testSequence( 2, 2, 1, "Start equal stop: positive increment" );
testSequence( 2, 2, -1, "Start equal stop: negative increment" );
testSequence( 2, 2, 0, "Start equal stop: zero increment" );
testSequence( 0, 0, 0, "Start equal stop equal zero: zero increment" )
end.
- Output:
Normal : -2 -1 0 1 2 Zero increment : -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value : First increment is beyond stop value : -2 Start more than stop: positive increment : Start equal stop: positive increment : 2 Start equal stop: negative increment : 2 Start equal stop: zero increment : 2 2 2 2 2 2 2 2 2 2 Start equal stop equal zero: zero increment : 0 0 0 0 0 0 0 0 0 0
Arturo
print "start stop increment"
loop @[
neg 2 2 1
neg 2 2 0
neg 2 2 neg 1
neg 2 2 10
2 neg 2 1
2 2 1
2 2 neg 1
2 2 0
0 0 0 ]
[start stop increment] ->
print [
pad ~"|start|" 2 pad ~"|stop|" 7 pad ~"|increment|" 7
pad "->" 9 try? -> @range.step: increment start stop
else -> "Error"
]
- Output:
start stop increment -2 2 1 -> [-2 -1 0 1 2] -2 2 0 -> Error -2 2 -1 -> [-2 -1 0 1 2] -2 2 10 -> [-2] 2 -2 1 -> [2 1 0 -1 -2] 2 2 1 -> [2] 2 2 -1 -> [2] 2 2 0 -> Error 0 0 0 -> Error
AWK
# syntax: GAWK -f LOOPS_WRONG_RANGES.AWK
BEGIN {
arr[++n] = "-2, 2, 1,Normal"
arr[++n] = "-2, 2, 0,Zero increment"
arr[++n] = "-2, 2,-1,Increments away from stop value"
arr[++n] = "-2, 2,10,First increment is beyond stop value"
arr[++n] = " 2,-2, 1,Start more than stop: positive increment"
arr[++n] = " 2, 2, 1,Start equal stop: positive increment"
arr[++n] = " 2, 2,-1,Start equal stop: negative increment"
arr[++n] = " 2, 2, 0,Start equal stop: zero increment"
arr[++n] = " 0, 0, 0,Start equal stop equal zero: zero increment"
print("start,stop,increment,comment")
for (i=1; i<=n; i++) {
split(arr[i],A,",")
printf("%-52s : ",arr[i])
count = 0
for (j=A[1]; j<=A[2] && count<10; j+=A[3]) {
printf("%d ",j)
count++
}
printf("\n")
}
exit(0)
}
- Output:
start,stop,increment,comment -2, 2, 1,Normal : -2 -1 0 1 2 -2, 2, 0,Zero increment : -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2, 2,-1,Increments away from stop value : -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -2, 2,10,First increment is beyond stop value : -2 2,-2, 1,Start more than stop: positive increment : 2, 2, 1,Start equal stop: positive increment : 2 2, 2,-1,Start equal stop: negative increment : 2 1 0 -1 -2 -3 -4 -5 -6 -7 2, 2, 0,Start equal stop: zero increment : 2 2 2 2 2 2 2 2 2 2 0, 0, 0,Start equal stop equal zero: zero increment : 0 0 0 0 0 0 0 0 0 0
BASIC
Applesoft BASIC
0 LIMIT = 10 :MAX=1E37
10 DATA-2,2,1,NORMAL
20 DATA-2,2,0,ZERO INCREMENT
30 DATA-2,2,-1,INCREMENTS AWAY FROM STOP VALUE
40 DATA-2,2,10,FIRST INCREMENT IS BEYOND STOP VALUE
50 DATA2,-2,1,"START MORE THAN STOP: POSITIVE INCREMENT
60 DATA2,2,1,"START EQUAL STOP: POSITIVE INCREMENT
70 DATA2,2,-1,"START EQUAL STOP: NEGATIVE INCREMENT
80 DATA2,2,0,"START EQUAL STOP: ZERO INCREMENT
90 DATA0,0,0,"START EQUAL STOP EQUAL ZERO: ZERO INCREMENT
100 FOR I = 1 TO 9
110 READ START,FINISH,INCR,COMMENT$
120 PRINT CHR$(13)COMMENT$
130 LAST = FINISH
140 REM D = SGN(FINISH - START)
150 REM IF D AND NOT (D = SGN(INCR)) THEN LAST = SGN(INCR)*MAX
160 PRINT TAB(5)CHR$(91)" "MID$(" ",(START<0)+1)START" TO "MID$(" ",(FINISH<0)+1)FINISH" STEP "MID$(" ",(INCR<0)+1)INCR" ] ";
170 COUNT = 0
180 PRINT MID$(" ",(START<0)+1);
190 FOR J = START TO LAST STEP INCR
200 PRINT MID$(" ",(COUNT=0)+1)J;
210 IF COUNT < LIMIT THEN COUNT = COUNT + 1 : NEXT J
220 IF COUNT = LIMIT THEN PRINT " ... ";:if ABS(LAST) = MAX THEN PRINT MID$("-",SGN(LAST)+2,1)"INFINITY";
230 NEXT I
- Output:
NORMAL [ -2 TO 2 STEP 1 ] -2 -1 0 1 2 ZERO INCREMENT [ -2 TO 2 STEP 0 ] -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 ... INCREMENTS AWAY FROM STOP VALUE [ -2 TO 2 STEP -1 ] -2 FIRST INCREMENT IS BEYOND STOP VALUE [ -2 TO 2 STEP 10 ] -2 START MORE THAN STOP: POSITIVE INCREMENT [ 2 TO -2 STEP 1 ] 2 START EQUAL STOP: POSITIVE INCREMENT [ 2 TO 2 STEP 1 ] 2 START EQUAL STOP: NEGATIVE INCREMENT [ 2 TO 2 STEP -1 ] 2 START EQUAL STOP: ZERO INCREMENT [ 2 TO 2 STEP 0 ] 2 START EQUAL STOP EQUAL ZERO: ZERO INCREMENT [ 0 TO 0 STEP 0 ] 0
BASIC256
arraybase 1
dim start(9) : dim fin(9) : dim inc(9) : dim cmt$(9)
start[1] = -2 : fin[1] = 2 : inc[1] = 1 : cmt$[1] = "Normal"
start[2] = -2 : fin[2] = 2 : inc[2] = 0 : cmt$[2] = "Zero increment"
start[3] = -2 : fin[3] = 2 : inc[3] = -1 : cmt$[3] = "Increments away from stop value"
start[4] = -2 : fin[4] = 2 : inc[4] = 10 : cmt$[4] = "First increment is beyond stop value"
start[5] = 2 : fin[5] = -2 : inc[5] = 1 : cmt$[5] = "Start more than stop: positive increment"
start[6] = 2 : fin[6] = 2 : inc[6] = 1 : cmt$[6] = "Start equal stop: positive increment"
start[7] = 2 : fin[7] = 2 : inc[7] = -1 : cmt$[7] = "Start equal stop: negative increment"
start[8] = 2 : fin[8] = 2 : inc[8] = 0 : cmt$[8] = "Start equal stop: zero increment"
start[9] = 0 : fin[9] = 0 : inc[9] = 0 : cmt$[9] = "Start equal stop equal zero: zero increment"
for i = 1 to 9
contar = 0
print cmt$[i]
print " Bucle de "; start[i]; " a "; fin[i]; " en incrementos de "; inc[i]
for vr = start[i] to fin[i] step inc[i]
print " Índice del bucle = "; vr
contar = contar + 1
if contar = 10 then
print " Saliendo de un bucle infinito"
exit for
endif
next vr
print " Bucle terminado" & chr(10) & chr(10)
next i
end
- Output:
Igual que la entrada de Yabasic.
Chipmunk Basic
100 cls
110 for i = 1 to 9
120 contar = 0
130 read start,fin,inc,cmt$
140 print cmt$
150 print " Bucle de ";start;"a ";fin;" en incrementos de ";inc
160 for vr = start to fin step inc
170 print " Indice del bucle = ";vr
180 contar = contar+1
190 if contar = 10 then
200 print " Saliendo de un bucle infinito"
210 goto 240
220 endif
230 next vr
240 print " Bucle terminado" : print : print
250 next i
260 end
270 data -2,2,1,"Normal",-2,2,0,"Zero increment",-2,2,-1,"Increments away from stop value"
280 data -2,2,10,"First increment is beyond stop value",2,-2,1,"Start more than stop: positive increment"
290 data 2,2,1,"Start equal stop: positive increment",2,2,-1,"Start equal stop: negative increment"
300 data 2,2,0,"Start equal stop: zero increment",0,0,0,"Start equal stop equal zero: zero increment"
- Output:
Normal Bucle de -2 a 2 en incrementos de 1 Indice del bucle = -2 Indice del bucle = -1 Indice del bucle = 0 Indice del bucle = 1 Indice del bucle = 2 Bucle terminado Zero increment Bucle de -2 a 2 en incrementos de 0 Bucle terminado Increments away from stop value Bucle de -2 a 2 en incrementos de -1 Bucle terminado First increment is beyond stop value Bucle de -2 a 2 en incrementos de 10 Indice del bucle = -2 Bucle terminado Start more than stop: positive increment Bucle de 2 a -2 en incrementos de 1 Bucle terminado Start equal stop: positive increment Bucle de 2 a 2 en incrementos de 1 Indice del bucle = 2 Bucle terminado Start equal stop: negative increment Bucle de 2 a 2 en incrementos de -1 Indice del bucle = 2 Bucle terminado Start equal stop: zero increment Bucle de 2 a 2 en incrementos de 0 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Saliendo de un bucle infinito Bucle terminado Start equal stop equal zero: zero increment Bucle de 0 a 0 en incrementos de 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Saliendo de un bucle infinito Bucle terminado
FreeBASIC
data -2,2,1,"Normal",-2,2,0,"Zero increment",-2,2,-1,"Increments away from stop value"
data -2,2,10,"First increment is beyond stop value",2,-2,1,"Start more than stop: positive increment"
data 2,2,1,"Start equal stop: positive increment",2,2,-1,"Start equal stop: negative increment"
data 2,2,0,"Start equal stop: zero increment",0,0,0,"Start equal stop equal zero: zero increment"
dim as integer i, start, fin, inc, vr, count
dim as string cmt
for i = 1 to 9
count = 0
read start, fin, inc, cmt
print cmt
print using " Looping from ### to ### in increments of ##"; start; fin; inc
for vr = start to fin step inc
print " Loop index = ",vr
count += 1
if count = 10 then
print " Breaking infinite loop"
exit for
end if
next vr
print " Loop finished"
print
print
next i
- Output:
Normal Looping from -2 to 2 in increments of 1 Loop index = -2 Loop index = -1 Loop index = 0 Loop index = 1 Loop index = 2 Loop finished Zero increment Looping from -2 to 2 in increments of 0 Loop index = -2 Loop index = -2 Loop index = -2 Loop index = -2 Loop index = -2 Loop index = -2 Loop index = -2 Loop index = -2 Loop index = -2 Loop index = -2 Breaking infinite loop Loop finished Increments away from stop value Looping from -2 to 2 in increments of -1 Loop finished First increment is beyond stop value Looping from -2 to 2 in increments of 10 Loop index = -2 Loop finished Start more than stop: positive increment Looping from 2 to -2 in increments of 1 Loop finished Start equal stop: positive increment Looping from 2 to 2 in increments of 1 Loop index = 2 Loop finished Start equal stop: negative increment Looping from 2 to 2 in increments of -1 Loop index = 2 Loop finished Start equal stop: zero increment Looping from 2 to 2 in increments of 0 Loop index = 2 Loop index = 2 Loop index = 2 Loop index = 2 Loop index = 2 Loop index = 2 Loop index = 2 Loop index = 2 Loop index = 2 Loop index = 2 Breaking infinite loop Loop finished Start equal stop equal zero: zero increment Looping from 0 to 0 in increments of 0 Loop index = 0 Loop index = 0 Loop index = 0 Loop index = 0 Loop index = 0 Loop index = 0 Loop index = 0 Loop index = 0 Loop index = 0 Loop index = 0 Breaking infinite loop Loop finished
GW-BASIC
The Chipmunk Basic solution works without any changes.
Minimal BASIC
100 CLS : REM 100 HOME for Applesoft BASIC : REM DELETE line for Minimal BASIC
110 DATA -2,2,1,"Normal",-2,2,0,"Zero increment"
120 DATA -2,2,-1,"Increments away from stop value"
130 DATA -2,2,10,"First increment is beyond stop value"
140 DATA 2,-2,1,"Start more than stop: positive increment"
150 DATA 2,2,1,"Start equal stop: positive increment"
160 DATA 2,2,-1,"Start equal stop: negative increment"
170 DATA 2,2,0,"Start equal stop: zero increment"
180 DATA 0,0,0,"Start equal stop equal zero: zero increment"
190 FOR j = 1 TO 9
200 LET c = 0
210 READ s, f, i, t$
220 PRINT t$
230 PRINT " Bucle de "; s; "a "; f; " en incrementos de "; i
240 FOR v = s TO f STEP i
250 PRINT " Indice del bucle = "; v
260 LET c = c + 1
270 IF c <> 10 THEN 300
280 PRINT " Saliendo de un bucle infinito"
290 GOTO 310
300 NEXT v
310 PRINT " Bucle terminado"
320 PRINT
330 NEXT j
340 END
MSX Basic
The Chipmunk Basic solution works without any changes.
Quite BASIC
See solution Minimal BASIC
Visual Basic .NET
Compiler: >= Visual Studio 2012
VB.NET's For loop accepts a starting and ending value and optional step.
Since the task mentions generators and a range of values, this implementation places the for loop in an iterator function (called a generator in many other languages) and yields the iteration variable in every iteration. The resulting IEnumerable object (whose actual class is generated by the compiler) is lazily-evaluated (i.e., it is run only when a new value is requested, and only until the next Yield statement).
The number of iterations is limited to 10 by the test code.
Module Program
Sub Main()
Example(-2, 2, 1, "Normal")
Example(-2, 2, 0, "Zero increment")
Example(-2, 2, -1, "Increments away from stop value")
Example(-2, 2, 10, "First increment is beyond stop value")
Example(2, -2, 1, "Start more than stop: positive increment")
Example(2, 2, 1, "Start equal stop: positive increment")
Example(2, 2, -1, "Start equal stop: negative increment")
Example(2, 2, 0, "Start equal stop: zero increment")
Example(0, 0, 0, "Start equal stop equal zero: zero increment")
End Sub
' Stop is a keyword and must be escaped using brackets.
Iterator Function Range(start As Integer, [stop] As Integer, increment As Integer) As IEnumerable(Of Integer)
For i = start To [stop] Step increment
Yield i
Next
End Function
Sub Example(start As Integer, [stop] As Integer, increment As Integer, comment As String)
' Add a space, pad to length 50 with hyphens, and add another space.
Console.Write((comment & " ").PadRight(50, "-"c) & " ")
Const MAX_ITER = 9
Dim iteration = 0
' The For Each loop enumerates the IEnumerable.
For Each i In Range(start, [stop], increment)
Console.Write("{0,2} ", i)
iteration += 1
If iteration > MAX_ITER Then Exit For
Next
Console.WriteLine()
End Sub
End Module
- Output:
Normal ------------------------------------------- -2 -1 0 1 2 Zero increment ----------------------------------- -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value ------------------ First increment is beyond stop value ------------- -2 Start more than stop: positive increment --------- Start equal stop: positive increment ------------- 2 Start equal stop: negative increment ------------- 2 Start equal stop: zero increment ----------------- 2 2 2 2 2 2 2 2 2 2 Start equal stop equal zero: zero increment ------ 0 0 0 0 0 0 0 0 0 0
uBasic/4tH
Push -2, 2, 1, "Normal"
Push -2, 2, 0, "Zero increment"
Push -2, 2, -1, "Increments away from stop value"
Push -2, 2, 10, "First increment is beyond stop value"
Push 2, -2, 1, "Start more than stop: positive increment"
Push 2, 2, 1, "Start equal stop: positive increment"
Push 2, 2, -1, "Start equal stop: negative increment"
Push 2, 2, 0, "Start equal stop: zero increment"
Push 0, 0, 0, "Start equal stop equal zero: zero increment"
Do While Used()
Print "(";Show (Pop());")"
i = Pop() : e = Pop () : s = Pop() : y = 0
Print "FOR X=";s;" TO ";e;" STEP ";i
For x = s To e Step i : Print x;" "; : While Set (y, y+1) < 10 : Next
Print Show(Iif (y < 10, Iif (y = 0, "None", ""), ".. infinite")) : Print
Loop
- Output:
(Start equal stop equal zero: zero increment) FOR X=0 TO 0 STEP 0 0 0 0 0 0 0 0 0 0 0 .. infinite (Start equal stop: zero increment) FOR X=2 TO 2 STEP 0 2 2 2 2 2 2 2 2 2 2 .. infinite (Start equal stop: negative increment) FOR X=2 TO 2 STEP -1 2 (Start equal stop: positive increment) FOR X=2 TO 2 STEP 1 2 (Start more than stop: positive increment) FOR X=2 TO -2 STEP 1 None (First increment is beyond stop value) FOR X=-2 TO 2 STEP 10 -2 (Increments away from stop value) FOR X=-2 TO 2 STEP -1 None (Zero increment) FOR X=-2 TO 2 STEP 0 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 .. infinite (Normal) FOR X=-2 TO 2 STEP 1 -2 -1 0 1 2 0 OK, 0:718
Yabasic
data -2,2,1,"Normal",-2,2,0,"Zero increment",-2,2,-1,"Increments away from stop value"
data -2,2,10,"First increment is beyond stop value",2,-2,1,"Start more than stop: positive increment"
data 2,2,1,"Start equal stop: positive increment",2,2,-1,"Start equal stop: negative increment"
data 2,2,0,"Start equal stop: zero increment",0,0,0,"Start equal stop equal zero: zero increment"
for i = 1 to 9
contar = 0
read start, fin, inc, cmt$
print cmt$
print " Bucle de ", start, " a ", fin, " en incrementos de ", inc
for vr = start to fin step inc
print " Indice del bucle = ", vr
contar = contar + 1
if contar = 10 then
print " Saliendo de un bucle infinito"
break
endif
next vr
print " Bucle terminado\n\n"
next i
end
- Output:
Normal Bucle de -2 a 2 en incrementos de 1 Indice del bucle = -2 Indice del bucle = -1 Indice del bucle = 0 Indice del bucle = 1 Indice del bucle = 2 Bucle terminado Zero increment Bucle de -2 a 2 en incrementos de 0 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Indice del bucle = -2 Saliendo de un bucle infinito Bucle terminado Increments away from stop value Bucle de -2 a 2 en incrementos de -1 Bucle terminado First increment is beyond stop value Bucle de -2 a 2 en incrementos de 10 Indice del bucle = -2 Bucle terminado Start more than stop: positive increment Bucle de 2 a -2 en incrementos de 1 Bucle terminado Start equal stop: positive increment Bucle de 2 a 2 en incrementos de 1 Indice del bucle = 2 Bucle terminado Start equal stop: negative increment Bucle de 2 a 2 en incrementos de -1 Indice del bucle = 2 Bucle terminado Start equal stop: zero increment Bucle de 2 a 2 en incrementos de 0 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Indice del bucle = 2 Saliendo de un bucle infinito Bucle terminado Start equal stop equal zero: zero increment Bucle de 0 a 0 en incrementos de 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Indice del bucle = 0 Saliendo de un bucle infinito Bucle terminado
C
C's 'for' statement appears to fit the bill here and so we use it directly to generate the required ranges of numbers though, as some of the ranges will be infinite, we limit the output to a maximum of 10 numbers.
#include <stdio.h>
#define TRUE 1
#define FALSE 0
typedef int bool;
typedef struct {
int start, stop, incr;
const char *comment;
} S;
S examples[9] = {
{-2, 2, 1, "Normal"},
{-2, 2, 0, "Zero increment"},
{-2, 2, -1, "Increments away from stop value"},
{-2, 2, 10, "First increment is beyond stop value"},
{2, -2, 1, "Start more than stop: positive increment"},
{2, 2, 1, "Start equal stop: positive increment"},
{2, 2, -1, "Start equal stop: negative increment"},
{2, 2, 0, "Start equal stop: zero increment"},
{0, 0, 0, "Start equal stop equal zero: zero increment"}
};
int main() {
int i, j, c;
bool empty;
S s;
const int limit = 10;
for (i = 0; i < 9; ++i) {
s = examples[i];
printf("%s\n", s.comment);
printf("Range(%d, %d, %d) -> [", s.start, s.stop, s.incr);
empty = TRUE;
for (j = s.start, c = 0; j <= s.stop && c < limit; j += s.incr, ++c) {
printf("%d ", j);
empty = FALSE;
}
if (!empty) printf("\b");
printf("]\n\n");
}
return 0;
}
- Output:
Normal Range(-2, 2, 1) -> [-2 -1 0 1 2] Zero increment Range(-2, 2, 0) -> [-2 -2 -2 -2 -2 -2 -2 -2 -2 -2] Increments away from stop value Range(-2, 2, -1) -> [-2 -3 -4 -5 -6 -7 -8 -9 -10 -11] First increment is beyond stop value Range(-2, 2, 10) -> [-2] Start more than stop: positive increment Range(2, -2, 1) -> [] Start equal stop: positive increment Range(2, 2, 1) -> [2] Start equal stop: negative increment Range(2, 2, -1) -> [2 1 0 -1 -2 -3 -4 -5 -6 -7] Start equal stop: zero increment Range(2, 2, 0) -> [2 2 2 2 2 2 2 2 2 2] Start equal stop equal zero: zero increment Range(0, 0, 0) -> [0 0 0 0 0 0 0 0 0 0]
C#
Behavior for naïve translation is different from VB.NET (and identical to C), as it does not handle an "overshot" iteration variable when the increment is negative.
using System;
using System.Collections.Generic;
static class Program
{
static void Main()
{
Example(-2, 2, 1, "Normal");
Example(-2, 2, 0, "Zero increment");
Example(-2, 2, -1, "Increments away from stop value");
Example(-2, 2, 10, "First increment is beyond stop value");
Example(2, -2, 1, "Start more than stop: positive increment");
Example(2, 2, 1, "Start equal stop: positive increment");
Example(2, 2, -1, "Start equal stop: negative increment");
Example(2, 2, 0, "Start equal stop: zero increment");
Example(0, 0, 0, "Start equal stop equal zero: zero increment");
}
static IEnumerable<int> Range(int start, int stop, int increment)
{
// To replicate the (arguably more correct) behavior of VB.NET:
//for (int i = start; increment >= 0 ? i <= stop : stop <= i; i += increment)
// Decompiling the IL emitted by the VB compiler (uses shifting right by 31 as the signum function and bitwise xor in place of the conditional expression):
//for (int i = start; ((increment >> 31) ^ i) <= ((increment >> 31) ^ stop); i += increment)
// "Naïve" translation.
for (int i = start; i <= stop; i += increment)
yield return i;
}
static void Example(int start, int stop, int increment, string comment)
{
// Add a space, pad to length 50 with hyphens, and add another space.
Console.Write((comment + " ").PadRight(50, '-') + " ");
const int MAX_ITER = 9;
int iteration = 0;
foreach (int i in Range(start, stop, increment))
{
Console.Write("{0,2} ", i);
if (++iteration > MAX_ITER) break;
}
Console.WriteLine();
}
}
- Output (identical to C):
Normal ------------------------------------------- -2 -1 0 1 2 Zero increment ----------------------------------- -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value ------------------ -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 First increment is beyond stop value ------------- -2 Start more than stop: positive increment --------- Start equal stop: positive increment ------------- 2 Start equal stop: negative increment ------------- 2 1 0 -1 -2 -3 -4 -5 -6 -7 Start equal stop: zero increment ----------------- 2 2 2 2 2 2 2 2 2 2 Start equal stop equal zero: zero increment ------ 0 0 0 0 0 0 0 0 0 0
C translation
Just for fun; some strictly unnecessary changes made to be closer to idiomatic C#.
using System;
static class Program {
struct S {
public int Start, Stop, Incr;
public string Comment;
}
static readonly S[] examples = {
new S{Start=-2, Stop=2, Incr=1, Comment="Normal"},
new S{Start=-2, Stop=2, Incr=0, Comment="Zero increment"},
new S{Start=-2, Stop=2, Incr=-1, Comment="Increments away from stop value"},
new S{Start=-2, Stop=2, Incr=10, Comment="First increment is beyond stop value"},
new S{Start=2, Stop=-2, Incr=1, Comment="Start more than stop: positive increment"},
new S{Start=2, Stop=2, Incr=1, Comment="Start equal stop: positive increment"},
new S{Start=2, Stop=2, Incr=-1, Comment="Start equal stop: negative increment"},
new S{Start=2, Stop=2, Incr=0, Comment="Start equal stop: zero increment"},
new S{Start=0, Stop=0, Incr=0, Comment="Start equal stop equal zero: zero increment"}
};
static int Main() {
const int limit = 10;
bool empty;
for (int i = 0; i < 9; ++i) {
S s = examples[i];
Console.Write("{0}\n", s.Comment);
Console.Write("Range({0:d}, {1:d}, {2:d}) -> [", s.Start, s.Stop, s.Incr);
empty = true;
for (int j = s.Start, c = 0; j <= s.Stop && c < limit; j += s.Incr, ++c) {
Console.Write("{0:d} ", j);
empty = false;
}
if (!empty) Console.Write("\b");
Console.Write("]\n\n");
}
return 0;
}
}
- Output:
Same as original C.
C++
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
struct LoopData {
int32_t start;
int32_t stop;
int32_t increment;
std::string comment;
};
void print_vector(const std::vector<int32_t>& list) {
std::cout << "[";
for ( uint64_t i = 0; i < list.size(); ++i ) {
std::cout << list[i];
if ( i < list.size() - 1 ) {
std::cout << ", ";
}
}
std::cout << "]";
}
void runTest(const LoopData& loop_data) {
std::vector<int32_t> values{};
for ( int32_t i = loop_data.start; i <= loop_data.stop; i += loop_data.increment ) {
values.emplace_back(i);
if ( values.size() >= 10 ) {
break;
}
}
std::cout << std::left << std::setw(45) << loop_data.comment; print_vector(values);
std::cout << ( values.size() == 10 ? " (loops forever)" : "" ) << std::endl;
}
int main() {
runTest(LoopData(-2, 2, 1, "Normal"));
runTest(LoopData(-2, 2, 0, "Zero increment"));
runTest(LoopData(-2, 2, -1, "Increments away from stop value"));
runTest(LoopData(-2, 2, 10, "First increment is beyond stop value"));
runTest(LoopData(2, -2, 1, "Start more than stop: positive increment"));
runTest(LoopData(2, 2, 1, "Start equal stop: positive increment"));
runTest(LoopData(2, 2, -1, "Start equal stop: negative increment"));
runTest(LoopData(2, 2, 0, "Start equal stop: zero increment"));
runTest(LoopData(0, 0, 0, "Start equal stop equal zero: zero increment"));
}
- Output:
Normal [-2, -1, 0, 1, 2] Zero increment [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2] (loops forever) Increments away from stop value [-2, -3, -4, -5, -6, -7, -8, -9, -10, -11] (loops forever) First increment is beyond stop value [-2] Start more than stop: positive increment [] Start equal stop: positive increment [2] Start equal stop: negative increment [2, 1, 0, -1, -2, -3, -4, -5, -6, -7] (loops forever) Start equal stop: zero increment [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] (loops forever) Start equal stop equal zero: zero increment [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] (loops forever)
Common Lisp
(dolist (lst '((-2 2 1 "Normal") ; Iterate the parameters list `start' `stop' `increment' and `comment'
(-2 2 0 "Zero increment")
(-2 2 -1 "Increments away from stop value")
(-2 2 10 "First increment is beyond stop value")
( 2 -2 1 "Start more than stop: positive increment")
( 2 2 1 "Start equal stop: positive increment")
( 2 2 -1 "Start equal stop: negative increment")
( 2 2 0 "Start equal stop: zero increment")
( 0 0 0 "Start equal stop equal zero: zero increment")))
(do ((i (car lst) (incf i (caddr lst))) ; Initialize `start' and set `increment'
(result ()) ; Initialize the result list
(loop-max 0 (incf loop-max))) ; Initialize a loop limit
((or (> i (cadr lst)) ; Break condition to `stop'
(> loop-max 10)) ; Break condition to loop limit
(format t "~&~44a: ~{~3d ~}" ; Finally print
(cadddr lst) ; The `comment'
(reverse result))) ; The in(de)creased numbers into result
(push i result))) ; Add the number to result
- Output:
Normal : -2 -1 0 1 2 Zero increment : -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value : -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 First increment is beyond stop value : -2 Start more than stop: positive increment : Start equal stop: positive increment : 2 Start equal stop: negative increment : 2 1 0 -1 -2 -3 -4 -5 -6 -7 -8 Start equal stop: zero increment : 2 2 2 2 2 2 2 2 2 2 2 Start equal stop equal zero: zero increment : 0 0 0 0 0 0 0 0 0 0 0
Delphi
program Wrong_ranges;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
procedure Example(start, stop, Increment: Integer; comment: string);
var
MAX_ITER, iteration, i: Integer;
begin
Write((comment + ' ').PadRight(50, '-') + ' ');
MAX_ITER := 9;
iteration := 0;
if Increment = 1 then
begin
for i := start to stop do
begin
Write(i: 2, ' ');
inc(iteration);
if iteration >= MAX_ITER then
Break;
end;
Writeln;
exit;
end;
if Increment = -1 then
begin
for i := start downto stop do
begin
Write(i: 2, ' ');
inc(iteration);
if iteration >= MAX_ITER then
Break;
end;
Writeln;
exit;
end;
Writeln('Not supported');
end;
begin
Example(-2, 2, 1, 'Normal');
Example(-2, 2, 0, 'Zero increment');
Example(-2, 2, -1, 'Increments away from stop value');
Example(-2, 2, 10, 'First increment is beyond stop value');
Example(2, -2, 1, 'Start more than stop: positive increment');
Example(2, 2, 1, 'Start equal stop: positive increment');
Example(2, 2, -1, 'Start equal stop: negative increment');
Example(2, 2, 0, 'Start equal stop: zero increment');
Example(0, 0, 0, 'Start equal stop equal zero: zero increment');
Readln;
end.
- Output:
Normal ------------------------------------------- -2 -1 0 1 2 Zero increment ----------------------------------- Not supported Increments away from stop value ------------------ First increment is beyond stop value ------------- Not supported Start more than stop: positive increment --------- Start equal stop: positive increment ------------- 2 Start equal stop: negative increment ------------- 2 Start equal stop: zero increment ----------------- Not supported Start equal stop equal zero: zero increment ------ Not supported
Version with TEnumerate:
program Wrong_rangesEnumerator;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
TRange = record
private
Fincrement: Integer;
FIndex: Integer;
FStart, FStop, FValue: Integer;
function GetCurrent: Integer; inline;
public
constructor Create(start, stop, Increment: Integer);
function MoveNext: Boolean; inline;
function GetEnumerator: TRange;
property Current: Integer read GetCurrent;
end;
{ TEnumerator<T> }
constructor TRange.Create(start, stop, Increment: Integer);
begin
FStart := start;
FStop := stop;
Fincrement := Increment;
FValue := start - Increment;
end;
function TRange.GetCurrent: Integer;
begin
Result := FValue;
end;
function TRange.GetEnumerator: TRange;
begin
Result := self;
end;
function TRange.MoveNext: Boolean;
begin
FValue := FValue + Fincrement;
if (Fincrement > 0) and (FValue > FStop) then
exit(False);
if (Fincrement < 0) and (FValue < FStop) then
exit(False);
Result := True;
end;
procedure Example(start, stop, Increment: Integer; comment: string);
var
MAX_ITER, iteration, i, e: Integer;
begin
Write((comment + ' ').PadRight(50, '-') + ' ');
MAX_ITER := 9;
iteration := 0;
for e in TRange.Create(start, stop, Increment) do
begin
Write(e: 2, ' ');
inc(iteration);
if iteration >= MAX_ITER then
Break;
end;
Writeln;
end;
begin
Example(-2, 2, 1, 'Normal');
Example(-2, 2, 0, 'Zero increment');
Example(-2, 2, -1, 'Increments away from stop value');
Example(-2, 2, 10, 'First increment is beyond stop value');
Example(2, -2, 1, 'Start more than stop: positive increment');
Example(2, 2, 1, 'Start equal stop: positive increment');
Example(2, 2, -1, 'Start equal stop: negative increment');
Example(2, 2, 0, 'Start equal stop: zero increment');
Example(0, 0, 0, 'Start equal stop equal zero: zero increment');
Readln;
end.
- Output:
Normal ------------------------------------------- -2 -1 0 1 2 Zero increment ----------------------------------- -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value ------------------ First increment is beyond stop value ------------- -2 Start more than stop: positive increment --------- Start equal stop: positive increment ------------- 2 Start equal stop: negative increment ------------- 2 Start equal stop: zero increment ----------------- 2 2 2 2 2 2 2 2 2 Start equal stop equal zero: zero increment ------ 0 0 0 0 0 0 0 0 0
Eiffel
example
-- Loops/Wrong ranges
do
⟳ ic:(-2 |..| 2) ¦ do_nothing ⟲ -- 2 2 1 Normal
⟳ ic:(-2 |..| 2).new_cursor + 0 ¦ do_nothing ⟲ -- -2 2 0 Zero increment
⟳ ic:(-2 |..| 2).new_cursor - 1 ¦ do_nothing ⟲ -- -2 2 -1 Increments away from stop value
⟳ ic:(-2 |..| 2).new_cursor + 10 ¦ do_nothing ⟲ -- -2 2 10 First increment is beyond stop value
⟳ ic:(-2 |..| 2).new_cursor.reversed ¦ do_nothing ⟲ -- 2 -2 1 Start more than stop: positive increment
⟳ ic:(2 |..| 2) ¦ do_nothing ⟲ -- 2 2 1 Start equal stop: positive increment
⟳ ic:(2 |..| 2).new_cursor - 1 ¦ do_nothing ⟲ -- 2 2 -1 Start equal stop: negative increment
⟳ ic:(2 |..| 2).new_cursor + 0 ¦ do_nothing ⟲ -- 2 2 0 Start equal stop: zero increment
⟳ ic:(0 |..| 0).new_cursor + 0 ¦ do_nothing ⟲ -- 0 0 0 Start equal stop equal zero: zero increment
end
- Output:
In this example, we are using the "symbolic form" of the Eiffel across loop, such as: ⟳ ¦ ⟲
In each case, we iterate over an INTEGER_INTERVAL (e.g. (-2 |..| 2), which represents a contiguous range of integers from a starting value to an ending value. The `ic' represents our integer value for each iteration. The call to `do_nothing' does exactly what you think--it does nothing at all because we are demonstrating the loop using various ranges and not what it processes on each iteration.
Design by Contract Errors
In both instances (below), it is a precondition (Design by Contract) error to attempt to step negative in a positive stepping iterator. If you want to go backwards, then do a reverse call on the cursor and provide a positive step value. Even in the example provided, these are logic errors (bugs) and not real examples of correct code.
1. ⟳ ic:(-2 |..| 2).new_cursor - 1 ¦ do_nothing ⟲
2. ⟳ ic:(2 |..| 2).new_cursor - 1 ¦ do_nothing ⟲
Factor
<range>
divides by the step value, so a step of 0 causes a divide by zero exception. For the purpose of getting through all the examples, the exceptions are dropped and execution continues, which in general should be avoided.
USING: continuations formatting io kernel math.ranges
prettyprint sequences ;
: try-range ( from length step -- )
[ <range> { } like . ]
[ 4drop "Exception: divide by zero." print ] recover ;
{
{ -2 2 1 } { 2 2 0 } { -2 2 -1 } { -2 2 10 } { 2 -2 1 }
{ 2 2 1 } { 2 2 -1 } { 2 2 0 } { 0 0 0 }
}
[
first3
[ "%2d %2d %2d <range> => " printf ]
[ try-range ] 3bi
] each
- Output:
-2 2 1 <range> => { -2 -1 0 1 2 } 2 2 0 <range> => Exception: divide by zero. -2 2 -1 <range> => { } -2 2 10 <range> => { -2 } 2 -2 1 <range> => { } 2 2 1 <range> => { 2 } 2 2 -1 <range> => { 2 } 2 2 0 <range> => Exception: divide by zero. 0 0 0 <range> => Exception: divide by zero.
Fermat
Although the examples are listed together, I ran them one at a time.
for a = -2 to 2 by 1 do !(a,' '); od;
for a = -2 to 2 by 0 do !(a,' '); od;
for a = -2 to 2 by -1 do !(a,' '); od;
for a = -2 to 2 by 10 do !(a,' '); od;
for a = 2 to -2 by 1 do !(a,' '); od;
for a = 2 to 2 by 1 do !(a,' '); od;
for a = 2 to 2 by -1 do !(a,' '); od;
for a = 2 to 2 by 0 do !(a,' '); od;
for a = 0 to 0 by 0 do !(a,' '); od;
- Output:
-2 -1 0 1 2 -2 -2 -2 -2 -2 ..... <no output> -2 <no output> 2 2 2 2 2 2 2 2 2 2 2 2 ..... 0 0 0 0 0 0 0 0 0 0 .....
Forth
Forth, being a language that assumes a smart programmer, has absolutely no qualms with integer overflow or zero increments; it simply does what you told it to, not what you meant. This is, of course, dangerous code, so another looping construct is provided that does check whether the bounds and increment are valid.
DO
: test-seq ( start stop inc -- )
cr rot dup ." start: " 2 .r
rot dup ." stop: " 2 .r
rot dup ." inc: " 2 .r ." | "
-rot swap do i . dup +loop drop ;
-2 2 1 test-seq
-2 2 0 test-seq
-2 2 -1 test-seq
-2 2 10 test-seq
2 -2 1 test-seq
2 2 1 test-seq
2 2 -1 test-seq
2 2 0 test-seq
0 0 0 test-seq
- Output:
Some of these loop infinitely, and some under/overflow, so for the sake of brevity long outputs will be truncated by ...
.
start: -2 stop: 2 inc: 1 | -2 -1 0 1 start: -2 stop: 2 inc: 0 | -2 -2 -2 -2 -2 ... start: -2 stop: 2 inc: -1 | -2 -3 -4 -5 ... 5 4 3 2 start: -2 stop: 2 inc: 10 | -2 start: 2 stop: -2 inc: 1 | 2 3 4 5 ... -6 -5 -4 -3 start: 2 stop: 2 inc: 1 | 2 3 4 5 ... -2 -1 0 1 start: 2 stop: 2 inc: -1 | 2 start: 2 stop: 2 inc: 0 | 2 2 2 2 2 ... start: 0 stop: 0 inc: 0 | 0 0 0 0 0 ...
?DO
This is almost exactly the same as the above DO, but the bounds are checked for validity first.
: test-seq ( start stop inc -- )
cr rot dup ." start: " 2 .r
rot dup ." stop: " 2 .r
rot dup ." inc: " 2 .r ." | "
-rot swap ?do i . dup +loop drop ;
-2 2 1 test-seq
-2 2 0 test-seq
-2 2 -1 test-seq
-2 2 10 test-seq
2 -2 1 test-seq
2 2 1 test-seq
2 2 -1 test-seq
2 2 0 test-seq
0 0 0 test-seq
- Output:
Some of these loop infinitely, and some under/overflow, so for the sake of brevity long outputs will be truncated by ...
. If there is no output beyond the |
symbol, then the loop was not entered.
start: -2 stop: 2 inc: 1 | -2 -1 0 1 start: -2 stop: 2 inc: 0 | -2 -2 -2 -2 -2 ... start: -2 stop: 2 inc: -1 | -2 -3 -4 -5 ... 5 4 3 2 start: -2 stop: 2 inc: 10 | -2 start: 2 stop: -2 inc: 1 | 2 3 4 5 ... -6 -5 -4 -3 start: 2 stop: 2 inc: 1 | start: 2 stop: 2 inc: -1 | start: 2 stop: 2 inc: 0 | start: 0 stop: 0 inc: 0 |
Go
Go has only one loop, a 'for' statement, which supports four different syntactical forms commonly found in other C-family languages:
1. A C-like 'for' loop with initialization, condition and increment sections.
2. The 'while' loop functionality (condition only)
3. Infinite loop, equivalent to for(;;) (all sections omitted)
4. Looping over a range of values, similar to foreach etc. (using 'range' keyword).
It appears that either #1 or #4 fits the requirements of this task so I've written a function which generates the appropriate sequence using #1 (limited to a maximum of 10 elements as some sequences will be infinite). I've then applied #4 to the resulting sequence. All sequences include the stop value if it's actually reached.
package main
import "fmt"
type S struct {
start, stop, incr int
comment string
}
var examples = []S{
{-2, 2, 1, "Normal"},
{-2, 2, 0, "Zero increment"},
{-2, 2, -1, "Increments away from stop value"},
{-2, 2, 10, "First increment is beyond stop value"},
{2, -2, 1, "Start more than stop: positive increment"},
{2, 2, 1, "Start equal stop: positive increment"},
{2, 2, -1, "Start equal stop: negative increment"},
{2, 2, 0, "Start equal stop: zero increment"},
{0, 0, 0, "Start equal stop equal zero: zero increment"},
}
func sequence(s S, limit int) []int {
var seq []int
for i, c := s.start, 0; i <= s.stop && c < limit; i, c = i+s.incr, c+1 {
seq = append(seq, i)
}
return seq
}
func main() {
const limit = 10
for _, ex := range examples {
fmt.Println(ex.comment)
fmt.Printf("Range(%d, %d, %d) -> ", ex.start, ex.stop, ex.incr)
fmt.Println(sequence(ex, limit))
fmt.Println()
}
}
- Output:
Normal Range(-2, 2, 1) -> [-2 -1 0 1 2] Zero increment Range(-2, 2, 0) -> [-2 -2 -2 -2 -2 -2 -2 -2 -2 -2] Increments away from stop value Range(-2, 2, -1) -> [-2 -3 -4 -5 -6 -7 -8 -9 -10 -11] First increment is beyond stop value Range(-2, 2, 10) -> [-2] Start more than stop: positive increment Range(2, -2, 1) -> [] Start equal stop: positive increment Range(2, 2, 1) -> [2] Start equal stop: negative increment Range(2, 2, -1) -> [2 1 0 -1 -2 -3 -4 -5 -6 -7] Start equal stop: zero increment Range(2, 2, 0) -> [2 2 2 2 2 2 2 2 2 2] Start equal stop equal zero: zero increment Range(0, 0, 0) -> [0 0 0 0 0 0 0 0 0 0]
Haskell
import Data.List
main = putStrLn $ showTable True '|' '-' '+' table
table = [["start","stop","increment","Comment","Code","Result/Analysis"]
,["-2","2","1","Normal","[-2,-1..2] or [-2..2]",show [-2,-1..2]]
,["-2","2","0","Zero increment","[-2,-2..2]","Infinite loop of -2 <=> repeat -2"]
,["-2","2","-1","Increments away from stop value","[-2,-3..2]",show [-2,-3..2]]
,["-2","2","10","First increment is beyond stop value","[-2,8..2]",show [-2,8..2]]
,["2","-2","1","Start more than stop: positive increment","[2,3.. -2]",show [2,3.. -2]]
,["2","2","1","Start equal stop: positive increment","[2,3..2]",show [2,3..2]]
,["2","2","-1","Start equal stop: negative increment","[2,1..2]",show [2,1..2]]
,["2","2","0","Start equal stop: zero increment","[2,2..2]","Infinite loop of 2 <=> repeat 2"]
,["0","0","0","Start equal stop equal zero: zero increment","[0,0..0]", "Infinite loop of 0 <=> repeat 0"]]
showTable::Bool -> Char -> Char -> Char -> [[String]] -> String
showTable _ _ _ _ [] = []
showTable header ver hor sep contents = unlines $ hr:(if header then z:hr:zs else intersperse hr zss) ++ [hr]
where
vss = map (map length) $ contents
ms = map maximum $ transpose vss ::[Int]
hr = concatMap (\ n -> sep : replicate n hor) ms ++ [sep]
top = replicate (length hr) hor
bss = map (\ps -> map (flip replicate ' ') $ zipWith (-) ms ps) $ vss
zss@(z:zs) = zipWith (\us bs -> (concat $ zipWith (\x y -> (ver:x) ++ y) us bs) ++ [ver]) contents bss
- Output:
+-----+----+---------+-------------------------------------------+---------------------+---------------------------------+ |start|stop|increment|Comment |Code |Result/Analysis | +-----+----+---------+-------------------------------------------+---------------------+---------------------------------+ |-2 |2 |1 |Normal |[-2,-1..2] or [-2..2]|[-2,-1,0,1,2] | |-2 |2 |0 |Zero increment |[-2,-2..2] |Infinite loop of -2 <=> repeat -2| |-2 |2 |-1 |Increments away from stop value |[-2,-3..2] |[] | |-2 |2 |10 |First increment is beyond stop value |[-2,8..2] |[-2] | |2 |-2 |1 |Start more than stop: positive increment |[2,3.. -2] |[] | |2 |2 |1 |Start equal stop: positive increment |[2,3..2] |[2] | |2 |2 |-1 |Start equal stop: negative increment |[2,1..2] |[2] | |2 |2 |0 |Start equal stop: zero increment |[2,2..2] |Infinite loop of 2 <=> repeat 2 | |0 |0 |0 |Start equal stop equal zero: zero increment|[0,0..0] |Infinite loop of 0 <=> repeat 0 | +-----+----+---------+-------------------------------------------+---------------------+---------------------------------+
Huginn
Huginn has the Range generator in Algorithms package. Instantiation of an a priori invalid range is a fatal error.
import Algorithms as algo;
class Example {
_start = none;
_stop = none;
_step = none;
_comment = none;
}
main() {
examples = [
Example( -2, 2, 1, "Normal" ),
Example( 2, 2, 0, "Start equal stop: zero increment" ),
Example( 0, 0, 0, "Start equal stop equal zero: zero increment" ),
Example( 2, 2, 1, "Start equal stop: positive increment" ),
Example( 2, 2, -1, "Start equal stop: negative increment" ),
Example( -2, 2, 10, "First increment is beyond stop value" ),
Example( -2, 2, 0, "Zero increment, stop greater than start" ),
Example( -2, 2, -1, "Increments away from stop value" ),
Example( 2, -2, 1, "Start more than stop: positive increment" )
];
for ( ex : examples ) {
print(
"{}\nRange( {}, {}, {} ) -> ".format(
ex._comment, ex._start, ex._stop, ex._step
)
);
r = algo.range( ex._start, ex._stop, ex._step );
print(
"{}\n\n".format(
algo.materialize( algo.slice( r, 22 ), list )
)
);
}
}
- Output:
Normal Range( -2, 2, 1 ) -> [-2, -1, 0, 1] Start equal stop: zero increment Range( 2, 2, 0 ) -> [] Start equal stop equal zero: zero increment Range( 0, 0, 0 ) -> [] Start equal stop: positive increment Range( 2, 2, 1 ) -> [] Start equal stop: negative increment Range( 2, 2, -1 ) -> [] First increment is beyond stop value Range( -2, 2, 10 ) -> [-2] Zero increment, stop greater than start Range( -2, 2, 0 ) -> ./range.hgn:32:17: Invalid range. Exit 3
J
J can build ranges.
NB. rank 3 integers with a bit of inversion i. 2 _3 6 12 13 14 15 16 17 6 7 8 9 10 11 0 1 2 3 4 5 30 31 32 33 34 35 24 25 26 27 28 29 18 19 20 21 22 23 NB. from _3 to 3 in 12 steps i: 3j12 _3 _2.5 _2 _1.5 _1 _0.5 0 0.5 1 1.5 2 2.5 3
The loops with multiple ranges shall use this version of range. Or so it is in on 2019, March 6. http://rosettacode.org/wiki/Loops/with_multiple_ranges#J
R =: ".;._2 [ 0 : 0 9 2 _2 NB. valid descending range _2 2 1 NB. valid ascending range _2 2 0 _2 2 _1 _2 2 10 2 _2 1 2 2 1 2 2 _1 2 2 0 0 0 0 ) 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 NB. the first two of these are ranges with valid arguments (; range :: ('*error*'"_))"1 R +-------+-----------+ |9 2 _2 |9 7 5 3 | +-------+-----------+ |_2 2 1 |_2 _1 0 1 2| +-------+-----------+ |_2 2 0 |*error* | +-------+-----------+ |_2 2 _1|_4 _3 _2 | +-------+-----------+ |_2 2 10|_2 | +-------+-----------+ |2 _2 1 |4 3 2 | +-------+-----------+ |2 2 1 |2 | +-------+-----------+ |2 2 _1 |2 | +-------+-----------+ |2 2 0 |2 | +-------+-----------+ |0 0 0 |0 | +-------+-----------+
Another approach
genrange=: {{
'start stop increment'=. y
start+increment*i.1+<.(stop-start)%increment
}}
Here, we generate n values (where n is defined based on the difference between the start and stop values, scaled by the increment), and scale them according to the increment and adjust the origin to match the start value.
That said, since J treats a negative n as a reversed sequence, what we get here is a truncated projection backwards from the start value when the increment would never reach the stop value:
genrange 9 2 _2 NB. valid
9 7 5 3
genrange _2 2 1 NB. valid
_2 _1 0 1 2
genrange _2 2 0 NB. invalid: requires at least an infinity of values
|domain error: genrange
genrange _2 2 _1 NB. projects backwards from _2
_4 _3 _2
genrange _2 2 10 NB. valid
_2
genrange 2 _2 1 NB. projects backwards from 2
4 3 2
genrange 2 2 1 NB. valid (increment is irrelevant)
2
genrange 2 2 _1 NB. valid (increment is irrelevant)
2
genrange 2 2 0 NB. valid (increment is irrelevant)
2
genrange 0 0 0 NB. valid (increment is irrelevant)
0
As an aside, J's range generation function i.
generates indices starting from 0 and not reaching the absolute value of its argument. This corresponds to integers in the interval [0,n). So we add 1 to n so that our range includes the end of the interval. However, when n is negative, adding 1 to n shortens the interval rather than extending it. So, when we "project backwards" we're 2 elements short of the number we would have expected if the sign of the interval had been reversed.
Java
import java.util.ArrayList;
import java.util.List;
public class LoopsWrongRanges {
public static void main(String[] args) {
runTest(new LoopTest(-2, 2, 1, "Normal"));
runTest(new LoopTest(-2, 2, 0, "Zero increment"));
runTest(new LoopTest(-2, 2, -1, "Increments away from stop value"));
runTest(new LoopTest(-2, 2, 10, "First increment is beyond stop value"));
runTest(new LoopTest(2, -2, 1, "Start more than stop: positive increment"));
runTest(new LoopTest(2, 2, 1, "Start equal stop: positive increment"));
runTest(new LoopTest(2, 2, -1, "Start equal stop: negative increment"));
runTest(new LoopTest(2, 2, 0, "Start equal stop: zero increment"));
runTest(new LoopTest(0, 0, 0, "Start equal stop equal zero: zero increment"));
}
private static void runTest(LoopTest loopTest) {
List<Integer> values = new ArrayList<>();
for (int i = loopTest.start ; i <= loopTest.stop ; i += loopTest.increment ) {
values.add(i);
if ( values.size() >= 10 ) {
break;
}
}
System.out.printf("%-45s %s%s%n", loopTest.comment, values, values.size()==10 ? " (loops forever)" : "");
}
private static class LoopTest {
int start;
int stop;
int increment;
String comment;
public LoopTest(int start, int stop, int increment, String comment) {
this.start = start;
this.stop = stop;
this.increment = increment;
this.comment = comment;
}
}
}
- Output:
Normal [-2, -1, 0, 1, 2] Zero increment [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2] (loops forever) Increments away from stop value [-2, -3, -4, -5, -6, -7, -8, -9, -10, -11] (loops forever) First increment is beyond stop value [-2] Start more than stop: positive increment [] Start equal stop: positive increment [2] Start equal stop: negative increment [2, 1, 0, -1, -2, -3, -4, -5, -6, -7] (loops forever) Start equal stop: zero increment [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] (loops forever) Start equal stop equal zero: zero increment [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] (loops forever)
jq
The following remarks also apply to gojq, the Go implmentation of jq.
jq has a filter `range(start; stop; increment)` which emits a (possibly empty) stream of numbers if given numeric inputs.
It meets the task criterion, e.g. `range(0;1;0.4)` generates 3 numbers.
In fact, it is quite similar to C's `for (i=start; i < stop; i+=increment)` except that if `increment` is 0 or in the "wrong" direction, then nothing is emitted.
None of the cases enumerated in the task description results in an error, and in all but two cases, the result is the empty stream.
To streamline the presentation of results, rather than showing the stream of values generated by stream(start;stop;increment), we will show the array of the generated values.
[range(-2; 2; 1)] #=> [-2,-1,0,1] [range(-2; 2; 0)] #=> [] [range(-2; 2; -1)] #=> [] [range(-2; 2; 10)] # [-2] [range(2; -2; 1)] #=> [] [range(2; 2; 1)] #=> [] [range(2; 2; 0)] #=> [] [range(0; 0; -1)] #=> []
Julia
Julia has a start:increment:stop iterator syntax, which allows negative increments, but not zero increments.
collect(-2:1:2) # → [-2, -1, 0, 1, 2]
collect(-2:0:2) # fails
collect(-2:-1:2) # → []
collect(-2:10:2) # → [-2]
collect(2:1:-2) # → []
collect(2:1:2) # → [2]
collect(2:-1:2) # → [2]
collect(2:0:2) # fails
collect(0:0:0) # fails
Kotlin
Although Kotlin's 'for' statement can deal with a range of integers, the increment must be positive and so it cannot be used for this task. We therefore use instead a 'while' statement to generate the same sequence as a C language 'for' statement would (limited to a maximum of 10 elements as some sequences will be infinite) and wrap it in a function.
// Version 1.2.70
class Example(val start: Int, val stop: Int, val incr: Int, val comment: String)
var examples = listOf(
Example(-2, 2, 1, "Normal"),
Example(-2, 2, 0, "Zero increment"),
Example(-2, 2, -1, "Increments away from stop value"),
Example(-2, 2, 10, "First increment is beyond stop value"),
Example(2, -2, 1, "Start more than stop: positive increment"),
Example(2, 2, 1, "Start equal stop: positive increment"),
Example(2, 2, -1, "Start equal stop: negative increment"),
Example(2, 2, 0, "Start equal stop: zero increment"),
Example(0, 0, 0, "Start equal stop equal zero: zero increment")
)
fun sequence(ex: Example, limit: Int) =
if (ex.incr == 0) {
List(limit) { ex.start }
}
else {
val res = mutableListOf<Int>()
var c = 0
var i = ex.start
while (i <= ex.stop && c < limit) {
res.add(i)
i += ex.incr
c++
}
res
}
fun main(args: Array<String>) {
for (ex in examples) {
println(ex.comment)
System.out.printf("Range(%d, %d, %d) -> ", ex.start, ex.stop, ex.incr)
println(sequence(ex, 10))
println()
}
}
- Output:
Normal Range(-2, 2, 1) -> [-2, -1, 0, 1, 2] Zero increment Range(-2, 2, 0) -> [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2] Increments away from stop value Range(-2, 2, -1) -> [-2, -3, -4, -5, -6, -7, -8, -9, -10, -11] First increment is beyond stop value Range(-2, 2, 10) -> [-2] Start more than stop: positive increment Range(2, -2, 1) -> [] Start equal stop: positive increment Range(2, 2, 1) -> [2] Start equal stop: negative increment Range(2, 2, -1) -> [2, 1, 0, -1, -2, -3, -4, -5, -6, -7] Start equal stop: zero increment Range(2, 2, 0) -> [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] Start equal stop equal zero: zero increment Range(0, 0, 0) -> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
langur
In the following example, we could have just started with a list of lists, but following the Python example, we process a data string into a table.
val data = qs:block END
start stop increment comment
-2 2 1 Normal
-2 2 0 Zero increment
-2 2 -1 Increments away from stop value
-2 2 10 First increment is beyond stop value
2 -2 1 Start more than stop: positive increment
2 2 1 Start equal stop: positive increment
2 2 -1 Start equal stop: negative increment
2 2 0 Start equal stop: zero increment
0 0 0 Start equal stop equal zero: zero increment
END
# Process data string into table.
# We could have just started with a list of lists, of course.
var table = submatches(data, by=RE/([^ ]+) +([^ ]+) +([^ ]+) +(.+)\n?/)
for i in 2..len(table) {
table[i] = map(table[i], by=[number, number, number, _])
}
for test in less(table, of=1) {
val start, stop, inc, comment = test
{
val s = series(start .. stop, inc=inc)
catch {
writeln "{{comment}}\nERROR: {{_err'msg:L200(...)}}\n"
} else {
writeln "{{comment}}\nresult: {{s}}\n"
}
}
}
- Output:
Normal result: [-2, -1, 0, 1, 2] Zero increment result: [] Increments away from stop value ERROR: Expected ascending range with positive increment, or descending range with negative increment First increment is beyond stop value result: [-2] Start more than stop: positive increment ERROR: Expected ascending range with positive increment, or descending range with negative increment Start equal stop: positive increment result: [2] Start equal stop: negative increment result: [2] Start equal stop: zero increment result: [] Start equal stop equal zero: zero increment result: []
Lua
Lua >= 5.4 will not allow a zero increment, causes a runtime error (trapped below). Lua 4.0 - 5.3 will allow a zero increment, causing either: no execution (start<stop) or infinite execution (start>=stop). (though Lua 4.0 is not supported in the code below for other reasons.) Lua <4.0 didn't have numeric for loops, so behaviour would depend on how an equivalent repeat/while loop was written.
tests = {
{ -2, 2, 1, "Normal" },
{-2, 2, 0, "Zero increment" }, -- 5.4 error
{-2, 2, -1, "Increments away from stop value" },
{-2, 2, 10, "First increment is beyond stop value" },
{ 2, -2, 1, "Start more than stop: positive increment" },
{ 2, 2, 1, "Start equal stop: positive increment" },
{ 2, 2, -1, "Start equal stop: negative increment" },
{ 2, 2, 0, "Start equal stop: zero increment" }, -- 5.4 error
{ 0, 0, 0, "Start equal stop equal zero: zero increment" } -- 5.4 error
}
unpack = unpack or table.unpack -- polyfill 5.2 vs 5.3
for _,test in ipairs(tests) do
start,stop,incr,desc = unpack(test)
io.write(string.format("%-44s (%2d, %2d, %2d) : ",desc,start,stop,incr))
local sta,err = pcall(function()
local n = 0
for i = start,stop,incr do
io.write(string.format("%2d, ", i))
n=n+1 if n>=10 then io.write("...") break end
end
io.write("\n")
end)
if err then io.write("RUNTIME ERROR!\n") end
end
- Output:
Using 5.3:
Normal (-2, 2, 1) : -2, -1, 0, 1, 2, Zero increment (-2, 2, 0) : Increments away from stop value (-2, 2, -1) : First increment is beyond stop value (-2, 2, 10) : -2, Start more than stop: positive increment ( 2, -2, 1) : Start equal stop: positive increment ( 2, 2, 1) : 2, Start equal stop: negative increment ( 2, 2, -1) : 2, Start equal stop: zero increment ( 2, 2, 0) : 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ... Start equal stop equal zero: zero increment ( 0, 0, 0) : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
Using 5.4:
Normal (-2, 2, 1) : -2, -1, 0, 1, 2, Zero increment (-2, 2, 0) : RUNTIME ERROR! Increments away from stop value (-2, 2, -1) : First increment is beyond stop value (-2, 2, 10) : -2, Start more than stop: positive increment ( 2, -2, 1) : Start equal stop: positive increment ( 2, 2, 1) : 2, Start equal stop: negative increment ( 2, 2, -1) : 2, Start equal stop: zero increment ( 2, 2, 0) : RUNTIME ERROR! Start equal stop equal zero: zero increment ( 0, 0, 0) : RUNTIME ERROR!
Maple
# Normal
seq(-2..2, 1);
# Zero increment
seq(-2..2, 0);
# Increments away from stop value
seq(-2..2, -1);
# First increment is beyond stop value
seq(-2..2, 10);
# Start more than stop: positive increment
seq(2..-2, 1);
# Start equal stop: positive increment
seq(2..2, 1);
# Start equal stop: negative increment
seq(2..2, -1);
# Start equal stop: zero increment
seq(2..2, 0);
# Start equal stop equal zero: zero increment
seq(0..0, 0);
- Output:
-2, -1, 0, 1, 2 Error, increment is zero in seq -2 2 2 2 0
Mathematica /Wolfram Language
All functions like Do, Table, Range, Sum, NSum, Product and NProduct use same 'iterator specification':
Table[i, {i, -2, 2, 1}]
Table[i, {i, -2, 2, 0}]
Table[i, {i, -2, 2, -1}]
Table[i, {i, -2, 2, 10}]
Table[i, {i, 2, -2, 1}]
Table[i, {i, 2, 2, 1}]
Table[i, {i, 2, 2, -1}]
Table[i, {i, 2, 2, 0}]
Table[i, {i, 0, 0, 0}]
- Output:
{-2, -1, 0, 1, 2} During evaluation of In[…]:= Table::iterb: Iterator {i,-2,2,0} does not have appropriate bounds. Table[i, {i, -2, 2, 0}] {} {-2} {} {2} {2} {2} {0}
Nim
In Nim, ranges are used in “for loops” with iterators “countup” and “countdown”. These iterators accept only positive steps which means that a negative step must be translated using iterator “countdown”. Using this convention, the given ranges can be expressed either using “countup” or using “countdown” according to the sign of the step. If the step is zero, an error is detected at compile time or at runtime.
The following program display the values yielded by “countup” our “countdown” for the given ranges:
import sequtils, strformat
proc displayRange(first, last, step: int) =
stdout.write &"({first:>2}, {last:>2}, {step:>2}): "
echo if step > 0: ($toSeq(countup(first, last, step)))[1..^1]
elif step < 0: ($toSeq(countdown(first, last, -step)))[1..^1]
else: "not allowed."
for (f, l, s) in [(-2, 2, 1), (-2, 2, 0), (-2, 2, -1),
(-2, 2, 10), (2, -2, 1), (2, 2, 1),
(2, 2, -1), (2, 2, 0), (0, 0, 0)]:
displayRange(f, l, s)
- Output:
(-2, 2, 1): [-2, -1, 0, 1, 2] (-2, 2, 0): not allowed. (-2, 2, -1): [] (-2, 2, 10): [-2] ( 2, -2, 1): [] ( 2, 2, 1): [2] ( 2, 2, -1): [2] ( 2, 2, 0): not allowed. ( 0, 0, 0): not allowed.
PascalABC.NET
procedure DisplayRange(first, last, step: integer);
begin
Print($'({first,2}, {last,2}, {step,2}): ');
if step = 0 then
Println('not allowed')
else Println(Range(first, last, step));
end;
begin
var ranges := |(-2, 2, 1), (-2, 2, 0), (-2, 2, -1),
(-2, 2, 10), (2, -2, 1), (2, 2, 1),
(2, 2, -1), (2, 2, 0), (0, 0, 0)|;
foreach var (f, l, s) in ranges do
DisplayRange(f,l,s);
end.
- Output:
(-2, 2, 1): [-2,-1,0,1,2] (-2, 2, 0): not allowed (-2, 2, -1): [] (-2, 2, 10): [-2] ( 2, -2, 1): [] ( 2, 2, 1): [2] ( 2, 2, -1): [2] ( 2, 2, 0): not allowed ( 0, 0, 0): not allowed
Perl
None of these sequences are 'errors', though some are of infinite length, and #5 has a length of zero.
for $i (
[ -2, 2, 1], #1 Normal
[ -2, 2, 0], #2 Zero increment
[ -2, 2, -1], #3 Increments away from stop value
[ -2, 2, 10], #4 First increment is beyond stop value
[ 2, -2, 1], #5 Start more than stop: positive increment
[ 2, 2, 1], #6 Start equal stop: positive increment
[ 2, 2, -1], #7 Start equal stop: negative increment
[ 2, 2, 0], #8 Start equal stop: zero increment
[ 0, 0, 0], #9 Start equal stop equal zero: zero increment
) {
$iter = gen_seq(@$i);
printf "start: %3d stop: %3d incr: %3d | ", @$i;
printf "%4s", &$iter for 1..10;
print "\n";
}
sub gen_seq {
my($start,$stop,$increment) = @_;
$n = 0;
return sub {
$term = $start + $n++ * $increment;
return $term > $stop ? '' : $term;
}
}
- Output:
start: -2 stop: 2 incr: 1 | -2 -1 0 1 2 start: -2 stop: 2 incr: 0 | -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 start: -2 stop: 2 incr: -1 | -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 start: -2 stop: 2 incr: 10 | -2 start: 2 stop: -2 incr: 1 | start: 2 stop: 2 incr: 1 | 2 start: 2 stop: 2 incr: -1 | 2 1 0 -1 -2 -3 -4 -5 -6 -7 start: 2 stop: 2 incr: 0 | 2 2 2 2 2 2 2 2 2 2 start: 0 stop: 0 incr: 0 | 0 0 0 0 0 0 0 0 0 0
Phix
Phix for loops do not allow a zero step, neither are any floating point values permitted.
The following shows the behaviour of both for and while loops, and the latter has a couple of
additional commented out termination checks that might be appropriate in some cases.
procedure test(integer start, stop, step, string legend, bool bFor) sequence res = {} if bFor then try for i=start to stop by step do res &= i if length(res)>9 then exit end if end for res = sprint(res) catch e res = e[E_USER] end try else integer i = start while (step>=0 and i<=stop) or (step<=0 and i>=stop) do res &= i if length(res)>9 then exit end if -- if i=stop then exit end if -- if step=0 then exit end if i += step end while res = sprint(res) end if printf(1,"%-43s: %s\n",{legend,res}) end procedure for i=1 to 2 do ?iff(i=1?"for":"while") test(-2, 2, 1, "Normal" ,i=1) test(-2, 2, 0, "Zero increment" ,i=1) test(-2, 2,-1, "Increments away from stop value" ,i=1) test(-2, 2,10, "First increment is beyond stop value" ,i=1) test( 2,-2, 1, "Start more than stop: positive increment" ,i=1) test( 2, 2, 1, "Start equal stop: positive increment" ,i=1) test( 2, 2,-1, "Start equal stop: negative increment" ,i=1) test( 2, 2, 0, "Start equal stop: zero increment" ,i=1) test( 0, 0, 0, "Start equal stop equal zero: zero increment",i=1) puts(1,"\n") end for
- Output:
"for" Normal : {-2,-1,0,1,2} Zero increment : for loop error, step is 0 Increments away from stop value : {} First increment is beyond stop value : {-2} Start more than stop: positive increment : {} Start equal stop: positive increment : {2} Start equal stop: negative increment : {2} Start equal stop: zero increment : for loop error, step is 0 Start equal stop equal zero: zero increment: for loop error, step is 0 "while" Normal : {-2,-1,0,1,2} Zero increment : {-2,-2,-2,-2,-2,-2,-2,-2,-2,-2} Increments away from stop value : {} First increment is beyond stop value : {-2} Start more than stop: positive increment : {} Start equal stop: positive increment : {2} Start equal stop: negative increment : {2} Start equal stop: zero increment : {2,2,2,2,2,2,2,2,2,2} Start equal stop equal zero: zero increment: {0,0,0,0,0,0,0,0,0,0}
PL/I
loops:procedure options (main);
declare i fixed binary;
put skip list ('-2 to 2 by 1:');
do i = -2 to 2 by 1;
put edit (i) (f(3));
end;
put skip list ('-2 to 2 by 0: infinite loop, prints -2');
put skip list ('-2 to 2 by -1: [no values printed]');
do i = -2 to 2 by -1;
put edit (i) (f(3));
end;
put skip list ('-2 to 2 by 10:');
do i = -2 to 2 by 1;
put edit (i) (f(3));
end;
put skip list (' 2 to 2 by 1:');
do i = 2 to 2 by 1;
put edit (i) (f(3));
end;
put skip list (' 2 to 2 by -1:');
do i = 2 to 2 by -1;
put edit (i) (f(3));
end;
put skip list (' 2 to 2 by 0: infinite loop, prints 2');
put skip list (' 0 to 0 by 0: infinite loop, prints 0');
end loops;
Output:
-2 to 2 by 1: -2 -1 0 1 2 -2 to 2 by 0: infinite loop, prints -2 -2 to 2 by -1: [no values printed] -2 to 2 by 10: -2 -1 0 1 2 2 to 2 by 1: 2 2 to 2 by -1: 2 2 to 2 by 0: infinite loop, prints 2 0 to 0 by 0: infinite loop, prints 0
Python
Python has the range function.
import re
from itertools import islice # To limit execution if it would generate huge values
# list(islice('ABCDEFG', 2)) --> ['A', 'B']
# list(islice('ABCDEFG', 4)) --> ['A', 'B', 'C', 'D']
data = '''
start stop increment Comment
-2 2 1 Normal
-2 2 0 Zero increment
-2 2 -1 Increments away from stop value
-2 2 10 First increment is beyond stop value
2 -2 1 Start more than stop: positive increment
2 2 1 Start equal stop: positive increment
2 2 -1 Start equal stop: negative increment
2 2 0 Start equal stop: zero increment
0 0 0 Start equal stop equal zero: zero increment
'''
table = [re.split(r'\s\s+', line.strip()) for line in data.strip().split('\n')]
#%%
for _start, _stop, _increment, comment in table[1:]:
start, stop, increment = [int(x) for x in (_start, _stop, _increment)]
print(f'{comment.upper()}:\n range({start}, {stop}, {increment})')
values = None
try:
values = list(islice(range(start, stop, increment), 999))
except ValueError as e:
print(' !!ERROR!!', e)
if values is not None:
if len(values) < 22:
print(' =', values)
else:
print(' =', str(values[:22])[:-1], '...')
- Output:
NORMAL: range(-2, 2, 1) = [-2, -1, 0, 1] ZERO INCREMENT: range(-2, 2, 0) !!ERROR!! range() arg 3 must not be zero INCREMENTS AWAY FROM STOP VALUE: range(-2, 2, -1) = [] FIRST INCREMENT IS BEYOND STOP VALUE: range(-2, 2, 10) = [-2] START MORE THAN STOP: POSITIVE INCREMENT: range(2, -2, 1) = [] START EQUAL STOP: POSITIVE INCREMENT: range(2, 2, 1) = [] START EQUAL STOP: NEGATIVE INCREMENT: range(2, 2, -1) = [] START EQUAL STOP: ZERO INCREMENT: range(2, 2, 0) !!ERROR!! range() arg 3 must not be zero START EQUAL STOP EQUAL ZERO: ZERO INCREMENT: range(0, 0, 0) !!ERROR!! range() arg 3 must not be zero
R
Aside from the second case, this behaviour is explained by two sentences of seq's documentation: "generates from, from+by, ..., up to the sequence value less than or equal to to. Specifying to - from and by of opposite signs is an error." As we can see, from is always included whenever an error is not thrown and to will be missed if it cannot be reached.
seq(from = -2, to = 2, by = 1)#Output: -2 -1 0 1 2
seq(from = -2, to = 2, by = 0)#Fails: "invalid '(to - from)/by'"
seq(from = -2, to = 2, by = -1)#Fails: As in the notes above - "Specifying to - from and by of opposite signs is an error."
seq(from = -2, to = 2, by = 10)#Output: -2
seq(from = 2, to = -2, by = 1)#Fails: Same as the third case.
seq(from = 2, to = 2, by = 1)#Output: 2
seq(from = 2, to = 2, by = -1)#Output: 2
seq(from = 2, to = 2, by = 0)#Output: 2
seq(from = 0, to = 0, by = 0)#Output: 0
Racket
#lang racket
(require racket/sandbox)
(define tests '([-2 2 1 "Normal"]
[-2 2 0 "Zero increment"]
[-2 2 -1 "Increments away from stop value"]
[-2 2 10 "First increment is beyond stop value"]
[2 -2 1 "Start more than stop: positive increment"]
[2 2 1 "Start equal stop: positive increment"]
[2 2 -1 "Start equal stop: negative increment"]
[2 2 0 "Start equal stop: zero increment"]
[0 0 0 "Start equal stop equal zero: zero increment"]))
(for ([test (in-list tests)])
(match-define (list st ed inc desc) test)
(printf "~a:\n (in-range ~a ~a ~a) = ~a\n\n"
desc st ed inc
(with-handlers ([exn:fail:resource? (thunk* 'timeout)])
(with-limits 1 #f
(sequence->list (in-range st ed inc))))))
- Output:
Normal: (in-range -2 2 1) = (-2 -1 0 1) Zero increment: (in-range -2 2 0) = timeout Increments away from stop value: (in-range -2 2 -1) = () First increment is beyond stop value: (in-range -2 2 10) = (-2) Start more than stop: positive increment: (in-range 2 -2 1) = () Start equal stop: positive increment: (in-range 2 2 1) = () Start equal stop: negative increment: (in-range 2 2 -1) = () Start equal stop: zero increment: (in-range 2 2 0) = () Start equal stop equal zero: zero increment: (in-range 0 0 0) = ()
Raku
(formerly Perl 6)
It would be odd to call ANY of these sequences "wrong" in Raku. Raku specifically has built in capability of working with infinite sequences. Just because a sequence is infinite, doesn't mean you can't define it, work with it or use values from it. Sure, if you try to reify the whole thing you may be waiting a while, but there is nothing preventing you from using a portion of it.
Raku sequence definitions specifically allow "ending points" that may never occur in the sequence. Since that is the case, you don't even really need to specify a stop value. You can just say stop at "whatever". Whatever is spelled "*" in Raku.
There is additional syntax you can add to stop at the nearest value, last value previous or first value successor to the "stop value" (Note I didn't say less than or greater than the stop value since the sequence can be ascending, descending or non-monotonic).
Also note: The iterator function for the sequence is literally a function. It is any expression that produces a value. These sequences all use simple arithmatic increments but that is not a limitation of the sequence operator.
# Given sequence definitions
# start stop inc. Comment
for -2, 2, 1, # Normal
-2, 2, 0, # Zero increment
-2, 2, -1, # Increments away from stop value
-2, 2, 10, # First increment is beyond stop value
2, -2, 1, # Start more than stop: positive increment
2, 2, 1, # Start equal stop: positive increment
2, 2, -1, # Start equal stop: negative increment
2, 2, 0, # Start equal stop: zero increment
0, 0, 0, # Start equal stop equal zero: zero increment
# Additional "problematic" sequences
1, Inf, 3, # Endpoint literally at infinity
0, π, τ/8, # Floating point numbers
1.4, *, -7.1 # Whatever
-> $start, $stop, $inc {
my $seq = flat ($start, *+$inc … $stop);
printf "Start: %3s, Stop: %3s, Increment: %3s | ", $start, $stop.Str, $inc;
# only show up to the first 15 elements of possibly infinite sequences
put $seq[^15].grep: +*.defined
}
# For that matter the start and end values don't need to be numeric either. Both
# or either can be a function, list, or other object. Really anything that a
# "successor" function can be defined for and produces a value.
say "\nDemonstration of some other specialized sequence operator functionality:";
# Start with a list, iterate by multiplying the previous 3 terms together
# and end with a term defined by a function.
put 1, -.5, 2.sqrt, * × * × * … *.abs < 1e-2;
# Start with an array, iterate by rotating, end when 0 is in the last place.
say [0,1,2,3,4,5], *.rotate(-1).Array … !*.tail;
# Iterate strings backwards.
put 'xp' … 'xf';
- Output:
Start: -2, Stop: 2, Increment: 1 | -2 -1 0 1 2 Start: -2, Stop: 2, Increment: 0 | -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Start: -2, Stop: 2, Increment: -1 | -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 Start: -2, Stop: 2, Increment: 10 | -2 8 18 28 38 48 58 68 78 88 98 108 118 128 138 Start: 2, Stop: -2, Increment: 1 | 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Start: 2, Stop: 2, Increment: 1 | 2 Start: 2, Stop: 2, Increment: -1 | 2 Start: 2, Stop: 2, Increment: 0 | 2 Start: 0, Stop: 0, Increment: 0 | 0 Start: 1, Stop: Inf, Increment: 3 | 1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 Start: 0, Stop: 3.141592653589793, Increment: 0.7853981633974483 | 0 0.7853981633974483 1.5707963267948966 2.356194490192345 3.141592653589793 Start: 1.4, Stop: *, Increment: -7.1 | 1.4 -5.7 -12.8 -19.9 -27 -34.1 -41.2 -48.3 -55.4 -62.5 -69.6 -76.7 -83.8 -90.9 -98 Demonstration of some other specialized sequence operator functionality: 1 -0.5 1.4142135623730951 -0.7071067811865476 0.5000000000000001 -0.5000000000000002 0.176776695296637 -0.04419417382415928 0.0039062500000000095 ([0 1 2 3 4 5] [5 0 1 2 3 4] [4 5 0 1 2 3] [3 4 5 0 1 2] [2 3 4 5 0 1] [1 2 3 4 5 0]) xp xo xn xm xl xk xj xi xh xg xf
REXX
Note that a do loop with zero by value, or a do loop that goes in the "wrong" direction is not considered an error in REXX as there are other methods of limiting the range (or stopping condition) within the loop body. A special check was made in this REXX version to check for a runaway (race) condition.
The REXX language will cause the do loop index to be checked at the "head" of the do loop to see if the index falls within the specified iteration range (if there is one).
/*REXX program demonstrates several versions of DO loops with "unusual" iterations. */
@.=; @.1= ' -2 2 1 ' /*"normal". */
@.2= ' -2 2 0 ' /*"normal", zero increment.*/
@.3= ' -2 2 -1 ' /*increases away from stop, neg increment.*/
@.4= ' -2 2 10 ' /*1st increment > stop, positive increment.*/
@.5= ' 2 -2 1 ' /*start > stop, positive increment.*/
@.6= ' 2 2 1 ' /*start equals stop, positive increment.*/
@.7= ' 2 2 -1 ' /*start equals stop, negative increment.*/
@.8= ' 2 2 0 ' /*start equals stop, zero increment.*/
@.9= ' 0 0 0 ' /*start equals stop, zero increment.*/
zLim= 10 /*a limit to check for runaway (race) loop.*/
/*a zero increment is not an error in REXX.*/
do k=1 while @.k\=='' /*perform a DO loop with several ranges. */
parse var @.k x y z . /*obtain the three values for a DO loop. */
say
say center('start of performing DO loop number ' k " with range: " x y z, 79, '═')
zz= 0
do j=x to y by z until zz>=zLim /* ◄─── perform the DO loop.*/
say ' j ───►' right(j, max(3, length(j) ) ) /*right justify J for alignment*/
if z==0 then zz= zz + 1 /*if zero inc, count happenings*/
end /*j*/
if zz>=zLim then say 'the DO loop for the ' k " entry was terminated (runaway)."
say center(' end of performing DO loop number ' k " with range: " x y z, 79, '─')
say
end /*k*/ /*stick a fork in it, we're all done. */
- output:
══════════start of performing DO loop number 1 with range: -2 2 1═══════════ j ───► -2 j ───► -1 j ───► 0 j ───► 1 j ───► 2 ────────── end of performing DO loop number 1 with range: -2 2 1─────────── ══════════start of performing DO loop number 2 with range: -2 2 0═══════════ j ───► -2 j ───► -2 j ───► -2 j ───► -2 j ───► -2 j ───► -2 j ───► -2 j ───► -2 j ───► -2 j ───► -2 the DO loop for the 2 entry was terminated (runaway). ────────── end of performing DO loop number 2 with range: -2 2 0─────────── ══════════start of performing DO loop number 3 with range: -2 2 -1══════════ ────────── end of performing DO loop number 3 with range: -2 2 -1────────── ══════════start of performing DO loop number 4 with range: -2 2 10══════════ j ───► -2 ────────── end of performing DO loop number 4 with range: -2 2 10────────── ══════════start of performing DO loop number 5 with range: 2 -2 1═══════════ ────────── end of performing DO loop number 5 with range: 2 -2 1─────────── ═══════════start of performing DO loop number 6 with range: 2 2 1═══════════ j ───► 2 ─────────── end of performing DO loop number 6 with range: 2 2 1─────────── ══════════start of performing DO loop number 7 with range: 2 2 -1═══════════ j ───► 2 ────────── end of performing DO loop number 7 with range: 2 2 -1─────────── ═══════════start of performing DO loop number 8 with range: 2 2 0═══════════ j ───► 2 j ───► 2 j ───► 2 j ───► 2 j ───► 2 j ───► 2 j ───► 2 j ───► 2 j ───► 2 j ───► 2 the DO loop for the 8 entry was terminated (runaway). ─────────── end of performing DO loop number 8 with range: 2 2 0─────────── ═══════════start of performing DO loop number 9 with range: 0 0 0═══════════ j ───► 0 j ───► 0 j ───► 0 j ───► 0 j ───► 0 j ───► 0 j ───► 0 j ───► 0 j ───► 0 j ───► 0 the DO loop for the 9 entry was terminated (runaway). ─────────── end of performing DO loop number 9 with range: 0 0 0───────────
RPL
start | stop | increment | Result |
---|---|---|---|
-2 | 2 | 1 | 5 loops |
-2 | 2 | 0 | endless loop |
-2 | 2 | -1 | 1 loop |
-2 | 2 | 10 | 1 loop |
2 | -2 | 1 | 1 loop |
2 | 2 | 1 | 1 loop |
2 | 2 | -1 | 1 loop |
2 | 2 | 0 | endless loop |
0 | 0 | 0 | endless loop |
Ruby
A Range with a step (without a block) results in an ArthmeticSequence (an object). A step size of zero is perfectly valid. To illustrate, a representation of the ArithmicSequence and it's size are shown.
examples = [
[ -2, 2, 1],
[ -2, 2, 0],
[ -2, 2, -1],
[ -2, 2, 10],
[ 2, -2, 1],
[ 2, 2, 1],
[ 2, 2, -1],
[ 2, 2, 0],
[ 0, 0, 0]
]
examples.each do |start, stop, step|
as = (start..stop).step(step)
puts "#{as.inspect} size: #{as.size}"
end
- Output:
((-2..2).step(1)) size: 5((-2..2).step(0)) size: Infinity ((-2..2).step(-1)) size: 0 ((-2..2).step(10)) size: 1 ((2..-2).step(1)) size: 0 ((2..2).step(1)) size: 1 ((2..2).step(-1)) size: 1 ((2..2).step(0)) size: Infinity ((0..0).step(0)) size: Infinity
Seed7
$ include "seed7_05.s7i";
const proc: testLoop (in integer: start, in integer: stop, in integer: incr, in string: comment) is func
local
const integer: limit is 10;
var integer: number is 0;
var integer: count is 0;
begin
writeln(comment);
write("Range(" <& start <& ", " <& stop <& ", " <& incr <& ") -> [ ");
block
for number range start to stop step incr do
write(number <& " ");
incr(count);
if count >= limit then
raise RANGE_ERROR;
end if;
end for;
exception
catch RANGE_ERROR: noop;
end block;
writeln("]");
writeln;
end func;
const proc: main is func
begin
testLoop(-2, 2, 1, "Normal");
testLoop(-2, 2, 0, "Zero increment");
testLoop(-2, 2, -1, "Increments away from stop value");
testLoop(-2, 2, 10, "First increment is beyond stop value");
testLoop( 2, -2, 1, "Start more than stop: positive increment");
testLoop( 2, 2, 1, "Start equal stop: positive increment");
testLoop( 2, 2, -1, "Start equal stop: negative increment");
testLoop( 2, 2, 0, "Start equal stop: zero increment");
testLoop( 0, 0, 0, "Start equal stop equal zero: zero increment");
end func;
- Output:
Normal Range(-2, 2, 1) -> [ -2 -1 0 1 2 ] Zero increment Range(-2, 2, 0) -> [ -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 ] Increments away from stop value Range(-2, 2, -1) -> [ -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 ] First increment is beyond stop value Range(-2, 2, 10) -> [ -2 ] Start more than stop: positive increment Range(2, -2, 1) -> [ ] Start equal stop: positive increment Range(2, 2, 1) -> [ 2 ] Start equal stop: negative increment Range(2, 2, -1) -> [ 2 1 0 -1 -2 -3 -4 -5 -6 -7 ] Start equal stop: zero increment Range(2, 2, 0) -> [ 2 2 2 2 2 2 2 2 2 2 ] Start equal stop equal zero: zero increment Range(0, 0, 0) -> [ 0 0 0 0 0 0 0 0 0 0 ]
Smalltalk
The basic loop is in the expression:
startExpr to:stopExpr by:incExpr do:[..]
The rest in the code is sugar for a nice output and a breakout if running endless.
MAX_ITER := 15.
#(
(-2 2 1 'Normal')
(-2 2 0 'Zero increment')
(-2 2 -1 'Increments away from stop value')
(-2 2 10 'First increment is beyond stop value')
(2 -2 1 'Start more than stop: positive increment')
(2 2 1 'Start equal stop: positive increment')
(2 2 -1 'Start equal stop: negative increment')
(2 2 0 'Start equal stop: zero increment')
(0 0 0 'Start equal stop equal zero: zero increment')
) do:[:testParams |
|start stop inc info countIter|
start := testParams first.
stop := testParams second.
inc := testParams third.
info := testParams fourth.
Transcript show:(info paddedTo:50 with:$.).
countIter := 0.
[:exit |
start to:stop by:inc do:[:n |
Transcript space; show:n.
(countIter := countIter + 1) > MAX_ITER ifTrue:[
Transcript show:'...'.
exit value
].
].
] valueWithExit.
Transcript cr.
].
- Output:
Normal............................................ -2 -1 0 1 2 Zero increment.................................... -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2... Increments away from stop value................... First increment is beyond stop value.............. -2 Start more than stop: positive increment.......... Start equal stop: positive increment.............. 2 Start equal stop: negative increment.............. 2 Start equal stop: zero increment.................. 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2... Start equal stop equal zero: zero increment....... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0...
Vala
static void example(int start, int stop, int increment, string comment) {
const int MAX_ITER = 9;
int iteration = 0;
stdout.printf("%-50s", comment);
for (int i = start; i <= stop; i += increment) {
stdout.printf("%3d ", i);
if (++iteration > MAX_ITER) break;
}
stdout.printf("\n");
}
void main () {
example(-2, 2, 1, "Normal");
example(-2, 2, 0, "Zero increment");
example(-2, 2, -1, "Increments away from stop value");
example(-2, 2, 10, "First increment is beyond stop value");
example(2, -2, 1, "Start more than stop: positive increment");
example(2, 2, 1, "Start equals stop: positive increment");
example(2, 2, -1, "Start equals stop: negative increment");
example(2, 2, 0, "Start equals stop: zero increment");
example(0, 0, 0, "Start equals stop equal zero: zero increment");
}
- Output:
Normal -2 -1 0 1 2 Zero increment -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 First increment is beyond stop value -2 Start more than stop: positive increment Start equals stop: positive increment 2 Start equals stop: negative increment 2 1 0 -1 -2 -3 -4 -5 -6 -7 Start equals stop: zero increment 2 2 2 2 2 2 2 2 2 2 Start equals stop equal zero: zero increment 0 0 0 0 0 0 0 0 0 0
VBA
Public Sub LoopsWrongRanges()
Call Example(-2, 2, 1, "Normal")
Call Example(-2, 2, 0, "Zero increment")
Call Example(-2, 2, -1, "Increments away from stop value")
Call Example(-2, 2, 10, "First increment is beyond stop value")
Call Example(2, -2, 1, "Start more than stop: positive increment")
Call Example(2, 2, 1, "Start equal stop: positive increment")
Call Example(2, 2, -1, "Start equal stop: negative increment")
Call Example(2, 2, 0, "Start equal stop: zero increment")
Call Example(0, 0, 0, "Start equal stop equal zero: zero increment")
End Sub
Private Sub Example(start As Integer, stop_ As Integer, by As Integer, comment As String)
Dim i As Integer
Dim c As Integer
Const limit = 10
c = 0
Debug.Print start; " "; stop_; " "; by; " | ";
For i = start To stop_ Step by
Debug.Print i & ",";
c = c + 1
If c > limit Then Exit For
Next i
Debug.Print
Debug.Print comment & vbCrLf
End Sub
- Output:
-2 2 1 | -2,-1,0,1,2,Normal
-2 2 0 | -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, Zero increment
-2 2 -1 | Increments away from stop value
-2 2 10 | -2, First increment is beyond stop value
2 -2 1 | Start more than stop: positive increment
2 2 1 | 2, Start equal stop: positive increment
2 2 -1 | 2, Start equal stop: negative increment
2 2 0 | 2,2,2,2,2,2,2,2,2,2,2, Start equal stop: zero increment
0 0 0 | 0,0,0,0,0,0,0,0,0,0,0,
Start equal stop equal zero: zero increment
V (Vlang)
Vlang has only one loop, a 'for' statement, which supports six different syntactical forms commonly found in other C-family languages:
1. A C-like 'for' loop with initialization, condition and increment sections (`for i := 0; i < 10; i += 2 {`).
2. The 'while' loop functionality (condition only) (`for i <= 100 {`)
3. Infinite loop, equivalent to for(;;) (all sections omitted) (`for {`)
4. Looping over a range of values (`for i in 0..5 {`).
5. Looping over map/array (`for key, value in m {` or `for idx, value in l {` or without idx `for value in l {`)
6. Custom iterators (see [docs](https://github.com/vlang/v/blob/master/doc/docs.md#custom-iterators))
It appears that either #5 fits the requirements of this task so I've translated a function which generates the appropriate sequence using #1 (limited to a maximum of 10 elements as some sequences will be infinite). I've then applied #5 to the resulting sequence. All sequences include the stop value if it's actually reached.
struct Seq {
start int
stop int
incr int
comment string
}
const examples = [
Seq{-2, 2, 1, "Normal"},
Seq{-2, 2, 0, "Zero increment"},
Seq{-2, 2, -1, "Increments away from stop value"},
Seq{-2, 2, 10, "First increment is beyond stop value"},
Seq{2, -2, 1, "Start more than stop: positive increment"},
Seq{2, 2, 1, "Start equal stop: positive increment"},
Seq{2, 2, -1, "Start equal stop: negative increment"},
Seq{2, 2, 0, "Start equal stop: zero increment"},
Seq{0, 0, 0, "Start equal stop equal zero: zero increment"},
]
fn sequence(s Seq, limit int) []int {
mut seq := []int{}
for i, c := s.start, 0; i <= s.stop && c < limit; i, c = i+s.incr, c+1 {
seq << i
}
return seq
}
fn main() {
limit := 10
for ex in examples {
println(ex.comment)
print("Range($ex.start, $ex.stop, $ex.incr) -> ")
println(sequence(ex, limit))
println('')
}
}
- Output:
Normal Range(-2, 2, 1) -> [-2, -1, 0, 1, 2] Zero increment Range(-2, 2, 0) -> [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2] Increments away from stop value Range(-2, 2, -1) -> [-2, -3, -4, -5, -6, -7, -8, -9, -10, -11] First increment is beyond stop value Range(-2, 2, 10) -> [-2] Start more than stop: positive increment Range(2, -2, 1) -> [] Start equal stop: positive increment Range(2, 2, 1) -> [2] Start equal stop: negative increment Range(2, 2, -1) -> [2, 1, 0, -1, -2, -3, -4, -5, -6, -7] Start equal stop: zero increment Range(2, 2, 0) -> [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] Start equal stop equal zero: zero increment Range(0, 0, 0) -> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Wren
import "./fmt" for Fmt
var loop = Fn.new { |start, stop, inc|
System.write("%(Fmt.v("dm", 3, [start, stop, inc], 0, " ", "[]")) -> ")
var count = 0
var limit = 10
var i = start
while (i <= stop) {
System.write("%(i) ")
count = count + 1
if (count == limit) break
i = i + inc
}
System.print()
}
var tests = [
[-2, 2, 1], [-2, 2, 0], [-2, 2, -1], [-2, 2, 10], [2, -2, 1], [2, 2, 1], [2, 2, -1], [2, 2, 0], [0, 0, 0]
]
for (test in tests) loop.call(test[0], test[1], test[2])
- Output:
[ -2 2 1] -> -2 -1 0 1 2 [ -2 2 0] -> -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 [ -2 2 -1] -> -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 [ -2 2 10] -> -2 [ 2 -2 1] -> [ 2 2 1] -> 2 [ 2 2 -1] -> 2 1 0 -1 -2 -3 -4 -5 -6 -7 [ 2 2 0] -> 2 2 2 2 2 2 2 2 2 2 [ 0 0 0] -> 0 0 0 0 0 0 0 0 0 0
XPL0
XPL0's 'for' statement only handles increments and decrements by one. However, a straightforward translation of the 'for' loop in the C example solves the task.
include xpllib; \for Print
def \S\ Start, Stop, Incr, Comment;
int S, Examples, I, J, C, Empty;
def Limit = 10;
[Examples:= [
[-2, 2, 1, "Normal"],
[-2, 2, 0, "Zero increment"],
[-2, 2, -1, "Increments away from stop value"],
[-2, 2, 10, "First increment is beyond stop value"],
[2, -2, 1, "Start more than stop: positive increment"],
[2, 2, 1, "Start equal stop: positive increment"],
[2, 2, -1, "Start equal stop: negative increment"],
[2, 2, 0, "Start equal stop: zero increment"],
[0, 0, 0, "Start equal stop equal zero: zero increment"]
];
for I:= 0 to 9-1 do
[S:= Examples(I);
Print("%s\n", S(Comment));
Print("Range(%d, %d, %d) -> [", S(Start), S(Stop), S(Incr));
Empty:= true;
\\ for (j:= s.start, c:= 0; j <= s.stop && c < limit; j += s.incr, ++c)
J:= S(Start); C:= 0;
while J <= S(Stop) and C < Limit do
[Print("%d ", J);
Empty:= false;
J:= J + S(Incr); C:= C+1;
];
if not Empty then ChOut(0, $08 \BS\);
Print("]\n\n");
]
]
- Output:
Normal Range(-2, 2, 1) -> [-2 -1 0 1 2] Zero increment Range(-2, 2, 0) -> [-2 -2 -2 -2 -2 -2 -2 -2 -2 -2] Increments away from stop value Range(-2, 2, -1) -> [-2 -3 -4 -5 -6 -7 -8 -9 -10 -11] First increment is beyond stop value Range(-2, 2, 10) -> [-2] Start more than stop: positive increment Range(2, -2, 1) -> [] Start equal stop: positive increment Range(2, 2, 1) -> [2] Start equal stop: negative increment Range(2, 2, -1) -> [2 1 0 -1 -2 -3 -4 -5 -6 -7] Start equal stop: zero increment Range(2, 2, 0) -> [2 2 2 2 2 2 2 2 2 2] Start equal stop equal zero: zero increment Range(0, 0, 0) -> [0 0 0 0 0 0 0 0 0 0]
Zig
const std = @import("std");
const stdout = @import("std").io.getStdOut().writer();
const limit = 10;
fn printRange(start: isize, stop: isize, step: isize, comment: []const u8) !void {
try stdout.print("{s}\r\x1b[43C: ", .{comment});
var c: u8 = 0;
var n = start;
while (n <= stop) : (n += step) {
c += 1;
if (c > limit) break;
try stdout.print("{d} ", .{n});
}
try stdout.print("\n", .{});
}
pub fn main() !void {
try printRange(-2, 2, 1, "Normal");
try printRange(-2, 2, 0, "Zero increment");
try printRange(-2, 2, -1, "Increments away from stop value");
try printRange(-2, 2, 10, "First increment is beyond stop value");
try printRange(2, -2, 1, "Start more than stop: positive increment");
try printRange(2, 2, 1, "Start equal stop: positive increment");
try printRange(2, 2, -1, "Start equal stop: negative increment");
try printRange(2, 2, 0, "Start equal stop: zero increment");
try printRange(0, 0, 0, "Start equal stop equal zero: zero increment");
}
- Output:
Normal : -2 -1 0 1 2 Zero increment : -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 Increments away from stop value : -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 First increment is beyond stop value : -2 Start more than stop: positive increment : Start equal stop: positive increment : 2 Start equal stop: negative increment : 2 1 0 -1 -2 -3 -4 -5 -6 -7 Start equal stop: zero increment : 2 2 2 2 2 2 2 2 2 2 Start equal stop equal zero: zero increment: 0 0 0 0 0 0 0 0 0 0
zkl
// zero increment (ie infnite loop) throws an error
// if stop is "*", the loop is has no end (ie infinite)
// stop is included unless step steps skips it
// if start > stop is a dead loop
// ranges ([a..b,c]) are lazy lists
fcn looper([(start,stop,increment)]){
print(" %3s %3s\t%2d --> ".fmt(start,stop,increment));
try{ foreach n in ([start..stop,increment]){ print(n," ") } }
catch{ print(__exception) }
println();
}
println("start stop increment");
T( T(-2,2,1),T(-2,2,0),T(-2,2,-1),T(-2,2,10),T( 2,-2,1),
T( 2,2,1),T( 2,2,-1),T( 2,2,0),T( 0,0,0),
T(0.0, (0.0).pi, 0.7853981633974483), T("a","e",1), T("e","a",1) )
.apply2(looper); // apply2 is apply (map) without saving results
- Output:
start stop increment -2 2 1 --> -2 -1 0 1 2 -2 2 0 --> ValueError(range: step == 0) -2 2 -1 --> -2 2 10 --> -2 2 -2 1 --> 2 2 1 --> 2 2 2 -1 --> 2 2 2 0 --> ValueError(range: step == 0) 0 0 0 --> ValueError(range: step == 0) 0 3.14159 0 --> 0 0.785398 1.5708 2.35619 3.14159 a e 1 --> a b c d e e a 1 -->
- Loop modifiers
- Programming Tasks
- Iteration
- 11l
- Ada
- ALGOL 68
- ALGOL W
- Arturo
- AWK
- BASIC
- Applesoft BASIC
- BASIC256
- Chipmunk Basic
- FreeBASIC
- GW-BASIC
- Minimal BASIC
- MSX Basic
- Quite BASIC
- Visual Basic .NET
- UBasic/4tH
- Yabasic
- C
- C sharp
- C++
- Common Lisp
- Delphi
- System.SysUtils
- Eiffel
- Factor
- Fermat
- Forth
- Go
- Haskell
- Huginn
- J
- Java
- Jq
- Julia
- Kotlin
- Langur
- Lua
- Maple
- Mathematica
- Wolfram Language
- Nim
- PascalABC.NET
- Perl
- Phix
- Phix/basics
- PL/I
- Python
- R
- Racket
- Raku
- REXX
- RPL
- Ruby
- Seed7
- Smalltalk
- Vala
- VBA
- V (Vlang)
- Wren
- Wren-fmt
- XPL0
- Zig
- Zkl