99 Bottles of Beer/Lisp: Difference between revisions

From Rosetta Code
Content added Content deleted
(Add Shen)
imported>Rowsety Moid
No edit summary
 
(9 intermediate revisions by 6 users not shown)
Line 4: Line 4:
{{collection|99 Bottles of Beer}}
{{collection|99 Bottles of Beer}}
[[99 Bottles of Beer]] done in Lisp-languages
[[99 Bottles of Beer]] done in Lisp-languages

<!--
See [[99 Bottles of Beer/Lisp]]
-->


<!-- still missing:
<!-- still missing:
Line 15: Line 11:
__toc__
__toc__


=={{header|ACL2}}==
===ACL2===
<lang Lisp>(defun bottles-of-beer (n)
<syntaxhighlight lang="lisp">(defun bottles-of-beer (n)
(if (zp n)
(if (zp n)
nil
nil
Line 29: Line 25:
(1- n)
(1- n)
(if (= n 2) 0 1))
(if (= n 2) 0 1))
(bottles-of-beer (- n 1)))))</lang>
(bottles-of-beer (- n 1)))))</syntaxhighlight>


=={{header|Common Lisp}}==
===Acornsoft Lisp===
<syntaxhighlight lang="lisp">(defun bottles ((n . 99))
===Sensible solution===
(loop
<lang lisp>(defun bottles (x)
(bob n) (otw) (nl)
(bob n) (nl)
(tod-pia) (nl) (setq n (sub1 n))
(bob n) (otw) (nl)
(nl)
(until (zerop n))))

(defun nl ()
(printc))

(defun sing (w)
(princ w '! ))

(defun bob (n)
(map sing
(list (any? n) (plural? n 'bottle 'bottles) 'of 'beer)))

(defun otw ()
(map sing (list 'on 'the 'wall)))

(defun tod-pia ()
(map sing (list 'Take 'one 'down!, 'pass 'it 'around)))

(defun any? (n)
(cond ((zerop n) 'no)
(t n)))

(defun plural? (n sing plur)
(cond ((onep n) sing)
(t plur)))</syntaxhighlight>

===Common Lisp===
====Sensible solution====
<syntaxhighlight lang="lisp">(defun bottles (x)
(loop for bottles from x downto 1
(loop for bottles from x downto 1
do (format t "~a bottle~:p of beer on the wall
do (format t "~a bottle~:p of beer on the wall~@
~:*~a bottle~:p of beer
~:*~a bottle~:p of beer~@
Take one down, pass it around
Take one down, pass it around~@
~a bottle~:p of beer on the wall~2%" bottles (1- bottles))))</lang>
~V[No more~:;~:*~a bottle~:p of~] beer on the wall~2%"
bottles (1- bottles))))
</syntaxhighlight>
and then just call
and then just call
<lang lisp>(bottles 99)</lang>
<syntaxhighlight lang="lisp">(bottles 99)</syntaxhighlight>


===Ridiculous===
====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%~}"
<syntaxhighlight 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>
(loop :for n :from 99 :downto 0 :collect n))</syntaxhighlight>
The [http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm FORMAT function] is probably the most baroque (i.e. featureful almost to a fault) function in Common Lisp.
The [http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm 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 <tt>~D</tt>
To really drive this point home, try replacing each instance of <tt>~D</tt>
Line 58: Line 90:
* <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====

<!-- missing here:
=={{header|Emacs Lisp}}==
-->

=={{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>
<syntaxhighlight lang="lisp">
(defun beer-verse (count)
(defun beer-verse (count)
"Recurses the verses"
"Recurses the verses"
Line 81: Line 108:
(beer-verse (- count 1))))
(beer-verse (- count 1))))
(beer-verse 99)
(beer-verse 99)
</syntaxhighlight>
</lang>


<!-- missing here:
{{Out}} (last three verses only):
===Emacs Lisp===
<pre>
-->
3 bottles of beer on the wall
3 bottles of beer
Take one down, pass it round
2 bottles of beer on the wall

2 bottles of beer on the wall
2 bottles of beer
Take one down, pass it round
1 bottle of beer on the wall

1 bottle of beer on the wall
1 bottle of beer
Take one down, pass it round
No bottles of beer on the wall
</pre>


===newLISP===
=={{header|NewLISP}}==
<lang newlisp>(for (n 99 1)
<syntaxhighlight 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 " 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!"))
(println (- n 1) "bottles of beer on the wall!"))
Line 113: Line 126:
" bottles of beer on the wall" (rec ( - bottles 1))))(list bottles))
" bottles of beer on the wall" (rec ( - bottles 1))))(list bottles))


(rec 99)</lang>
(rec 99)</syntaxhighlight>

===Ol===
<syntaxhighlight lang="scheme">
(define nn 99)

(for-each (lambda (n)
(let ((bottle (lambda (n) (if (eq? n 1) " bottle" " bottles")))
(m (- n 1)))
(print
n (bottle n) " of beer on the wall, "
n (bottle n) " of beer." "\n"
"Take one down and pass it around, "
(if (eq? m 0) "no more" m)
(bottle m) " of beer on the wall.\n")))
(reverse (iota nn 1)))
(print
"No more bottles of beer on the wall, "
"no more bottles of beer." "\n"
"Go to the store and buy some more, "
nn " bottles of beer on the wall.")
</syntaxhighlight>


=={{header|PicoLisp}}==
===PicoLisp===
<lang PicoLisp>(de bottles (N)
<syntaxhighlight lang="picolisp">(de bottles (N)
(case N
(case N
(0 "No more beer")
(0 "No more beer")
Line 127: Line 161:
(prinl "Take one down, pass it around,")
(prinl "Take one down, pass it around,")
(prinl (bottles (dec 'N)) " on the wall.")
(prinl (bottles (dec 'N)) " on the wall.")
(prinl) )</lang>
(prinl) )</syntaxhighlight>


=={{header|Shen}}==
===Shen===
<lang Shen>(define bottles-h
<syntaxhighlight lang="shen">(define bottles-h
{ number --> string }
{ number --> string }
0 -> "No more beer"
0 -> "No more beer"
Line 141: Line 175:
X -> (let Msg (bottles-h X)
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)))
(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>
(bottles (- X 1)))))</syntaxhighlight>


=={{header|Wart}}==
===Wart===
<lang python>def (beer n)
<syntaxhighlight lang="python">def (beer n)
when (n > 0)
when (n > 0)
prn n " bottles of beer on the wall"
prn n " bottles of beer on the wall"
Line 151: Line 185:
prn n-1 " bottles of beer on the wall"
prn n-1 " bottles of beer on the wall"
prn ""
prn ""
beer n-1</lang>
beer n-1</syntaxhighlight>

Latest revision as of 11:44, 3 September 2023

99 Bottles of Beer/Lisp is part of 99 Bottles of Beer. You may find other members of 99 Bottles of Beer at Category:99 Bottles of Beer.

99 Bottles of Beer done in Lisp-languages


ACL2

(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)))))

Acornsoft Lisp

(defun bottles ((n . 99))
  (loop
    (bob n) (otw) (nl)
    (bob n)       (nl)
    (tod-pia)     (nl)  (setq n (sub1 n))
    (bob n) (otw) (nl)
    (nl)
    (until (zerop n))))

(defun nl ()
  (printc))

(defun sing (w)
  (princ w '! ))

(defun bob (n)
  (map sing
    (list (any? n) (plural? n 'bottle 'bottles) 'of 'beer)))

(defun otw ()
  (map sing (list 'on 'the 'wall)))

(defun tod-pia ()
  (map sing (list 'Take 'one 'down!, 'pass 'it 'around)))

(defun any? (n)
  (cond ((zerop n) 'no)
        (t n)))

(defun plural? (n sing plur)
  (cond ((onep n) sing)
        (t plur)))

Common Lisp

Sensible solution

(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~@
                      ~V[No more~:;~:*~a bottle~:p of~] beer on the wall~2%"
                   bottles (1- bottles))))

and then just call

(bottles 99)

Ridiculous

(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))

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:

(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)


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)

Ol

(define nn 99)

(for-each (lambda (n)
   (let ((bottle (lambda (n) (if (eq? n 1) " bottle" " bottles")))
         (m (- n 1)))
      (print
         n (bottle n) " of beer on the wall, "
         n (bottle n) " of beer." "\n"
         "Take one down and pass it around, "
         (if (eq? m 0) "no more" m)
         (bottle m) " of beer on the wall.\n")))
   (reverse (iota nn 1)))
(print
   "No more bottles of beer on the wall, "
   "no more bottles of beer." "\n"
   "Go to the store and buy some more, "
   nn " bottles of beer on the wall.")

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

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

Wart

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