Ninety-Nine Bottles Of Beer
August 5, 2011
Somebody has to be the designated driver, so we’ll give the straight forward solution, but you should feel free to be as creative with your solution as you can. Even though it’s straight forward, the appalling badness of Scheme’s string notation is on glaring display:
(define (beer n)
(define (upword str)
(string-append (string (char-upcase (string-ref str 0)))
(substring str 1 (string-length str))))
(let ((n-words (upword (num->words n)))
(n1-words (upword (num->words (- n 1)))))
(if (< 1 n)
(begin
(display n-words)
(display " bottles of beer on the wall.")
(newline)
(display n-words)
(display " bottles of beer.")
(newline)
(display "Take one down and pass it around.")
(newline)
(display n1-words)
(display " bottles of beer on the wall.")
(newline)
(newline)
(beer (- n 1)))
(begin
(display "Only one bottle of beer on the wall.")
(newline)
(display "Only one bottle of beer.")
(newline)
(display "Take it down and pass it around.")
(newline)
(display "Now there's no more beer on the wall.")
(newline)))))
To run the program, say (beer 99).
We wrote the num->words function in a previous exercise. You can run the program at http://programmingpraxis.codepad.org/TMOKOo5n.
already amazingy done in every possibne way : http://99-bottles-of-beer.net/
UNO - Universal Notation (in development) #sing(x,y,z) $'{x} bottle{x|s} of beer on the wall, {x} bottle{x|s} of beer. Take one down and pass it around, {z} bottle{y|s} of beer on the wall',x,y,z ?y=0 $'No more bottles of beer on the wall, no more bottles of beer. Go to the store and buy some more, 99 bottles of beer on the wall.' @99-1:i sing(i,i-1,i-1|'no more')UNO is based in one simple principle: #=def, $=print, ?=cond, @=loop is all you need to build any algorithm
Wrote this a while ago for Rosetta Code:
#!/usr/bin/env python3 """\ {0} {2} of beer on the wall {0} {2} of beer Take one down, pass it around {1} {3} of beer on the wall """ print("\n".join( __doc__.format( i, i - 1, "bottle" if i == 1 else "bottles", "bottle" if i - 1 == 1 else "bottles" ) for i in range(99, 0, -1) ), end=""print '\n'.join('{0} bottle{2} of beer on the wall, {0} bottle{2} of beer!\nTake one down, pass it around,\n{0} bottle{3} of beer on the wall!\n'.format(i, i - 1, i > 1 and 's' or '', i > 2 and 's' or '') for i in range(100, 0, -1))ok, sorry :)
print '\n'.join('{0} bottle{2} of beer on the wall, {0} bottle{2} of beer!\nTake one down, pass it around,\n{1} bottle{3} of beer on the wall!\n'.format(i, i - 1, i > 1 and 's' or '', i > 2 and 's' or '') for i in xrange(99, 0, -1))First time poster. But I’ll give it a shot.
using System;
class Program
{
static void Main(string[] args)
{
for (int number = 99; number > 0; number–)
{
int nextNumber = number – 1;
Console.WriteLine("{0} {1} of beer on the wall, {0} {1} of beer…", number, number > 1 ? "bottles":"bottle" );
Console.WriteLine("Take one down, pass it around {0} {1} of beer on the wall.", nextNumber, nextNumber != 1 ? "bottles" : "bottle");
Console.WriteLine();
}//end for
}
}
Try that again.
using System; class Program { static void Main(string[] args) { for (int number = 99; number > 0; number--) { int nextNumber = number - 1; Console.WriteLine("{0} {1} of beer on the wall, {0} {1} of beer...", number, number > 1 ? "bottles":"bottle" ); Console.WriteLine("Take one down, pass it around {0} {1} of beer on the wall.", nextNumber, nextNumber != 1 ? "bottles" : "bottle"); Console.WriteLine(); }//end for } }Implementations in a zillion languages, including Brainf*ck and INTERCAL:
http://99-bottles-of-beer.net/
http://99-bottles-of-beer.net/language-brainfuck-101.html
http://99-bottles-of-beer.net/language-intercal-333.html
My implementation, which uses C++ template metaprogramming with the Boost MPL library, generates the text of the song at compile time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99bob.cpp
hosted with ❤ by GitHub
It also generates english words instead of digits (i.e. “forty-four” instead of “44”). Not sure if that was part of the brief or not – wasn’t too hard to implement anyway.
Some timing… I recently wrote two versions of the “song”
http://www.emmanueloga.com/2011/07/29/drinking-contest.html
Greetings.
I once SSH’d into my roommate’s mac and ran this little bash script while I was at work and he was home alone.
for ((i=99; i>0 ; i–));
do
let “j = i – 1”;
say $i bottles of beer on the wall;
say $i bottles of beer;
say take one down ;
say pass it around;
say $j bottles of beer on the wall;
done
Then I denied all knowledge of it, and told him the computer must have just been really bored.
def song(num):
if num == 0:
print “Song is over”
elif num == 1:
print str(num) + ” bottle of beer on the wall”
else:
print str(num) + ” bottles of beer on the wall”
song(num-1)
Nothing particularly clever, but FWIW… In PLT Racket.
#lang scheme (require srfi/1) ; for iota ;;; Converts 1 to 99 into words ;;; There's a PLaneT package for this: (require (planet neil/numspell:1:2)) ;;; But I whipped this up before I went to find it ;;; Turns out that Neil used the same two lists that I did (define (number->words n) (let ((uniques '("zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve" "thirteen" "fourteen" "fifteen" "sixteen" "seventeen" "eighteen" "nineteen")) (tens '("twenty" "thirty" "fourty" "fifty" "sixty" "seventy" "eighty" "ninety"))) (cond ((< n 20) (list-ref uniques n)) ((< n 100) (string-append (list-ref tens (- (quotient n 10) 2)) (let ((r (remainder n 10))) (if (= r 0) "" (string-append "-" (list-ref uniques r)))))) (else #f)))) ;;; There's certainly a better way...didn't think too long about it ;;; Unfortunately string-titlecase doesn't do exactly what I want (define (capitalize word) (let-values (((head tail) (car+cdr (string->list word)))) (list->string (cons (char-upcase head) tail)))) ;;; Print the lyrics for "Ninety-nine bottles of beer" ;;; The value of fall (#t or #f) will determine the variant (define (sing-it fall) (for-each (lambda (n) (let ((n-bottles-of-beer (string-append (capitalize (number->words n)) " " (if (= n 1) "bottle" "bottles") " of beer"))) (unless (= n 99) (displayln (string-append n-bottles-of-beer " on the wall!")) (newline)) (displayln (string-append n-bottles-of-beer " on the wall!")) (displayln (string-append n-bottles-of-beer "!")) (if fall (displayln "If one of those bottles should happen to fall,") (displayln "Take one down; pass it around!")))) (iota 99 99 -1)) (displayln "No more bottles of beer on the wall!")) (sing-it #t)