[PLUG-TALK] Autodialer numerical math puzzle

Russell Senior seniorr at aracnet.com
Wed Jun 14 09:30:17 UTC 2006


>>>>> "Keith" == Keith Lofstrom <keithl at kl-ic.com> writes:

Keith> Math puzzle:

Keith> John Jones sets up a program to use his nifty new computer
Keith> autodialer.  He sets the program up to call "911".
Keith> Unfortunately, he hits the shift key and enters 9!! instead.
Keith> That is, (9 factorial)factorial.

Keith> His autodialer contains a powerful computer capable of very
Keith> high precision integer math, and it proceeds to compute this
Keith> long integer, and dial it.  John has a regular telephone on the
Keith> US public telephone network.  His autodialer dials 3 digits a
Keith> second.  He pays 3 cents per minute for long distance charges,
Keith> rounded up to the nearest cent.

Keith> Question one: What person or company does he end up calling,
Keith> with the first usable digits?  Name and address, please, as of
Keith> June 2006.

Keith> Question two: How long (in seconds) will the autodialer dial?
Keith> Ignoring taxes, how much will the phone service cost John, if
Keith> he (and the recipient) allows the whole sequence of digits to
Keith> complete?

Keith> Keith

Keith> (yes, it IS a waste of time)

This is one of the problems that is is so fun to use Lisp for.  I used
CLISP, a byte-code interpretted implementation.  The naive
implementation of factorial tends to blow the stack and/or the normal
floating point representations, or scroll the interesting bits off the
top of the screen.  So, we get slightly clever and do the math on
log-transformed values and use an iteration instead of recursion:

  > (defun factorial (n) 
      (exp (loop for i from 1 upto n 
              sum (log (coerce i 'long-float)))))

  > (factorial 9)
    => 362879.99999999999991L0
  > (time (factorial 362880))
  Real time: 48.807139 sec.
  Run time: 48.763047 sec.
  Space: 1144749160 Bytes
  GC: 1697, GC time: 20.813321 sec.
   =>1.6097144004283187662L1859933

A long-float in CLISP is a 10-byte float with 64-bits of mantissa by
default, but it is configurable at runtime, which is pretty cool.  So,
just to make sure that precision didn't mess me up, i'll try bumping
it.

  > (long-float-digits) 
  64
  > (setf (long-float-digits) 128)
  128
  > (long-float-digits) 
  128
  > (time (factorial 362880))
  Real time: 74.233911 sec.
  Run time: 74.044627 sec.
  Space: 1707733928 Bytes
  GC: 2532, GC time: 30.81393 sec.
  1.60971440041001262110344361073509278104L1859933

So, that looks stable enough to give the same first 10 digits.  BTW,
(long-float-digits) tells you how many bits (not decimal digits!) in
the float representation's mantissa.  And note how Common Lisp
magically pushes a value into a function call using 'setf.  Too cool.

Answer 1: the number is 1-609-714-4004.  Google doesn't tell me who
that is, so I give up.  Intelius says it is an "available number" in
MEDFORD, NJ. 

Answer 2: from the exponent on the resulting value, the number would
have 1859934 digits.  At three digits a second, that's 619978 seconds,
which is 30,998.9 minutes (a little over a week: 7 days, 4 hours, 12
minutes and 58 seconds).  Let's say the phone company charges in full
minutes, that's 30,999 minutes, times $0.03 = $929.97.

Note the run-time on these calculations: ~49 and ~74 seconds,
respectively, (on a 1GHz P3) so it didn't waste *that* much time.  

I wasn't willing to waste enough time to confirm I got the right
number.  I just trust that the underlying implementation of log and
exp are good enough.

For kicks, here's the output when I bump the long-float-digits to 640
(ten times normal).  

  > (setf (long-float-digits) 640)
  640
  > (time (factorial 362880))
  Real time: 408.273091 sec.
  Run time: 407.269453 sec.
  Space: 8283795960 Bytes
  GC: 12283, GC time: 129.568113 sec.
  1.609714400410012621103443610733317726505520397622886158329835221246398515391430218331773756126649701931616812922151308253312687565407611350763177052692072075380992663287299539692920504232785533L1859933

How'd I do?  Do I win anything?


-- 
Russell Senior         ``I have nine fingers; you have ten.''
seniorr at aracnet.com



More information about the PLUG-talk mailing list