From: job-271842874 on
A friend passed on an article regarding the difficulty job candidates
had in producing even simple programs (simple as in should take a minute
or less). One example was a program to print the numbers 1 to 100 except
that "Fizz" should be substituted for numbers divisible by 3, "Buzz"
should be substituted for numbers divisible by 5, and "FizzBuzz" should
be substituted for numbers divisible by both 3 and 5.

So, having received my "ANSI Common Lisp" and "Practical Common Lisp"
books two days ago (still waiting for "Structure and Interpretation of
Computer Programs") and having a *couple hours* of Lisp under my belt, I
cranked out a Lisp version. It seems a bit clunky, so I thought I'd see
if anyone had suggestions for improvements.

Here's a Ruby version for comparison:

def fizz_buzz n
1.upto(n) do |i|
print "Fizz" if fizz = (i % 3) == 0
print "Buzz" if buzz = (i % 5) == 0
puts fizz || buzz ? "" : i
end
end

fizz_buzz 100

and the Lisp version

(defun fizz-buzz (n)
(do ((i 1 (+ i 1)))
((> i n))
(let
((fizz (= 0 (mod i 3)))
(buzz (= 0 (mod i 5))))
(if fizz (format t "Fizz"))
(if buzz (format t "Buzz"))
(format t "~A~%"
(if (or fizz buzz) "" i)))))

(fizz-buzz 100)

By the way, it seems more folks recommend starting with "Practical
Common Lisp" instead of "ANSI Common Lisp" (when both are mentioned),
but being a newbie myself, it seems that the latter is a better
introduction to the language.

Brian
From: Frank Buss on
job-271842874(a)craigslist.org wrote:

> I cranked out a Lisp version. It seems a bit clunky, so I thought I'd see
> if anyone had suggestions for improvements.

looks ok, but I would use loop and organize the body of the loop a bit
different:

(defun fizz-buzz (n)
(loop for i from 1 to n
for fizz = (zerop (mod i 3))
for buzz = (zerop (mod i 5)) do
(when fizz (princ "Fizz"))
(when buzz (princ "Buzz"))
(when (not (or fizz buzz)) (princ i))
(terpri)))

--
Frank Buss, fb(a)frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: job-271842874 on
Frank Buss wrote:
> job-271842874(a)craigslist.org wrote:
>
>> I cranked out a Lisp version. It seems a bit clunky, so I thought I'd see
>> if anyone had suggestions for improvements.
>
> looks ok, but I would use loop and organize the body of the loop a bit
> different:
>
> (defun fizz-buzz (n)
> (loop for i from 1 to n
> for fizz = (zerop (mod i 3))
> for buzz = (zerop (mod i 5)) do
> (when fizz (princ "Fizz"))
> (when buzz (princ "Buzz"))
> (when (not (or fizz buzz)) (princ i))
> (terpri)))
>

Thanks. Some questions/comments:

1) In "ANSI Common Lisp", Graham makes the following comments:
"The loop macro was originally designed to help inexperienced Lisp
users write iterative code...Unfortunately, loop is more like English
than its designers ever intended...to understand it in the abstract is
almost impossible...For such reasons, the use of loop cannot be
recommended."

Is this a minority view? One of the things that attracted me to Lisp
was the simplicity, consistency, etc. of the language, so when I read
the above, it seemed reasonable.

2) Thanks for the zerop tip. I like (zerop (mod m n)) better than (= 0
(mod m n))

3) Any reason why you chose (when fizz (princ "Fizz")) instead of (if
fizz (princ "Fizz")) ?

4) Curious about the history of "terpri" - I guess it's shorter than
"newline" but not very intuitive :)

I'm really enjoying learning Lisp. I realize at this stage I still have
some "the grass is greener" and "oh cool, something new to learn!"
influences, but I expect as that wears off the merits of the language
will continue to shine through.

Brian
From: Lars Rune Nøstdal on
My first try:


(loop :for i :from 1 :upto 100
:doing (cond
((= 0 (mod i 3) (mod i 5)) (write-line "FizzBuzz"))
((= 0 (mod i 3)) (write-line "Fizz"))
((= 0 (mod i 5)) (write-line "Buzz"))
(t (format t "~A~%" i))))


...then..


(loop :for i :from 1 :upto 100
:doing
(let ((fizz-or-buzz nil))
(when (= 0 (mod i 3)) (princ "Fizz") (setf fizz-or-buzz t))
(when (= 0 (mod i 5)) (princ "Buzz") (setf fizz-or-buzz t))
(unless fizz-or-buzz (princ i))
(terpri)))


I suppose one could write a version of cond with a :when-no-clauses clause
or something to do some hiding. Maybe `loop' already has something? Well,
gonna try:


(defmacro cond* (&body body)
`(let ((any-clause-p nil))
,@(mapcar (lambda (clause-form)
(if (eq :unless-till-now (first clause-form))
`(unless any-clause-p ,(second clause-form))
`(when ,(first clause-form)
,(second clause-form)
(setf any-clause-p t))))
body)))


(loop :for i :from 1 :upto 100
:doing
(cond*
((= 0 (mod i 3)) (princ "Fizz"))
((= 0 (mod i 5)) (princ "Buzz"))
(:unless-till-now (princ i)))
(terpri))


":unless-till-now" .. not sure about the name, but I'm thinking "unless
any clause has been true up to now". So it works in the middle too.

Now, hoping that I've not made too many mistakes; is there anyone who would
like to pay me to do tasks like this? :}


--
Lars Rune Nøstdal
http://nostdal.org/
From: Paul Wallich on
job-271842874(a)craigslist.org wrote:
> A friend passed on an article regarding the difficulty job candidates
> had in producing even simple programs (simple as in should take a minute
> or less). One example was a program to print the numbers 1 to 100 except
> that "Fizz" should be substituted for numbers divisible by 3, "Buzz"
> should be substituted for numbers divisible by 5, and "FizzBuzz" should
> be substituted for numbers divisible by both 3 and 5.
>
> So, having received my "ANSI Common Lisp" and "Practical Common Lisp"
> books two days ago (still waiting for "Structure and Interpretation of
> Computer Programs") and having a *couple hours* of Lisp under my belt, I
> cranked out a Lisp version. It seems a bit clunky, so I thought I'd see
> if anyone had suggestions for improvements.
>
> Here's a Ruby version for comparison:
>
> def fizz_buzz n
> 1.upto(n) do |i|
> print "Fizz" if fizz = (i % 3) == 0
> print "Buzz" if buzz = (i % 5) == 0
> puts fizz || buzz ? "" : i
> end
> end
>
> fizz_buzz 100
>
> and the Lisp version
>
> (defun fizz-buzz (n)
> (do ((i 1 (+ i 1)))
> ((> i n))
> (let
> ((fizz (= 0 (mod i 3)))
> (buzz (= 0 (mod i 5))))
> (if fizz (format t "Fizz"))
> (if buzz (format t "Buzz"))
> (format t "~A~%"
> (if (or fizz buzz) "" i)))))

In both cases, what the local variables add in supposed elegance seems
to me lost by the clunkiness of setting them in the first place (which
you haven't done correctly).

I'd probably brute-force the problem with a simple cond with a nested
conditions, along the lines of
(cond ((zerop (mod i 5))
(cond ((zerop (mod i 3)) (print "FizzBuzz"))
(t (print "Buzz"))))
((zerop (mod i 3))
(print "Fizz"))
(t (print i)))

Someone else can do the loop version, the version with a macro that
generates any possible fizz-buzz function of two small integers, the ver