From: Ken Tilton on 1 Mar 2007 02:12 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 1 Mar 2007 03:30 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 1 Mar 2007 03:43 <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 1 Mar 2007 05:16 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 1 Mar 2007 05:32
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 |