Skip to content

Commit

Permalink
add more variants to the Armstrong numbers sample
Browse files Browse the repository at this point in the history
  • Loading branch information
mayerrobert committed Oct 19, 2023
1 parent 080fdc5 commit a3f99d2
Showing 1 changed file with 62 additions and 1 deletion.
63 changes: 62 additions & 1 deletion samples.mlib/arms.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@
(require "mlib")

(defmacro pr items
"Helper that will print each argument and then a newline."
`(progn ,@(mapcar (lambda (it)
(list 'write it nil))
items)
(writeln)))



(pr #\Newline "Nested loops:")

(defun arms ()
"Print all Armstrong numbers from 0 to 999."
(let ((count 0) (abc 0))
(dotimes (a 10)
(dotimes (b 10)
Expand All @@ -30,9 +36,13 @@
(time (arms))



(pr #\Newline "One loop:")

(defun arms2 ()
"Print all Armstrong numbers from 0 to 999."
(let ((count 0))
(dotimes (abc 999)
(dotimes (abc 1000)
(let ((a3b3c3 (+ (expt (floor abc 100) 3)
(expt (mod (floor abc 10) 10) 3)
(expt (mod abc 10) 3))))
Expand All @@ -41,3 +51,54 @@
(pr "Armstrong number " count ": " abc))))))

(time (arms2))



(pr #\Newline "Using serapeum's 'summing' macro and a generator:")

(defun digits (n)
"Return a generator (parameterless function)
that on subsequent invocations will return
the base 10 digits of 'n' from right to left."
(lambda ()
(if n
(values (if (< n 10)
(prog1 n
(setq n nil))
(prog1 (mod n 10)
(setq n (truncate n 10))))
t)
(values nil nil))))


(defun armstrongp (n)
"Return true if 'n' is an Armstrong number."
(= n (summing
(dogenerator (n (digits n))
(sum (expt n 3))))))

(time (let ((count 0))
(dotimes (n 1000)
(when (armstrongp n)
(incf count)
(pr "Armstrong number " count ": " n)))))



(pr #\Newline "Using mapcar:")

(defun armsp (n)
"Return true if 'n' is an Armstrong number."
(labels ((number->digit-list (n)
(string->list (format nil "%d" n)))
(char->number (c)
(- (char-code c) (char-code #\0))))

(= n (apply + (mapcar (lambda (c) (expt (char->number c) 3))
(number->digit-list n))))))

(time (let ((count 0))
(dotimes (n 1000)
(when (armsp n)
(incf count)
(pr "Armstrong number " count ": " n)))))

0 comments on commit a3f99d2

Please sign in to comment.