[REBOL] Re: Question and comment about randomizing a block of values
From: joel:neely:fedex at: 18-Jun-2001 17:44
Hi, Jos (and all),
Sorry to be replying to my own post, but another bit of explanation
might be in order...
Joel Neely wrote:
> random-iota: func [n [integer!] /local m f c r] [
> f: n + 1
> m: f * f
> c: 0
> r: make block! n
> loop n [append r (f * random m) + c: c + 1]
> ]
>
The reason why F needs to be N + 1 is that REBOL uses 1-origin
indexing instead of 0-origin indexing. Since our weird numbers
have to have remainders in the range 1..N we have to multiply
the high-order randomness by N + 1 to protect all of the indexes.
The reason why M is F * F is simply to give RANDOM more of a
chance to "spread" the high-order randomness out, reducing the
probability that we'll get duplicates in the H-O R.
HOWEVER...
Upon further reflection, I've decided that the coupling between
RANDOM-IOTA and SHUFFLED is just too ugly for words. Therefore,
I propose to atone for that ugliness that by offering the
slightly-less-ugly:
shuffled-iota: func [n [integer!] /local m f c r] [
m: n * n
c: -1
r: make block! n
loop n [append r (n * random m) + c: c + 1]
sort r
forall r [change r r/1 // n + 1]
head r
]
shuffled-block: func [b [block!] /local n i r] [
r: make block! n: length? b
i: shuffled-iota n
foreach n i [append r pick b n]
]
which push all the arithmetic nastiness into SHUFFLED-IOTA,
and still behave as follows:
>> test-data: iota 20
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
>> new-data: shuffled-block test-data
== [16 8 11 20 5 2 19 10 18 1 17 15 7 4 13 12 9 3 14 6]
>> sort copy new-data
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
Cleaner is better!
-jn-
___ ___ ___
\/ 2 + \/ 2 = 4 (for sufficiently large approximations of \/ 2 )
joel'dot'neely'at'fedex'dot'com