From: Ken Tilton on


Vassil Nikolov wrote:
> On Wed, 28 Feb 2007 22:29:20 -0600, rpw3(a)rpw3.org (Rob Warnock) said:
> | ...
> | 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")))
>
> But there is nothing special about primes in this problem. It is all
> about having a finite number of (possibly overlapping) classes (whose
> union does not necessarily cover the universe), and tagging values
> with regards to membership in said classes. ("Class", of course, in
> the usual set-theoretical sense, not in the more specialized OO
> sense.)
>
> Here is a sketch of the nucleus of a solution that trivially scales
> into an arbitrary number of such classes, each specified by its
> predicate. It uses divisibility-by-a-prime classes only to illustrate,
> but obviously the arithmetic aspect is abstracted away.

Thank you! Finally someone has come to grips with the problem scalably.

I say we move into beta testing Q2 of '07 and production Q3.

Is this what the OE (original employer) was looking for?

hth,kt

--
Well, I've wrestled with reality for 35 years, Doctor, and
I'm happy to state I finally won out over it.
-- Elwood P. Dowd

In this world, you must be oh so smart or oh so pleasant.
-- Elwood's Mom
From: Rainer Joswig on
In article <yy8virdlegpk.fsf(a)eskimo.com>,
Vassil Nikolov <vnikolov+usenet(a)pobox.com> wrote:

> On Wed, 28 Feb 2007 14:48:27 +0100, Rainer Joswig <joswig(a)lisp.de> said:
> | ...
> | Take this (not written by me).
>
> Zmacs?
>
> | ...
> | How about this? This is clearly from aliens.
>
> But was ported to Common Lisp at some point, wasn't it?

Not sure. There are selected libraries that got ported.
But the system runs several Lisp dialects at the same time.

>
> ---Vassil.
From: themba.fletcher on
<snip>
> There's your spec. Where's your code? ;-}
>
> -Rob

OK, hello c.l.l from another noob lurker. I guess this is as good a
way to jump in as any. It's my first macro, so please be gentle.

I had to unquote the arguments to def-fizz-buzz in order to make it
work. I'm wondering why, since macro arguments aren't evaluated, your
spec quoted both the name and the alist?

(defun new-counter (target true-value &optional (false-value ""))
(let ((counter 0))
#'(lambda ()
(if (= (incf counter) target)
(progn
(setf counter 0)
true-value)
false-value))))


(defmacro def-fizz-buzz (name condition-list)
;; sample call: (def-fizz-buzz fizz-buzz ((3 . "Fizz") (5 .
"Buzz")))
(let ((conditions (loop for e in condition-list collecting
(list 'new-counter (car e) (cdr e)))))
`(defun ,name (n)
(let ((conds (list ,@conditions)))
(loop for i from 1 to n do
(let ((print-value (apply #'concatenate 'string
(mapcar #'funcall conds))))
(if (string= print-value "")
(print i)
(print print-value))))))))


CL-USER> (def-fizz-buzz very-fizzy ((2 . "Burp") (3 . "Fizz") (5 .
"Buzz") (7 . "Bang")))

VERY-FIZZY
CL-USER> (very-fizzy 16)

1
"Burp"
"Fizz"
"Burp"
"Buzz"
"BurpFizz"
"Bang"
"Burp"
"Fizz"
"BurpBuzz"
11
"BurpFizz"
13
"BurpBang"
"FizzBuzz"
"Burp"
NIL
CL-USER>


Regards,

Themba

From: krewinkel on
On Mar 1, 6:00 am, Vassil Nikolov <vnikolov+use...(a)pobox.com> wrote:
> ((lambda (n) (format t "~:{~[~[~3@*~A~A~:;~3@*~A~]~:;~[~4@*~A~:;~D~]~] ~}" (mapcar #'(lambda (i) `(,(mod i 3) ,(mod i 5) ,i fizz buzz)) (loop for i from 1 to n collect i)))) 100)
>
> (yes, this still uses LOOP, but it is somewhat buried).
>
> (defun fb (n)
> ((lambda (c p) (funcall c c p 1))
> (lambda (c p i)
> (or (> i n) (funcall p c p i)))
> (lambda (c p i)
> (format t "~[~[~3@*~A~A~:;~3@*~A~]~:;~[~4@*~A~:;~D~]~]~%"
> (mod i 3) (mod i 5) i "Fizz" "Buzz")
> (funcall c c p (1+ i)))))
>
> ---Vassil.
>
> --
> mind mate, n.
> One of two persons mentally compatible with each other (cf. soul mate).

Noobs allowed in this discussion? Well, I'll give it a try.
Using some previously posted ideas, I got rid of an explicit
loop by using:

(defvar *i* 0)
(defun foo (outstream format-string colon-p at-sign-p)
(declare (ignore format-string colon-p at-sign-p))
(prog1
(format outstream "~[~[~3@*~A~A~:;~3@*~A~]~:;~[~4@*~A~:;~D~]~]~
%"
(mod *i* 3) (mod *i* 5) *i* "Fizz" "Buzz")
(incf *i*)))

(defun fizzbuzz (n)
(let ((*i* 1))
(format t (format nil "~~~A@{~~/foo/~~:*~~}" n) nil)))

(fizzbuzz 15)

Total abuse of the language.

Albert

From: Rob Warnock on
lojic <lojicdotcom(a)gmail.com> wrote:
+---------------
| r...(a)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(a)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(a)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(a)rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607