Loops/Wrong ranges
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 than 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
Perl 6
It would be odd to call ANY of these sequences "wrong" in Perl 6. Perl 6 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.
Perl 6 sequence definitions specifically allow "ending points" that may never occur in the sequence. 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). 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 Perl 6.
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 the that is not a limitation of the sequence operator.
<lang perl6># 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, 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 1, 2, 0, # Increment will never reach endpoint 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].defined ?? $seq[^15].grep: +*.so !! $seq
}</lang>
- 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: 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: 1, Stop: 2, Increment: 0 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 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
Python
Python has the range function. <lang python>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})') error, values = None, None try: values = list(islice(range(start, stop, increment), 999)) except ValueError as e: error = e print(' !!ERROR!!', e) if values is not None: if len(values) < 22: print(' =', values) else: print(' =', str(values[:22])[:-1], '...')
</lang>
- 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
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. <lang rexx>/*REXX program demonstrates several versions of DO loops with "unusual" interations. */ @.=; @.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. */</lang>
- 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───────────