99 bottles of beer
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
In this puzzle, write code to print out the entire "99 bottles of beer on the wall" song. For those who do not know the song, the lyrics follow this form:
X bottles of beer on the wall X bottles of beer Take one down, pass it around X-1 bottles of beer on the wall X-1 bottles of beer on the wall ... Take one down, pass it around 0 bottles of beer on the wall
Where X and X-1 are replaced by numbers of course. Grammatical support for "1 bottle of beer" is optional. As with any puzzle, try to do it in as creative/concise/comical a way as possible (simple, obvious solutions allowed, too).
See also: http://99-bottles-of-beer.net/
ABAP
<lang ABAP>REPORT z99bottles.
DATA lv_no_bottles(2) TYPE n VALUE 99.
DO lv_no_bottles TIMES.
WRITE lv_no_bottles NO-ZERO. WRITE ' bottles of beer on the wall'. NEW-LINE. WRITE lv_no_bottles NO-ZERO. WRITE ' bottles of beer'. NEW-LINE. WRITE 'Take one down, pass it around'. NEW-LINE. SUBTRACT 1 FROM lv_no_bottles. WRITE lv_no_bottles NO-ZERO. WRITE ' bottles of beer on the wall'. WRITE /.
ENDDO.</lang>
ActionScript
<lang ActionScript>for(var numBottles:uint = 99; numBottles > 0; numBottles--) { trace(numBottles, " bottles of beer on the wall"); trace(numBottles, " bottles of beer"); trace("Take one down, pass it around"); trace(numBottles - 1, " bottles of beer on the wall\n"); }</lang>
Ada
Simple version
<lang ada>with Ada.Text_Io; use Ada.Text_Io;
procedure Bottles is begin for X in reverse 1..99 loop Put_Line(Integer'Image(X) & " bottles of beer on the wall"); Put_Line(Integer'Image(X) & " bottles of beer"); Put_Line("Take one down, pass it around"); Put_Line(Integer'Image(X - 1) & " bottles of beer on the wall"); New_Line; end loop; end Bottles;</lang>
Concurrent version
with 1 task to print out the information and 99 tasks to specify the number of bottles <lang Ada>with Ada.Text_Io; use Ada.Text_Io;
procedure Tasking_99_Bottles is
subtype Num_Bottles is Natural range 1..99; task Print is entry Set (Num_Bottles); end Print; task body Print is Num : Natural; begin for I in reverse Num_Bottles'range loop select accept Set(I) do -- Rendezvous with Counter task I Num := I; end Set; Put_Line(Integer'Image(Num) & " bottles of beer on the wall"); Put_Line(Integer'Image(Num) & " bottles of beer"); Put_Line("Take one down, pass it around"); Put_Line(Integer'Image(Num - 1) & " bottles of beer on the wall"); New_Line; or terminate; -- end when all Counter tasks have completed end select; end loop; end Print; task type Counter(I : Num_Bottles); task body Counter is begin Print.Set(I); end Counter; type Task_Access is access Counter; Task_List : array(Num_Bottles) of Task_Access;
begin
for I in Task_List'range loop -- Create 99 Counter tasks Task_List(I) := new Counter(I); end loop;
end Tasking_99_Bottles;</lang>
Aime
<lang aime>integer main(void) {
cardinal bottles;
bottles = 99;
do {
o_cardinal(bottles);
o_text(" bottles of beer on the wall\n");
o_cardinal(bottles);
o_text(" bottles of beer\n"); o_text("Take one down, pass it around\n"); bottles -= 1;
o_cardinal(bottles);
o_text(" bottles of beer on the wall\n\n"); } while (bottles);
return 0;
}</lang>
ALGOL 68
<lang algol68>main:(
FOR bottles FROM 99 TO 1 BY -1 DO printf(($z-d" bottles of beer on the wall"l$, bottles)); printf(($z-d" bottles of beer"l$, bottles)); printf(($"Take one down, pass it around"l$)); printf(($z-d" bottles of beer on the wall"ll$, bottles-1)) OD
)</lang>
AmigaE
<lang amigae>PROC main()
DEF t: PTR TO CHAR, s: PTR TO CHAR, u: PTR TO CHAR, i, x t := 'Take one down, pass it around\n' s := '\d bottle\s of beer\s\n' u := ' on the wall' FOR i := 99 TO 0 STEP -1 ForAll({x}, [u, NIL], `WriteF(s, i, IF i <> 1 THEN 's' ELSE NIL, x)) IF i > 0 THEN WriteF(t) ENDFOR
ENDPROC</lang>
APL
bob ← { (⍕⍵), ' bottle', (1=⍵)↓'s of beer'} bobw ← {(bob ⍵) , ' on the wall'} beer ← { (bobw ⍵) , ', ', (bob ⍵) , '; take one down and pass it around, ', bobw ⍵-1} ↑beer¨ ⌽(1-⎕IO)+⍳99
Argile
<lang Argile>use std
let X be an int for each X from 99 down to 1
prints X bottles of beer on the wall prints X bottles of beer prints "Take one down, pass it" around if X == 1 echo No more "beer." Call da "amber lamps" break X-- prints X bottles of beer on the wall "\n" X++ .:around :. -> text {X>59 ? "around", "to me"} .:bottles:. -> text {X> 5 ? "bottles", (X>1 ? "buttles", "wall")} .:of beer:. -> text {X>11 ? "of beer", "ov beeer"} .:on the wall:. -> text { X>17 ? "on the wall", (X>1 ? "on the bwall", "in the buttle") }</lang>
AutoHotkey
<lang AutoHotkey>; RC: 99 bottles of beer
b = 99 Loop, %b% { s .= b . " bottles of beer on the wall,`n" . b . " bottles of beer.`nTake one down, pass it around,`n" . b-1 . " bottles of beer on the wall.`n`n" b-- } Gui, Add, Edit, w200 h200, %s% Gui, Show, , 99 bottles of beer
Return ; end of auto-execute section
GuiClose:
ExitApp
Return</lang>
Delayed Sing along <lang AutoHotkey>n=99 Gui, Font, s20 cMaroon, Comic Sans MS Gui, Add, Text, w500 vLyrics, %n% bottles of beer on the wall... Gui, Show Loop {
Sleep, 2000 GuiControl,,Lyrics,% n!=1 ? n " bottles of beer.":n " bottle of beer." Sleep, 2000 GuiControl,,Lyrics,% n ? "Take one down, pass it around...":"Go to the store, buy some more..." Sleep, 2000 n := n ? --n:99 GuiControl,,Lyrics,% n!=1 ? n " bottles of beer on the wall.":n " bottle of beer on the wall." Sleep, 2000 GuiControl,,Lyrics,% n!=1 ? n " bottles of beer on the wall...":n " bottle of beer on the wall..."
} GuiClose: ExitApp</lang>
Fast and Short <lang AutoHotkey>b=99 Loop, %b% { s := b " bottles of beer on the wall, " b " bottles of beer, Take one down, pass it around " b-1 " bottles of beer on the wall" b-- TrayTip,,%s% sleep, 40 }</lang>
With a GUI and slight grammatical variation: <lang AutoHotkey>N=o more Z=99 L:=Z M:=(B:=" bottle")"s" Loop 99 V.=L (W:=(O:=" of beer")" on the wall")",`n"L O ",`nTake one down and pass it around,`n"(L:=(--Z ? Z:"N"N)(Z=1 ? B:M))W ".`n`n" Gui,Add,Edit,w600 h250,% V L W ", n"N M O ".`nGo to the store and buy some more, 99"M W "." Gui,Show Return GuiClose: ExitApp</lang>
AutoIt
<lang AutoIt>
local $bottleNo=99
local $lyrics=" "
While $bottleNo<>0 If $bottleNo=1 Then $lyrics&=$bottleNo & " bottles of beer on the wall" & @CRLF $lyrics&=$bottleNo & " bottles of beer" & @CRLF $lyrics&="Take one down, pass it around" & @CRLF Else $lyrics&=$bottleNo & " bottles of beer on the wall" & @CRLF $lyrics&=$bottleNo & " bottles of beer" & @CRLF $lyrics&="Take one down, pass it around" & @CRLF EndIf If $bottleNo=1 Then $lyrics&=$bottleNo-1 & " bottle of beer" & @CRLF Else $lyrics&=$bottleNo-1 & " bottles of beer" & @CRLF EndIf $bottleNo-=1 WEnd MsgBox(1,"99",$lyrics) </lang>
AWK
<lang awk>{ i = 99 while (i > 0) {print i, " bottles of beer on the wall," print i, " bottles of beer." print "Take one down, pass it around," i-- print i, " bottles of beer on the wall\n"}}</lang>
BASIC
Sound
This version plays the tune 100 times while printing out the lyrics (not synchronized). <lang qbasic>PLAY "<" FOR x = 99 TO 0 STEP -1
PRINT x; "bottles of beer on the wall" PRINT x; "bottles of beer" PRINT "Take one down, pass it around" PRINT x-1; "bottles of beer on the wall" PRINT PLAY "e-8e-8e-8<b-8b-8b-8>e-8e-8e-8e-4"'X bottles of beer on the wall PLAY "f8f8f8c8c8c8f4"'X bottles of beer PLAY "d4d8d8 N0 d8d8d8d4"'take one down, pass it around PLAY "<a+8a+8a+8>c8c8d8d+8d+8d+8d+4"'X-1 bottles of beer on the wall
NEXT x</lang>
Text
<lang qbasic>FOR x = 99 TO 1 STEP -1
PRINT x; "bottles of beer on the wall" PRINT x; "bottles of beer" PRINT "Take one down, pass it around" PRINT x-1; "bottles of beer on the wall" PRINT
NEXT x</lang>
Batch File
<lang dos>@echo off setlocal
- main
for /L %%i in (99,-1,1) do ( call :verse %%i ) echo no bottles of beer on the wall echo no bottles of beer echo go to the store and buy some more echo 99 bottles of beer on the wall echo. set /p q="Keep drinking? " if %q% == y goto main if %q% == Y goto main goto :eof
- verse
call :plural %1 res echo %res% of beer on the wall echo %res% of beer call :oneit %1 res echo take %res% down and pass it round set /a c=%1-1 call :plural %c% res echo %res% of beer on the wall echo. goto :eof
- plural
if %1 gtr 1 goto :gtr if %1 equ 1 goto :equ set %2=no bottles goto :eof
- gtr
set %2=%1 bottles goto :eof
- equ
set %2=1 bottle goto :eof
- oneit
if %1 equ 1 ( set %2=it ) else ( set %2=one ) goto :eof</lang>
BBC BASIC
<lang bbcbasic>
N_Bottles = 99 beer$ = " of beer" wall$ = " on the wall" unit$ = "99 bottles" WHILE N_Bottles >= 0 IF N_Bottles=0 THEN PRINT '"No more bottles" beer$ wall$ ", " unit$ beer$ "." PRINT "Go to the store and buy some more, "; ELSE PRINT 'unit$ beer$ wall$ ", " unit$ beer$ "." PRINT "Take one down and pass it around, "; ENDIF N_Bottles -= 1 CASE N_Bottles OF WHEN 0: unit$ = "no more bottles" WHEN 1: unit$ = "1 bottle" OTHERWISE: unit$ = STR$((N_Bottles + 100) MOD 100) + " bottles" ENDCASE PRINT unit$ beer$ wall$ "." ENDWHILE END
</lang>
Befunge
This outputs a single CR (ASCII code 13) between verses; this needs changing for systems other than DOS, Windows, and Mac OS.
<lang befunge><v <.g10" bottles of beer on the wall"+*4310 < c>:,|
<v <.g10" bottles of beer"+*4310 >:,| <v <"take one down, pass it around"+*4310 >:,| >01g1-:01p v
v <.g10" bottles of beer on the wall"+*4310< >:,|
>134*+0` | @</lang>
Brainf***
<lang bf>>+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>> [-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+< -]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<< [>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++ +++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>- ]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+ ++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]> >>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++ +>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------
>-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++
++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++ [<---------->-]<++.>++++++++[<++++++++++>-]<++++.----------- -.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-. >++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<
.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++
+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<. ><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++ ++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++ +++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++ +++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]< -.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++.
.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-.
-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>- ]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-] <++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++ +++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<-----> -]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[< ++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++ .>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.---- ---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[ -]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-] >[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]< <+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]< <-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+ <<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++> -]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---
.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++
.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<- -.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-] <.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[ <+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++ ++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+. >++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++ ..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]</lang>
Brat
<lang brat>99.to 2 { n |
p "#{n} bottles of beer on the wall, #{n} bottles of beer!" p "Take one down, pass it around, #{n - 1} bottle#{true? n > 2 's' } of beer on the wall."
}
p "One bottle of beer on the wall, one bottle of beer!" p "Take one down, pass it around, no more bottles of beer on the wall."</lang>
C
The simple solution
<lang c>#include <stdlib.h>
- include <stdio.h>
int main(void) {
unsigned int bottles = 99; do { printf("%u bottles of beer on the wall\n", bottles); printf("%u bottles of beer\n", bottles); printf("Take one down, pass it around\n"); printf("%u bottles of beer on the wall\n\n", --bottles); } while(bottles > 0); return EXIT_SUCCESS;
}</lang>
Code golf
<lang c>#include <stdio.h> main(){_=100;while(--_)printf("%i bottle%s of beer in the wall,\n%i bottle%" "s of beer.\nTake one down, pass it round,\n%s%s\n\n",_,_-1?"s":"",_,_-1?"s"
- "",_-1?(char[]){(_-1)/10?(_-1)/10+48:(_-1)%10+48,(_-1)/10?(_-1)%10+48:2+30,
(_-1)/10?32:0,0}:"",_-1?"bottles of beer in the wall":"No more beers");}</lang>
A preprocessor solution
Of course, with the template metaprogramming solution, the program has still do the conversion of numbers to strings at runtime, and those function calls also cost unnecessary time. Couldn't we just compose the complete text at compile time, and just output it at run time? Well, with the preprocessor, that's indeed possible:
<lang c>#include <stdlib.h>
- include <stdio.h>
- define BOTTLE(nstr) nstr " bottles of beer"
- define WALL(nstr) BOTTLE(nstr) " on the wall"
- define PART1(nstr) WALL(nstr) "\n" BOTTLE(nstr) \
"\nTake one down, pass it around\n"
- define PART2(nstr) WALL(nstr) "\n\n"
- define MIDDLE(nstr) PART2(nstr) PART1(nstr)
- define SONG PART1("100") CD2 PART2("0")
- define CD2 CD3("9") CD3("8") CD3("7") CD3("6") CD3("5") \
CD3("4") CD3("3") CD3("2") CD3("1") CD4("")
- define CD3(pre) CD4(pre) MIDDLE(pre "0")
- define CD4(pre) MIDDLE(pre "9") MIDDLE(pre "8") MIDDLE(pre "7") \
MIDDLE(pre "6") MIDDLE(pre "5") MIDDLE(pre "4") MIDDLE(pre "3") \ MIDDLE(pre "2") MIDDLE(pre "1")
int main(void) {
(void) printf(SONG); return EXIT_SUCCESS;
}</lang>
An inspection of the generated executable proves that it indeed contains the complete text of the song in one block.
The bottled version
WYSIWYG (with correct plurals and can buy some more):<lang c> int b= 99,u=1;
#include<stdio.h> char * d[ 16 ]; char y[]= "#:o" "ttle/ of:eer" "_ a_Go<o5st>" "y\x20some6_T" "ake8;down4pa" "=1rou7_17 _<" "h;_ m?_nd_ o" "n_085wall_ b" "_e _ t_ss it" "_?4bu_ore_9," " \060.@, 9$"; # define xor ^= #include<string.h> #define or(x,z) else\ if(c==x/*smokescreen*/\ && !(c = 0) && (c =! z));
int p(char*x){char *s = x \
- unsigned char c; for ( d[
c = 0]=y; ! x && (d[c + 1]= strchr( s = d[c], '_')); *( d[++c]++)= 0); for (x = s?: x; (c = *s++); c?putchar(c)
- 0) {if (! (((c xor 48) & ~
0xf) && (c xor 48 ))) p( d[ c ]), c = 0; or ('$', p (b- 99 ? ".\n":".") && p (b- 99 ? x : "")) or( '\x40', c && p(d[!!b--+2])) or('/', c && p (b ^1 ? "s" : "")) or( '\ \043', b++ ? p("So6"+--b) : ! printf ( "%d" , b? -- b : (b += 99 ) ) ) or ('S', !( ++u % 3 ) * 32 + 78) or('.' ,puts("" ".")) } return c;}
int main() {return p(0);}</lang>
C++
The simple solution
<lang cpp>#include <iostream> using namespace std;
int main() {
int bottles = 99; do { cout << bottles << " bottles of beer on the wall" << endl; cout << bottles << " bottles of beer" << endl; cout << "Take one down, pass it around" << endl; cout << --bottles << " bottles of beer on the wall\n" << endl; } while (bottles > 0);
}</lang>
An object-oriented solution
See: 99 Bottles of Beer/C++/Object Oriented
A template metaprogramming solution
Of course, the output of the program always looks the same. One may therefore question why the program has to do all that tedious subtracting during runtime. Couldn't the compiler just generate the code to output the text, with ready-calculated constants? Indeed, it can, and the technique is called template metaprogramming. The following short code gives the text without containing a single variable, let alone a loop:
<lang cpp>#include <iostream>
template<int max, int min> struct bottle_countdown {
static const int middle = (min + max)/2; static void print() { bottle_countdown<max, middle+1>::print(); bottle_countdown<middle, min>::print(); }
};
template<int value> struct bottle_countdown<value, value> {
static void print() { std::cout << value << " bottles of beer on the wall\n" << value << " bottles of beer\n" << "Take one down, pass it around\n" << value-1 << " bottles of beer\n\n"; }
};
int main() {
bottle_countdown<100, 1>::print(); return 0;
}</lang>
A Recursive solution
<lang cpp>#include <iostream> using namespace std; void rec(int bottles) { if ( bottles!=0)
{ cout << bottles << " bottles of beer on the wall" << endl; cout << bottles << " bottles of beer" << endl; cout << "Take one down, pass it around" << endl; cout << --bottles << " bottles of beer on the wall\n" << endl; rec(bottles); }
}
int main()
{
rec(99); system("pause"); return 0; } </lang>
A preprocessor solution
Of course, with the template metaprogramming solution, the program has still do the conversion of numbers to strings at runtime, and those function calls also cost unnecessary time. Couldn't we just compose the complete text at compile time, and just output it at run time? Well, with the preprocessor, that's indeed possible:
<lang cpp>#include <iostream>
- include <ostream>
- define BOTTLE(nstr) nstr " bottles of beer"
- define WALL(nstr) BOTTLE(nstr) " on the wall"
- define PART1(nstr) WALL(nstr) "\n" BOTTLE(nstr) \
"\nTake one down, pass it around\n"
- define PART2(nstr) WALL(nstr) "\n\n"
- define MIDDLE(nstr) PART2(nstr) PART1(nstr)
- define SONG PART1("100") CD2 PART2("0")
- define CD2 CD3("9") CD3("8") CD3("7") CD3("6") CD3("5") \
CD3("4") CD3("3") CD3("2") CD3("1") CD4("")
- define CD3(pre) CD4(pre) MIDDLE(pre "0")
- define CD4(pre) MIDDLE(pre "9") MIDDLE(pre "8") MIDDLE(pre "7") \
MIDDLE(pre "6") MIDDLE(pre "5") MIDDLE(pre "4") MIDDLE(pre "3") \ MIDDLE(pre "2") MIDDLE(pre "1")
int main() {
std::cout << SONG; return 0;
}</lang>
C#
<lang csharp>using System;
class Program {
static void Main(string[] args) { for (int i = 99; i > -1; i--) { if (i == 0) { Console.WriteLine("No more bottles of beer on the wall, no more bottles of beer."); Console.WriteLine("Go to the store and buy some more, 99 bottles of beer on the wall."); break; } if (i == 1) { Console.WriteLine("1 bottle of beer on the wall, 1 bottle of beer."); Console.WriteLine("Take one down and pass it around, no more bottles of beer on the wall."); Console.WriteLine(); } else { Console.WriteLine("{0} bottles of beer on the wall, {0} bottles of beer.", i); Console.WriteLine("Take one down and pass it around, {0} bottles of beer on the wall.", i - 1); Console.WriteLine(); } } }
}</lang>
Another Implementation using Linq
<lang csharp>using System; using System.Linq;
class Program {
static void Main() { var query = from total in Enumerable.Range(0,100).Reverse() select (total > 0) ? string.Format("{0} bottles of beer on the wall\n{0} bottles of beer\nTake one down, pass it around", total) : string.Format("{0} bottles left", total); foreach (var item in query) { Console.WriteLine(item); } }
}</lang>
Using iterator blocks
<lang csharp>using System; using System.Linq;
class Program {
static void Main() { BeerBottles().Take(99).ToList().ForEach(Console.WriteLine); }
static IEnumerable<String> BeerBottles() { int i = 100; String f = "{0}, {1}. Take one down, pass it around, {2}"; Func<int, bool, String> booze = (c , b) => String.Format("{0} bottle{1} of beer{2}", c > 0 ? c.ToString() : "no more", (c == 1 ? "" : "s"), b ? " on the wall" : "");
while (--i >= 1) yield return String.Format(f, booze(i, true), booze(i, false), booze(i - 1, true)); }
}</lang>
Clay
<lang Clay>/* A few options here: I could give n type Int; or specify that n is of any
numeric type; but here I just let it go -- that way it'll work with anything that compares with 1 and that printTo knows how to convert to a string. And all checked at compile time, remember. */
getRound(n) {
var s = String(); var bottle = if (n == 1) " bottle " else " bottles "; printTo(s, n, bottle, "of beer on the wall\n", n, bottle, "of beer\n", "take one down, pass it around\n", n, bottle, "of beer on the wall!\n"); return s;
}
main() {
println(join("\n", mapped(getRound, reversed(range(100)))));
} </lang>
Chef
<lang chef>99 Bottles Of Beer.
Ingredients. 99 bottles
Method. Loop the bottles. Put bottles into 1st mixing bowl. Serve with bottles of beer on the wall. Clean 1st mixing bowl. Put bottles into 1st mixing bowl. Serve with bottles of beer. Clean 1st mixing bowl. Serve with Take one down and pass it around. Clean 1st mixing bowl. Loop the bottles until looped. Serve with No more bottles of beer. Clean 1st mixing bowl. Pour contents of the 3rd mixing bowl into the 1st baking dish.
Serves 1.
bottles of beer on the wall.
Prints out "n" bottles of beer on the wall.
Ingredients. 108 g lime 97 cups asparagus 119 pinches watercress 32 tablespoons pickles 101 pinches eggplant 104 g huckleberry 116 teaspoons turnip 110 tablespoons nannyberry 111 tablespoons onion 114 tablespoons raspberry 98 g broccoli 102 g feijoa 115 teaspoons squach 10 ml new line
Method. Put new line into 1st mixing bowl. Put lime into 2nd mixing bowl. Put lime into 2nd mixing bowl. Put asparagus into 2nd mixing bowl. Put watercress into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put huckleberry into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put nannyberry into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put raspberry into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put broccoli into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put feijoa into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put squach into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put lime into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put broccoli into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Liquify contents of the 2nd mixing bowl. Pour contents of the 2nd mixing bowl into the baking dish. Pour contents of the mixing bowl into the baking dish. Refrigerate for 1 hour.
bottles of beer.
Prints out "n" bottles of beer.
Ingredients. 114 tablespoons raspberry 101 pinches eggplant 98 teaspoons broccoli 32 pinches pickles 102 tablespoons feijoa 111 teaspoons onion 115 cups squach 108 cups lime 116 teaspoons turnip 10 ml new line
Method. Put new line into 1st mixing bowl. Put raspberry into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put broccoli into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put feijoa into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put squach into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put lime into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put broccoli into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Liquify contents of the 2nd mixing bowl. Pour contents of the 2nd mixing bowl into the baking dish. Pour contents of the mixing bowl into the baking dish. Refrigerate for 1 hour.
Take one down and pass it around.
Prints out "Take one down and pass it around".
Ingredients. 100 cups dandelion 110 g nannyberry 117 pinches cucumber 111 pinches onion 114 pinches raspberry 97 g asparagus 32 tablespoons pickles 116 pinches turnip 105 g chestnut 115 g squach 112 g pumpkin 119 cups watercress 101 g eggplant 107 g kale 84 cups tomatoe 10 ml new line
Method. Put new line into 3rd mixing bowl. Put dandelion into 2nd mixing bowl. Put nannyberry into 2nd mixing bowl. Put cucumber into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put raspberry into 2nd mixing bowl. Put asparagus into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put chestnut into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put squach into 2nd mixing bowl. Put squach into 2nd mixing bowl. Put asparagus into 2nd mixing bowl. Put pumpkin into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put dandelion into 2nd mixing bowl. Put nannyberry into 2nd mixing bowl. Put asparagus into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put nannyberry into 2nd mixing bowl. Put watercress into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put dandelion into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put nannyberry into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put kale into 2nd mixing bowl. Put asparagus into 2nd mixing bowl. Put tomatoe into 2nd mixing bowl. Liquify contents of the 2nd mixing bowl. Pour contents of the 2nd mixing bowl into the baking dish. Pour contents of the 3rd mixing bowl into the baking dish. Refrigerate for 1 hour.
No more bottles of beer.
Prints out "No more bottles of beer".
Ingredients. 114 pinches raspberry 101 teaspoons eggplant 98 cups broccoli 32 tablespoons pickles 102 pinches feijoa 111 cups onion 115 tablespoons squach 108 tablespoons lime 116 pinches turnip 109 cups mushrooms 78 g nectarine 10 ml new line
Method. Put new line into 3rd mixing bowl. Put new line into 2nd mixing bowl. Put raspberry into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put broccoli into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put feijoa into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put squach into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put lime into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put turnip into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put broccoli into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put eggplant into 2nd mixing bowl. Put raspberry into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put mushrooms into 2nd mixing bowl. Put pickles into 2nd mixing bowl. Put onion into 2nd mixing bowl. Put nectarine into 2nd mixing bowl. Liquify contents of the 2nd mixing bowl. Pour contents of the 2nd mixing bowl into the baking dish. Pour contents of the 3rd mixing bowl into the baking dish. Refrigerate for 1 hour.</lang>
CLIPS
<lang clips>(deffacts beer-bottles
(bottles 99))
(deffunction bottle-count
(?count) (switch ?count (case 0 then "No more bottles of beer") (case 1 then "1 more bottle of beer") (default (str-cat ?count " bottles of beer"))))
(defrule stanza
?bottles <- (bottles ?count) => (retract ?bottles) (printout t (bottle-count ?count) " on the wall," crlf) (printout t (bottle-count ?count) "." crlf) (printout t "Take one down, pass it around," crlf) (printout t (bottle-count (- ?count 1)) " on the wall." crlf crlf) (if (> ?count 1) then (assert (bottles (- ?count 1)))))</lang>
Clojure
<lang lisp>(defn verse [n]
(printf
"%d bottles of beer on the wall %d bottles of beer Take one down, pass it around %d bottles of beer on the wall\n\n" n n (dec n)))
(defn sing [start]
(dorun (map verse (range start 0 -1))))</lang>
COBOL
Another free-form version, with no DISPLAY NO ADVANCING. <lang cobol>identification division. program-id. ninety-nine. environment division. data division. working-storage section. 01 counter pic 99. 88 no-bottles-left value 0. 88 one-bottle-left value 1.
01 parts-of-counter redefines counter. 05 tens pic 9. 05 digits pic 9.
01 after-ten-words. 05 filler pic x(7) value spaces. 05 filler pic x(7) value "Twenty". 05 filler pic x(7) value "Thirty". 05 filler pic x(7) value "Forty". 05 filler pic x(7) value "Fifty". 05 filler pic x(7) value "Sixty". 05 filler pic x(7) value "Seventy". 05 filler pic x(7) value "Eighty". 05 filler pic x(7) value "Ninety". 05 filler pic x(7) value spaces.
01 after-ten-array redefines after-ten-words. 05 atens occurs 10 times pic x(7).
01 digit-words. 05 filler pic x(9) value "One". 05 filler pic x(9) value "Two". 05 filler pic x(9) value "Three". 05 filler pic x(9) value "Four". 05 filler pic x(9) value "Five". 05 filler pic x(9) value "Six". 05 filler pic x(9) value "Seven". 05 filler pic x(9) value "Eight". 05 filler pic x(9) value "Nine". 05 filler pic x(9) value "Ten". 05 filler pic x(9) value "Eleven". 05 filler pic x(9) value "Twelve". 05 filler pic x(9) value "Thirteen". 05 filler pic x(9) value "Fourteen". 05 filler pic x(9) value "Fifteen". 05 filler pic x(9) value "Sixteen". 05 filler pic x(9) value "Seventeen". 05 filler pic x(9) value "Eighteen". 05 filler pic x(9) value "Nineteen". 05 filler pic x(9) value spaces.
01 digit-array redefines digit-words. 05 adigits occurs 20 times pic x(9).
01 number-name pic x(15).
01 stringified pic x(30). 01 outline pic x(50). 01 other-numbers. 03 n pic 999. 03 r pic 999.
procedure division. 100-main section. 100-setup. perform varying counter from 99 by -1 until no-bottles-left move spaces to outline perform 100-show-number string stringified delimited by "|", space, "of beer on the wall" into outline end-string display outline end-display move spaces to outline string stringified delimited by "|", space, "of beer" into outline end-string display outline end-display move spaces to outline move "Take" to outline if one-bottle-left string outline delimited by space, space, "it" delimited by size, space, "|" into outline end-string else string outline delimited by space, space, "one" delimited by size, space, "|" into outline end-string end-if string outline delimited by "|", "down and pass it round" delimited by size into outline end-string display outline end-display move spaces to outline subtract 1 from counter giving counter end-subtract perform 100-show-number string stringified delimited by "|", space, "of beer on the wall" into outline end-string display outline end-display add 1 to counter giving counter end-add display space end-display end-perform. display "No more bottles of beer on the wall" display "No more bottles of beer" display "Go to the store and buy some more" display "Ninety-Nine bottles of beer on the wall" stop run.
100-show-number. if no-bottles-left move "No more|" to stringified else if counter < 20 string function trim( adigits( counter ) ), "|" into stringified else if counter < 100 move spaces to number-name string atens( tens ) delimited by space, space delimited by size, adigits( digits ) delimited by space into number-name end-string move function trim( number-name) to stringified divide counter by 10 giving n remainder r end-divide if r not = zero inspect stringified replacing first space by "-" end-if inspect stringified replacing first space by "|" end-if end-if end-if. if one-bottle-left string stringified delimited by "|", space, "bottle|" delimited by size into stringified end-string else string stringified delimited by "|", space, "bottles|" delimited by size into stringified end-string end-if.
100-end. end-program.</lang>
Free form version. <lang cobol>identification division. program-id. ninety-nine. environment division. data division. working-storage section. 01 counter pic 99. 88 no-bottles-left value 0. 88 one-bottle-left value 1.
01 parts-of-counter redefines counter. 05 tens pic 9. 05 digits pic 9.
01 after-ten-words. 05 filler pic x(7) value spaces. 05 filler pic x(7) value "Twenty". 05 filler pic x(7) value "Thirty". 05 filler pic x(7) value "Forty". 05 filler pic x(7) value "Fifty". 05 filler pic x(7) value "Sixty". 05 filler pic x(7) value "Seventy". 05 filler pic x(7) value "Eighty". 05 filler pic x(7) value "Ninety". 05 filler pic x(7) value spaces.
01 after-ten-array redefines after-ten-words. 05 atens occurs 10 times pic x(7).
01 digit-words. 05 filler pic x(9) value "One". 05 filler pic x(9) value "Two". 05 filler pic x(9) value "Three". 05 filler pic x(9) value "Four". 05 filler pic x(9) value "Five". 05 filler pic x(9) value "Six". 05 filler pic x(9) value "Seven". 05 filler pic x(9) value "Eight". 05 filler pic x(9) value "Nine". 05 filler pic x(9) value "Ten". 05 filler pic x(9) value "Eleven". 05 filler pic x(9) value "Twelve". 05 filler pic x(9) value "Thirteen". 05 filler pic x(9) value "Fourteen". 05 filler pic x(9) value "Fifteen". 05 filler pic x(9) value "Sixteen". 05 filler pic x(9) value "Seventeen". 05 filler pic x(9) value "Eighteen". 05 filler pic x(9) value "Nineteen". 05 filler pic x(9) value spaces.
01 digit-array redefines digit-words. 05 adigits occurs 20 times pic x(9).
01 number-name pic x(15).
procedure division. 100-main section. 100-setup. perform varying counter from 99 by -1 until no-bottles-left perform 100-show-number display " of beer on the wall" perform 100-show-number display " of beer" display "Take " with no advancing if one-bottle-left display "it " with no advancing else display "one " with no advancing end-if display "down and pass it round" subtract 1 from counter giving counter perform 100-show-number display " of beer on the wall" add 1 to counter giving counter display space end-perform. display "No more bottles of beer on the wall" display "No more bottles of beer" display "Go to the store and buy some more" display "Ninety Nine bottles of beer on the wall" stop run.
100-show-number. if no-bottles-left display "No more" with no advancing else if counter < 20 display function trim( adigits( counter ) ) with no advancing else if counter < 100 move spaces to number-name string atens( tens ) delimited by space, space delimited by size, adigits( digits ) delimited by space into number-name display function trim( number-name) with no advancing end-if end-if end-if. if one-bottle-left display " bottle" with no advancing else display " bottles" with no advancing end-if.
100-end. end-program.</lang>
CoffeeScript
<lang coffeescript>n = 99 bottles = () -> if n isnt 1 then "#{n} bottles" else "1 bottle"
while n
console.log """ #{bottles()} of beer on the wall #{bottles()} of beer Take one down, pass it around #{n-- and bottles()} of beer on the wall \r"""</lang>
ColdFusion
Classic tag based
<lang Coldfusion><cfoutput>
<cfloop index="x" from="99" to="0" step="-1"> <cfset plur = iif(x is 1,"",DE("s"))> #x# bottle#plur# of beer on the wall
#x# bottle#plur# of beer
Take one down, pass it around
#iif(x is 1,DE("No more"),"x-1")# bottle#iif(x is 2,"",DE("s"))# of beer on the wall
</cfloop>
</cfoutput></lang> or if you prefer: (identical output, grammatically correct to the last stanza)
CFScript
<lang CFScript><cfscript>
for (x=99; x gte 1; x--) { plur = iif(x==1,,DE('s')); WriteOutput("#x# bottle#plur# of beer on the wall
#x# bottle#plur# of beer
Take one down, pass it around
#iif(x is 1,DE('No more'),'x-1')# bottle#iif(x is 2,,DE('s'))# of beer on the wall
"); }
</cfscript></lang>
Common Lisp
<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>
D
Based on Steward Gordon's code at: 99-bottles-of-beer.net. <lang d>import std.stdio;
void main() {
int bottles = 99;
while (bottles > 1) { writeln(bottles, " bottles of beer on the wall,"); writeln(bottles, " bottles of beer."); writeln("Take one down, pass it around,"); if (--bottles > 1) { writeln(bottles, " bottles of beer on the wall.\n"); } } writeln("1 bottle of beer on the wall.\n");
writeln("No more bottles of beer on the wall,"); writeln("no more bottles of beer."); writeln("Go to the store and buy some more,"); writeln("99 bottles of beer on the wall.");
}</lang>
Delphi
- See Pascal
- Or
<lang Delphi>program Hundred_Bottles;
{$APPTYPE CONSOLE}
uses SysUtils;
const C_1_Down = 'Take one down, pass it around' ;
Var i : Integer ;
// As requested, some fun : examples of Delphi basic techniques. Just to make it a bit complex
procedure WriteABottle( BottleNr : Integer ) ; begin
Writeln( IntToStr(BottleNr) + ' bottles of beer on the wall' ) ;
end ;
begin
for i := 99 Downto 1 do begin WriteABottle(i); Writeln( Format('%d bottles of beer' , [i] ) ) ; Writeln( C_1_Down ) ; WriteABottle(i-1); Writeln ;
End ;
end.</lang>
Dylan
<lang dylan>Module: bottles define method bottles (n :: <integer>)
for (n from 99 to 1 by -1) format-out("%d bottles of beer on the wall,\n" "%d bottles of beer\n" "Take one down, pass it around\n" "%d bottles of beer on the wall\n", n, n, n - 1); end
end method</lang>
E
<lang e>def bottles(n) {
return switch (n) { match ==0 { "No bottles" } match ==1 { "1 bottle" } match _ { `$n bottles` } }
} for n in (1..99).descending() {
println(`${bottles(n)} of beer on the wall,
${bottles(n)} of beer. Take one down, pass it around, ${bottles(n.previous())} of beer on the wall. `) }</lang>
Ela
<lang Ela>open Core
let beer 1 = "1 bottle of beer on the wall\n1 bottle of beer\nTake one down, pass it around"
beer 0 = "better go to the store and buy some more." beer v = show v ++ " bottles of beer on the wall\n" ++ show v ++" bottles of beer\nTake one down, pass it around\n"
map beer [99,98..0]</lang>
Erlang
<lang erlang>-module(beersong). -export([sing/0]). -define(TEMPLATE_0, "~s of beer on the wall, ~s of beer.~nGo to the store and buy some more, 99 bottles of beer on the wall.~n"). -define(TEMPLATE_N, "~s of beer on the wall, ~s of beer.~nTake one down and pass it around, ~s of beer on the wall.~n~n").
create_verse(0) -> {0, io_lib:format(?TEMPLATE_0, phrase(0))}; create_verse(Bottle) -> {Bottle, io_lib:format(?TEMPLATE_N, phrase(Bottle))}.
phrase(0) -> ["No more bottles", "no more bottles"]; phrase(1) -> ["1 bottle", "1 bottle", "no more bottles"]; phrase(2) -> ["2 bottles", "2 bottles", "1 bottle"]; phrase(Bottle) -> lists:duplicate(2, integer_to_list(Bottle) ++ " bottles") ++ [integer_to_list(Bottle-1) ++ " bottles"].
bottles() -> lists:reverse(lists:seq(0,99)).
sing() ->
lists:foreach(fun spawn_singer/1, bottles()), sing_verse(99).
spawn_singer(Bottle) ->
Pid = self(), spawn(fun() -> Pid ! create_verse(Bottle) end).
sing_verse(Bottle) ->
receive {_, Verse} when Bottle == 0 -> io:format(Verse); {N, Verse} when Bottle == N -> io:format(Verse), sing_verse(Bottle-1) after 3000 -> io:format("Verse not received - re-starting singer~n"), spawn_singer(Bottle), sing_verse(Bottle) end.</lang>
Euphoria
This is based on the Batch File example. <lang Euphoria> include std/console.e include std/search.e
function one_or_it( atom n ) if n = 1 then return "it" else return "one" end if end function
function numberable( atom n ) if n = 0 then return "no" else return sprintf( "%d", n ) end if end function
function plural( atom n ) if n != 1 then return "s" else return "" end if end function
atom stillDrinking = 1
sequence yn sequence plurality sequence numerality
while stillDrinking do for bottle = 99 to 1 by -1 do plurality = plural( bottle ) numerality = numberable( bottle ) printf( 1, "%s bottle%s of beer on the wall\n%s bottle%s of beer\n", { numerality, plurality, numerality, plurality } ) printf( 1, "Take %s down and pass it round\n", { one_or_it( bottle ) } ) printf( 1, "%s bottle%s of beer on the wall\n\n", { numberable( bottle - 1 ), plural( bottle - 1 ) } ) end for puts( 1, "No more bottles of beer on the wall\nNo more bottles of beer\n" ) puts( 1, "Go to the store and buy some more\n99 bottles of beer on the wall\n" ) puts( 1, "\nKeep drinking? " ) yn = gets(0) stillDrinking = find_any( "yY", yn ) puts( 1, "\n" ) end while</lang>
F#
<lang fsharp>#light let rec bottles n =
let (before, after) = match n with | 1 -> ("bottle", "bottles") | 2 -> ("bottles", "bottle") | n -> ("bottles", "bottles") printfn "%d %s of beer on the wall" n before printfn "%d %s of beer" n before printfn "Take one down, pass it around" printfn "%d %s of beer on the wall\n" (n - 1) after if n > 1 then bottles (n - 1)</lang>
Factor
<lang factor>USING: io kernel make math math.parser math.ranges sequences ;
- bottle ( -- quot )
[ [ [ [ # " bottles of beer on the wall,\n" % ] [ # " bottles of beer.\n" % ] bi ] keep "Take one down, pass it around,\n" % 1 - # " bottles of beer on the wall\n" % ] " " make print ] ; inline
- last-verse ( -- )
"Go to the store and buy some more," "no more bottles of beer on the wall!" [ print ] bi@ ;
- bottles ( n -- )
1 [a,b] bottle each last-verse ;
! Usage: 99 bottles</lang>
Falcon
<lang falcon>for i in [99:1]
> i, " bottles of beer on the wall" > i, " bottles of beer" > "Take one down, pass it around" > i-1, " bottles of beer on the wall\n"
end</lang>
A more robust version to handle plural/not plural conditions <lang falcon>for i in [99:1]
plural = (i != 1) ? 's' : "" > @ "$i bottle$plural of beer on the wall" > @ "$i bottle$plural of beer" > "Take one down, pass it around" > i-1, @ " bottle$plural of beer on the wall\n"
end</lang>
FALSE
<lang false>[$." bottle"$1-["s"]?" of beer"]b: 99 [$][b;!" on the wall "b;!" Take one down and pass it around "1-b;!" on the wall "]#%</lang>
ferite
copied from 99-bottles-of-beer.net.
<lang ferite>uses "console";
number bottles = 99; boolean looping = true; object counter = closure { if (--bottles > 0) { return true; } else { return false; } };
while (looping) { Console.println("${bottles} bottles of beer on the wall,"); Console.println("${bottles} bottles of beer,"); Console.println("Take one down, pass it around,");
looping = counter.invoke();
Console.println("${bottles} bottles of beer on the wall.");</lang>
Forth
<lang forth>:noname dup . ." bottles" ;
- noname ." 1 bottle" ;
- noname ." no more bottles" ;
create bottles , , ,
- .bottles dup 2 min cells bottles + @ execute ;
- .beer .bottles ." of beer" ;
- .wall .beer ." on the wall" ;
- .take ." Take one down, pass it around" ;
- .verse .wall cr .beer cr
1- .take cr .wall cr ;
- verses begin cr .verse ?dup 0= until ;
99 verses</lang>
Fortran
<lang fortran>program bottlestest
implicit none
integer :: i character(len=*), parameter :: bwall = " on the wall", & bottles = "bottles of beer", & bottle = "bottle of beer", & take = "Take one down, pass it around", & form = "(I0, ' ', A)"
do i = 99,0,-1 if ( i /= 1 ) then write (*,form) i, bottles // bwall if ( i > 0 ) write (*,form) i, bottles else write (*,form) i, bottle // bwall write (*,form) i, bottle end if if ( i > 0 ) write (*,*) take end do
end program bottlestest</lang>
Frink
Frink tracks units of measure through all calculations. It has a large library of built-in units of measure, including volume. The following program prints out the remaining volume of beer (assuming we start with 99 bottles of beer, each containing 12 fluid ounces) in different random units of volume, never repeating a unit. <lang frink> units = array[units[volume]] showApproximations[false]
for n = 99 to 0 step -1 {
unit = units.removeRandom[] str = getBottleString[n, unit] println["$str of beer on the wall, $str."]
if (n == 0) println["Go to the store and buy some more, 99 bottles of beer on the wall."] else println["Take one down and pass it around, " + getBottleString[n-1, unit] + " on the wall.\n"]
}
getBottleString[n, unit] := format[n*12 floz, unit, 6] + "s" </lang>
Sample randomized output:
0.019386 facecords of beer on the wall, 0.019386 facecords. Take one down and pass it around, 0.019190 facecords on the wall. 36.750000 quarts of beer on the wall, 36.750000 quarts. Take one down and pass it around, 36.375000 quarts on the wall. 581539.650545 brminims of beer on the wall, 581539.650545 brminims. Take one down and pass it around, 575544.396416 brminims on the wall. 10.377148 scotsoatlippys of beer on the wall, 10.377148 scotsoatlippys. Take one down and pass it around, 10.269053 scotsoatlippys on the wall. 7.416004 cangallons of beer on the wall, 7.416004 cangallons. Take one down and pass it around, 7.337941 cangallons on the wall. 3335.894135 dessertspoons of beer on the wall, 3335.894135 dessertspoons. Take one down and pass it around, 3300.405899 dessertspoons on the wall. 0.233105 barrelbulks of beer on the wall, 0.233105 barrelbulks. Take one down and pass it around, 0.230599 barrelbulks on the wall. 21.766118 magnums of beer on the wall, 21.766118 magnums. Take one down and pass it around, 21.529530 magnums on the wall. 1092.000000 fluidounces of beer on the wall, 1092.000000 fluidounces. Take one down and pass it around, 1080.000000 fluidounces on the wall. ... 12.000000 ponys of beer on the wall, 12.000000 ponys. Take one down and pass it around, 0.000000 ponys on the wall. 0.000000 brfluidounces of beer on the wall, 0.000000 brfluidounces. Go to the store and buy some more, 99 bottles of beer on the wall.
GAP
<lang gap>Bottles := function(n) local line, i, j, u; line := function(n) s := String(n); if n < 2 then return Concatenation(String(n), " bottle of beer"); else return Concatenation(String(n), " bottles of beer"); fi; end; for i in [1 .. n] do j := n - i + 1; u := line(j); Display(Concatenation(u, " on the wall")); Display(u); Display("Take one down, pass it around"); Display(Concatenation(line(j - 1), " on the wall")); if i <> n then Display(""); fi; od; end;</lang>
gnuplot
<lang gnuplot>if (!exists("bottles")) bottles = 99 print sprintf("%i bottles of beer on the wall", bottles) print sprintf("%i bottles of beer", bottles) print "Take one down, pass it around" bottles = bottles - 1 print sprintf("%i bottles of beer on the wall", bottles) print "" if (bottles > 0) reread</lang>
Go
<lang Go>package main
import "fmt"
func main() { cardinality := func (i int) string { if i!=1 { return "s" } return "" } for i := 5; i > 0; i-- { fmt.Printf("%d bottle%s of beer on the wall\n", i, cardinality(i)) fmt.Printf("%d bottle%s of beer\n", i, cardinality(i)) fmt.Printf("Take one down, pass it around\n") fmt.Printf("%d bottle%s of beer on the wall\n", i-1, cardinality(i-1)) } }</lang>
Go!
Copied from The 99 Bottles of Beer web site with a minor bug fix. <lang go!>-- -- 99 Bottles of Beer in Go! -- John Knottenbelt -- -- Go! is a multi-paradigm programming language that is oriented -- to the needs of programming secure, production quality, agent -- based applications. -- -- http://www.doc.ic.ac.uk/~klc/dalt03.html --
main .. {
include "sys:go/io.gof". include "sys:go/stdlib.gof".
main() -> drink(99); stdout.outLine("Time to buy some more beer...").
drink(0) -> {}. drink(i) -> stdout.outLine( bottles(i) <> " on the wall,\n" <> bottles(i) <> ".\n" <> "take one down, pass it around,\n" <> bottles(i-1) <> " on the wall.\n"); drink(i-1).
bottles(0) => "no bottles of beer". bottles(1) => "1 bottle of beer". bottles(i) => i^0 <> " bottles of beer".
}</lang>
Groovy
Basic Solution
With a closure to handle special cardinalities of bottles. <lang groovy>def bottles = { "${it==0 ? 'No more' : it} bottle${it==1 ? : 's' }" }
99.downto(1) { i ->
print """
${bottles(i)} of beer on the wall ${bottles(i)} of beer Take one down, pass it around ${bottles(i-1)} of beer on the wall """ }</lang>
Single Print Version
Uses a single print algorithm for all four lines. Handles cardinality on bottles, uses 'No more' instead of 0. <lang groovy>298.downto(2) {
def (m,d) = [it%3,(int)it/3] print "${m==1?'\n':}${d?:'No more'} bottle${d!=1?'s':} of beer" + "${m?' on the wall':'\nTake one down, pass it around'}\n"
}</lang>
Bottomless Beer Solution
Using more closures to create a richer lyrical experience. <lang groovy>def bottles = { "${it==0 ? 'No more' : it} bottle${it==1 ? : 's' }" }
def initialState = {
"""${result(it)}
${resultShort(it)}""" }
def act = {
it > 0 ? "Take ${it==1 ? 'it' : 'one'} down, pass it around" : "Go to the store, buy some more"
}
def delta = { it > 0 ? -1 : 99 }
def resultShort = { "${bottles(it)} of beer" }
def result = { "${resultShort(it)} on the wall" }
// //// uncomment commented lines to create endless drunken binge //// // // while (true) { 99.downto(0) { i ->
print """
${initialState(i)} ${act(i)} ${result(i+delta(i))} """ } // Thread.sleep(1000) // }</lang>
GUISS
We will just use the calculator and keep taking one off. We do not get the full text here, but the number of the calculator shows how many bottles we still have left to drink:
<lang guiss>Start,Programs,Accessories,Calculator,Button:9,Button:9, Button:[hyphen],Button:1,Button:[equals],Button:[hyphen],Button:1,Button:[equals], Button:[hyphen],Button:1,Button:[equals],Button:[hyphen],Button:1,Button:[equals], Button:[hyphen],Button:1,Button:[equals],Button:[hyphen],Button:1,Button:[equals], Button:[hyphen],Button:1,Button:[equals],Button:[hyphen],Button:1,Button:[equals] </lang> We haven't drank all of the bottles at this point, but we can keep going, if we want.
Haskell
A relatively concise solution:
<lang haskell>main = mapM_ (putStrLn . beer) [99, 98 .. 0] beer 1 = "1 bottle of beer on the wall\n1 bottle of beer\nTake one down, pass it around" beer 0 = "better go to the store and buy some more." beer v = show v ++ " bottles of beer on the wall\n"
++ show v ++" bottles of beer\nTake one down, pass it around\n" ++ head (lines $ beer $ v-1) ++ "\n"</lang>
As a list comprehension:
<lang haskell>import qualified Char
main = putStr $ concat
[up (bob n) ++ wall ++ ", " ++ bob n ++ ".\n" ++ pass n ++ bob (n - 1) ++ wall ++ ".\n\n" | n <- [99, 98 .. 0]] where bob n = (num n) ++ " bottle" ++ (s n) ++ " of beer" wall = " on the wall" pass 0 = "Go to the store and buy some more, " pass _ = "Take one down and pass it around, " up (x : xs) = Char.toUpper x : xs num (-1) = "99" num 0 = "no more" num n = show n s 1 = "" s _ = "s"</lang>
Another version, which uses a Writer monad to collect each part of the song. It also uses Template Haskell to generate the song at compile time.
<lang haskell>{-# LANGUAGE TemplateHaskell #-} -- build with "ghc --make beer.hs" module Main where import Language.Haskell.TH import Control.Monad.Writer
-- This is calculated at compile time, and is equivalent to -- songString = "99 bottles of beer on the wall\n99 bottles..." songString =
$(let sing = tell -- we can't sing very well...
someBottles 1 = "1 bottle of beer " someBottles n = show n ++ " bottles of beer "
bottlesOfBeer n = (someBottles n ++)
verse n = do sing $ n `bottlesOfBeer` "on the wall\n" sing $ n `bottlesOfBeer` "\n" sing $ "Take one down, pass it around\n" sing $ (n - 1) `bottlesOfBeer` "on the wall\n\n"
song = execWriter $ mapM_ verse [99,98..1]
in return $ LitE $ StringL $ song)
main = putStr songString</lang>
haXe
<lang haXe>class RosettaDemo {
static public function main() { singBottlesOfBeer(100); }
static function singBottlesOfBeer(bottles : Int) { var plural : String = 's';
while (bottles >= 1) { neko.Lib.print(bottles + " bottle" + plural + " of beer on the wall,\n"); neko.Lib.print(bottles + " bottle" + plural + " of beer!\n"); neko.Lib.print("Take one down, pass it around,\n"); if (bottles - 1 == 1) { plural = ; }
if (bottles > 1) { neko.Lib.print(bottles-1 + " bottle" + plural + " of beer on the wall!\n\n"); } else { neko.Lib.print("No more bottles of beer on the wall!\n"); } bottles--; } }
}</lang>
HicEst
<lang hicest>DO x = 99, 1, -1
WRITE() x , "bottles of beer on the wall" BEEP("T16 be be be bH bH bH be be be 2be ")
WRITE() x , "bottles of beer" BEEP("2p f f f c c c 2f ")
WRITE() "take one down, pass it around" BEEP("2p 2d d d 2p d d d 2d ")
WRITE() x , "bottles of beer on the wall" BEEP("2p #A #A #A c c d #d #d #d 2#d 2p")
ENDDO</lang>
HQ9+
<lang hq9p>9</lang>
Icon and Unicon
The default is 99 bottles, but you can change this on the command line for really long trips... <lang icon>procedure main(args)
numBeers := integer(args[1]) | 99 drinkUp(numBeers)
end
procedure drinkUp(beerMax)
static beerMap initial { beerMap := table(" bottles") beerMap[1] := " bottle" }
every beerCount := beerMax to 1 by -1 do { writes( beerCount,beerMap[beerCount]," of beer on the wall, ") write( beerCount,beerMap[beerCount]," of beer.")
writes("Take one down and pass it around, ") write(case x := beerCount-1 of { 0 : "no more bottles" default : x||beerMap[x] }," of beer on the wall.\n") }
write("No more bottles of beer on the wall, no more bottles of beer.") write("Go to the store and buy some more, ", beerMax," bottles of beer on the wall.")
end</lang>
IDL
<lang IDL>Pro bottles
for i=1,99 do begin
print, 100-i, " bottles of beer on the wall.", 100-i, $ " bottles of beer.", " Take one down, pass it around," , $ 99-i, " bottles of beer on the wall."
endfor End
}</lang>
Since in IDL "FOR"-loops are the embodiment of pure evil (see http://www.idlcoyote.com/tips/forloops.html and http://www.idlcoyote.com/tips/forloops2.html) there is also a loop free IDL way:
<lang IDL>Pro bottles_noloop
b=(reverse(shift(sindgen(100),-1)))[1:99] b2=reverse(sindgen(99)) wallT=replicate(' bottles of beer on the wall.', 100) wallT2=replicate(' bottles of beer.', 100) takeT=replicate('Take one down, pass it around,', 100) print, b+wallT+string(10B)+b+wallT2+string(10B)+takeT+string(10B)+b2+wallT+string(10B)
End</lang>
Inform 7
Programmatic solution
<lang inform7>Beer Hall is a room.
When play begins: repeat with iteration running from 1 to 99: let N be 100 - iteration; say "[N] bottle[s] of beer on the wall[line break]"; say "[N] bottle[s] of beer[line break]"; say "Take one down, pass it around[line break]"; say "[N - 1] bottle[s] of beer on the wall[paragraph break]"; end the story.</lang>
World model solution
This solution uses in-game objects to represent the wall and the bottles.
<lang inform7>Beer Hall is a room.
The plural of bottle of beer is bottles of beer. A bottle of beer is a kind of thing.
The wall is a scenery supporter in Beer Hall. 99 bottles of beer are on the wall.
When play begins: while something is on the wall: say "[what's on the wall] on the wall[line break]"; say "[what's on the wall][line break]"; say "Take one down, pass it around[line break]"; remove a random thing on the wall from play; say "[what's on the wall] on the wall[paragraph break]"; end the story.
To say what's on the wall: if more than one thing is on the wall, say list of things on the wall; otherwise say "[number of things on the wall in words] bottle[s] of beer".</lang>
Intercal
See 99 Bottles of Beer/Intercal
Io
<lang io>bottles := method(i,
if(i==0, return "no more bottles of beer") if(i==1, return "1 bottle of beer") "" .. i .. " bottles of beer"
) for(i, 99, 1, -1,
write( bottles(i), " on the wall, ", bottles(i), ",\n", "take one down, pass it around,\n", bottles(i - 1), " on the wall.\n\n" )
)</lang>
Ioke
<lang ioke>bottle = method(i,
case(i, 0, "no more bottles of beer", 1, "1 bottle of beer", "#{i} bottles of beer"))
(99..1) each(i,
"#{bottle(i)} on the wall, " println "take one down, pass it around," println "#{bottle(i - 1)} on the wall.\n" println
)</lang>
J
As posted at the J wiki <lang j>bob =: ": , ' bottle' , (1 = ]) }. 's of beer'"_ bobw=: bob , ' on the wall'"_ beer=: bobw , ', ' , bob , '; take one down and pass it around, ' , bobw@<: beer"0 >:i.-99</lang>
Output: <lang j>99 bottles of beer on the wall, 99 bottles of beer; take one down and pass it around, 98 bottles of beer on the wall 98 bottles of beer on the wall, 98 bottles of beer; take one down and pass it around, 97 bottles of beer on the wall ... 3 bottles of beer on the wall, 3 bottles of beer; take one down and pass it around, 2 bottles of beer on the wall 2 bottles of beer on the wall, 2 bottles of beer; take one down and pass it around, 1 bottle of beer on the wall 1 bottle of beer on the wall, 1 bottle of beer; take one down and pass it around, 0 bottles of beer on the wall </lang>
Java
Console
MessageFormat's choice operator is used to properly format plurals. <lang java>import java.text.MessageFormat; public class Beer {
static String bottles(final int n) { return MessageFormat.format("{0,choice,0#No more bottles|1#One bottle|2#{0} bottles} of beer", n); } public static void main(final String[] args) { String byob = bottles(99); for (int x = 99; x > 0;) { System.out.println(byob + " on the wall"); System.out.println(byob); System.out.println("Take one down, pass it around"); byob = bottles(--x); System.out.println(byob + " on the wall\n"); } }
}</lang>
Optimized <lang java>public class Beer {
public static void main(final String[] args) { int beer = 99; StringBuilder sb = new StringBuilder(); String data[] = new String[] { " bottles of beer on the wall\n", " bottles of beer.\nTake one down, pass it around,\n", "Better go to the store and buy some more." };
while (beer > 0) sb.append(beer).append(data[0]).append(beer).append(data[1]).append(--beer).append(data[0]).append("\n");
System.out.println(sb.append(data[2]).toString()); }
}</lang>
An object-oriented solution
See: 99 Bottles of Beer/Java/Object Oriented
GUI
This version requires user interaction. The first two lines are shown in a text area on a window. The third line is shown on a button which you need to click to see the fourth line in a message box. The numbers update and the process repeats until "0 bottles of beer on the wall" is shown in a message box, when the program ends. <lang java>import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JTextArea; public class Beer extends JFrame implements ActionListener{
private int x; private JButton take; private JTextArea text; public static void main(String[] args){ new Beer();//build and show the GUI }
public Beer(){ x= 99; take= new JButton("Take one down, pass it around"); text= new JTextArea(4,30);//size the area to 4 lines, 30 chars each text.setText(x + " bottles of beer on the wall\n" + x + " bottles of beer"); text.setEditable(false);//so they can't change the text after it's displayed take.addActionListener(this);//listen to the button setLayout(new BorderLayout());//handle placement of components add(text, BorderLayout.CENTER);//put the text area in the largest section add(take, BorderLayout.SOUTH);//put the button underneath it pack();//auto-size the window setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//exit on "X" (I hate System.exit...) setVisible(true);//show it }
public void actionPerformed(ActionEvent arg0){ if(arg0.getSource() == take){//if they clicked the button JOptionPane.showMessageDialog(null, --x + " bottles of beer on the wall");//show a popup message text.setText(x + " bottles of beer on the wall\n" + x + " bottles of beer");//change the text } if(x == 0){//if it's the end dispose();//end } }
}</lang>
JavaScript
The simple solution
<lang javascript>// Line breaks are in HTML var beer = 99; while (beer > 0) {
document.write( beer + " bottles of beer on the wall
" ); document.write( beer + " bottles of beer
" ); document.write( "Take one down, pass it around
" ); document.write( (beer - 1) + " bottles of beer on the wall
" ); beer--;
}</lang>
More skilled solution "one-liner" with grammar check
<lang javascript>// Line breaks are in HTML
var beer; while ((beer = typeof beer === "undefined" ? 99 : beer) > 0) document.write( beer + " bottle" + (beer != 1 ? "s" : "") + " of beer on the wall
" + beer + " bottle" + (beer != 1 ? "s" : "") + " of beer
Take one down, pass it around
" + (--beer) + " bottle" + (beer != 1 ? "s" : "") + " of beer on the wall
" );</lang>
Object Oriented with DOM
<lang javascript>// Line breaks are in HTML function Bottles(count){
this.count = (!!count)?count:99; this.knock = function(){ var c = document.createElement('div'); c.id="bottle-"+this.count;
c.innerHTML = "
"+this.count+" bottles of beer on the wall
" +"
"+this.count+" bottles of beer!
" +"
Take one down,
Pass it around
" +"
"+(--this.count)+" bottles of beer on the wall
";
document.body.appendChild(c); } this.sing = function(){ while (this.count>0) { this.knock(); } }
}
(function(){
var bar = new Bottles(99); bar.sing();
})();</lang>
Joy
<lang joy>LIBRA
_beerlib == true ;
HIDE beer == "of beer " putchars ; wall == "on the wall" putchars ; take1 == "Take one down and pass it around, " putchars ; dup3 == dup dup dup ; comma == ", " putchars ; period == '. putch ; bottles == [dup small] [ [null] [pop "no more bottles " putchars] [put "bottle " putchars] ifte] [put "bottles " putchars] ifte ; sing-verse == dup3 bottles beer wall comma bottles beer ".\n" putchars take1 1 - bottles beer wall period newline newline ; sing-verse-0 == "No more bottles of beer on the wall, no more bottles of beer\n" putchars "Go to the store and buy some more, " putchars 99 bottles pop beer wall period newline ;
IN (* n -- *) sing-verses == [null] [sing-verse-0] [sing-verse 1 -] tailrec .</lang>
K
<lang k>`0:\:{x[z],y,a,x[z],a,"Take one down, pass it around",a,x[z-1],y,a,a:"\n"}[{($x)," bottle",:[x=1;"";"s"]," of beer"};" on the wall"]'|1_!100</lang>
LaTeX
Recursive
<lang LaTeX>\documentclass{article}
\newcounter{beer}
\newcommand{\verses}[1]{
\setcounter{beer}{#1} \par\noindent \arabic{beer} bottles of beer on the wall,\\ \arabic{beer} bottles of beer!\\ Take one down, pass it around---\\ \addtocounter{beer}{-1} \arabic{beer} bottles of beer on the wall!\\ \ifnum#1>0 \verses{\value{beer}} \fi
}
\begin{document} \verses{99} \end{document}</lang>
Iterative
The \loop macro is tail-recursive (Knuth 1984, page 219). Just for fun, this version uses Roman numerals.
<lang LaTeX>\documentclass{article}
\newcounter{beer} \newcounter{showC}
\newcommand{\verses}[1]{
\setcounter{beer}{#1} \loop \par\noindent \Roman{beer} bottles of beer on the wall,\\ \Roman{beer} bottles of beer!\\ Take one down, pass it around---\\ \addtocounter{beer}{-1}
% Romans didn't know how to write zero ;-)
\ifnum\value{beer}=0 ZERO \else\Roman{beer} \fi bottles of beer on the wall!\\ \ifnum\value{beer}>0 \repeat
}
\begin{document} \verses{99} \end{document}</lang>
References
- Knuth, Donald E. (1984). The TeXbook, Addison Wesley.
Liberty BASIC
<lang lb>For bottles = 99 To 1 Step -1
song$ = song$ + str$(bottles) + " bottle" If (bottles > 1) Then song$ = song$ + "s" song$ = song$ + " of beer on the wall, " + str$(bottles) + " bottle" If (bottles > 1) Then song$ = song$ + "s" song$ = song$ + " of beer," + chr$(13) + chr$(10) + "Take one down, pass it around, " + str$(bottles - 1) + " bottle" If (bottles > 2) Or (bottles = 1) Then song$ = song$ + "s" song$ = song$ + " of beer on the wall." + chr$(13) + chr$(10)
Next bottles song$ = song$ + "No more bottles of beer on the wall, no more bottles of beer." _
+ chr$(13) + chr$(10) + "Go to the store and buy some more, 99 bottles of beer on the wall."
Print song$</lang>
Logo
<lang logo>to bottles :n
if :n = 0 [output [No more bottles]] if :n = 1 [output [1 bottle]] output sentence :n "bottles
end to verse :n
print sentence bottles :n [of beer on the wall] print sentence bottles :n [of beer] print [Take one down, pass it around] print sentence bottles :n-1 [of beer on the wall]
end for [n 99 1] [verse :n (print)]</lang>
Logtalk
<lang logtalk>:- object(bottles).
:- initialization(sing(99)).
sing(0) :- write('No more bottles of beer on the wall, no more bottles of beer.'), nl, write('Go to the store and buy some more, 99 bottles of beer on the wall.'), nl, nl. sing(N) :- N > 0, N2 is N -1, beers(N), write(' of beer on the wall, '), beers(N), write(' of beer.'), nl, write('Take one down and pass it around, '), beers(N2), write(' of beer on the wall.'), nl, nl, sing(N2).
beers(0) :- write('no more bottles'). beers(1) :- write('1 bottle'). beers(N) :- N > 1, write(N), write(' bottles').
- - end_object.</lang>
Lua
<lang lua>local bottles = 99
local function plural (bottles) if bottles == 1 then return end return 's' end while bottles > 0 do
print (bottles..' bottle'..plural(bottles)..' of beer on the wall') print (bottles..' bottle'..plural(bottles)..' of beer') print ('Take one down, pass it around') bottles = bottles - 1 print (bottles..' bottle'..plural(bottles)..' of beer on the wall') print ()
end</lang>
Lucid
<lang lucid>// Run luval with -s inside the lucid shell script // The print out is a list of lines. So the output is not separated by new lines, rather // by '[' and ']' -- I cant figure out how to do string concatenation with numbers in lucid. // beer(N) ^ bottle(N) ^ wall ^ beer(N) ^ bottle(N) ^ pass ^ beer(N-1) ^ bottle(N-1) ^ wall // should have worked but doesn't [%beer(N),bottle(N),wall,beer(N),bottle(N),pass,beer(N-1),bottle(N-1),wall%]
where N = 100 fby N - 1; wall = if N > 0 then ` On the wall ' else eod fi; pass = `Take one down and pass it around.'; beer(A) = if A > 0 then A else `No more' fi; bottle(A) = if A eq 1 then `bottle of beer' else `bottles of beer' fi; end</lang>
M4
<lang m4>define(`BOTTLES', `bottles of beer')dnl define(`BOTTLE', `bottle of beer')dnl define(`WALL', `on the wall')dnl define(`TAKE', `take one down, pass it around')dnl define(`NINETEEN', `$1 ifelse(`$1',`1',BOTTLE,BOTTLES) WALL $1 ifelse(`$1',`1',BOTTLE,BOTTLES) ifelse(`$1',`0',,`TAKE') ifelse(`$1',`0',,`NINETEEN(eval($1-1))')')dnl NINETEEN(99)</lang>
make
BSD make
<lang make>START = 99 UP != jot - 2 `expr $(START) - 1` 1
0-bottles-of-beer: 1-bottle-of-beer @echo No more bottles of beer on the wall!
1-bottle-of-beer: 2-bottles-of-beer @echo One last bottle of beer on the wall! @echo @echo One last bottle of beer on the wall, @echo One last bottle of beer, @echo Take it down, pass it around.
.for COUNT in $(UP) ONE_MORE != expr 1 + $(COUNT) $(COUNT)-bottles-of-beer: $(ONE_MORE)-bottles-of-beer @echo $(COUNT) bottles of beer on the wall! @echo @echo $(COUNT) bottles of beer on the wall, @echo $(COUNT) bottles of beer, @echo Take one down, pass it around. .endfor
$(START)-bottles-of-beer: @echo $(START) bottles of beer on the wall, @echo $(START) bottles of beer. @echo Take one down, pass it around.</lang>
Usage: make or make START=99
GNU make
<lang make>PRED=`expr $* - 1`
1-bottles: 1-beer pass @echo "No more bottles of beer on the wall"
%-bottles: %-beer pass @echo "$(PRED) bottles of beer on the wall\n" @-$(MAKE) $(PRED)-bottles
1-beer: @echo "One bottle of beer on the wall, One bottle of beer"
%-beer: @echo "$* bottles of beer on the wall, $* bottles of beer"
pass: @echo "Take one down and pass it around,"</lang>
Usage: make 99-bottles
This will fork 99 make processes. You might need to raise your process limit (ulimit -p).
Mathematica
<lang Mathematica>texts = ToString[#] <> " bottles of beer on the wall\n" <> ToString[#] <>
" bottles of beer\nTake one down and pass it around\n" <> ToString[# - 1] <> " bottles of beer on the wall" & /@ Range[99, 1, -1];
AppendTo[texts, "No more bottles of beer on the wall, no more bottles of beer\nGo \ to the store and buy some more, 99 bottles of beer on the wall"]; texts = StringJoin@Riffle[texts, "\n\n"]; Print@StringReplace[texts, "\n1 bottles" -> "\n1 bottle"]</lang>
A more terse example
<lang Mathematica>Uses Map[]as above, but with a function and some text variables.
f[n_,str_] := ToString[n]<>str bw = "bottles of beer on the wall\n"; b = "bottles of beer\n"; td = "take one down and pass it around\n"; StringJoin[StringJoin[Most[Map[f[#,bw]<> f[#, b]<>td<>f[#-1,bw]<>"\n"&,Range[99,0,-1]]]],"No more bottles ... etc."]</lang>
MATLAB
<lang MATLAB>function ninetyNineBottlesOfBeer()
disp( [ sprintf(['%d bottles of beer on the wall, %d bottles of beer.\n'... 'Take one down, pass it around...\n'],[(99:-1:2);(99:-1:2)])... sprintf(['1 bottle of beer on the wall, 1 bottle of beer.\nTake'... 'one down, pass it around;\nNo more bottles of beer on the wall.']) ] ); %The end of this song makes me sad. The shelf should always have more %beer...like college.
end</lang>
MAXScript
<lang maxscript>escapeEnable = true resetMaxFile #noPrompt viewport.setType #view_top max tool maximize viewport.SetRenderLevel #smoothhighlights delay = 1.6 a = text size:30 a.wirecolor = white theMod = extrude() addModifier a theMod
for i in 99 to 1 by -1 do -- this will iterate through 99 times use the escape key to terminate. (
a.text = (i as string + " bottles of beer on the wall") redrawViews() sleep delay a.text = (i as string + " bottles of beer") redrawViews() sleep delay a.text = "Take one down, pass it around" redrawViews() sleep delay a.text = ((i-1) as string + " bottles of beer on the wall") redrawViews() sleep delay
)</lang>
A one-line version
Since MAXscript is an expression based language (everything returns a value), it is relatively easy to write long expressions that are only one line long. the following single-line snippet (broken for clarity on the webpage) produces a grammatically correct printout of the song.
<lang maxscript>for i = 99 to 1 by -1 do (print (i as string + (if i == 1 then " bottle" else " bottles") + " of beer on the wall\n" + i as string +\ (if i == 1 then " bottle" else " bottles") + " of beer\nTake one down, pass it around\n" + (i - 1) as string + (if i - 1 == 1 then "\ bottle" else " bottles") + " of beer on the wall\n" + (if i - 1 == 0 then "\nno more beer" else "")))</lang>
Mirah
<lang Mirah>plural = 's' 99.downto(1) do |i|
puts "#{i} bottle#{plural} of beer on the wall," puts "#{i} bottle#{plural} of beer" puts "Take one down, pass it around!" plural = if i - 1 == 1 if i > 1 puts "#{i-1} bottle#{plural} of beer on the wall!" puts else puts "No more bottles of beer on the wall!" end
end </lang>
ML/I
Simple iterative version
<lang ML/I>MCSKIP "WITH" NL "" 99 bottles - simple iterative version MCSKIP MT,<> MCINS %. "" Macro to generate singular or plural bottle(s) MCDEF BOT WITHS () AS <bottle<>MCGO L0 IF %A1. EN 1 s> "" Main macro - argument is initial number of bottles MCDEF BOTTLES NL AS <MCSET T1=%A1. %L1.%T1. BOT(%T1.) of beer on the wall %T1. BOT(%T1.) of beer Take one down, pass it around MCSET T1=T1-1 %T1. BOT(%T1.) of beer on the wall MCGO L0 IF T1 EN 0
MCGO L1 > "" Do it BOTTLES 99</lang>
Recursive version
<lang ML/I>MCINS "WITH" NL "" 99 bottles - recursive version MCSKIP MT,<> MCINS %. "" Macro to generate singular or plural bottle(s) MCDEF BOT WITHS () AS <bottle<>MCGO L0 IF %A1. EN 1 s> "" Main macro - recurses for each verse - argument is initial number of bottles MCDEF BOTTLES NL AS <MCSET T1=%A1. %T1. BOT(%T1.) of beer on the wall %T1. BOT(%T1.) of beer Take one down, pass it around MCSET T1=T1-1 %T1. BOT(%T1.) of beer on the wall MCGO L0 IF T1 EN 0
BOTTLES %T1. > "" Do it BOTTLES 99</lang>
Modula-2
<lang modula2>MODULE b99;
IMPORT InOut;
VAR nr : CARDINAL;
BEGIN
nr := 99; REPEAT InOut.WriteCard (nr, 4); InOut.WriteString (" bottles of beer on the wall"); InOut.WriteLn; InOut.WriteCard (nr, 4); InOut.WriteString (" bottles of beer"); InOut.WriteLn; InOut.WriteString ("Take one down, pass it around"); InOut.WriteLn; DEC (nr); InOut.WriteCard (nr, 4); InOut.WriteString (" bottles of beer on the wall"); InOut.WriteLn; InOut.WriteLn UNTIL nr = 0
END b99.</lang>
Modula-3
<lang modula3>MODULE Bottles EXPORTS Main;
IMPORT IO, Fmt;
BEGIN
FOR i := 99 TO 1 BY -1 DO IO.Put(Fmt.Int(i) & " bottles of beer on the wall\n"); IO.Put(Fmt.Int(i) & " bottles of beer\n"); IO.Put("Take one down, pass it around\n"); IO.Put(Fmt.Int(i - 1) & " bottles of beer on the wall\n"); IO.Put("\n"); END;
END Bottles.</lang>
MPIF90
<lang fortran>program bottlesMPI
implicit none
integer :: ierr,rank,nproc character(len=*), parameter :: bwall = " on the wall", & bottles = "bottles of beer", & bottle = "bottle of beer", & take = "Take one down, pass it around", & form = "(I0, ' ', A)"
call mpi_init(ierr) call mpi_comm_size(MPI_COMM_WORLD,nproc, ierr) call mpi_comm_rank(MPI_COMM_WORLD,rank,ierr)
if ( rank /= 1 ) then write (*,form) rank, bottles // bwall if ( rank > 0 ) write (*,form) rank, bottles else write (*,form) rank, bottle // bwall write (*,form) rank, bottle end if if ( rank > 0 ) write (*,*) take
call mpi_finalize(ierr)
end program bottlesMPI</lang>
Usage
mpif90 filename.f90 mpiexec -np 99 a.out
MUMPS
Recursive
<lang MUMPS>beer(n) If n<1 Write "No bottles of beer on the wall... " Quit Write !!,n," bottle",$Select(n=1:"",1:"s")," of beer on the wall." Write !,n," bottle",$Select(n=1:"",1:"s")," of beer." Write !,"Take one down, pass it around." Do beer(n-1) Quit
Do beer(99)</lang>
Iterative
<lang MUMPS>beer(n) If n<1 Write "No bottles of beer on the wall... " Quit Write !!,n," bottle",$Select(n=1:"",1:"s")," of beer on the wall." Write !,n," bottle",$Select(n=1:"",1:"s")," of beer." Write !,"Take one down, pass it around." Quit
For ii=99:-1:0 Do beer(ii)</lang>
Nemerle
<lang Nemerle>using System; using System.Console;
module Bottles {
Sing(x : int, bev = "beer", surface = "wall") : void { match(x) { |0 => WriteLine($"No more bottles of $bev on the $surface, no more bottles of $bev"); WriteLine($"Go to the store and get some more $bev, 99 bottles of $bev on the $surface") |1 => WriteLine($"One bottle of $bev on the $surface, one bottle of $bev"); WriteLine($"Take it down, pass it around, no more bottles of $bev on the $surface") |_ => WriteLine($"$x bottles of $bev on the $surface, $x bottles of $bev"); WriteLine($"Take one down and pass it around, $(x-1) bottles of $bev on the $surface") } } Main() : void { foreach (i in [99, 98 .. 0]) Sing(i) }
}</lang>
NetRexx
<lang netrexx> beer = "bottles of beer on the wall" removeOne = "Take one down, pass it arround," say 99 beer"," say 99 beer.subword(1,3)"," loop i = 98 to 2 by -1
say removeOne say i beer"." say say i beer"," say i beer.subword(1,3)","
end lastCall = "bottle" beer.delword(1,1) say removeOne say i lastCall"." say say i lastCall"," say i lastCall.subword(1,3)"," say removeOne say "No more" beer </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>
Nial
<lang nial>line is fork [
0=, 'No more bottles of beer' first, 1=, 'One bottle of beer' first, link [string,' bottles of beer' first]
]
verse is link [
line, ' on the wall, ' first,line, '. Take it down and pass it around, ' first, line (-1+),'on the wall. ' first
]
bottles is iterate (write verse) reverse count</lang>
Nimrod
<lang nimrod>proc GetBottleNumber(n: int): string =
var bs: string if n == 0: bs = "No more bottles" elif n == 1: bs = "1 bottle" else: bs = $n & " bottles" return bs & " of beer"
for bn in countdown(99, 1):
var cur = GetBottleNumber(bn) echo(cur, " on the wall, ", cur, ".") echo("Take one down and pass it around, ", GetBottleNumber(bn-1), " on the wall.\n")
echo "No more bottles of beer on the wall, no more bottles of beer." echo "Go to the store and buy some more, 99 bottles of beer on the wall."</lang>
Objective-C
<lang objc>#import <Foundation/Foundation.h>
int main() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int bottles = 99; do { NSLog(@"%i bottles of beer on the wall\n", bottles); NSLog(@"%i bottles of beer\n", bottles); NSLog(@"Take one down, pass it around\n"); NSLog(@"%i bottles of beer on the wall\n\n", --bottles); } while (bottles > 0);
[pool drain]; return 0;
}</lang>
Oberon-2
<lang oberon2>MODULE b99;
IMPORT Out;
VAR nr : INTEGER;
BEGIN
nr := 99; REPEAT Out.Int (nr, 4); Out.String (" bottles of beer on the wall"); Out.Ln; Out.Int (nr, 4); Out.String (" bottles of beer"); Out.Ln; Out.String ("Take one down, pass it around"); Out.Ln; DEC (nr); Out.Int (nr, 4); Out.String (" bottles of beer on the wall"); Out.Ln; Out.Ln UNTIL nr = 0
END b99.</lang>
OCaml
<lang ocaml>for n = 99 downto 1 do
Printf.printf "%d bottles of beer on the wall\n" n; Printf.printf "%d bottles of beer\n" n; Printf.printf "Take one down, pass it around\n"; Printf.printf "%d bottles of beer on the wall\n\n" (pred n);
done</lang>
Recursive version that handles plurals.
<lang ocaml>let verse n =
let line2 x = match x with | 0 -> "No more bottles of beer" | 1 -> "1 bottle of beer" | n -> string_of_int n ^ " bottles of beer" in let line1or4 y = line2 y ^ " on the wall" in let line3 n = match n with | 1 -> "Take it down, pass it around" | _ -> "Take one down, pass it around" in line1or4 n ^ "\n" ^ line2 n ^ "\n" ^ line3 n ^ "\n" ^ line1or4 (n-1) ^ "\n";;
let rec beer n =
print_endline (verse n); if n > 1 then beer (n-1);;
beer 99;;</lang>
Octave
<lang octave>function bottles(n)
bottle = "bottle"; ofbeer = "of beer"; wall = "on the wall"; for i = n:-1:0 if ( i == 1 ) s = ""; else s = "s"; endif for j = 0:1 w = wall; if ( j == 1 )
w = "";
endif printf("%d %s%s %s %s\n",\
i, bottle, s, ofbeer, w);
endfor printf("Take one down, pass it around\n"); endfor
endfunction
bottles(99);</lang>
OpenEdge/Progress
<lang Progress (Openedge ABL)>DEFINE VARIABLE amountofbottles AS INTEGER NO-UNDO INITIAL 99. &GLOBAL-DEFINE bbm bottles of beer &GLOBAL-DEFINE bbs bottle of beer &GLOBAL-DEFINE otw on the wall &GLOBAL-DEFINE tow Take one down and pass it around, &GLOBAL-DEFINE gts Go to the store and buy some more, FUNCTION drinkBottle RETURNS INTEGER PRIVATE (INPUT bc AS INTEGER) FORWARD.
OUTPUT TO OUTPUT.txt. drinkBottle(amountofbottles). OUTPUT CLOSE.
FUNCTION drinkBottle RETURNS INTEGER.
IF bc >= 0 THEN DO: CASE bc: WHEN 2 THEN PUT UNFORMATTED bc " {&bbm} {&otw}, " bc " {&bbm}" SKIP "{&tow} " bc - 1 " {&bbs} {&otw}" SKIP. WHEN 1 THEN PUT UNFORMATTED bc " {&bbs} {&otw}, " bc " {&bbs}" SKIP "{&tow} no more {&bbm} {&otw}" SKIP. WHEN 0 THEN PUT UNFORMATTED "no more" " {&bbm} {&otw}, no more {&bbm}" SKIP "{>s} " amountofbottles " {&bbm} {&otw}" SKIP. OTHERWISE PUT UNFORMATTED bc " {&bbm} {&otw}, " bc " {&bbm}" SKIP "{&tow} " bc - 1 " {&bbm} {&otw}" SKIP. END CASE. drinkBottle(bc - 1). RETURN bc. END. RETURN 0.
END FUNCTION.</lang>
Oz
Constraint Programming
Note: In real life, you would never solve a simple iterative task like this with constraint programming. This is just for fun. <lang oz>declare
%% describe the possible solutions of the beer 'puzzle' proc {BeerDescription Solution} N = {FD.int 1#99} %% N is an integer in [1, 99] in %% distribute starting with highest value {FD.distribute generic(value:max) [N]}
Solution = {Bottles N}#" of beer on the wall\n"# {Bottles N}#" bottles of beer\n"# "Take one down, pass it around\n"# {Bottles N-1}#" of beer on the wall\n" end
%% pluralization proc {Bottles N Txt} cond N = 1 then Txt ="1 bottle" else Txt = N#" bottles" end end
in
%% show all solutions to the 'puzzle' {ForAll {SearchAll BeerDescription} System.showInfo}</lang>
Iterative
<lang oz>declare
fun {Bottles N} if N == 1 then "1 bottle" else N#" bottles" end end
in
for I in 99..1;~1 do {System.showInfo {Bottles I}#" of beer on the wall\n"# {Bottles I}#" bottles of beer\n"# "Take one down, pass it around\n"# {Bottles I-1}#" of beer on the wall\n"} end</lang>
PARI/GP
<lang parigp>forstep(n=99,3,-1,
print(n" bottles of beer on the wall"); print(n" bottles of beer"); print("Take one down, pass it around"); print(n-1," bottles of beer on the wall\n")
); print("2 bottles of beer on the wall\n2 bottles of beer\nTake one down, pass it around\n1 bottle of beer on the wall\n"); print("1 bottle of beer on the wall\n1 bottle of beer\nTake one down, pass it around\nNo more bottles of beer on the wall")</lang>
Pascal
<lang pascal>procedure BottlesOfBeer; var
i: Integer;
begin
for i := 99 downto 1 do begin if i = 1 then begin WriteLn('1 bottle of beer on the wall'); WriteLn('1 bottle of beer'); WriteLn('Take one down, pass it around'); WriteLn('No more bottles of beer on the wall'); Exit; end; WriteLn(Format('%d bottles of beer on the wall', [i])); WriteLn(Format('%d bottles of beer', [i])); WriteLn('Take one down, pass it around'); WriteLn(Format('%d bottles of beer on the wall', [Pred(i)])); WriteLn(); end;
end;</lang>
Perl
<lang perl>#!/usr/bin/perl -w
my $verse = <<"VERSE"; 100 bottles of beer on the wall, 100 bottles of beer! Take one down, pass it around! 99 bottles of beer on the wall!
VERSE
{
$verse =~ s/(\d+)/$1-1/ge; $verse =~ s/\b1 bottles/1 bottle/g; my $done = $verse =~ s/\b0 bottle/No bottles/g; # if we make this replacement, we're also done.
print $verse; redo unless $done;
}</lang>
Alternatively: <lang perl>for $n (reverse(0..99)) {
$bottles = sprintf("%s bottle%s of beer on the wall\n",(($n==0)?"No":$n), (($n==1)?"":"s")); print( (($n==99)?"":"$bottles\n") .
(($n==0)?"":(substr(${bottles}x2,0,-12) . "\nTake one down, pass it around\n")) ); }</lang>
Perl 6
A Simple Way
<lang perl6>my $b = 99;
sub b($b) {
"$b bottle{'s'.substr($b == 1)} of beer";
}
repeat while --$b {
.say for "&b($b) on the wall", b($b), 'Take one down, pass it around', "&b($b-1) on the wall", ;
} </lang>
A More Extravagant Way
<lang perl6>my @quantities = (99 ... 1), 'No more', 99; my @bottles = 'bottles' xx 98, 'bottle', 'bottles' xx 2; my @actions = 'Take one down, pass it around' xx 99,
'Go to the store, buy some more';
for @quantities Z @bottles Z @actions Z
@quantities[1 .. *] Z @bottles[1 .. *] -> $a, $b, $c, $d, $e { say "$a $b of beer on the wall"; say "$a $b of beer"; say $c; say "$d $e of beer on the wall\n";
}</lang>
PHP
<lang php><?php $plural = 's'; foreach (range(99, 1) as $i) {
echo "$i bottle$plural of beer on the wall,\n"; echo "$i bottle$plural of beer!\n"; echo "Take one down, pass it around!\n"; if ($i - 1 == 1) $plural = ; if ($i > 1) echo ($i - 1) . " bottle$plural of beer on the wall!\n\n"; else echo "No more bottles of beer on the wall!\n";
} ?></lang>
shorter way: <lang php><?php foreach(range(99,1) as $i) {
$p = ($i>1)?"s":""; echo <<< EOV
$i bottle$p of beer on the wall $i bottle$p of beer Take one down, pass it around
EOV;
}
echo "No more Bottles of beer on the wall";
?></lang>
modifing way:
<lang php><?php
$verse = <<<VERSE
100 bottles of beer on the wall,
100 bottles of beer!
Take one down, pass it around!
99 bottles of beer on the wall!
VERSE;
foreach (range(1,99) as $i) { // loop 99 times
$verse = preg_replace('/\d+/e', '$0 - 1', $verse); $verse = preg_replace('/\b1 bottles/', '1 bottle', $verse); $verse = preg_replace('/\b0 bottle/', 'No bottles', $verse);
echo $verse;
} ?></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>
Piet
Pike
<lang pike>int main(){
for(int i = 99; i > 0; i--){ write(i + " bottles of beer on the wall, " + i + " bottles of beer.\n"); write("Take one down and pass it around, " + (i-1) + " bottles of beer on the wall.\n\n"); } write("No more bottles of beer on the wall, no more bottles of beer.\n"); write("Go to the store and buy some more, 99 bottles of beer on the wall.\n");
}</lang>
PIR
<lang pir>.sub sounding_smart_is_hard_after_drinking_this_many
.param int b if b == 1 goto ONE .return(" bottles ")
ONE:
.return(" bottle ") end
.end
.sub main :main
.local int bottles .local string b bottles = 99
LUSH:
if bottles == 0 goto DRUNK b = sounding_smart_is_hard_after_drinking_this_many( bottles ) print bottles print b print "of beer on the wall\n" print bottles print b print "of beer\nTake one down, pass it around\n" dec bottles b = sounding_smart_is_hard_after_drinking_this_many( bottles ) print bottles print b print "of beer on the wall\n\n" goto LUSH
DRUNK:
end
.end</lang>
Plain TeX
<lang tex>\obeylines \newtoks\bottle \bottle={bottle} \newtoks\ofbeer \ofbeer={of beer} \newtoks\onthewall \onthewall={on the wall} \newtoks\passit \passit={Take one down, pass it around} \def\song#1{#1 \the\bottle\ifnum#1>1\relax s\fi% \ \the\ofbeer\ \the\onthewall
- 1 \the\bottle\ifnum#1>1\relax s\fi\ \the\ofbeer
\the\passit} \newcount\bottles \bottles99 \loop\song{\number\bottles} \advance\bottles-1\ifnum\bottles>1\repeat 0 \the\bottle s \the\ofbeer\ \the\onthewall \bye</lang>
Pop11
<lang pop11>define bootles(n);
while n > 0 do printf(n, '%p bottles of beer on the wall\n'); printf(n, '%p bottles of beer\n'); printf('Take one down, pass it around\n'); n - 1 -> n; printf(n, '%p bottles of beer on the wall\n'); endwhile;
enddefine;
bootles(99);</lang>
PowerShell
A standard impementation using a For loop
<lang PowerShell>for($n=99; $n -gt 0; $n--) {
"$n bottles of beer on the wall" "$n bottles of beer" "Take one down, pass it around" [string]($n-1) + " bottles of beer on the wall" ""
}</lang>
Consolidating the static text and using a Do loop
<lang PowerShell>$n=99 do {
"{0} bottles of beer on the wall`n{0} bottles of beer`nTake one down, pass it around`n{1} bottles of beer on the wall`n" -f $n, --$n
} while ($n -gt 0)</lang>
Consolidating the static text even more
<lang PowerShell>$s = "{0} bottles of beer on the wall`n{0} bottles of beer`nTake one down, pass it around`n{1} bottles of beer on the wall`n" $n=99 do { $s -f $n, --$n } while ($n -gt 0)</lang>
Using the Pipeline
<lang Powershell>99..1 | ForEach-Object {
$s=$( if( $_ -ne 1 ) { 's' } else { } ) $s2=$( if( $_ -ne 2 ) { 's' } else { } ) "$_ bottle$s of beer on the wall`n$_ bottle$s of beer`nTake one down`npass it around`n$( $_ - 1 ) bottle$s2 of beer on the wall`n"}</lang>
Prolog
<lang prolog>bottles(0):-!. bottles(X):-
writef('%t bottles of beer on the wall \n',[X]), writef('%t bottles of beer\n',[X]), write('Take one down, pass it around\n'), succ(XN,X), writef('%t bottles of beer on the wall \n\n',[XN]), bottles(XN).
- - bottles(99).</lang>
An other version that handles plural/not plural conditions.
<lang prolog>line1(X):- line2(X),write(' on the wall'). line2(0):- write('no more bottles of beer'). line2(1):- write('1 bottle of beer'). line2(X):- writef('%t bottles of beer',[X]). line3(1):- write('Take it down, pass it around'). line3(X):- write('Take one down, pass it around'). line4(X):- line1(X).
bottles(0):-!. bottles(X):-
succ(XN,X), line1(X),nl, line2(X),nl, line3(X),nl, line4(XN),nl,nl, !, bottles(XN).
- - bottles(99).</lang>
PureBasic
Normal version
<lang PureBasic>If OpenConsole()
Define Bottles=99 While Bottles PrintN(Str(Bottles)+" bottles of beer on the wall") PrintN(Str(Bottles)+" bottles of beer") PrintN("Take one down, pass it around") Bottles-1 PrintN(Str(Bottles)+" bottles of beer on the wall"+#CRLF$) Wend PrintN(#CRLF$+#CRLF$+"Press ENTER to exit"):Input() CloseConsole()
EndIf</lang>
An object-oriented solution
<lang PureBasic>Prototype Wall_Action(*Self, Number.i)
Structure WallClass
Inventory.i AddBottle.Wall_Action DrinkAndSing.Wall_Action
EndStructure
Procedure.s _B(n, Short=#False)
Select n Case 0 : result$="No more bottles " Case 1 : result$=Str(n)+" bottle of beer" Default: result$=Str(n)+" bottles of beer" EndSelect If Not Short: result$+" on the wall": EndIf ProcedureReturn result$+#CRLF$
EndProcedure
Procedure PrintBottles(*Self.WallClass, n)
Bottles$=" bottles of beer " Bottle$ =" bottle of beer " txt$ = _B(*Self\Inventory) txt$ + _B(*Self\Inventory, #True) txt$ + "Take one down, pass it around"+#CRLF$ *Self\AddBottle(*Self, -1) txt$ + _B(*self\Inventory) PrintN(txt$) ProcedureReturn *Self\Inventory
EndProcedure
Procedure AddBottle(*Self.WallClass, n)
i=*Self\Inventory+n If i>=0 *Self\Inventory=i EndIf
EndProcedure
Procedure InitClass()
*class.WallClass=AllocateMemory(SizeOf(WallClass)) If *class InitializeStructure(*class, WallClass) With *class \AddBottle =@AddBottle() \DrinkAndSing =@PrintBottles() EndWith EndIf ProcedureReturn *class
EndProcedure
If OpenConsole()
*MyWall.WallClass=InitClass() If *MyWall *MyWall\AddBottle(*MyWall, 99) While *MyWall\DrinkAndSing(*MyWall, #True): Wend ; PrintN(#CRLF$+#CRLF$+"Press ENTER to exit"):Input() CloseConsole() EndIf
EndIf</lang>
Python
Normal Code
<lang python>def plural(word, amount): # Correctly pluralize a word.
if amount == 1: return word else: return word + 's'
def sing(b, end): # Sing a phrase of the song, for b bottles, ending in end
print b or 'No more', plural('bottle', b), end
for i in range(99, 0, -1):
sing(i, 'of beer on the wall,') sing(i, 'of beer,') print 'Take one down, pass it around,' sing(i-1, 'of beer on the wall.\n')</lang>
Using a template
<lang python>verse = \ %i bottles of beer on the wall %i bottles of beer Take one down, pass it around %i bottles of beer on the wall
for bottles in range(99,0,-1):
print verse % (bottles, bottles, bottles-1) </lang>
New-style template (Python 2.6)
<lang python>verse = \ {some} bottles of beer on the wall {some} bottles of beer Take one down, pass it around {less} bottles of beer on the wall
for bottles in range(99,0,-1):
print verse.format(some=bottles, less=bottles-1) </lang>
"Clever" generator expression
<lang python>a, b, c, s = " bottles of beer", " on the wall\n", "Take one down, pass it around\n", str print "\n".join(s(x)+a+b+s(x)+a+"\n"+c+s(x-1)+a+b for x in xrange(99, 0, -1))</lang>
Enhanced "Clever" generator expression using lambda
<lang python>a = lambda n: "%u bottle%s of beer on the wall\n" % (n, "s"[n==1:]) print "\n".join(a(x)+a(x)[:-13]+"\nTake one down, pass it around\n"+a(x-1) for x in xrange(99, 0, -1))</lang>
Using a generator expression (Python 3)
<lang python>#!/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="")</lang>
A wordy version
<lang python>ones = ( , 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine' ) prefixes = ('thir', 'four', 'fif', 'six', 'seven', 'eigh', 'nine') tens = [, , 'twenty' ] teens = ['ten', 'eleven', 'twelve'] for prefix in prefixes:
tens.append(prefix + 'ty') teens.append(prefix +'teen')
tens[4] = 'forty'
def number(num):
"get the wordy version of a number" ten, one = divmod(num, 10) if ten == 0 and one == 0: return 'no' elif ten == 0: return ones[one] elif ten == 1: return teens[one] elif one == 0: return tens[ten] else: return "%s-%s" % (tens[ten], ones[one])
def bottles(beer):
"our rephrase" return "%s bottle%s of beer" % ( number(beer).capitalize(), 's' if beer > 1 else )
onthewall = 'on the wall' takeonedown = 'Take one down, pass it around' for beer in range(99, 0, -1):
print bottles(beer), onthewall print bottles(beer) print takeonedown print bottles(beer-1), onthewall print</lang>
String Formatting
<lang python>for n in xrange(99, 0, -1):
## The formatting performs a conditional check on the variable. ## If it formats the first open for False, and the second for True print n, 'bottle%s of beer on the the wall.' % ('s', )[n == 1] print n, 'bottle%s of beer.' % ('s', )[n == 1] print 'Take one down, pass it around.' print n - 1, 'bottle%s of beer on the wall.\n' % ('s', )[n - 1 == 1]</lang>
Quill
<lang quill>bottles := void(int count) {
(count > 0) if { new_count := count - 1; ( count, " bottles of beer on the wall", nl, count, " bottles of beer", nl, "Take one down, pass it around", nl, new_count, " bottles of beer on the wall" ) print; new_count bottles } else { "No more bottles of beer on the wall!" print }
}; 99 bottles</lang>
R
<lang R>
- only one line!
cat(paste(99:0, ifelse((99:0)!=1," bottles"," bottle")," of beer on the wall\n",ifelse(99:0>0,paste(" ",99:0, ifelse((99:0)!=1," bottles"," bottle"), " of beer\n"," Take one down, pass it around\n",sep=""),""), sep=""))</lang>
<lang R>
- a naive function to sing for N bottles of beer...
song = function(bottles){
for(i in bottles:1){ #for every integer bottles, bottles-1 ... 1 cat(bottles,"bottles of beer on the wall \n",bottles,"bottles of beer \n Take one down, pass it around \n", bottles-1, "bottles of beer on the wall \n"," \n" ) #join and print the text (\n means new line) bottles = bottles - 1 #take one down... }
}
song(99)#play the song by calling the function
</lang>
Racket
<lang scheme>
- lang racket
(define (plural n)
(string-append (number->string n) " bottle" (if (equal? n 1) "" "s")))
(define (sing bottles)
(printf "~a of beer on the wall\n~a of beer\nTake on down, pass it around\n~a of beer on the wall\n\n" (plural bottles) (plural bottles) (plural (sub1 bottles))))
(for ((i (in-range 100 0 -1)))
(sing i))
</lang>
REALbasic
Place the following in the "open" event of a console application. <lang REALBasic>dim bottles as Integer = 99 While bottles > 0 stdout.writeline(str(bottles) + " bottles of beer on the wall") stdout.writeline(str(bottles) + " bottles of beer") stdout.writeline("Take one down, pass it around") bottles = bottles - 1 stdout.writeline(str(bottles) + " bottles of beer on the wall") Wend</lang>
REBOL
<lang REBOL>rebol [
Title: "99 Bottles of Beer" Author: oofoe Date: 2009-12-11 URL: http://rosettacode.org/wiki/99_Bottles_of_Beer
]
- The 'bottles' function maintains correct grammar.
bottles: func [n /local b][ b: either 1 = n ["bottle"]["bottles"] if 0 = n [n: "no"] reform [n b] ]
for n 99 1 -1 [print [ bottles n "of beer on the wall" crlf bottles n "of beer" crlf "Take one down, pass it around" crlf bottles n - 1 "of beer on the wall" crlf ]]</lang>
Output (selected highlights):
99 bottles of beer on the wall 2 bottles of beer on the wall 99 bottles of beer 2 bottles of beer Take one down, pass it around Take one down, pass it around 98 bottles of beer on the wall 1 bottle of beer on the wall ...Continues... 1 bottle of beer on the wall 1 bottle of beer Take one down, pass it around no bottles of beer on the wall
Retro
This is based on the Forth example.
<lang Retro>[ dup "%d bottles" puts ] [ "1 bottle" puts ] [ "no more bottles" puts ] create bottles , , ,
- .bottles dup 2 ^math'min bottles + @ do ;
- .beer .bottles " of beer" puts ;
- .wall .beer " on the wall" puts ;
- .take "Take one down, pass it around" puts ;
- .verse .wall cr .beer cr
1- .take cr .wall cr ;
- ?dup dup 0; ;
- verses [ cr .verse dup 0 <> ] while drop ;
99 verses bye</lang>
REXX
<lang rexx> do j=99 by -1
say j 'bottle's(j) "of beer the wall" say j 'bottle's(j) "of beer" say 'Take one down, pass it around' n=j-1 if n==0 then n='no' say n 'bottle's(j-1) "of beer the wall" say if j==1 then exit end
s:if arg(1)=1 then return ; return 's' /*simple pluralizer.*/</lang> Below is the last three verses of the song.
3 bottles of beer the wall 3 bottles of beer Take one down, pass it around 2 bottles of beer the wall 2 bottles of beer the wall 2 bottles of beer Take one down, pass it around 1 bottle of beer the wall 1 bottle of beer the wall 1 bottle of beer Take one down, pass it around no bottles of beer the wall
RPL/2
Simple solution
<lang rpl/2>BEER <<
99 do dup ->str PLURAL " on the wall," + disp dup ->str PLURAL "." + disp "Take one down, pass it around," disp 1 - if dup then dup ->str else "No more" end PLURAL " on the wall." + disp "" disp until dup 0 == end drop
>>
PLURAL <<
" bottle" + over if 1 <> then "s" + end " of beer" +
>></lang>
Recursive and multithreaded solution
<lang rpl/2>BOTTLES <<
// Child process is started. 100 'RECURSIVE' detach -> PROC << do PROC recv until end drop2
do // Parent waits for datas sent by child. do PROC recv until end list-> drop dup " on the wall," + disp "." + disp "Take one down, pass it around," disp
if dup 1 same not then do PROC recv until end list-> drop else 1 "No more bottles of beer" end " on the wall." + disp drop "" disp until 1 same end
// Parent waits for Child's death. PROC wfproc >>
>>
RECURSIVE <<
while dup repeat 1 - dup dup ->str if over 1 > then " bottles " else " bottle " end + "of beer" + 2 ->list dup // Child send datas to parent process. send send // Recursive function is caught. RECURSIVE end
>></lang>
Ruby
<lang ruby>plural = 's' 99.downto(1) do |i|
puts "#{i} bottle#{plural} of beer on the wall," puts "#{i} bottle#{plural} of beer" puts "Take one down, pass it around!" plural = if i - 1 == 1 if i > 1 puts "#{i-1} bottle#{plural} of beer on the wall!" puts else puts "No more bottles of beer on the wall!" end
end</lang>
Ruby has variable traces, so we can do <lang ruby>trace_var :$bottle_num do |val|
$bottles = %Q{#{val == 0 ? 'No more' : val.to_s} bottle#{val == 1 ? : 's'}}
end
($bottle_num = 99).times do
puts "#{$bottles} of beer on the wall" puts "#{$bottles} of beer" puts "Take one down, pass it around" $bottle_num -= 1 puts "#{$bottles} of beer on the wall" puts ""
end</lang> or... <lang ruby>def bottles(of_beer, ending)
puts "#{of_beer} bottle#{ending} of beer on the wall," puts "#{of_beer} bottle#{ending} of beer" puts "Take one down, pass it around!"
end
99.downto(0) do |left|
if left > 1 bottles(left, "s") elsif left == 1 bottles(left, "") else puts "No more bottles of beer on the wall!" end
end</lang> or... <lang ruby>def bottles(beer, wall = false)
"#{beer>0 ? beer : "no more"} bottle#{"s" if beer!=1} of beer#{" on the wall" if wall}"
end
99.downto(0) do |remaining|
puts "#{bottles(remaining,true).capitalize}, #{bottles(remaining)}." if remaining==0 print "Go to the store and buy some more" remaining=100 else print "Take one down, pass it around" end puts ", #{bottles(remaining-1,true)}.\n\n"
end</lang>
Sather
<lang sather>class MAIN is
main is s :STR; p1 ::= "<##> bottle<#> of beer"; w ::= " on the wall"; t ::= "Take one down, pass it around\n"; loop i ::= 99.downto!(0); if i /= 1 then s := "s" else s := ""; end; #OUT + #FMT(p1 + w + "\n", i, "s"); #OUT + #FMT(p1 + "\n", i, "s"); if i > 0 then #OUT + t; end; end; end;
end;</lang>
Scala
Scheme
<lang scheme>(define (bottles x) (format #t "~a bottles of beer on the wall~%" x) (format #t "~a bottles of beer~%" x) (format #t "Take one down, pass it around~%") (format #t "~a bottles of beer on the wall~%" (- x 1)) (if (> (- x 1) 0) (bottles (- x 1))))</lang>
Scratch
Seed7
<lang seed7>$ include "seed7_05.s7i";
const proc: main is func
local var integer: number is 0; begin for number range 99 downto 2 do write( number <& " bottles of beer on the wall, "); writeln( number <& " bottles of beer."); write( "Take one down and pass it around, "); writeln( pred(number) <& " bottles of beer on the wall."); writeln; end for; writeln("1 bottle of beer on the wall, 1 bottle of beer."); writeln("Take one down and pass it around, no more bottles of beer on the wall."); writeln; writeln("No more bottles of beer on the wall, no more bottles of beer."); writeln("Go to the store and buy some more, 99 bottles of beer on the wall.") end func;</lang>
Shiny
<lang shiny>for 99 i:99-a
s: if i > 1 's' end
if i > 0 and i < 99 switch if i = 6 say "A six-pack on the wall!\n" break if i = 24 say "A carton on the wall!\n" break say "$i bottle$s of beer on the wall!\n" ends
say "$i bottle$s of beer on the wall," say "$i bottle$s of beer!" say "Take one down, pass it around!"
end say "Aww...no more bottles of beer on the wall... it must be your shout :)"</lang>
Slate
<lang slate>n@(Integer traits) bottleVerse [| nprinted |
nprinted: n printString ; ' bottle' ; (n > 1 ifTrue: ['s'] ifFalse: []) ; ' of beer'. inform: nprinted ; ' on the wall.'. inform: nprinted. inform: 'Take one down, pass it around.'. inform: nprinted ; ' on the wall.'.
].
x@(Integer traits) bottles [
x downTo: 0 do: #bottleVerse `er
].
99 bottles.</lang>
Smalltalk
A straightforward approach: <lang smalltalk>Smalltalk at: #sr put: 0 ; at: #s put: 0 ! sr := Dictionary new. sr at: 0 put: ' bottle' ;
at: 1 put: ' bottles' ; at: 2 put: ' of beer' ; at: 3 put: ' on the wall' ; at: 4 put: 'Take one down, pass it around' !
99 to: 0 by: -1 do: [:v | v print.
( v == 1 ) ifTrue: [ s := 0. ]
ifFalse: [ s := 1. ]. Transcript show: (sr at:s) ; show: (sr at:2) ; show: (sr at:3) ; cr. v print. Transcript show: (sr at:s) ; show: (sr at:2) ; cr. (v ~~ 0) ifTrue: [ Transcript show: (sr at:4) ; cr. ].
].</lang>
SNOBOL4
<lang snobol> x = 99 again output = X " bottles of beer on the wall" output = X " bottles of beer" ?eq(X,0) :s(zero) output = "Take one down, pass it around" output = (X = gt(x,0) X - 1) " bottle of beer on the wall..." :s(again) zero output = "Go to store, get some more" output = "99 bottles of beer on the wall" end</lang>
Function
Function version with string composition. Function returns one verse for x bottles. Correctly handles bottle/bottles. <lang SNOBOL4> define('bottles(x)')
nl = char(13) char(10) ;* Win/DOS, change as needed s2 = ' of beer'; s3 = ' on the wall' s4 = 'Take one down, pass it around' s5 = 'Go to the store, get some more' :(bottles_end)
bottles s1 = (s1 = ' Bottle') ne(x,1) 's'
output = nl x s1 s2 s3 nl x s1 s2 x = gt(x,0) x - 1 :f(done) s1 = (s1 = ' Bottle') ne(x,1) 's' output = s4 nl x s1 s2 s3 :(return)
done output = s5 nl 99 s1 s2 s3 :(return) bottles_end
- # Test and display, only 2 bottles!
n = 2
loop bottles(n); n = gt(n,0) n - 1 :s(loop) end</lang>
Output:
2 Bottles of beer on the wall 2 Bottles of beer Take one down, pass it around 1 Bottle of beer on the wall 1 Bottle of beer on the wall 1 Bottle of beer Take one down, pass it around 0 Bottles of beer on the wall 0 Bottles of beer on the wall 0 Bottles of beer Go to the store, get some more 99 Bottles of beer on the wall
SNUSP
<lang snusp> /=!/===========!/==+++++++++# +9
| | /=!/=====@/==@@@+@+++++# +48 (itoa) | | | | /==!/==@@@@=++++# +32 (space) | | | | | \==@@++\!+++++++++++++\!+++++\ 9 9 '9 9' space 'b' 'o' 't' $@/>@/>@/>@/>@/>========@/>============@/>====@/>++++++++++ \n setup
/====================================loop=====>\!=>\!<<<<<<<< / \@\@\>cr.@\< ?\<->+++++++++>->+++++++++\ | |
! | | \===-========>=>-==BCD==!\< @\< ?/< ?/# no more beer! /=|=====|================================/ | | \<++t.<<----a.>----k.<++++e.<_.>>++++o.-n.< e.<_.>-d.>+o.>+++w.<-n.<<_.\ | | / / | | \>---a.>n.<+++d.<_.>>++p.<---a.>>----s.s.<<<_.>>-------i.>+t.<<<_.\ | | / / | | \>a.>>--r.<++++++o.>+++u.<-n.<+++d.>>>cr.<-T<+O<--B<<<# | ! \@\<<<_.>>o.-n.<<_.>>>++t.<<+++h.---e.<_.>>>+++w.<<----a.>--l.l.>>CR.<---T<+++O<+B<<<# | \9.>9.>_.>B.>O.>T.t.<---l.<+++e.>>-s.<<<_.>>+++O.<+f.<_.>----b.+++e.E.>>-R.#</lang>
Standard ML
<lang sml>fun bottles 0 = ()
| bottles x = ( print (Int.toString x ^ " bottles of beer on the wall\n"); print (Int.toString x ^ " bottles of beer\n"); print "Take one down, pass it around\n"; print (Int.toString (x-1) ^ " bottles of beer on the wall\n"); bottles (x-1) )</lang>
Suneido
<lang Suneido>i = 99 while (i > 0)
{ Print(i $ ' bottles of beer on the wall') Print(i $ ' bottles of beer') Print('Take one down, pass it around') --i if i is 0 Print('Ahh poo, we are out of beer\n') else Print(i $ ' bottles of beer on the wall\n') }</lang>
Tcl
<lang tcl>set s "s"; set ob "of beer"; set otw "on the wall"; set more "Take one down and pass it around" for {set n 100} {$n ne "No more"} {} { switch -- [incr n -1] { 1 {set s ""} 0 {set s "s"; set n "No more"; set more "Go to the store and buy some more"} } lappend verse ". $n bottle$s $ob $otw.\n" lappend verse "\n$n bottle$s $ob $otw, [string tolower $n] bottle$s $ob.\n$more" } puts -nonewline [join [lreplace $verse 0 0] ""][lindex $verse 0]</lang> Version which converts numbers to words, optimized for script length while retaining readability: <lang tcl>proc 0-19 {n} {
lindex {"no more" one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen} $n
}
proc TENS {n} {
lindex {twenty thirty fourty fifty sixty seventy eighty ninety} [expr {$n - 2}]
}
proc num2words {n} {
if {$n < 20} {return [0-19 $n]} set tens [expr {$n / 10}] set ones [expr {$n % 10}] if {$ones == 0} {return [TENS $tens]} return "[TENS $tens]-[0-19 $ones]"
}
proc get_words {n} {
return "[num2words $n] bottle[expr {$n != 1 ? "s" : ""}] of beer"
}
for {set i 99} {$i > 0} {incr i -1} {
puts [string totitle "[get_words $i] on the wall, [get_words $i]."] puts "Take one down and pass it around, [get_words [expr {$i - 1}]] on the wall.\n"
}
puts "No more bottles of beer on the wall, no more bottles of beer." puts "Go to the store and buy some more, 99 bottles of beer on the wall."</lang> See also 99 Bottles of Beer/Tcl
Thyrd
![](http://static.miraheze.org/rosettacodewiki/thumb/d/d0/Thyrd-9bottles.png/300px-Thyrd-9bottles.png)
![](http://static.miraheze.org/rosettacodewiki/thumb/b/bc/Thyrd-9bottles-detail.png/300px-Thyrd-9bottles-detail.png)
TI-89 BASIC
<lang ti89b>Prgm
Local i,plural,clockWas,t,k,wait "s" → plural 0 → k isClkOn() → clockWas
Define wait() = Prgm EndPrgm
ClockOn
For i,99,0,–1 Disp "" Disp string(i) & " bottle" & plural & " of beer on the" Disp "wall, " & string(i) & " bottle" & plural & " of beer."
getTime()[3]→t While getTime()[3] = t and k = 0 : getKey() → k : EndWhile If k ≠ 0 Then : Exit : EndIf
Disp "Take one down, pass it" Disp "around."
getTime()[3]→t While getTime()[3] = t and k = 0 : getKey() → k : EndWhile If k ≠ 0 Then : Exit : EndIf
If i - 1 = 1 Then "" → plural EndIf If i > 1 Then Disp string(i-1) & " bottle" & plural & " of beer on the" Disp "wall." Else Disp "No more bottles of beer on" Disp "the wall." EndIf
getTime()[3]→t While abs(getTime()[3] - t)<2 and k = 0 : getKey() → k : EndWhile If k ≠ 0 Then : Exit : EndIf
EndFor If not clockWas Then ClockOff ENdIf
EndPrgm</lang>
TIScript
<lang javascript> var beer = 99; while (beer > 0) {
stdout.printf( "%d bottles of beer on the wall\n", beer); stdout.printf( "%d bottles of beer\n", beer); stdout.println( "Take one down, pass it around" ); stdout.printf( "%d bottles of beer on the wall\n", --beer );
} </lang>
TUSCRIPT
<lang tuscript> $$ MODE TUSCRIPT LOOP bottle=1,100 SET bottlenr=100-bottle IF (bottlenr==0) THEN PRINT "no bottle of beer on the wall" EXIT ELSEIF (bottlenr==1) THEN PRINT bottlenr, " bottle of beer on the wall" PRINT bottlenr, " bottle of beer" ELSE PRINT bottlenr, " bottles of beer on the wall" PRINT bottlenr, " bottles of beer" ENDIF PRINT "Take one down, pass it around" ENDLOOP </lang>
UNIX Shell
<lang bash>#!/bin/sh
i=99 s=s
while [ $i -gt 0 ]; do
echo "$i bottle$s of beer on the wall" echo "$i bottle$s of beer
Take one down, pass it around"
# POSIX allows for $(( i - 1 )) but some older Unices didn't have that i=`expr $i - 1`
[ $i -eq 1 ] && s= || s=s
echo "$i bottle$s of beer on the wall
" done</lang>
<lang bash>bottles() {
beer=$1 [ $((beer)) -gt 0 ] && echo -n $beer || echo -n "No more" echo -n " bottle" [ $((beer)) -ne 1 ] && echo -n "s" echo -n " of beer"
}
for ((i=99;i>=0;i--)); do
((remaining=i)) echo "$(bottles $remaining) on the wall" echo "$(bottles $remaining)" if [ $((remaining)) -eq 0 ]; then echo "Go to the store and buy some more" ((remaining+=99)) else echo "Take one down, pass it around" ((remaining--)) fi echo "$(bottles $remaining) on the wall" echo
done</lang>
C Shell
<lang csh>@ i=99 set s=s while ($i > 0) echo "$i bottle$s of beer on the wall" echo "$i bottle$s of beer" echo "Take one down, pass it around" @ i = $i - 1 if ($i == 1) then set s= else set s=s endif echo "$i bottle$s of beer on the wall" echo "" end</lang>
UnixPipes
- Unix Pipes, avoiding all the turing complete sub programs like sed, awk,dc etc.
<lang bash>mkdir 99 || exit 1 trap "rm -rf 99" 1 2 3 4 5 6 7 8
(cd 99
mkfifo p.b1 p.b2 p.verse1 p.wall p.take yes "on the wall" > p.wall & yes "Take one down and pass it around, " > p.take & (yes "bottles of beer" | nl -s\ | head -n 99 | tac | head -n 98 ; echo "One bottle of beer"; echo "No more bottles of beer") | tee p.b1 p.b2 | paste -d"\ " - p.wall p.b1 p.take | head -n 99 > p.verse1 & cat p.b2 | tail -99 | paste -d"\ " p.verse1 - p.wall | head -n 99
) rm -rf 99</lang>
Ursala
<lang Ursala>#import nat
- each function takes a natural number to a block of text
quantity = # forms the plural as needed
~&iNC+ --' of beer'+ ~&?(
1?=/'1 bottle'! --' bottles'+ ~&h+ %nP, 'no more bottles'!)
verse =
^(successor,~&); ("s","n"). -[
-[quantity "s"]- on the wall, -[quantity "s"]-, Take one down and pass it around, -[quantity "n"]- on the wall.]-
refrain "n" =
-[
No more bottles of beer on the wall, -[quantity 0]-. Go to the store and buy some more, -[quantity "n"]- on the wall.]-
whole_song "n" = ~&ittt2BSSL (verse*x iota "n")--<refrain "n">
- show+
main = whole_song 99</lang>
V
<lang v>[bottles
[newline '' puts]. [beer [0 =] ['No more bottles of beer' put] if [1 =] ['One bottle of beer' put] if [1 >] [dup put ' bottles of beer' put] if]. [0 =] [newline] [beer ' on the wall, ' put beer newline 'Take one down and pass it around, ' put pred beer ' on the wall' puts newline] tailrec].
99 bottles</lang>
VBScript
Simple Method
<lang vb>sub song( numBottles ) dim i for i = numBottles to 0 step -1 if i > 0 then wscript.echo pluralBottles(i) & " of beer on the wall" wscript.echo pluralBottles(i) & " of beer" if i = 1 then wscript.echo "take it down" else wscript.echo "take one down" end if wscript.echo "and pass it round" wscript.echo pluralBottles(i-1) & " of beer on the wall" wscript.echo else wscript.echo "no more bottles of beer on the wall" wscript.echo "no more bottles of beer" wscript.echo "go to the store" wscript.echo "and buy some more" wscript.echo pluralBottles(numBottles) & " of beer on the wall" wscript.echo end if next end sub
function pluralBottles( n ) select case n case 1 pluralBottles = "one bottle" case 0 pluralBottles = "no more bottles" case else pluralBottles = n & " bottles" end select end function
song 3</lang> Outputs: <lang vbscript>3 bottles of beer on the wall 3 bottles of beer take one down and pass it round 2 bottles of beer on the wall
2 bottles of beer on the wall 2 bottles of beer take one down and pass it round one bottle of beer on the wall
one bottle of beer on the wall one bottle of beer take it down and pass it round no more bottles of beer on the wall
no more bottles of beer on the wall no more bottles of beer go to the store and buy some more 3 bottles of beer on the wall</lang>
Regular Expressions and Embedded Scripting
Another way of doing it, using Regular Expressions to locate executable code inside {} and replacing the code with the result of its evaluation.
<lang vb>function pluralBottles( n ) select case n case 1 pluralBottles = "one bottle" case 0 pluralBottles = "no more bottles" case else pluralBottles = n & " bottles" end select end function
function eef( b, r1, r2 ) if b then eef = r1 else eef = r2 end if end function
Function evalEmbedded(sInput, sP1) dim oRe, oMatch, oMatches dim sExpr, sResult Set oRe = New RegExp 'Look for expressions as enclosed in braces oRe.Pattern = "{(.+?)}" sResult = sInput do Set oMatches = oRe.Execute(sResult) if oMatches.count = 0 then exit do for each oMatch in oMatches '~ wscript.echo oMatch.Value for j = 0 to omatch.submatches.count - 1 sExpr = omatch.submatches(j) sResult = Replace( sResult, "{" & sExpr & "}", eval(sExpr) ) next next loop evalEmbedded = sResult End Function
sub sing( numBottles ) dim i for i = numBottles to 0 step -1 if i = 0 then wscript.echo evalEmbedded("no more bottles of beer on the wall" & vbNewline & _ "no more bottles of beer" & vbNewline & _ "go to the store and buy some more" & vbNewline & _ "{pluralBottles(sP1)} of beer on the wall" & vbNewline, numBottles) else wscript.echo evalEmbedded("{pluralBottles(sP1)} of beer on the wall" & vbNewline & _ "{pluralBottles(sP1)} of beer" & vbNewline & _ "take {eef(sP1=1,""it"",""one"")} down and pass it round" & vbNewline & _ "{pluralBottles(sP1-1)} of beer on the wall" & vbNewline, i) end if next end sub
sing 3</lang>
Visual Basic
<lang vb>Sub Main()
Const bottlesofbeer As String = " bottles of beer" Const onthewall As String = " on the wall" Const takeonedown As String = "Take one down, pass it around" Const onebeer As String = "1 bottle of beer"
Dim bottles As Long
For bottles = 99 To 3 Step -1 Debug.Print CStr(bottles) & bottlesofbeer & onthewall Debug.Print CStr(bottles) & bottlesofbeer Debug.Print takeonedown Debug.Print CStr(bottles - 1) & bottlesofbeer & onthewall Debug.Print Next
Debug.Print "2" & bottlesofbeer & onthewall Debug.Print "2" & bottlesofbeer Debug.Print takeonedown Debug.Print onebeer & onthewall Debug.Print
Debug.Print onebeer & onthewall Debug.Print onebeer Debug.Print takeonedown Debug.Print "No more" & bottlesofbeer & onthewall Debug.Print
Debug.Print "No" & bottlesofbeer & onthewall Debug.Print "No" & bottlesofbeer Debug.Print "Go to the store, buy some more" Debug.Print "99" & bottlesofbeer & onthewall
End Sub</lang>
Visual Basic .NET
Platform: .NET <lang vbnet>Module Module1
Sub Main() Dim Bottles As Integer For Bottles = 99 To 0 Step -1 If Bottles = 0 Then Console.WriteLine("No more bottles of beer on the wall, no more bottles of beer.") Console.WriteLine("Go to the store and buy some more, 99 bottles of beer on the wall.") Console.ReadLine() ElseIf Bottles = 1 Then Console.WriteLine(Bottles & " bottle of beer on the wall, " & Bottles & " bottle of beer.") Console.WriteLine("Take one down and pass it around, no more bottles of beer on the wall.") Console.ReadLine() Else Console.WriteLine(Bottles & " bottles of beer on the wall, " & Bottles & " bottles of beer.") Console.WriteLine("Take one down and pass it around, " & (Bottles - 1) & " bottles of beer on the wall.") Console.ReadLine() End If Next End Sub
End Module</lang>
Whenever
<lang whenever>1 defer (4 || N(1)<N(2) && N(2)<N(3)) print(N(1)+" bottles of beer on the wall, "+N(1)+" bottles of beer,"); 2 defer (4 || N(1)==N(2)) print("Take one down and pass it around,"); 3 defer (4 || N(2)==N(3)) print(N(1)+" bottles of beer on the wall."); 4 1#98,2#98,3#98;</lang>
Wrapl
<lang wrapl>MOD Bottles;
IMP IO.Terminal USE Out; IMP Std.String;
VAR i, s <- "s", ob <- "of beer", otw <- "on the wall",
more <- "Take one down and pass it around", verse <- [];
EVERY i <- 99:to(0,-1) DO (
(i = 1) & (s <- ""); (i = 0) & (s <- "s"; i <- "No more"; more <- "Go to the store and buy some more"); verse:put('. {i} bottle{s} {ob} {otw}.\n'); verse:put('\n{i} bottle{s} {ob} {otw}, {(i@String.T):lower} bottle{s} {ob}.\n{more}');
);
Out:write(verse[2,0]@(String.T, "") + verse[1]);
END Bottles.</lang>
X86 Assembly
Using Windows/MASM32. <lang asm>.386 .model flat, stdcall option casemap :none
include \masm32\include\kernel32.inc include \masm32\include\masm32.inc include \masm32\include\user32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\masm32.lib includelib \masm32\lib\user32.lib
.DATA
buffer db 1024 dup(?) str1 db "%d bottles of beer on the wall.",10,13,0 str2 db "%d bottles of beer",10,13,0 str3 db "Take one down, pass it around",10,13,0 str4 db "No more bottles of beer on the wall!",10,13,0 nline db 13,10,0
bottles dd 99
.CODE
start: INVOKE wsprintfA, offset buffer, offset str1, [bottles] INVOKE StdOut, offset buffer
INVOKE wsprintfA, offset buffer, offset str2, [bottles] INVOKE StdOut, offset buffer
INVOKE StdOut, offset str3
DEC [bottles]
INVOKE wsprintfA, offset buffer, offset str1, [bottles] INVOKE StdOut, offset buffer INVOKE StdOut, offset nline
CMP [bottles], 1 JNE start
INVOKE StdOut, offset str4 INVOKE ExitProcess, 0 end start</lang>
Yorick
Looped version
<lang yorick>bottles = 99; while(bottles) {
write, format=" %d bottles of beer on the wall\n", bottles; write, format=" %d bottles of beer\n", bottles; write, "Take one down, pass it around"; write, format=" %d bottles of beer on the wall\n\n", --bottles;
}</lang>
Vectorized version
<lang yorick>song = "%d bottles of beer on the wall\n"; song += "%d bottles of beer\n"; song += "Take one down, pass it around\n"; song += "%d bottles of beer on the wall\n"; beer = indgen(99:1:-1); write, format=song, beer, beer, beer-1;</lang>
- Programming Tasks
- Solutions by Programming Task
- ABAP
- ActionScript
- Ada
- Aime
- ALGOL 68
- AmigaE
- APL
- Argile
- AutoHotkey
- AutoIt
- AWK
- BASIC
- Batch File
- BBC BASIC
- Befunge
- Brainf***
- Brat
- C
- C++
- C sharp
- Clay
- Chef
- CLIPS
- Clojure
- COBOL
- CoffeeScript
- ColdFusion
- Common Lisp
- D
- Delphi
- Dylan
- E
- Ela
- Erlang
- Euphoria
- F Sharp
- Factor
- Falcon
- FALSE
- Ferite
- Forth
- Fortran
- Frink
- GAP
- Gnuplot
- Go
- Go!
- Groovy
- GUISS
- Haskell
- HaXe
- HicEst
- HQ9+
- Icon
- Unicon
- IDL
- Inform 7
- Intercal
- Io
- Ioke
- J
- Java
- Swing
- AWT
- JavaScript
- Joy
- K
- LaTeX
- Liberty BASIC
- Logo
- Logtalk
- Lua
- Lucid
- M4
- Make
- Jot
- Mathematica
- MATLAB
- MAXScript
- Mirah
- ML/I
- Modula-2
- Modula-3
- MPIF90
- MUMPS
- Nemerle
- NetRexx
- NewLISP
- Nial
- Nimrod
- Objective-C
- Oberon-2
- OCaml
- Octave
- OpenEdge/Progress
- Oz
- PARI/GP
- Pascal
- Perl
- Perl 6
- PHP
- PicoLisp
- Piet
- Pike
- PIR
- PlainTeX
- Pop11
- PowerShell
- Prolog
- PureBasic
- Python
- Quill
- R
- Racket
- REALbasic
- REBOL
- Retro
- REXX
- RPL/2
- Ruby
- Sather
- Scala
- Scheme
- Scratch
- Seed7
- Shiny
- Slate
- Smalltalk
- SNOBOL4
- SNUSP
- Standard ML
- Suneido
- Tcl
- Thyrd
- TI-89 BASIC
- TIScript
- TUSCRIPT
- UNIX Shell
- C Shell
- UnixPipes
- Ursala
- V
- VBScript
- Visual Basic
- Visual Basic .NET
- Whenever
- Wrapl
- X86 Assembly
- Yorick