Tamas K Papp <tkpapp@gmail.com> wrote:
+---------------
| Others have already provided solutions. I wanted to add mine because it
| is important to realize that you do not need the intermediate list of
| digits, and you can proceed from either end (+ is commutative). So
|
| (defun sum-digits (i)
| (declare ((integer 0) i)) ;; we want a nonnegative integer
| (let ((sum 0))
| (tagbody
| top
| (multiple-value-bind (quotient remainder) (truncate i 10)
| (incf sum remainder)
| (when (plusp quotient)
| (setf i quotient)
| (go top))))
| sum))
|
| (sum-digits (expt 2 1000))
|
| Some consider tagbody ugly - it is their loss :-)
+---------------
I cheerfully use TAGBODY when it's appropriate, but I don't consider
the above to be such a case, especially given that there's a considerably
simpler way *without* it, viz.:
(defun sum-digits (i)
(assert (and (integerp i) (>= i 0)))
(loop while (plusp i)
summing (multiple-value-bind (quotient remainder)
(truncate i 10)
(setf i quotient)
remainder)))
-Rob
p.s. Note that I changed your DECLARE to an ASSERT, since DECLARE is
a promise *by* the programmer, not a check *of* the programmer/user!
I suppose I could have written (ASSERT (TYPEP I '(INTEGER 0 *))),
but the TYPEP is likely to be slower.
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607