# cycling

### [1/3] from: joel:neely:fedex at: 5-Jul-2001 12:58

Given a set of M "index" values, what's the simplest way to
cycle through them, both forward and backward?
In the two commonest cases, the M values might occupy either
the range 0 thru M - 1 or the range 1 thru M.
Let N0F, N0B, N1F, and N1B hold the current counters for all
combinations of ranges and directions.
------ range of ------
direction 0 .. m - 1 1 .. m
--------- ---------- --------
forward n0f n1f
backward n0b n1b
The simplest possibilities I've found for putting these
variables through their paces are:
Pure Arithmetic:
n0f: (n0f + 1) // m
n0b: (n0b + m - 1) // m
n1f: (n1f // m) + 1
n1b: (n1b + m - 2) // m + 1
Expressional:
n0f: either m - 1 = n0f [0] [n0f + 1]
n0b: either 0 = n0b [m - 1] [n0b - 1]
n1f: either m = n1f [1] [n1f + 1]
n1b: either 1 = n1b [m] [n1b - 1]
Imperative:
n0f: n0f + 1 if n0f = m [n0f: 0]
if n0b = 0 [n0b: m] n0b: n0b - 1
n1f: n1f + 1 if n1f > m [n1f: 1]
n1b: n1b - 1 if n1b = 0 [n1b: m]
For example, using the pure arithmetic version:

>> n0f: n0b: n1f: n1b: 1

== 1

>> m: 5

== 5

>> loop 15 [

[ print [n0f n0b n1f n1b]
[ set [n0f n0b n1f n1b] reduce [
[ (n0f + 1) // m (n0b + m - 1) // m
[ (n1f // m) + 1 (n1b + m - 2) // m + 1
[ ]
[ ]
1 1 1 1
2 0 2 5
3 4 3 4
4 3 4 3
0 2 5 2
1 1 1 1
2 0 2 5
3 4 3 4
4 3 4 3
0 2 5 2
1 1 1 1
2 0 2 5
3 4 3 4
4 3 4 3
0 2 5 2
= [1 1 1 1]
A comparison of these options, along with relative timings
based on a 3,000,000 cycle benchmark, includes the following
observations:
Option Time Pro Con
--------------- ---- ---------------- ------------------
Pure Arithmetic 1.00 * Fastest * Least obvious to
* Most compact casual reader
Expressional 1.31 * Most obvious * Slowest
Imperative 1.15 * Somewhat obvious * Can't be used as
subexpressions
Other observations or alternative calculations are welcomed.
-jn-
--
------------------------------------------------------------
Programming languages: compact, powerful, simple ...
Pick any two!
joel'dot'neely'at'fedex'dot'com

### [2/3] from: jeff::rebol::net at: 6-Jul-2001 6:12

> Given a set of M "index" values, what's the simplest way to
> cycle through them, both forward and backward?

A set of M 'index' values
-- you mean a block?
b: copy [1 2 3 ... m]
;-- or b: copy [0 1 2 3 ... (m - 1)]
forever [
forall b [print index? b]
until [print index? b head? b: back b]
]
-jeff

### [3/3] from: joel:neely:fedex at: 6-Jul-2001 13:33

Jeff Kreis wrote:

> > Given a set of M "index" values, what's the simplest way to
> > cycle through them, both forward and backward?
>
> "A set of M 'index' values" -- you mean a block?
>

No, I was referring to manipulating the value of a counter.
Given a variable set to an integer within a restricted range of M
values (either 0 .. M-1 or 1 .. M), what is the simplest way to
step that variable to the next or previous value within the range,
with "wrap-around" at either end of the range.
If the range is 0 .. 4, then successive steps forward from 3 would
produce 4, 0, 1, 2, 3, 4, 0, 1, 2, ...
If the range is 1 .. 5, then successive steps backward from 3 would
produce 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, ...
Hope that's clearer.
-jn-
___________________________________________________________________
The purpose of computing is insight, not numbers!
- R. W. Hamming
joel'dot'neely'at'fedex'dot'com