cyclic values
[1/11] from: rebol665::ifrance::com at: 29-Sep-2002 10:50
Hi List,
I want to get values in order from a block, the first value coming again
after the last, and this forever. Is there a better way than the one I am
using now ?
colors: [red green blue]
; I want color to be red, then green, then blue, then red again forever
; the first value is duplicated
color: first colors
append colors color
; then forever
color: select colors color
Patrick
[2/11] from: anton:lexicon at: 29-Sep-2002 19:55
That's a bit unclear what you want.
What do you want it for?
If you have an increasing number n,
then you can do this:
colors: [red green blue]
n: 1
loop 200 [
color: pick colors either n > length? colors [n][1]
n: n + 1
]
Anton.
[3/11] from: carl:cybercraft at: 29-Sep-2002 23:38
On 29-Sep-02, pat665 wrote:
> Hi List,
> I want to get values in order from a block, the first value coming
> again after the last, and this forever. Is there a better way than
> the one I am using now ?
There may be, but it's pretty nice as it is. That said, if the colors
block was very long it might give variable performance between
finding color near the beginning and near the end of the block.
> colors: [red green blue]
> ; I want color to be red, then green, then blue, then red again
<<quoted lines omitted: 3>>
> ; then forever
> color: select colors color
--
Carl Read
[4/11] from: gscottjones:mchsi at: 29-Sep-2002 7:09
From: "Patrick"
> I want to get values in order from a block, the first value
> coming again after the last, and this forever. Is there a
<<quoted lines omitted: 6>>
> ; then forever
> color: select colors color
Hi, Patrick,
This is just a slight variation:
colors: [red green blue]
color: first colors
loop 100 [
if not color: select colors color [color: first colors]
print color
]
Of course, 'forever is substituted in place of 'loop.
--Scott Jones
[5/11] from: ingo:2b1 at: 29-Sep-2002 15:18
Hi Patrick,
Am Son, 2002-09-29 um 10.50 schrieb pat665:
<...>
> colors: [red green blue]
> ; I want color to be red, then green, then blue, then red again forever
<<quoted lines omitted: 3>>
> ; then forever
> color: select colors color
That looks like a pretty clever use of select to me. My ideas would have
been:
for i 1 10 1 [
print colors/1
colors: next colors
if tail? colors [colors: head colors]
]
or
i: 1
for j 1 10 1 [
print pick colors i
i: i // (length? colors) + 1
]
But I like your version much more.
Kind regards,
Ingo
[6/11] from: joel:neely:fedex at: 29-Sep-2002 7:52
Hi, Pat,
Ingeneous!!!
(...of course, with me, there's always a "but"... ;-)
pat665 wrote:
> I want to get values in order from a block, the first value
> coming again after the last, and this forever. Is there a
<<quoted lines omitted: 7>>
> ; then forever
> color: select colors color
That's a nice compact way to accomplish your stated result,
but under two constraints:
1) the number of values in the block is very small, and
2) the values are all distinct.
SMALL NUMBER OF VALUES
----------------------
Given REBOL 1-origin indexing, the fastest/simplest way I've
found for cycling an integer counter through the range of
values 1..N is
cnt: 0 ;; initialization
cnt: cnt // N + 1
which means we could get your "forever" case above by using
color: pick colors cnt: cnt // + 1
The alternative to using the modulus operator is explicit
logic, as in
color: pick colors counter:
either counter < length? colors [counter + 1] [1]
but that is very sub-optimal...
In any case, the time complexity of modifying the integer
index is O(1) -- constant -- while the time complexity of
SELECT on an ordinary block is O(N) -- linear on the size
of the block. A little quick benchmarking shows that this
adds up very quickly. On my old slow benchmarking box
(200 MHz Pentium, w95) the timings are (in microseconds)
SELECT modulus EITHER...
3 elements 13.94 14.28 18.73
10 elements 16.76 14.72 19.33
(As you can see from the second column, there's still some
statistical variability...)
The above times were taken using function evaluations, so
after removing that overhead, we get the following ratios:
SELECT EITHER...
vs vs
modulus modulus
3 elements 0.97 1.41
10 elements 1.18 1.41
With only three elements, the SELECT approach saves 3% over
the modulus approach, but the EITHER strategy costs 41% extra.
But with ten elements, SELECT is now 18% slower than modulus,
while EITHER is still 41% slower.
CONCLUSION: The SELECT strategy doesn't scale well.
DISTINCT VALUES
---------------
Suppose you wanted to simulate a monitor which was cycling between
the primary colors (e.g. using your original COLORS data), but went
off in between each color (e.g. interspersed black displays). If
we change our block to contain:
colors: [red black green black blue black]
color: first colors
and then try
color: select colors color
We'll find that we're stuck in a green/black cycle, since the first
occurrence of black is always the one that's found by SELECT.
CONCLUSION: The SELECT strategy doesn't handle cases with values
that occur more than once in the block.
HOWEVER... With all of the above said, for small blocks with
distinct values, your approach is quite elegant. Thanks for
posting it!
-jn-
--
; Joel Neely joeldotneelyatfedexdotcom
REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip
do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] {
| e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]
[7/11] from: rebol665:ifrance at: 29-Sep-2002 18:14
Hi Joel
Amazing! When will you write a full book about Rebol ?
Great post! Thanks
Patrick
[8/11] from: tomc:darkwing:uoregon at: 29-Sep-2002 11:22
Hi Pat,
>> colors: [red green blue]
== [red green blue]
>> forever [append colors colors]
== [red green blue red green blue]
== [red green blue red green blue red green blue red green blue]
...
will get you to forever quickly ;)
On Sun, 29 Sep 2002, pat665 wrote:
[9/11] from: carl:cybercraft at: 30-Sep-2002 9:01
On 30-Sep-02, Tom Conlin wrote:
> Hi Pat,
>>> colors: [red green blue]
<<quoted lines omitted: 4>>
> ...
> will get you to forever quickly ;)
Indeed. But it suggests a way I haven't seen posted...
>> colors: [red green blue]
== [red green blue]
>> forever [print color: colors/1 remove append colors color]
red
green
blue
red
green
blue
red
green
blue
red
green
blue
red
green
blue
red
(escape)
Has the advantage of no extra words being needed. The disadvantages
being the contents of the colors block is cycling, (might or might
not matter), and it may be slower than Joel's best effort. It should
have a consistant speed though. Comments Joel?
--
Carl Read
[10/11] from: tomc:darkwing:uoregon at: 29-Sep-2002 15:17
hmmm! alonge the same line
how about a _pseudo_ monty carlo method
>> forever[random/seed 13 print pick colors: random colors 1]
red
green
blue
red
green
blue
red
green
blue
red
green
blue
red
green
blue
red
(escape)
On Mon, 30 Sep 2002, Carl Read wrote:
[11/11] from: joel:neely:fedex at: 29-Sep-2002 21:26
Hi, Carl
Carl Read wrote:
> > ...
> Indeed. But it suggests a way I haven't seen posted...
<<quoted lines omitted: 22>>
> cycling, (might or might not matter), and it may be slower...
> It should have a consistant speed though. Comments Joel?
Don't try this at home kids! ;-)
Cycling the values within the block does matter; there's much
more memory management overhead. Using the same benchmarks as
in the earlier comparison, the block-cycling version takes 4
to 5 times as long as the modulus approach for 3-10 elements.
In addition the
overhead grows with the length of the block being cycled:
bruteforce: func [n [integer!] c [integer!] /local t b v] [
b: make block! n
repeat i n [insert tail b i]
t: now/time/precise
loop c [ remove append b v: b/1 ]
t: to-decimal now/time/precise - t
]
behaves as:
>> for i 10 200 10 [print [i bruteforce i 500000]]
10 24.99
20 22.91
30 29.49
40 25.27
50 23.45
60 27.19
70 25.76
80 29.22
90 25.98
100 29.6
110 26.75
120 30.05
130 27.24
140 28.89
150 29.83
160 30.71
170 30.97
180 31.2
190 33.18
200 32.9
The raggedness likely indicates intermittent gc operations; the
trend is definitely upward as the block length grows.
-jn-
--
; Joel Neely joeldotneelyatfedexdotcom
REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip
do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] {
| e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted