Mmm, this looks like "number of trailing zeroes in n! when written in base 10", or, equivalently, "number of factors of 5 in n!". If we let that be f(n), and u = floor(n/5), then f(n) = u + f(u). Then, instead of writing out all the powers of 5 up to whatever your integer limit is... if you think for a little bit, this will work:
(defun calc-trailing-zeros-2 (n)
(do ((n (floor n 5) (floor n 5))
(total 0 (+ total n)))
((zerop n) total)))
Methinks this is much better; if there is a performance disadvantage, I wouldn't care about it (and you can add type-decs as you wish; if you do, note that you'd probably have to say (the fixnum (+ a b)) even if a and b are known fixnums). If you want to verify that it works...
(dotimes (i 30) (print (= (calc-trailing-zeros i) (calc-trailing-zeros-2 i))))
It prints a bunch of T.
As for the performance comparison, I'd echo what others have said: I expect the I/O (read-line, princ, terpri) to dominate the run time. ... Now for some experimentation. "randomthing" is an SBCL image in my executable "mybin" directory that executes the "let ..." code at the bottom; achieved with (save-lisp-and-die "randomthing" :executable t :toplevel (lambda () (let ...))). Let's test it:
;Clipboard is "100000" followed by 100000 instances of "500000"
$ time pbpaste | randomthing > /dev/null
real 0m0.453s
user 0m0.352s
sys 0m0.096s
;Clipboard is "100000" followed by 100000 instances of "000000"
$ time pbpaste | randomthing > /dev/null
real 0m0.352s
user 0m0.263s
sys 0m0.091s
In the case of "000000", the "calc-trailing-zeros" part should take about zero time, and therefore the remaining time is all the I/O stuff. Depending on whether we go by the "real" or "user" thing, this tells us that the math part takes up either 2/7 or 2/9 of the time of the whole program.
And just to be sure that "pbpaste" isn't the main cause of slowness:
$ time pbpaste > /dev/null
real 0m0.024s
user 0m0.012s
sys 0m0.009s
Fairly insignificant. Likewise, startup time for this Lisp image can be experimentally determined by having my clipboard only contain "10" followed by 10 integers:
$ time pbpaste | randomthing > /dev/null
real 0m0.032s
user 0m0.010s
sys 0m0.027s
So, yeah, I/O dominates the run time, at least on my SBCL (SBCL 1.0.47).
As for the performance comparison, I'd echo what others have said: I expect the I/O (read-line, princ, terpri) to dominate the run time. ... Now for some experimentation. "randomthing" is an SBCL image in my executable "mybin" directory that executes the "let ..." code at the bottom; achieved with (save-lisp-and-die "randomthing" :executable t :toplevel (lambda () (let ...))). Let's test it:
In the case of "000000", the "calc-trailing-zeros" part should take about zero time, and therefore the remaining time is all the I/O stuff. Depending on whether we go by the "real" or "user" thing, this tells us that the math part takes up either 2/7 or 2/9 of the time of the whole program.And just to be sure that "pbpaste" isn't the main cause of slowness:
Fairly insignificant. Likewise, startup time for this Lisp image can be experimentally determined by having my clipboard only contain "10" followed by 10 integers: So, yeah, I/O dominates the run time, at least on my SBCL (SBCL 1.0.47).