lojic <lojicdotcom@gmail.com> wrote:
+---------------
| r...@rpw3.org (Rob Warnock) wrote:
| > Write the general version of DEF-FIZZ-BUZZ that accepts a
| > function name (so we can tell them apart) and an alist of primes
| > and strings, and emits similarly-correct/fast code. E.g., the
| > example we've been using all along would be generated like so:
| >
| > (def-fizz-buzz 'fizz-buzz '((3 "Fizz") (5 "Buzz")))
|
| That goes back to my earlier post of the following generalized
| solution:
|
| (defun fizz-buzz (n lst)
| (do ((i 1 (+ i 1)))
| ((> i n))
| (let
| ((fizzed nil))
| (dolist (obj lst)
| (let ((a (car obj))
| (str (car (cdr obj))))
| (when (zerop (mod i a))
| (princ str)
| (setf fizzed t))))
| (if (not fizzed)
| (princ i))
| (terpri))))
|
| (fizz-buzz 15 '((3 "Fizz") (5 "Buzz")))
+---------------
That's fine, for a run-time function. [I had a bit of a chuckle at what
(fizz-buzz 100 '((2 "Burp")(3 "Fizz") (5 "Buzz")(7 "Bang")(11 "Boom!")))
outputs...]
+---------------
| This was my off-the-cuff approach from a non-Lisp background.
+---------------
It's actually reasonably "Lispy" as is. Oh, sure, you might use
(DOTIMES (I N) ...) or (LOOP FOR I FROM 1 TO N DO ...) instead of DO;
and you might want to use CADR or SECOND instead of (CAR (CDR ...))
and hold off on fetching that until inside the WHEN; and also the
LET is formatted uncommonly; and use UNLESS instead of (IF (NOT...)...);
and call things LIST, not LST; little stuff like that, e.g.:
(defun fizz-buzz (n list)
(dotimes (i n)
(let ((fizzed nil))
(dolist (item list)
(when (zerop (mod i (first item)))
(princ (second item))
(setf fizzed t)))
(unless fizzed
(princ i))
(terpri))))
And you could use LOOP instead of the inner DOLIST and replace the
LET with a WITH term, but then it'd probably look *less* "Lispy"
to many people:
(defun fizz-buzz (n list)
(dotimes (i n)
(loop with fizzed = nil
for item in list
when (zerop (mod i (first item)))
do (princ (second item))
(setf fizzed t)
finally (unless fizzed
(princ i))
(terpri))))
+---------------
| I would like to see a macro-ized version...
+---------------
Did you see <nallen05@gmail.com>'s version for the case of a
hard-coded '((3 "Fizz") (5 "Buzz")) list?
+---------------
| ...and get some feedback from the group regarding the
| appropriateness of macros in this case vs. a simple
| function as in the above.
+---------------
A macro would fix the LIST at macroexpansion time, which allows
the macro to potentially generate better code [possibly *much*
better code, as <nallen05@gmail.com> showed], but loses the
runtime flexibility of your above function.
One hybrid that might be useful would be a function that
looked at N and the length of LIST (and all the CARs) and
decided whether to do it the straightforward way (as above)
or whether to use an initialization step to pre-bake some
auxiliary tables to speed up the computation [e.g., like
the circular lists in my version, to avoid MOD, but computed
at runtime].
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607