From: job-271842874 on 28 Feb 2007 02:33 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 28 Feb 2007 02:46 <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 28 Feb 2007 03:17 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 28 Feb 2007 03:24 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 28 Feb 2007 05:33
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) |