Recreate '99 bottles of beers on the wall'.

The desired output is this:

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.

97 bottles of beer on the wall, 97 bottles of beer.
Take one down and pass it around, 96 bottles of beer on the wall.

96 bottles of beer on the wall, 96 bottles of beer.
Take one down and pass it around, 95 bottles of beer on the wall.

95 bottles of beer on the wall, 95 bottles of beer.
Take one down and pass it around, 94 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.
Go to the store and buy some more, 99 bottles of beer on the wall.

Show me how you would solve this with your favorite programming language. Most creative use of a language wins.

closed as too broad by Dennis Jan 30 '16 at 22:30

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

locked by Dennis Jan 30 '16 at 22:30

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site, so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. More info: help center.

  • 30
    "Most creative use" is too subjective for an SE site, I think. We should aim to use objective criteria, such as "shortest code". – Chris Jester-Young Jan 27 '11 at 21:04
  • 5
    Still a good question though – Chris Laplante Jan 27 '11 at 21:06
  • 3
    Is it supposed to run infinitely? I assumed so. Also codegolf doesn't own 99 bottles of beer so there is not reason to even discuss it. – Mike Bethany Jan 28 '11 at 8:04
  • 1
    @Chris -- That is going to be the toughest part of this SE site, because the whole thing is based on creativity, because that is half the fun of programming puzzles. The most creative solution isn't always the most efficient or shortest. – Nick Berardi Jan 28 '11 at 14:13
  • 2
    @Nick: I hear you. I just want to know how one can determine how creative a solution is---based on your own judgement? Based on the voters'? Neither is particularly reliable (no offence). Something like brevity is indisputable---for example, nobody can dispute the "goodness" of the 1-byte stack overflow code golf solution. – Chris Jester-Young Jan 28 '11 at 14:26

117 Answers 117

C++

#include<iostream>

using namespace std;

int f(int n)
{
    if(!(n-1))
    { 
        cout<<"Take one down and pass it around, 1 bottle of beer on the wall."<<endl<<endl;

        cout<<"1 bottle of beer on the wall, 1 bottle of beer."<<endl;
        cout<<"Go to the store and buy some more, 99 bottles of beer on the wall."<<endl<<endl; 
        return 0;
    }

    n!=99 && cout<<"Take one down and pass it around, "<<n <<" bottles of beer on the wall."<<endl<<endl;
    cout<<n<<" bottles of beer on the wall, "<< n<< " bottles of beer. "<<endl;

    return f(--n);
}   

int main()
{
    f(99);
    return 0;
}

QBasic - Runs in MS-DOS 6.22

DATA "abdefghiklmnoprstuwy ,."
DATA 6,2,4,1,1,2,3,4,4,3,4,3,4,2,6,2,2,5,3,4,4,1,1
DATA 2,13,17,17,10,4,13,5,2,4,4,15,21,16,13,12,17,7,4,19,1,10,10,-17,1,9,4,13,12,4,3,13,19,12,1,12,3,14,1,16,16,8,17,1,15,13,18,12,3,-6,13,17,13,16,17,13,15,4,2,18,20,16,13,11,4,11,13,15,4,22,23
DATA 7,6,6,13,15,1,1
DATA 4,1,5,4,2,4,3
DATA 4,1,4,2,4,3
DATA 4,6,4,7,4,8
DATA 9,4,10,4,11,4,12,4,13,4,14,4,15
DATA 16,4,17,4,7,4,18,4,12,4,19,4,20,4,21
DATA 22
DATA 23

READ l$
DIM z$(LEN(l$))
DIM x%(LEN(l$))
DIM u%(7)
m% = 1

FOR y% = 1 TO UBOUND(x%)
        READ x%(y%)
NEXT y%

FOR y% = 1 TO 6
        m% = m% * x%(y%)
NEXT y%

m% = m% + x%(y%)

FOR y% = 1 TO UBOUND(z$)
        FOR w% = 1 TO x%(y%)
                READ v%
                IF v% > 0 THEN
                        z$(y%) = z$(y%) + MID$(l$, v%, 1)
                ELSE
                        z$(y%) = z$(y%) + UCASE$(MID$(l$, -1 * v%, 1))

                END IF
        NEXT w%
NEXT y%

FOR y% = 1 TO UBOUND(u%)
        READ u%(y%)
NEXT y%

FOR y% = 1 TO UBOUND(u%)
        FOR w% = 1 TO u%(y%)
                READ v%
                s$(y%) = s$(y%) + z$(v%)
        NEXT w%
NEXT y%

FOR i% = m% TO 1 STEP -1

        IF i% > 2 THEN
                PRINT STR$(i%) + s$(1) + s$(3) + s$(6) + STR$(i%) + s$(3) + s$(7)
                PRINT s$(4) + s$(6) + STR$(i% - 1) + s$(1) + s$(3) + s$(7)
        ELSEIF i% = 2 THEN
                PRINT STR$(i%) + s$(1) + s$(3) + s$(6) + STR$(i%) + s$(1) + s$(7)
                PRINT s$(4) + s$(6); STR$(i% - 1) + s$(2) + s$(3) + s$(7)
        ELSE
                PRINT STR$(i%) + s$(2) + s$(3) + s$(6) + STR$(i%) + s$(2) + s$(7)
                PRINT s$(5) + s$(6) + STR$(m%) + s$(1) + s$(3) + s$(7)
        END IF

        PRINT ""
NEXT i%

LaTeX / PGF

Using (almost) only the new logic facilities of the PGF/TikZ project:

\documentclass[twocolumn]{article} % Use twocolumn option to ... um ... save paper
\usepackage{tikz}
\usepackage{fmtcount}

\begin{document}
\pgfkeyssetvalue{/singular/0}{s}
\pgfkeyssetvalue{/singular/1}{}

\pgfkeys{/text/1/.code={\numberstringnum{#1}}}
\pgfkeys{/text/0/.code={no more}}

\foreach \x in {99, 98 , ..., 1} {
  \pgfmathequalto{\x}{1}
  \noindent
  \Numberstringnum{\x} bottle\pgfkeys{/singular/\pgfmathresult} of beer of the wall,\\
  \numberstringnum{\x} bottle\pgfkeys{/singular/\pgfmathresult} of beer.\\
  Take one down pass it around,\\
  \pgfmathtruncatemacro{\y}{\x - 1}
  \pgfmathgreaterthan{\y}{0}
  \pgfkeys{/text/\pgfmathresult=\y}\pgfmathequalto{\y}{1}
    bottle\pgfkeys{/singular/\pgfmathresult} of beer on the wall.\\
  \\
}

\end{document}
  • that language seems pretty hard to write, to do "\" in my keyboard I must click ctrl + alt + <another key> – ajax333221 Mar 26 '12 at 23:41
  • I don't know about your keyboard, but no, doing logic in LaTeX is not simple. – Joel Berger Mar 27 '12 at 4:17

Not the shortest, but an attempt to use the most extraordinary Duff's Device.

#include <stdio.h>

void print_beer(int *n)
{
    printf("%d bottles of beer on the wall, %d bottles of beer.\n", *n, *n);
    --*n;
    printf("Take one down and pass it around, %d bottle%s of beer on the wall.\n\n", *n, *n > 1 ? "s" : "");
}

void beer(int n)
{
    switch (((n - 1)) % 7) {
        case  0:   do { print_beer(&n);
        case  6:        print_beer(&n);
        case  5:        print_beer(&n);
        case  4:        print_beer(&n);
        case  3:        print_beer(&n);
        case  2:        print_beer(&n);
        case  1:        print_beer(&n);
                   } while (n - 6 > 0);
    }
}

int main(void)
{
    int n = 99;

    beer(n);
    printf("1 bottle of beer on the wall, 1 bottle of beer.\n");
    printf("Go to the store and buy some more, %d bottles of beer on the wall.\n", n);

    return 0;
}

Q, 245

{-1(-3!x),b,$[x=1;e;d],a,", ",(-3!x),b,$[x=1;e;d]," of beer.\n",$[x=1;"Go to the store and buy some more, ";"Take one down and pass it around, "],(-3!$[x=1;99;x-1]),(b:" bottle"),$[x=2;e:"";d:"s"],(a:" of beer on the wall"),".";}each(99-til 99);

PHP - 176

My implementation has some null bytes or other random "?" characters, so I wrote a wrapper around it to show how to get the string, as well as the total characters output:

$string = gzdeflate('$a=" bottle";$b=" of beer";$c=" on the wall";for($i=99;$i>1;)echo"$i{$a}s$b$c, $i{$a}s$b.\nTake one down and pass it around, ".--$i.$a."s$b$c.\n\n";echo"$i$a$b$c, $i$a$b.\nGo to the store and buy some more, 99{$a}s$b$c.";');
$total  = strlen($string);
$total += strlen("eval(gzinflate(''))");

echo 'Total characters: '.$total."\n\n\n";
eval(gzinflate($string));

JAVA (353)

public static void main(String[] args) {
    String s[] = new String[]{"s", "", "Take one down and pass it around, %d bottle%s of beer on the wall.\n", "Go to the store and buy some more, 99 bottles of beer on the wall\n"};
    for (int i=1; i<100;) System.out.println(String.format("%d bottle%s of beer on the wall, %d bottle%s of beer.\n%s", 100-i, s[i/99], 100-i, s[i++/99], String.format(s[i/100+2], 100-i, s[i/99])));
}

Java (543 Characters)

Here is my attempt at this challenge.

public class BottlesOfBear {

    public static void main(String[] args) {

        final int BOTTLEAMOUNT = 99;
        int bottleCount = 99;

        for (int i = 0; i < BOTTLEAMOUNT; i++) {
            System.out.println(bottleCount + (bottleCount == 1 ? " bottle " : " bottles ") + "of beer on the wall, " + bottleCount + (bottleCount == 1 ? " bottle " : " bottles ") + "of beer.");
            bottleCount--;
            System.out.println("Take one down and pass it around, " + bottleCount + (bottleCount == 1 ? " bottle " : " bottles ") + "of beer on the wall.");
        }

    }

}

PHP (225 chars)

<?=preg_replace('/\w/e','$0=="b"?"$n bottle".($n>1?"s":"")." of beer":($0=="w"?"on the wall":(--$n?"Take one down and pass it around":(($n=99)?"Go to the store and buy some more":"")))',str_repeat('b w, b.
t, b w.

',$n=99));

C++

Uses recursion.

#include <iostream>
using namespace std;
void f(int n)
{
    if(n==0)
    {
        cout<<"Go to the store and buy some more, 99 bottles of beer on the wall.";
    }
    else
    {
        if(n==94)cout<<"....\n\n";
        else if(n>94||n<4)
            cout<<n<<" bottles of beer on the wall, "<<n<<" bottles of beer.\nTake one down and pass it around, "<<n-1<<" bottles of beer on the wall.\n\n";
        f(n-1);
    }
}
int main()
{
f(99);
return 0;
}

Python 2.x - (306 293 288 bytes)

So, this is was an older script of mine. It is a one-liner and heavily golfed. Demo

print(lambda x:x(x,99,lambda c,w=1,p=0:"%s %s of beer%s"%(c or"nN"[p]+"o more","bottle"+"s"*(c!=1)," on the wall"*w)))(lambda x,c,y:c+1and"%s, %s.\n%s"%(y(c,1,1),y(c,0),"Take one down and pass it around, %s.\n\n"%y(c-1)*(c>0))+x(x,c-1,y)or"Go to the store and buy some more, %s.\n"%y(99))

293 bytes version

print(lambda x:x(x,99,lambda c,w=1,p=0:"%s %s of beer%s"%(c or("n","N")[p]+"o more","bottle"+"s"*(c!=1)," on the wall"*w)))(lambda x,c,y:c+1and"%s, %s.\n%s"%(y(c,1,1),y(c,0),"Take one down and pass it around, %s.\n\n"%y(c-1)*(c>0))+x(x,c-1,y)or"Go to the store and buy some more, %s.\n"%y(99))

306 bytes version

print(lambda x:x(x,99,lambda c,w=1,p=0:"%s %s of beer%s"%(c or("n","N")[p]+"o more","bottle"+("s","")[c==1],(""," on the wall")[w])))(lambda x,c,y:c+1and"%s, %s.\n%s"%(y(c,1,1),y(c,0),c and"Take one down and pass it around, %s.\n\n"%y(c-1)or"")+x(x,c-1,y)or"Go to the store and buy some more, %s.\n"%y(99))

Fixing it for Python 3 would add two characters (untested):

print((lambda x:x(x,99,lambda c,w=1,p=0:"%s %s of beer%s"%(c or"nN"[p]+"o more","bottle"+"s"*(c!=1)," on the wall"*w)))(lambda x,c,y:c+1and"%s, %s.\n%s"%(y(c,1,1),y(c,0),"Take one down and pass it around, %s.\n\n"%y(c-1)*(c>0))+x(x,c-1,y)or"Go to the store and buy some more, %s.\n"%y(99)))

I would like to note that it isn't exactly elegant. To change the starting amount, you would need to change both occurences of 99 (one at the beginning and one at the end).

Edit: I think I should explain how it works. I circumvent the fact that I can't recurse a function if it's not named by creating an anonymous function, which takes an anonymous function as a parameter and calls it, passing it as an argument. Then it's just string formatting and neat little if-clauses built by using tuples and selecting the value with a boolean. Furthermore, I used c or "no more" to select c if it's greater than 0 and otherwise "no more".

Edit 2: Seems like I missed some pretty big things like multiplying strings with booleans instead of ("","text")[bool] and the fact that strings are iterable (("n","N")[p] -> "nN"[p])

C++

Why output to the console when you can output error messages?

main.cpp:

#include "99.h"
int main(){return 0;}

99.h:

#error 99 bottles of beer on the wall...
#include "98.h"

98.h:

#error 98 bottles of beer on the wall...
#include "97.h"

This is continued all the way through 1.h:

#error 1 bottle of beer on the wall...

When the programmer tries to compile it, the compiler outputs the error message

99 bottles of beer on the wall...

The programmer then removes the #error statement and recompiles the program, getting the error message

98 bottles of beer on the wall...

Eventually this outputs the entire song.

Vitsy, 273 227 Bytes

Most Recent Update

&".reeb fo selttob "?b9*D1-\[1m4m2maO"dnuora ti ssap dna nwod eno ekaT"6m4m2maO1-]DN3m{?5m4m3mDO{?aO" ,erom emos yub dna erots eht ot oG"6mXb9*1m"."OaO
DN?l1-\[DO{]{?5m
?l\[DO{]?
?7\[DO{]{8\[DO{]
" ,"OODN
"llaw eht no "6m
l1-\O

This basically does the same thing as the old method, the difference being that commonly used functions are moved to separate lines. Then, those lines are called and executed with m, where the number preceding tells the instruction pointer which line to go to. Once that line finishes, it'll go back to where m was last called.

Old Method

This is a bit complex. Method is in the code block.

&".reeb fo selttob "?9b*D1-\[DN?l1-\[DO{]{?" ,llaw eht no "l1-\ODN?l\[DO{]?aO" ,dnuora ti ssap dna nwod eno ekaT"l1-\ODN?l\[DO{]?1-aO]DN?7\[DO{]{8\[DO{]{?" ,llaw eht no "l1-\ODN?7\[DO{]{9\[DO{]?aO"99 ,erom emos yub dna erots eht ot oG"l1-\O?l1-\[DO{]{?".llaw eht no "l1-\O
&               Instantiate a new stack.
 ".reeb fo selttob "    Push " bottles of beer." to the current stack.
                    ?     Rotate to the next stack.
                     9b*    Push 99 to the stack.
                        D1-\[...]     Do everything in the top set of brackets 98 times.
                             DN       Duplicate the top item of the stack and output it as a number.
                               ?       Rotate a stack - this contains " bottles of beer."
                                l1-\[DO{]      Print it out (except for the period), but don't remove any items.
                                         {       Rotate the current stack - this skips the period.
                                          ?       Rotate back to the original stack.
                                           " ,llaw eht no "l1-\O   Push " on the wall, " to the stack, then print it out.
                                                                DN   Print out the top item of the stack as a number.
                                                                  ?    Rotate to the next stack.
                                                                   l\[DO{]     Print it all out, but don't remove any items.
                                                                          ? Rotate to the next stack (top stack again).
                                                                           aO    Print a newline.
                                                                             " ,dnuora ti ssap dna nwod eno ekaT"l1-\ODN  Push "Take one down and pass it around, " to the stack and print it out.
                                                                                                                        ?  Rotate to the next stack.
                                                                                                                         l\[DO{]  Print out everything in the stack, but don't remove anything.
                                                                                                                                ?  Rotate to the next stack.
                                                                                                                                 1-  Subtract one from the top item of the stack.
                                                                                                                                   aO  Print a newline.
                                                                                                                                     ]  End the main loop.
                                                                                                                                      DN  Duplicate the top item of the stack and print it out.
                                                                                                                                        ?7\[DO{]{8\[DO{]{?  Print out the next stack over (the one holding " bottles of beer.", but skip the period and the "s".
                                                                                                                                                          " ,llaw eht no "l1-\O  Push " on the wall, " to the stack and print it out.
                                                                                                                                                                               DN Duplicate the top item of the stack and print it out as a number.
                                                                                                                                                                                 ?7\[DO{]{9\[DO{]? Print out everything in the next stack except the period.
                                                                                                                                                                                                  aO Print a newline.
                                                                                                                                                                                                    "99 ,erom emos yub dna erots eht ot oG"l1-\O  Push "Go to the store and buy some more, 99" to the stack and print it out.
                                                                                                                                                                                                                                                ?l1-\[DO{]{? Move over a stack, print everything out but the ".".
                                                                                                                                                                                                                                                            ".llaw eht no "l1-\O  Push " on the wall." to the stack, then print it out.
  • This isn't code-golf; you don't need to list byre count. – lirtosiast Nov 5 '15 at 18:02
  • @ThomasKwa I wrote it for the purpose of code-golfing, though - even though the competition was aimed at pop-con, I wrote the post aimed mostly at code-golfing. Mostly to see how short I could make it. :D – Addison Crump Nov 5 '15 at 18:05

node/javascript - 180

b=' bottles of beer';w=' on the wall';i=99;while(i)console.log(i+b+w+', '+i+b+'\n'+(!--i?'Go to the store and buy some more, 99':'Take one down and pass it around, '+i)+b+w+'.\n');
  • Could you add an explanation/an ungolfed version, please? – Addison Crump Nov 5 '15 at 19:54
  • 2
    Golfing tip: never use while(cond). It's the same length as for(;cond;), and you can nearly always take advantage of moving something into the initialisation and something into the update parts of the for to save at least one character each for a semicolon. – Peter Taylor Nov 5 '15 at 21:31

MS Excel (14,683bytes)

MS Excel 2003, saved in .xlsx format (14,683 bytes) (is this really "programming") https://www.dropbox.com/s/40v2byau92ifka9/99bottles4.xlsx

  • "is this really "programming"" - no, unless you used VBA to fill out the data :) – Nate Koppenhaver Aug 4 '11 at 16:53

Erlang - 326

-module(d).
-export([b/1]).
b(1)->io:format("1 bottle of beer on the wall, 1 bottle of beer.~nGo to the store and buy some more, 99 bottles of beer on the wall."),b(99);b(B)->C=B-1,io:format("~p bottles of beer on the wall, ~p bottles of beer.~nTake one down and pass it around, ~p bottles of beer on the wall.",[B,B,C]),b(C).

PHP - first time there :)

<?php

$b = "bottles of beer";
$bw = "$b on the wall";
$t = "Take one down and pass it around,";
$cnt = 99;

     while(true)
     {
        echo "$cnt $bw, $cnt $b.\n";
        $cnt--;
        if ($cnt==0) break;
        echo "$t $cnt $bw.\n\n";
     }

     echo "Go to the store and buy some more, 99 $bw.\n\n";

?>
  • 1
    1 bottles of beer on the wall? – boothby Jul 18 '11 at 20:32

Here. First time post. JAVA

public static void main(String [] args){
for(int i = 99; i>=2; i--){

    System.out.println(i + " bottles of beer on the wall, "+i+" bottles of beer. "
            + "\n Take one down and pass it around, "+(i-1)+" bottles of beer on the wall.\n");

}
 System.out.println("1 bottle of beer on the wall, 1 bottle of beer."
                   + " \n Go to the store and buy some more, 99 bottles of beer on the wall.");
}

PHP (172)

for($i=99;$i>0;$i--){$s=($i>0)?'s':'';echo "$i bottle$s of beer on the wall, $i bottle$s of beer.\nTake one down and pass it around, $i bottle$s of beer on the wall.\n\n";}

C# (271 Characters)

class P{static void Main(){string b=" bottle",w=" on the wall",o=" of beer",p=".\n",z;for(int i=99;i>0;)System.Console.Write((z=i+b+(i>1?"s":"")+o)+w+", "+z+p+(i-->1?"Take one down and pass it around, "+i:"Go to the store and buy some more, 99")+b+(i>1?"s":"")+o+w+p);}}

Delphi (349)

program B;{$APPTYPE CONSOLE}const c=' of beer on the wall';d:array[Boolean]of string=(' bottles', ' bottle');var i:Byte;begin for i:=99downto 1do begin WriteLn(i,d[i=1],c,', ',i,d[i=1],' of beer.');if i>1then WriteLn('Take one down and pass it around, ',i-1,d[i<3],c,'.'#13#10)else Write('Go to the store and buy some more, 99',d[1=2],c,'.')end;end.

Python 3 (not really golfed, just a bit creative)

b=lambda n:'%d bottl%s of beer'%(n,n>1and'es'or'e')
any(map(print,(((2*'%s, %s on the wall, %s.\n')[4:42]+'.\n')%(2*(b(i),)+(i>1and('Take one down and pass it around',b(i-1))or('Go to the store and buy some more',b(99))))for i in range(99,0,-1))))

PHP 132 chars =]

    $e='bottles of beer';$x='on the wall';$i=100;while($i>0)echo"$i $e $x, $i $e.
Take one down and pass it around,  ".--$i." $e $x.

";
  • Go to the store and buy some more, 99 bottles of beer on the wall.? – Gareth Oct 22 '11 at 10:16
  • I didn't read that until it was too late =[ – Korvin Szanto Oct 24 '11 at 13:20

C# - 324

using System;class b{ static void Main(){for(int i=99;i>1;i--){Console.WriteLine("{0} bottles of beer on the wall, {0} bottles of beer,\n"+"take one down, pass it around...\n", i);}Console.WriteLine("1 bottle of beer on the wall, 1 bottle of beer,\n"+"go to the store and buy some more, 99 bottles of beer on the wall!");}}

C# - 304 significant characters.

Left this way to make it a little bit more readable, but it is 304 when all non-essential whitespace is removed.

string[] s = { "{0} {2}{3} {5}{6}, {0} {2}{3} {5}.\n", 
               "Take one down, pass it around, {1} {2}{4} {5}{6}.\n", 
               "Go to the store and buy some more, 99 {2}{4} {5}{6}." };
Func<int, string> t = e => e !=1 ? "s" : "" ;
for (int i = 99; i > 0; i--)
    Console.WriteLine(
         s[0] + s[i > 1 ? 1 : 2], 
         i, i - 1, 
         "bottle", t(i), t(i-1), "of beer", " on the wall");

PYTHON

for x in xrange(99,0,-1):
    print('.\n\n'.join(('%(b)s on the wall',)*(2-x/99))+', %(b)s.\n%(c)s')%{'b':'%s bottle%s of beer'%(x,x-1 and's'or ''),'c':('Take one down, pass it around,','Go to the store and buy some more, 99 bottles of beer on the wall.')[(100-x)/99]},

My PHP implementation:

<?php
$i = 99;
$s = '{i} bottles of beer on the wall';
$r = 'Take one down and pass it around';
$f = 'Go to the store and buy some more';

while($i > 0) 
{    
    $sub = array('{i}' => &$i);

    if($i == 1)
        $sub['bottles'] = 'bottle';

    $sen = strtr($s, $sub);
    echo $sen, ', ', substr($sen, 0, strpos($sen, 'on')), PHP_EOL;

    if($i == 1)
        break;

    $i--;
    $sen = strtr($s, $sub);
    echo $r, ', ', $sen, PHP_EOL, PHP_EOL;
}    

$i = 99;
$sub = array('{i}' => $i); 
$sen = strtr($s, $sub);
echo $f, ', ', $sen, PHP_EOL;
?>   

Ruby 1.9.2p0 -- 208 C

b="%d bottle%s of beer";99.downto(1){|n|s=b%[n,n>1?'s':''];a=n-1;puts s+" on the wall, "+s+(n>1?"\nTake one down and pass it around,#{b%[a,a>1?'s':'']}":"\nGo to the store and buy some more, #{b%[99,'s']}.")}

Ocaml - Hope this counts as creative

open Printf

let display () =
   let language = ref 99 in
   let ocaml = "bottles of beer on the the wall, " in
   let joy = " bottles of beer." in
   let usage = "Take one down and " in
   let is = "pass it around, " in
   let recommended = " bottles of beer on the wall." in
   let what = "bottle of beer on the wall, " in
   let like = "bottle of beer." in
   let applauded = " bottle of beer on the wall." in
   while (!language > 1) do
      let say = (string_of_int !language) in
      let strongly = (string_of_int (!language - 1)) in
      printf "%s %s %s %s\n" say ocaml say joy;
      if (!language > 2) then
         printf "%s %s %s %s\n" usage is strongly recommended
      else 
         printf "%s %s %s %s\n" usage is strongly applauded;
      language:= !language - 1;
   done;
   let say = (string_of_int !language) in
   let the_end = "Go to the store and buy some more, 99 bottles of beer on the wall." in
   printf "%s %s %s %s\n" say what say like;
   printf "%s\n" the_end

Javascript (234)

o=' bottle',b=' of beer',s=o+'s'+b,w=' on the wall',t='.\nTake one down and pass it around, ',g='.\nGo to the store and buy some more, ',c=', ',i=99,n=i+s;while(i>1)print(n+w+c+n+t+(n=--i+o+[i>1?'s':'']+b));print(n+w+c+n+g+99+s+w+'.')

There is probably a way to reduce even further by avoiding the double print.

Not the answer you're looking for? Browse other questions tagged or ask your own question.