1. sleepless night & UFOs

Sorry, Guys,

I know I should not even be here, I am supposed to be chasing
international driving licences or packing, but I hope somebody will
help me get over a nasty mental block. I need a fast function to
change an arbitrary element of a sequence:

    s = remap( s, { i1, i2, ...., iN }, newvalue)

In other words:

    s[i1][i2]...[iN] = newvalue

where s is a nested sequence of an arbitrary depth, and i1, ..., iN
are indexes of the element to be assigned the newvalue. I think it is
possible, in fact I think I once devised a recursive formula to do
exactly that for a version of my menus, but I just cannot find it. So,
please, I already had one sleepless night!


[Side note to Robert]
Since we already have a 'nan' (not-a-number) quantity, can we have a
similar, possibly even more useful 'thing' for general objects?
Something like 'null', or 'NULL' or 'Null' in some hated environments,
or 'None' in Python. 'nao' would be ok with me, but my personal
preference is for 'ufo' (undefined-f...-object).

Just one other thing: Ralf, your 'each' construct is an excellent
idea. I also think, given plenty of time, even Gabriel will eventually
like it. (Sorry, Gabriel, *any* sign of conservatism brings out the
worst in me!) jiri

new topic     » topic index » view message » categorize

2. Re: sleepless night & UFOs

Jiri Babor wrote:

>Sorry, Guys,
>
>I know I should not even be here, I am supposed to be chasing
>international driving licences or packing, but I hope somebody will
>help me get over a nasty mental block. I need a fast function to
>change an arbitrary element of a sequence:
>
>    s = remap( s, { i1, i2, ...., iN }, newvalue)
>
>In other words:
>
>    s[i1][i2]...[iN] = newvalue
>
>where s is a nested sequence of an arbitrary depth, and i1, ..., iN
>are indexes of the element to be assigned the newvalue. I think it is
>possible, in fact I think I once devised a recursive formula to do
>exactly that for a version of my menus, but I just cannot find it. So,
>please, I already had one sleepless night!

This should work:

sequence list
object val

function remap_recursive(sequence s)
integer i
   i = list[1]
   list = list[2..length(list)]
   if length(list) then
      s[i] = remap_recursive(s[i])
   else
      s[i] = val
   end if
   return s
end function

global function remap(sequence s, sequence index_list, object newvalue)
   list = index_list
   val = newvalue
   return remap_recursive(s)
end function


>Just one other thing: Ralf, your 'each' construct is an excellent
>idea. I also think, given plenty of time, even Gabriel will eventually
>like it. (Sorry, Gabriel, *any* sign of conservatism brings out the
>worst in me!) jiri

And all this time, I thought we were getting to see your *good* side! :)


Be seeing you,
   Gabriel Boehme


 ------
Money is not a problem, only a difficulty.

Robert Fripp
 ------

new topic     » goto parent     » topic index » view message » categorize

3. Re: sleepless night & UFOs

Thanks, Gabriel! I was so close so many times, I suppose
I just had too many sleepless nights lately... jiri

new topic     » goto parent     » topic index » view message » categorize

4. Re: sleepless night & UFOs

Hello Jiri;

Is this what you are looking for?
function remap(sequence s, sequence in, atom value)
  return (s * 0) + value
end function

        Happily, Lucius L. Hilley III
        http://www.cdc.net/~lhilley
        A happy member of the webring
        ICQ# 9638898
        AIM Screen Name: LLH III

On Tue, 20 Apr 1999 10:32:40 +1200, Jiri Babor <J.Babor at GNS.CRI.NZ> wrote:

>Sorry, Guys,
>
>I know I should not even be here, I am supposed to be chasing
>international driving licences or packing, but I hope somebody will
>help me get over a nasty mental block. I need a fast function to
>change an arbitrary element of a sequence:
>
>    s = remap( s, { i1, i2, ...., iN }, newvalue)
>
>In other words:
>
>    s[i1][i2]...[iN] = newvalue
>
>where s is a nested sequence of an arbitrary depth, and i1, ..., iN
>are indexes of the element to be assigned the newvalue. I think it is
>possible, in fact I think I once devised a recursive formula to do
>exactly that for a version of my menus, but I just cannot find it. So,
>please, I already had one sleepless night!
>
>
>[Side note to Robert]
>Since we already have a 'nan' (not-a-number) quantity, can we have a
>similar, possibly even more useful 'thing' for general objects?
>Something like 'null', or 'NULL' or 'Null' in some hated environments,
>or 'None' in Python. 'nao' would be ok with me, but my personal
>preference is for 'ufo' (undefined-f...-object).
>
>Just one other thing: Ralf, your 'each' construct is an excellent
>idea. I also think, given plenty of time, even Gabriel will eventually
>like it. (Sorry, Gabriel, *any* sign of conservatism brings out the
>worst in me!) jiri

new topic     » goto parent     » topic index » view message » categorize

5. Re: sleepless night & UFOs

Not really, Lucius, I do not want to remap every element
of a sequence to the same atom value. Gabriel has already
given me what I wanted. But thanks anyway, much appreciated.

jiri

new topic     » goto parent     » topic index » view message » categorize

6. Re: sleepless night & UFOs

Jiri,

Assuming that indexList isn't empty and is valid for the contents of s, the
following should work:

function remap (sequence s, sequence indexList, newValue)

    integer listLen, i1

    listLen = length (indexList)
    i1 = indexList [1]

    if listLen > 1 then
        s [i1] = remap (s [i1], indexList [2..listLen], newValue)
    elsif listLen = 1 then
        s [i1] = newValue
    end if

    return s

end function

Have a safe trip...
Joe

-----Original Message-----
From:   Jiri Babor [SMTP:J.Babor at GNS.CRI.NZ]
Sent:   Monday, April 19, 1999 5:33 PM
To:     EUPHORIA at LISTSERV.MUOHIO.EDU
Subject:        sleepless night & UFOs

Sorry, Guys,

I know I should not even be here, I am supposed to be chasing
international driving licences or packing, but I hope somebody will
help me get over a nasty mental block. I need a fast function to
change an arbitrary element of a sequence:

    s = remap( s, { i1, i2, ...., iN }, newvalue)

In other words:

    s[i1][i2]...[iN] = newvalue

where s is a nested sequence of an arbitrary depth, and i1, ..., iN
are indexes of the element to be assigned the newvalue. I think it is
possible, in fact I think I once devised a recursive formula to do
exactly that for a version of my menus, but I just cannot find it. So,
please, I already had one sleepless night!


[Side note to Robert]
Since we already have a 'nan' (not-a-number) quantity, can we have a
similar, possibly even more useful 'thing' for general objects?
Something like 'null', or 'NULL' or 'Null' in some hated environments,
or 'None' in Python. 'nao' would be ok with me, but my personal
preference is for 'ufo' (undefined-f...-object).

Just one other thing: Ralf, your 'each' construct is an excellent
idea. I also think, given plenty of time, even Gabriel will eventually
like it. (Sorry, Gabriel, *any* sign of conservatism brings out the
worst in me!) jiri
________________________________________________________
NetZero - We believe in a FREE Internet.  Shouldn't you?
Get your FREE Internet Access and Email at
http://www.netzero.net/download.html

new topic     » goto parent     » topic index » view message » categorize

7. Re: sleepless night & UFOs

Hi Joe,

I just made a quick speed comparison of your routine and that of
Gabriel. Since they are functionally identical and yours saves a
function call as well as a couple of local variable assignments, I
expected it to be a little faster. Not so! In fact they are almost the
same, if anything, Gabriel's routine seems to be consistently about
0.5 to 1.0 % faster in my limited tests. Thank you very much. jiri


----- Original Message -----
From: Joe Otto <jotto at NETZERO.NET>
To: <EUPHORIA at LISTSERV.MUOHIO.EDU>
Sent: Tuesday, April 20, 1999 2:33 PM
Subject: Re: sleepless night & UFOs


> Jiri,
>
> Assuming that indexList isn't empty and is valid for the contents of s,
the following should work:
>
> function remap (sequence s, sequence indexList, newValue)
>
>     integer listLen, i1
>
>     listLen = length (indexList)
>     i1 = indexList [1]
>
>     if listLen > 1 then
>         s [i1] = remap (s [i1], indexList [2..listLen], newValue)
>     elsif listLen = 1 then
>         s [i1] = newValue
>     end if
>
>     return s
>
> end function
>
> Have a safe trip...
> Joe

new topic     » goto parent     » topic index » view message » categorize

8. Re: sleepless night & UFOs

Jiri,

I have managed to shave a few percentage points from my remap routine,
thanks to an idea I picked up from Joe Otto's routine. I also renamed my
local variables to help avoid name conflicts within large programs.


sequence remap_list
object remap_value

function remap_recursive(sequence s)
integer i, len
   i = remap_list[1]
   len = length(remap_list)
   if len > 1 then
      remap_list = remap_list[2..len]
      s[i] = remap_recursive(s[i])
   else
      s[i] = remap_value
   end if
   return s
end function

function remap(sequence s, sequence index_list, object new_value)
   remap_list = index_list
   remap_value = new_value
   return remap_recursive(s)
end function


From my tests, this is about 5% faster than my original routine.


BTW, am I understanding the concept of % faster correctly? Is it calculated
like this?

routine1_percent_faster = ((routine1_time / routine2_time) - 1) * 100



Pleasant dreams,
   Gabriel Boehme



 ----------
From: jiri babor
To: EUPHORIA; GBOEHME
Subject: Re: sleepless night & UFOs
Date: Tuesday, April 20, 1999 8:35AM

Hi Joe,

I just made a quick speed comparison of your routine and that of
Gabriel. Since they are functionally identical and yours saves a
function call as well as a couple of local variable assignments, I
expected it to be a little faster. Not so! In fact they are almost the
same, if anything, Gabriel's routine seems to be consistently about
0.5 to 1.0 % faster in my limited tests. Thank you very much. jiri

new topic     » goto parent     » topic index » view message » categorize

9. Re: sleepless night & UFOs

Jiri,

I don't see how a complex function like Gabriel's can possibly be faster
than a straight-forward approach such as:

function remap(sequence s, sequence index, object newvalue)
    if length(index) > 1 then
        s[index[1]] =3D remap(s[index[1]], index[2..length(index)], newva=
lue)
    else
        s[index[1]] =3D newvalue
    end if
    return s
end function  -- remap

Are you sure you are timing it right?  Sometimes the first function in a
comparison takes longer - due to Causway memory allocation time?  I don't=

know the reason.

Vaya con dinero, Colin

new topic     » goto parent     » topic index » view message » categorize

10. Re: sleepless night & UFOs

Message text written by Me:
>I don't see how a complex function like Gabriel's can possibly be faster=

than a straight-forward approach...<

Okay, okay, Gabriel's *is* faster.  The speed seems to come mostly from
passing less variables to the recursive function.  Next time I'll load my=

gun before shooting...

Colin

new topic     » goto parent     » topic index » view message » categorize

11. Re: sleepless night & UFOs

Colin Taylor wrote:

>I don't see how a complex function like Gabriel's can possibly be faster
>than a straight-forward approach such as:
>
>function remap(sequence s, sequence index, object newvalue)
>    if length(index) > 1 then
>        s[index[1]] = remap(s[index[1]], index[2..length(index)], newvalue)
>    else
>        s[index[1]] = newvalue
>    end if
>    return s
>end function  -- remap

In my tests, both my original and modified routines are almost always faster
than Joe Otto's routine. Colin's routine (shown above) is almost always
*slower* than Joe's. There are several good reasons why my two "complex"
routines are generally faster than either Joe's or Colin's. Code efficiency
doesn't always result from code simplicity; there are other factors which
come into play.


1) Calling length() multiple times vs. storing it once in a variable

If you're going to use a sequence's length value more than once in a given
section of code (and the sequence's length isn't changing), it's almost
always faster to define another integer variable, store the length() value
there, and then reference the variable instead. This is one reason why
Colin's routine is slower than Joe's, and this is the main change I made to
my original routine to gain 5+% in execution speed.


2) Subscripting a sequence vs. storing the value in a variable

If you're going to access a given sequence element more than once in a given
section of code (and the sequence element isn't changing), it's almost
always faster to define another variable, store the sequence element there,
and then reference the variable instead. This is another reason why Colin's
routine is slower than Joe's -- Colin's routine references "index[1]" twice
in the recursive call, while Joe's routine stores "index[1]" in a variable
and uses that instead.


3) Recursive calls: parameter passing vs. local variables

When writing recursive functions, there is usually only one parm actually
being treated recursively -- the others are just along for the ride. This is
quite true with remap() -- newvalue only actually gets used on the final
recursive call, the rest of the time it just takes up space. Instead of
requiring the interpreter to continually reallocate space for a variable
that will only be used once, it makes more sense just to store it in a local
variable until you actually need it. This is also true for the index_list --
instead of passing index_list[2..length(index_list)] along as a parm, it's
much faster to store the list in a local variable and grab the first
element. Then, *only* if you have another recursive call coming up, you
truncate index_list to index_list[2..len] before making the call.


4) The test data

This is an often-overlooked part of any benchmarking procedure. The data
being used to test your routines can have a *major* impact on your results.
Whatever routines you're testing, it's a good idea to vary the test data.
Look closely at your code, and choose data that will test very specific
parts of the routines (if conditions, recursive calls, etc.). Also, keep in
mind the most likely real-world uses of your routines, to avoid testing
unnecessary or unlikely situations.

In my remap() tests, I found that my routines always run faster with an
index_list length of 3 or more. Joe's routine runs faster with an index_list
length of 2, and Colin's runs the fastest with an index_list length of 1.
The longer index_list is, the more recursive calls the routine has to make,
and the more points 1-3 above come into play.

Now, it's unlikely that a programmer will use remap() very often on length-1
index_lists -- it may occur incidentally as part of an algorithm, but it's
not likely to be the primary use of remap(). So, if you'll primarily be
using length-2 index_lists in your program, Joe's routine will be faster. If
you'll primarily be using length-3 or greater index_lists in your program,
then my modified routine is the faster. My assumption (which may be wrong)
is that general use of remap() would regularly involve length-3 or longer
index_lists. I therefore conclude that my modified routine is probably the
best choice for general-purpose use.


No matter what coding tips or suggestions you follow, it's *always* a good
idea to run some benchmarks and check things out for yourself. I have
included my remap benchmark program below. It's not too flashy, but it gets
the job done. (I don't trust call_func() anymore, since the exact *same*
code will come back with *different* execution times, depending on the
code's physical location in the program!)

I hope all of this has been helpful and/or educational (and I hope I got all
my facts right!).


Be seeing you,
   Gabriel Boehme


 -----------------------------------------------------------------
 -- remap.exw by Gabriel Boehme
 --
 -- This benchmark program will run under Windows or DOS.
 --
 -- However, Windows tickcounts are more reliable, since they
 -- only count the time the program is actually executing.
 -- (Somebody correct me if this statement is inaccurate!)
 -----------------------------------------------------------------

include get.e
include machine.e -- for running under DOS
tick_rate(10000)  -- does nothing under Windows

 -- execution parms
constant
 ITER = 1e6     -- benchmark iterations
                -- test sequence depth determined by LEVELS length
,LEVELS = {5,10,3} -- length of each level in the test sequence
,LIST = {3,5,2} -- *must* all be integers >= 1 and <= LEVELS[x]


 -----------------------------------------------------------------

 -- Gabriel Boehme's original routine
sequence list
object val

function remap_recursive_old(sequence s)
integer i
   i = list[1]
   list = list[2..length(list)]
   if length(list) then
      s[i] = remap_recursive_old(s[i])
   else
      s[i] = val
   end if
   return s
end function

function remap1(sequence s, sequence index_list, object newvalue)
   list = index_list
   val = newvalue
   return remap_recursive_old(s)
end function
 -----------------------------------------------------------------

 -- Joe Otto's routine
function remap2 (sequence s, sequence indexList, object newValue)
    integer listLen, i1

    listLen = length (indexList)
    i1 = indexList [1]

    if listLen > 1 then
        s [i1] = remap2 (s [i1], indexList [2..listLen], newValue)
    elsif listLen = 1 then
        s [i1] = newValue
    end if

    return s
end function
 -----------------------------------------------------------------

 -- Gabriel Boehme's modified routine
sequence remap_list
object remap_value

function remap_recursive(sequence s)
integer i, len
   i = remap_list[1]
   len = length(remap_list)
   if len > 1 then
      remap_list = remap_list[2..len]
      s[i] = remap_recursive(s[i])
   else
      s[i] = remap_value
   end if
   return s
end function

function remap3(sequence s, sequence index_list, object new_value)
   remap_list = index_list
   remap_value = new_value
   return remap_recursive(s)
end function
 -----------------------------------------------------------------

 -- Colin Taylor's routine
function remap4(sequence s, sequence index, object newvalue)
    if length(index) > 1 then
        s[index[1]] = remap4(s[index[1]], index[2..length(index)], newvalue)
    else
        s[index[1]] = newvalue
    end if
    return s
end function  -- remap
 -----------------------------------------------------------------


procedure msg_wait(sequence msg)
   puts(2, msg & "\n\nPress any key to continue . . .")
   if wait_key() then end if
   puts(2, "\n")
end procedure

 -- verify execution parms
if length(LIST) = 0 or length(LIST) > length(LEVELS) then
   msg_wait("Invalid LIST sequence length")
   abort(1)
end if

for i = 1 to length(LIST) do
   if not integer(LIST[i]) or LIST[i] < 1 or LIST[i] > LEVELS[i] then
      msg_wait("Invalid LIST sequence - index values out of bounds")
      abort(1)
   end if
end for

 -- build the test sequence
sequence s
s = repeat(0, LEVELS[length(LEVELS)])  -- start with the innermost level
for i = length(LEVELS)-1 to 1 by -1 do -- and work your way outward
   s = repeat(s, LEVELS[i])
end for

printf(1, "A remap() benchmark program by Gabriel Boehme\n"
        & "Sequence depth %d, remap depth %d\n\n",
          {length(LEVELS), length(LIST)})

puts(1, "[Smaller values are better]\n---------------------------\n")

 -----------------------------------------------------------------
atom t

 -- the moment of truth
puts(1, "Gabriel's original routine: ")
t = time()
for i = 1 to ITER do
   s = remap1(s, LIST, 1)
end for
? time() - t

puts(1, "Joe's routine:              ")
t = time()
for i = 1 to ITER do
   s = remap2(s, LIST, 1)
end for
? time() - t

puts(1, "Gabriel's modified routine: ")
t = time()
for i = 1 to ITER do
   s = remap3(s, LIST, 1)
end for
? time() - t

puts(1, "Colin's routine:            ")
t = time()
for i = 1 to ITER do
   s = remap4(s, LIST, 1)
end for
? time() - t


msg_wait("")
 -----------------------------------------------------------------

new topic     » goto parent     » topic index » view message » categorize

12. Re: sleepless night & UFOs

Gabriel,

Thanks for the code revision. jiri

new topic     » goto parent     » topic index » view message » categorize

13. Re: sleepless night & UFOs

I concur, Gabriel.  Your routine looks like it would execute faster than
mine for more than a couple of recursions.  I knew that passing the extra
variables would make it slower (although I didn't know by how much).  I
think my routine is slightly more readable than yours, but for long
sequences, yours would be much faster than mine.

IMHO, unless speed is critical, I think it's best to opt for readability.
 If it executes too slowly, you can always optimize it.

Anyway, sorry if I wasted your time.  I've never written a program in
Euphoria.  I just saw an opportunity to try to help someone, so I wrote my
posting off the top of my head without testing it...

Joe

-----Original Message-----
From:   Boehme, Gabriel [SMTP:gboehme at MUSICLAND.COM]
Sent:   Tuesday, April 20, 1999 5:23 PM
To:     EUPHORIA at LISTSERV.MUOHIO.EDU
Subject:        Re: sleepless night & UFOs

Colin Taylor wrote:

>I don't see how a complex function like Gabriel's can possibly be faster
>than a straight-forward approach such as:
>
>function remap(sequence s, sequence index, object newvalue)
>    if length(index) > 1 then
>        s[index[1]] = remap(s[index[1]], index[2..length(index)],
newvalue)
>    else
>        s[index[1]] = newvalue
>    end if
>    return s
>end function  -- remap

In my tests, both my original and modified routines are almost always
faster
than Joe Otto's routine. Colin's routine (shown above) is almost always
*slower* than Joe's. There are several good reasons why my two "complex"
routines are generally faster than either Joe's or Colin's. Code efficiency
doesn't always result from code simplicity; there are other factors which
come into play.


1) Calling length() multiple times vs. storing it once in a variable

If you're going to use a sequence's length value more than once in a given
section of code (and the sequence's length isn't changing), it's almost
always faster to define another integer variable, store the length() value
there, and then reference the variable instead. This is one reason why
Colin's routine is slower than Joe's, and this is the main change I made to
my original routine to gain 5+% in execution speed.


2) Subscripting a sequence vs. storing the value in a variable

If you're going to access a given sequence element more than once in a
given
section of code (and the sequence element isn't changing), it's almost
always faster to define another variable, store the sequence element there,
and then reference the variable instead. This is another reason why Colin's
routine is slower than Joe's -- Colin's routine references "index[1]" twice
in the recursive call, while Joe's routine stores "index[1]" in a variable
and uses that instead.


3) Recursive calls: parameter passing vs. local variables

When writing recursive functions, there is usually only one parm actually
being treated recursively -- the others are just along for the ride. This
is
quite true with remap() -- newvalue only actually gets used on the final
recursive call, the rest of the time it just takes up space. Instead of
requiring the interpreter to continually reallocate space for a variable
that will only be used once, it makes more sense just to store it in a
local
variable until you actually need it. This is also true for the index_list
--
instead of passing index_list[2..length(index_list)] along as a parm, it's
much faster to store the list in a local variable and grab the first
element. Then, *only* if you have another recursive call coming up, you
truncate index_list to index_list[2..len] before making the call.


4) The test data

This is an often-overlooked part of any benchmarking procedure. The data
being used to test your routines can have a *major* impact on your results.
Whatever routines you're testing, it's a good idea to vary the test data.
Look closely at your code, and choose data that will test very specific
parts of the routines (if conditions, recursive calls, etc.). Also, keep in
mind the most likely real-world uses of your routines, to avoid testing
unnecessary or unlikely situations.

In my remap() tests, I found that my routines always run faster with an
index_list length of 3 or more. Joe's routine runs faster with an
index_list
length of 2, and Colin's runs the fastest with an index_list length of 1.
The longer index_list is, the more recursive calls the routine has to make,
and the more points 1-3 above come into play.

Now, it's unlikely that a programmer will use remap() very often on
length-1
index_lists -- it may occur incidentally as part of an algorithm, but it's
not likely to be the primary use of remap(). So, if you'll primarily be
using length-2 index_lists in your program, Joe's routine will be faster.
If
you'll primarily be using length-3 or greater index_lists in your program,
then my modified routine is the faster. My assumption (which may be wrong)
is that general use of remap() would regularly involve length-3 or longer
index_lists. I therefore conclude that my modified routine is probably the
best choice for general-purpose use.


No matter what coding tips or suggestions you follow, it's *always* a good
idea to run some benchmarks and check things out for yourself. I have
included my remap benchmark program below. It's not too flashy, but it gets
the job done. (I don't trust call_func() anymore, since the exact *same*
code will come back with *different* execution times, depending on the
code's physical location in the program!)

I hope all of this has been helpful and/or educational (and I hope I got
all
my facts right!).


Be seeing you,
   Gabriel Boehme


 -----------------------------------------------------------------
 -- remap.exw by Gabriel Boehme
 --
 -- This benchmark program will run under Windows or DOS.
 --
 -- However, Windows tickcounts are more reliable, since they
 -- only count the time the program is actually executing.
 -- (Somebody correct me if this statement is inaccurate!)
 -----------------------------------------------------------------

include get.e
include machine.e -- for running under DOS
tick_rate(10000)  -- does nothing under Windows

 -- execution parms
constant
 ITER = 1e6     -- benchmark iterations
                -- test sequence depth determined by LEVELS length
,LEVELS = {5,10,3} -- length of each level in the test sequence
,LIST = {3,5,2} -- *must* all be integers >= 1 and <= LEVELS[x]


 -----------------------------------------------------------------

 -- Gabriel Boehme's original routine
sequence list
object val

function remap_recursive_old(sequence s)
integer i
   i = list[1]
   list = list[2..length(list)]
   if length(list) then
      s[i] = remap_recursive_old(s[i])
   else
      s[i] = val
   end if
   return s
end function

function remap1(sequence s, sequence index_list, object newvalue)
   list = index_list
   val = newvalue
   return remap_recursive_old(s)
end function
 -----------------------------------------------------------------

 -- Joe Otto's routine
function remap2 (sequence s, sequence indexList, object newValue)
    integer listLen, i1

    listLen = length (indexList)
    i1 = indexList [1]

    if listLen > 1 then
        s [i1] = remap2 (s [i1], indexList [2..listLen], newValue)
    elsif listLen = 1 then
        s [i1] = newValue
    end if

    return s
end function
 -----------------------------------------------------------------

 -- Gabriel Boehme's modified routine
sequence remap_list
object remap_value

function remap_recursive(sequence s)
integer i, len
   i = remap_list[1]
   len = length(remap_list)
   if len > 1 then
      remap_list = remap_list[2..len]
      s[i] = remap_recursive(s[i])
   else
      s[i] = remap_value
   end if
   return s
end function

function remap3(sequence s, sequence index_list, object new_value)
   remap_list = index_list
   remap_value = new_value
   return remap_recursive(s)
end function
 -----------------------------------------------------------------

 -- Colin Taylor's routine
function remap4(sequence s, sequence index, object newvalue)
    if length(index) > 1 then
        s[index[1]] = remap4(s[index[1]], index[2..length(index)],
newvalue)
    else
        s[index[1]] = newvalue
    end if
    return s
end function  -- remap
 -----------------------------------------------------------------


procedure msg_wait(sequence msg)
   puts(2, msg & "\n\nPress any key to continue . . .")
   if wait_key() then end if
   puts(2, "\n")
end procedure

 -- verify execution parms
if length(LIST) = 0 or length(LIST) > length(LEVELS) then
   msg_wait("Invalid LIST sequence length")
   abort(1)
end if

for i = 1 to length(LIST) do
   if not integer(LIST[i]) or LIST[i] < 1 or LIST[i] > LEVELS[i] then
      msg_wait("Invalid LIST sequence - index values out of bounds")
      abort(1)
   end if
end for

 -- build the test sequence
sequence s
s = repeat(0, LEVELS[length(LEVELS)])  -- start with the innermost level
for i = length(LEVELS)-1 to 1 by -1 do -- and work your way outward
   s = repeat(s, LEVELS[i])
end for

printf(1, "A remap() benchmark program by Gabriel Boehme\n"
        & "Sequence depth %d, remap depth %d\n\n",
          {length(LEVELS), length(LIST)})

puts(1, "[Smaller values are better]\n---------------------------\n")

 -----------------------------------------------------------------
atom t

 -- the moment of truth
puts(1, "Gabriel's original routine: ")
t = time()
for i = 1 to ITER do
   s = remap1(s, LIST, 1)
end for
? time() - t

puts(1, "Joe's routine:              ")
t = time()
for i = 1 to ITER do
   s = remap2(s, LIST, 1)
end for
? time() - t

puts(1, "Gabriel's modified routine: ")
t = time()
for i = 1 to ITER do
   s = remap3(s, LIST, 1)
end for
? time() - t

puts(1, "Colin's routine:            ")
t = time()
for i = 1 to ITER do
   s = remap4(s, LIST, 1)
end for
? time() - t


msg_wait("")
 -----------------------------------------------------------------

________________________________________________________
NetZero - We believe in a FREE Internet.  Shouldn't you?
Get your FREE Internet Access and Email at
http://www.netzero.net/download.html

new topic     » goto parent     » topic index » view message » categorize

14. Re: sleepless night & UFOs

Joe Otto wrote:

>IMHO, unless speed is critical, I think it's best to opt for readability.

I *definitely* agree with you here -- all things being equal, I'd prefer
your routine or Colin's to mine, because of their simplicity.


>Anyway, sorry if I wasted your time.  I've never written a program in
>Euphoria.  I just saw an opportunity to try to help someone, so I wrote my
>posting off the top of my head without testing it...

No problem -- that's what the list is for. Your post and Colin's helped me
to clarify for myself exactly why I wrote my routine the way I did in the
first place. I felt that my conclusions were potentially useful to others on
the list, so I decided to share them. This is how we all learn more about
Euphoria -- a lot of what I wrote about in that post I learned just from
being here on the list.


Keep on coding,
   Gabriel Boehme


 ------
The work of one supports the work of all.

Robert Fripp
 ------

new topic     » goto parent     » topic index » view message » categorize

15. Re: sleepless night & UFOs

"Boehme, Gabriel" quoted jiri on Mon, 19 Apr 1999:
>>Just one other thing: Ralf, your 'each' construct is an excellent
>>idea. I also think, given plenty of time, even Gabriel will eventually
>>like it. (Sorry, Gabriel, *any* sign of conservatism brings out the
>>worst in me!) jiri

All this talk of 'each' reminds me a lot of Icon, the 'successor' (if it can be
called that) to SNOBOL. There one can have statements as generators of
sequences. Interesting concept but is it Euphoria?

Bruce.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu