99 Bottles of Beer/Lisp: Difference between revisions
No edit summary |
m (moved to Common Lisp) |
||
Line 58: | Line 58: | ||
* <tt>~:P</tt> is for English plurals: it prints <tt>s</tt> if the last argument wasn't 1; it prints nothing otherwise. There's also <tt>~@P</tt> for <tt>y</tt>/<tt>ies</tt>, in case you were worried about that. |
* <tt>~:P</tt> is for English plurals: it prints <tt>s</tt> if the last argument wasn't 1; it prints nothing otherwise. There's also <tt>~@P</tt> for <tt>y</tt>/<tt>ies</tt>, in case you were worried about that. |
||
Note, by the way, how the emoticons <tt>:*~D</tt> and <tt>:P</tt> have shown up in the format string. FORMAT is so powerful, it's even self-aware about how silly it is. |
Note, by the way, how the emoticons <tt>:*~D</tt> and <tt>:P</tt> have shown up in the format string. FORMAT is so powerful, it's even self-aware about how silly it is. |
||
===Alternate solution=== |
|||
⚫ | |||
⚫ | |||
⚫ | |||
=={{header|Lisp}}== |
|||
Bit of a beginner in Lisp, but this seems to work: |
Bit of a beginner in Lisp, but this seems to work: |
||
<lang lisp> |
<lang lisp> |
||
Line 82: | Line 77: | ||
(beer-verse 99) |
(beer-verse 99) |
||
</lang> |
</lang> |
||
⚫ | |||
⚫ | |||
⚫ | |||
=={{header|NewLISP}}== |
=={{header|NewLISP}}== |
Revision as of 12:43, 10 March 2018
99 Bottles of Beer done in Lisp-languages
ACL2
<lang Lisp>(defun bottles-of-beer (n)
(if (zp n) nil (prog2$ (cw (concatenate 'string "~%" "~N0 bottle~#1~[~/s~] of beer on the wall,~%" "~n0 bottle~#1~[~/s~] of beer.~%" "Take one down, pass it around,~%" "~n2 bottle~#3~[~/s~] of beer on the wall.~%") n (if (= n 1) 0 1) (1- n) (if (= n 2) 0 1)) (bottles-of-beer (- n 1)))))</lang>
Common Lisp
Sensible solution
<lang lisp>(defun bottles (x)
(loop for bottles from x downto 1 do (format t "~a bottle~:p of beer on the wall
~:*~a bottle~:p of beer Take one down, pass it around ~a bottle~:p of beer on the wall~2%" bottles (1- bottles))))</lang> and then just call <lang lisp>(bottles 99)</lang>
Ridiculous
<lang lisp>(format t "~{~[~^~]~:*~D bottle~:P of beer on the wall~%~:*~D bottle~:P of beer~%Take one down, pass it around~%~D bottle~:P~:* of beer on the wall~2%~}"
(loop :for n :from 99 :downto 0 :collect n))</lang>
The FORMAT function is probably the most baroque (i.e. featureful almost to a fault) function in Common Lisp. To really drive this point home, try replacing each instance of ~D with ~R, and then with ~@R. Yes, this is all standard and dependable (dys?)functionality.
Explanation of the format string for the uninitiated:
- ~{fmt~} expects the next argument to be a list (which is of the integers from 99 down to 0), and executes the format string fmt on each element. It is essentially a map or foreach.
- ~[...~] is a case/switch. It executes the nth clause, where n is taken from the next argument. Since there is only one clause here, it will be executed only when the argument is 0.
- ~^ will terminate formatting.
- ~:* will back-up to the most-recently used argument.
- ~D prints the next argument as a decimal number.
- ~:P is for English plurals: it prints s if the last argument wasn't 1; it prints nothing otherwise. There's also ~@P for y/ies, in case you were worried about that.
Note, by the way, how the emoticons :*~D and :P have shown up in the format string. FORMAT is so powerful, it's even self-aware about how silly it is.
Alternate solution
Bit of a beginner in Lisp, but this seems to work: <lang lisp> (defun beer-verse (count)
"Recurses the verses" (format t "~A bottle~:P of beer on the wall~%" count) (format t "~A bottle~:P of beer~%" count) (format t "Take one down, pass it round~%") (format t "~A bottle~A of beer on the wall~%~%"
(if (= count 1) "No" (- count 1)) (if (/= count 2) "s" ""))
(if (> count 1) (beer-verse (- count 1))))
(beer-verse 99) </lang>
NewLISP
<lang newlisp>(for (n 99 1) (println n " bottles of beer on the wall," n " bottles of beer. Take one down, pass it around. ") (println (- n 1) "bottles of beer on the wall!"))
- recursive
- also shows list afterword
(define (rec bottles) (if (!= 0 bottles) (print "/n" bottles " bottles of beer on the wall" bottles " bottles of beer. \nTake one down, pass it around, " (- bottles 1) " bottles of beer on the wall" (rec ( - bottles 1))))(list bottles))
(rec 99)</lang>
Ol
<lang ol> (setq nn 99) (let loop ((n nn))
(print n " bottles of beer on the wall,") (print n " bottles of beer.") (print "Take one down, pass it around, ") (if (eq? n 1) (begin (print "No more bottles of beer on the wall.") (print)) (begin (print (- n 1) " bottles of beer on the wall,") (print) (loop (- n 1)))))
(print "No more bottles of beer on the wall,") (print "No more bottles of beer.") (print "Go to the store and buy some more,") (print nn " bottles of beer on the wall.") </lang>
PicoLisp
<lang PicoLisp>(de bottles (N)
(case N (0 "No more beer") (1 "One bottle of beer") (T (cons N " bottles of beer")) ) )
(for (N 99 (gt0 N))
(prinl (bottles N) " on the wall,") (prinl (bottles N) ".") (prinl "Take one down, pass it around,") (prinl (bottles (dec 'N)) " on the wall.") (prinl) )</lang>
Shen
<lang Shen>(define bottles-h
{ number --> string } 0 -> "No more beer" 1 -> "One bottle of beer" N -> (make-string "~A bottles of beer" N))
(define bottles
{ number --> number } 0 -> 0 X -> (let Msg (bottles-h X) (do (output "~A on the wall~%~A~%Take one down, pass it around~%~A on the wall~%~%" Msg Msg (bottles-h (- X 1))) (bottles (- X 1)))))</lang>
Wart
<lang python>def (beer n)
when (n > 0) prn n " bottles of beer on the wall" prn n " bottles of beer" prn "take one down, pass it around" prn n-1 " bottles of beer on the wall" prn "" beer n-1</lang>