[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

LOGO-L> Re: factorials




hi george and yehuda


just a few remarks
my code is slower mainly because i calculate
the sum of the factorials and the numeric value
with apply or recuresively.

whe i change that (see enclosed code)
the runtimes goes down to 50% and i am
"back to normal"

i also changed the cache for the factorials from
a list to an array,
that had almost no influence on runtime.

i know that using apply and similar constructs
slows down things.

BUT

i think the real power of a part of logo lies
in these constructs.

we are selecting elements with certain properties
from a basic set of elements we create.
that is a fundamental pattern,
and filter exists just to be able to express
this fundamental pattern.

in fact, i teach my students (beginning university students)
in the third unit of a logo course about filter an map

filter and map combined are empirical equations solving:
find all the ellemenents of a base set fulfilling
a certain euqation!

so i think it is true but sad that
most students working with logo never meet these
parts of the language.

if i remember correctly, both of you are splitting the a number
into digits with the item function.
this is something i would discourage my students to do.

item is essentially a list and string function,
so using item for gettibg digits uses implicit type conversion
between integers and strings, and that also costs time.
besides, i think it is porgramming style that sometimes
can be useful but should be discouraged.

of course, using crossmap to create the digit lists also
is not extremely efficient.

but it is a natural consequence
of the way i structured the problem.

i did not view the numbers to be tested as a linear
sequence of integers. just taking the numbers from 100 to 999
is, i think, the reason that you overlooked ths possible 
simplification that digits above 6 cannot be used.

so inherently, i am using lists of digits as my findamental data 
type, from this representation i am calculating the
factval and the numval.

additionally, since i am using this representation,
i can change my code very quickly to deal with 
the same problem in a different number base
like
which 3 digit hexadecimal numbers have their value equal
to the sum of their digit factorials.

all i have to change is the iseq's in crossmap
and numval.

of course, my numval can easily be extended to
take the number base as a parameter,
and then i can deal with the problem in any number base.

using apply for factval and the recursive formulation
for numval as i did in my original code
the immediately allows me to reuse the code
for numbers with any given
number of digits in any number base system.

i tend to show my students to write easily generalizable programs.
of course, the price you pay for a general solutions
is that in specific situations there are faster specific 
solutions.

but after all i am a mathematician,
and i like general solutions.
and i am willing to a factor of 2 in runtime
of the code is much more general.

additionally,
with our problem here, the questions is 
1 second or 2 seconds.

if the program is run only a few times,
making it faster does not pay off
compared to the time needed to create the faster version.

and with a problem like ours, you only need the code to run it once.
so, if you have a structured program giving you the solution
in reasonable time ans allowing you to study similar problems,
you should think twice before trying to make it faster
for just one special problem.


p.s.: the enclosed code which is somewhat optimized for speed
by working only for 3 digit numbers
can be made a little bit faster by using 
explicit lookup in factval
instead of encapsulating
the lookup in the function fact

so the program becomes faster if we define

to factval :x1 :x2 :x3
output (item :x1 :factlist) + (item :x2 :factlist) ~
   + (item :x3 :factlist) 
end





-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==

to fact :n
output item :n :factlist
end

to fact1 :n
output ifelse :n = 0 [1] [:n * fact1 :n - 1]
end

to factval :x1 :x2 :x3
output (fact :x1) + (fact :x2) + (fact :x3)
end

to iseq :a :b
if :a > :b [output []]
output fput :a iseq :a + 1 :b
end

to make.factlist :n
make "factlist (array :n + 1 0) 
foreach iseq 0 :n [setitem ? :factlist fact1 ?]
end

to numval :x1 :x2 :x3
output 100 * :x1 + 10 * :x2 + :x3
end

to runsolve
local "start
local "result
make "start timemilli
make "result solve
show timemilli - :start
show :result
end

to solve
output  filter [[x] equalp first :x first butfirst :x] ~
  (crossmap [list factval ?1 ?2 ?3  numval ?1 ?2 ?3] iseq 1 6 iseq 0 
6 iseq 0 6)
end


--
Erich Neuwirth <neuwirth@smc.univie.ac.at>
Computer Supported Didactics Working Group, University of Vienna
Currently Visiting Professor at the 
National Institute of Multimedia Education, Chiba, Japan
Visit our SunSITE at http://sunsite.univie.ac.at
---------------------------------------------------------------
Please post messages to the Logo forum to logo-l@gsn.org.  Mail
questions about the list administration to logofdn@gsn.org.  To
unsubscribe send    unsubscribe logo-l    to majordomo@gsn.org.



Global SchoolNet Foundation - Linking Kids Around the World!
Copyright GSN - All Rights Reserved - Comments & Questions
Visit GSN's Global Schoolhouse for more exciting learning resources!
Search our Site - Home