[REBOL] creation of a block with a lot of integers Re:(3)
From: joel:neely:fedex at: 6-Oct-2000 14:36
Thanks for the numbers!
[peoyli--algonet--se] wrote:
> > Hi, peoyli,
> >
> ...
> >
> > It would be interesting to have you try a couple of the above options
> > along with your original for version and post the timings, if you
> > have the spare time.
> >
> > -jn-
>
> Ok,,
>
> here comes my test results, along with the code being tested..
>
> Method 0: 1st try: unallocated block, for-loop, insert
> Method 1: 2nd try: allocated block, for-loop, insert tail
> Method 2: 3rd try: allocated block, modified iota to accept a minimum value (repeat-loop)
> Method 3: 4th try: allocated block, map iota... (repeat-loop)
> Method 4: 5th try: allocated block, filter iota / range...
> Method 5: 6th try: allocated block, fromto function... (while-loop)
>
> Summary:
> Method 0 is slow (only timed with 5000 values)
> Method 2 is twice as fast as method 1 (repeat vs. for)
> Method 3 always gave incorrect result or failed otherwise (and was also twice as slow
as method 1)
> Method 4 did not work with negative values, and was about as slow as method 3
> Method 5 is almost as fast as method 2
>
> Method 2 (3rd try) & Method 5 (6th try) are those who produce the
> desired result, and is most efficient.
>
Method 3 is buggy as written:
; 4th try: allocated block, map iota...
3 [
tim1: now/time
b: map iota (max - min + 1) func [n] [if n >= min [n]]
print [now/time - tim1 " 4th try: allocated block, map iota..."]
]
Taking as an example MIN=2000 and MAX=5000, the expression
iota (max - min + 1)
evaluates to
[1 2 3 4 5 ... 2999 3000 3001]
The function
func [n] [if n>= min [n]]
applied by MAP essentially says "discard everything below 2000".
The result is that you should get
[2000 2001 2002 2003 ... 2998 2999 3000 3001]
as the result, which isn't the range MIN thru MAX.
To use a combination of MAP and IOTA to create the range MIN thru MAX,
you'll need to do one of the following:
1) Create the full range of values (1 thru MAX), then discard all values
outside the desired range (below MIN). I gave this as an example in
my earlier post, using something like:
map iota max func [n] [if n >= min [n]]
2) Create the correct number of values (1 thru something), then adjust
all values in the created block up/down to the desired range. This
would look something like this:
map iota (max - min + 1) func [n] [n + min - 1]
(The IOTA (MAX - MIN + 1) gets you [1 ... 3001], then the MAP adds
1999 to each of those values, leaving you with [2000 ... 5000].)
If you mix these two techniques, they don't play well together.
It's also no surprise that this will be slower than the custom-made
versions, as it is creating the block of numbers and then revisiting
all of them a second time. Classic tradeoff #27: speed vs. generality!
-jn-
--
; Joel Neely [joel--neely--fedex--com] 901-263-4460 38017/HKA/9677
REBOL [] print to-string debase decompress #{
789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC
B6F4F574CFC888342AC949CE74B50500E1710C0C24000000}