From: job-271842874 on
Ken Tilton wrote:
>
>
> Rob Warnock wrote:
>> <job-271842874(a)craigslist.org> wrote:
>> +---------------
>> | Another friend of mine commenting on the same FizzBuzz thread
>> supplied | the following Python code. It certainly is concise:
>> | | for i in xrange(1,101):
>> | print(str(i), "Fizz", "Buzz", "FizzBuzz")[(i%3==0)|(i%5==0)<<1]
>> | | I thought about retrofitting my Ruby version as an exercise, but
>> alas, | Ruby doesn't allow shifting truth to the left :)
>> | | Forgive my ignorance, but is anything like the boolean bit
>> shifting | technique used in the Python code above possible in Lisp?
>> No big loss if | it isn't, just curious.
>> +---------------
>>
>> Well, sort of... ;-} ;-}
>>
>> This one is both efficient -- *no* MOD calls at all! --
>> *and* so ugly only a parent could love it: ;-} ;-}
>>
>> (defun fizz-buzz (n)
>> (loop for i from 1 to n and three-p in '#3=(nil nil t .
>> #3#)
>> and five-p in '#5=(nil nil nil nil t . #5#)
>> do (format t "~a~%" (cond
>> ((and three-p five-p) "FizzBuzz")
>> (three-p "Fizz")
>> (five-p "Buzz")
>> (t i)))))
>
> Yer a sick puppy, Rob, but I like it.

Yeah, I know I should just turn away, but I can't help myself :)

I'll have to file this away and come back to it when I've learned enough
to understand it. Looks like read macros are involved, but I don't want
to get ahead of myself...

>
> kt
From: Rob Warnock on
<job-271842874(a)craigslist.org> wrote:
+---------------
| I'll have to file this away and come back to it when I've
| learned enough to understand it. Looks like read macros
| are involved, but I don't want to get ahead of myself...
+---------------

When you're ready, see:

http://www.lisp.org/HyperSpec/Body/sec_2-4-8-15.html
2.4.8.15 Sharpsign Equal-Sign

http://www.lisp.org/HyperSpec/Body/sec_2-4-8-16.html
2.4.8.16 Sharpsign Sharpsign

Just remember to (SETF *PRINT-CIRCLE* T) before trying
experiments at the REPL...


-Rob

p.s. The fact that I used #3= and #5= carried no semantics;
it was just for documentation. They could have been any two
distinct non-zero positive integers.

-----
Rob Warnock <rpw3(a)rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

From: Joel Wilsson on
On Feb 28, 7:09 am, job-271842...(a)craigslist.org wrote:
> Another friend of mine commenting on the same FizzBuzz thread supplied
> the following Python code. It certainly is concise:
>
> for i in xrange(1,101):
> print(str(i), "Fizz", "Buzz", "FizzBuzz")[(i%3==0)|(i%5==0)<<1]
>
> I thought about retrofitting my Ruby version as an exercise, but alas,
> Ruby doesn't allow shifting truth to the left :)

While it's "nice" in this case, I think it's a sign of a weak type
system.
Even Java has a boolean type.

> Forgive my ignorance, but is anything like the boolean bit shifting
> technique used in the Python code above possible in Lisp? No big loss if
> it isn't, just curious.

No, but of course you could easily make it.
(flet ((num-zerop (x)
(if (zerop x)
1
0)))
(defun fizz-buzz (n)
(dotimes (i (1+ n))
(format t "~A~%" (nth (logior (num-zerop (mod i 3))
(ash (num-zerop (mod i 5)) 1))
(list i "Fizz" "Buzz" "FizzBuzz"))))))

> I suppose it's unreasonable to expect the Lisp version to be as concise
> as the Python version

Due to the nature of the problem I don't think any language where
equality
testing returns true booleans can be shorter than that Python version.
This is closer to Common Lisp style I think, and slightly more
verbose:

(defun fizz-buzz (n)
(dotimes (i (1+ n))
(format t "~A~%" (nth (+ (if (zerop (mod i 3)) 1 0)
(if (zerop (mod i 5)) 2 0))
(list i "Fizz" "Buzz" "FizzBuzz")))))

In my opinion some of the first versions posted in this thread were
the
best, since they were much easier to read and understand. We're just
doing obfuscated stuff now, might as well go all out:

(defun fizz-buzz (n)
(format t "~{~A~%~}" (reduce (lambda (h r)
(cons (nth (reduce (lambda (x y)
(if (zerop (mod
h (1+ (* 2 y))))
(+ y x)
x))
'(1 2) :initial-
value 0)
(list h "Fizz" "Buzz"
"FizzBuzz")) r))
(reduce (lambda (x y)
(cons (decf n) y))
(make-list (incf n)) :from-end
t)
:from-end t :initial-value nil)))


As for your question about loop, you really should learn it. Even if
you don't use it much yourself, plenty of code written by others does.

Regards,
Joel

From: Rainer Joswig on
In article <p6aFh.35598$p9.19111(a)bignews7.bellsouth.net>,
Brian Adkins <brian(a)lojic.com> wrote:

> Ken Tilton wrote:
> > job-271842874(a)craigslist.org wrote:
> >> job-271842874(a)craigslist.org wrote:
> >> Another friend of mine commenting on the same FizzBuzz thread supplied
> >> the following Python code. It certainly is concise:
> >>
> >> for i in xrange(1,101):
> >> print(str(i), "Fizz", "Buzz", "FizzBuzz")[(i%3==0)|(i%5==0)<<1]
> >
> > But this is a programming disaster, stupid pet trick atop stupid pet
> > trick. It collapses in a heap the minute anything changes. It builds
> > into itself all sorts of things that just happen to be true. You have
> > missed that what I am driving at is good programming, you are caught up
> > in cleverness, the road to hell in programming.
>
> Agreed. Don't read too much into "It certainly is concise." My statement
> was intentionally terse.
>
> In the context of the "FizzBuzz" toy example, it can be fun to look at
> some clever code, but don't infer that I'm "caught up in cleverness". In
> fact, I've counseled countless coders to comprehend the concealed costs
> of clever code. *ducks*
>
> > Let me help you. If, as it seems, the spec is that FizzBuzz is not
> > accidentally Fizz and Buzz together, then the strings Fizz and Buzz must
> > appear only once in the program, as must the tests (mod x 3) and (mod x 5).
>
> I feel the same way; I guess my original Lisp hack wasn't so terrible -
> a couple 'o mods and a couple 'o strings. Incorporating some of the
> feedback from the group gives the following:
>
> (defun fizz-buzz (n)
> (do ((i 1 (+ i 1))) ((> i n))
> (let
> ((fizz (zerop (mod i 3)))
> (buzz (zerop (mod i 5))))
> (when fizz (princ "Fizz"))
> (when buzz (princ "Buzz"))
> (format t "~A~%" (if (or fizz buzz) "" i)))))

In DO you can have more than one clauses for iteration.
So you could get rid of the extra LET.

>
> (fizz-buzz 100)
>
> Now on to chapter 3 "Lists" :)
>
> > The punch line is that no good programmer could write anything in five
> > minutes, unless the instructions included: "Just frickin make these
> > results appear from this input."
> >
> > kt
> >
From: Tim Bradshaw on
On Feb 28, 2:02 am, job-271842...(a)craigslist.org wrote:

>
> 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."

Reading Paul Graham is a bit like reading reviews of films by a good
critic: he is almost always wrong about everything, but has
interesting things to say and it's possible to reliably predict
whether you'll like something from what he says about it (though often
you will differ from him on whether you like it, due to the above-
mentioned almost-always-being-wrong thing). He's kind of the Barry
Norman of Lisp, really.

>
> 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.

Simplicity? consistency? I think you're thinking of some other
language there. CL is this vast industrial thing full of enormous
machines, oil and rust. Some compartments are full of water, and no
one knows what some of the machines do, if anything. Many parts of it
use a mixture of Whitworth & BSF threads (some left-handed), though
much has now been converted to BA or metric, sometimes by use of taps
& dies, sometimes with a hammer.

CL's closest living relative is FORTRAN: always remember that.

Incidentally, I'm deeply disappointed in the quality of answers in
this thread. In the elder days there would have been at least a few
followups showing how to do this in the proper "FORMAT string
indistinguishable from line noise" way. No true CL programmer ever
uses any other construct when the problem can be solved with a
combination of FORMAT, LOOP & GO (FORMAT being always preferable,
obviously). There may yet be those reading cll who know this, though
I suspect they have all gone into the west now.

--tim (who has used the FORMAT string mentioned in
http://www.tfeb.org/lisp/obscurities.html in anger)