Apart from its popularity as a drinking song, the classic
99 Bottles of Beer
is ideal for singing to while away the hours on long trips because it takes
a long time to sing and its repetitive format is easily memorized.
It also pops up often in popular culture, especially film and TV.
I remember the late Patrick Swayze, for example, singing it over and over
again to Whoopi Goldberg in the movie Ghost in order to get her to go
downtown (which she would never normally do).

The article capitalizes on the tendency of popular songs to evolve
from long and content-rich ballads to highly repetitive texts with
little or no meaningful content.
Knuth writes that "our ancient ancestors invented the concept of refrain"
to reduce the space complexity of songs, which becomes crucial when a
large number of songs is to be committed to one's memory ...
more ingenious approaches yield songs of complexity O(logN),
a class known as "m bottles of beer on the wall".

While the affection for this song among computer programmers may have begun in 1977,
with the publication of Knuth's seminal paper,
it didn't become wildly popular until 1994, when some nitwit posted the entire
lyrics of the song to a humour mailing list, provoking a BASIC version to be
written:

10 REM BASIC Version of 99 Bottles of beer
20 FOR X=100 TO 1 STEP -1
30 PRINT X;"Bottle(s) of beer on the wall,";X;"bottle(s) of beer"
40 PRINT "Take one down and pass it around,"
50 PRINT X-1;"bottle(s) of beer on the wall"
60 NEXT

Over the years, many different Perl solutions have been proposed.
On December 25 1998, for instance, Damian Conway composed
a version using his Lingua::EN::Inflect module:

use Lingua::EN::Inflect 'inflect';
$n=shift||99;
print inflect<<BURP while $n;
NO(bottle of beer,$n) on the wall, NO(bottle of beer,$n)!
Take one down, pass it around,
NO(bottle of beer,@{[--$n]}) on the wall.
BURP

Finally, we come to the reason for this node.
Despite being the most popular code golf game of all time,
precious few quality bottle golf solutions have ever been published.
While there are
vasthordes
of reallyawfulbottlegolfsolutions
out there, the only half way decent one I'm aware of was whipped up
in a few hours by Ton Hospel and Mtv Europe
way back in 2003:

Many top quality golf solutions have been concocted though.
For example, the 99 Bottles of Beer challenge at
codegolf.com
attracted over 1000 entries,
more than twice as many as the next most popular game.
And the leading scoreboard entries there are very short.
It's just that none of them are available for public viewing.

Being a repeatcodegolf vandal,
I'm not shy about publishing my codegolf entries here,
especially given the codegolf site seems to have been abandoned,
and their beer bottle challenge has been running for over five years now.
There is one caveat though: after discussions with the founders of
this new PHP golf site,
I won't be discussing my PHP solutions in this node,
so as not to spoil their most popular game.
Apart from that, I won't hold back, analysing general approaches
to writing the shortest possible code to emit the lyrics of the
classic drinking song and revealing all interesting Perl,
Ruby and Python solutions I found while playing this game.

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

Your program's stdout must match the above output exactly,
with one exception: the codegolf.com entry checking program
strips trailing whitespace, so emitting any amount of trailing
whitespace is permitted.
Note that anything written to stderr is ignored, as is the program's exit code.
So terminating your program by crashing it (dividing by zero, for example)
is legitimate ... and surprisingly common and strangely satisfying.

did not turn up anything useful.
Perhaps because of its popularity and low barrier of entry,
if you randomly google for "99 bottles of beer golf", you'll be
overwhelmed by some mind-bogglingly awful golf.
Given the high number of hits, it's possible I overlooked some gems,
but the only useful prior art I found for this game was from a
Korean (kldp) web site where two different 174 stroke solutions
had been posted:

sub b{[@b=(abs||99,bottle."s"x!!++$_,of,beer),on,the,wall]}print"@{+b}+, @b.
",$_?"Take one down and pass it around":"Go to the store and buy some +more",", @{+b}.
"for-99..-1

If you squint, you'll see that these two are based on the venerable 2003 solution of Hospel and Europe.

Given that the leader at this time, Polish golfing veteran "0xF", had already
posted a 165-stroker, I was not hopeful that this approach could seriously
threaten this experienced Polish golfing maestro.
Still, I had to try at least.

First, I noticed that Ton and Mtv's snippet
can be further shortened by changing "s" to 's' and
embedding the sub inside the first @{} block like so:

Notice that this solution exploits undeclared Perl variables
(i.e. $n above) being initialized to undef. I employed this tactical
trick time and time again in this game in both Perl and PHP ... though not
in Python, where it can't be done. You can pull it off in Ruby too,
though you must scour RubyDoc for any "Perl-compatible" Ruby special
variables (e.g. $., $_, $&, $', $`, ...) that might be gainfully employed.

Around this time, I also composed Python (195) and Ruby (191) equivalents
of my early Perl subroutine-based solution.

Note that in the Python solution:

n=99
z=lambda:`n or 99`+" bottle"+"s of beer on the wall"[n==1:]
while n:y=z();n-=1;print"%s, %s.\n"*2%(y,y[:-12],n and"Take one down a+nd pass it around"or"Go to the store and buy some more",z())

This syntactic quirk, where an assignment expression, sans parentheses, can be placed
at the end of an expression, is used ad nauseam in both Ruby and PHP golf ...
though not in Perl or Python, where it produces a syntax error.

I felt quite hungover around this time because these solutions were
over ten strokes behind in Python and nearly twenty behind in Ruby!
It was becoming increasingly obvious that using a function was
consuming far too many strokes and therefore had to be eliminated.
Less obvious in Perl perhaps, given I was only three behind,
but my golfing instincts were telling me that a Perl solution
without a sub should be considerably shorter than my
168-stroke subroutine-based solution.

Though I reached this conclusion some years ago, I didn't have the time
to pursue it back then, and so put this game on hold for a little while.
Actually, I forgot about it for several years until "reminded"
of it by approaches from the founders of a
new PHP golf site,
where they were hosting the identical game.

When I returned to this game earlier this year, I noticed that "Rhebus",
a young whipper snapper from London, had posted a sensational 162 strokes,
thus snatching the Perl lead from the grasp of grizzled Polish
expert 0xF.

Bottle Golf Tip No 1: Don't use a function

To eliminate the function, you need somehow to set up the loop so that
the count of beer bottles is the same for each loop iteration.
That is, instead of the "natural":

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

where each paragraph must emit both n bottles and n-1 bottles,
you might try breaking up the song as shown below:

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, 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.

That's better!
Note that, crucial for a function-free solution, the two lines
between the lines of dashes above now contain the same beer bottle count.
There is a catch though: you must deal somehow with the
annoyance of the first iteration, which does not
contain a Take one down... line.
The last line is also a pest, but can be dealt with simply
by printing it after the main loop has terminated.
As a variation, you can place the pestiferous last line first:

Go to the store and buy some more, 99 bottles of beer on the wall.
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, 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.

which nicely clarifies the essentially circular nature of the ditty.
The "uniformity" of this output is attractive for a golfer
because uniformity often means shorter code.
To exploit this uniformity, however, you cannot just
print the song on the fly; you must instead build a string or list
in a loop, then print two separate bits of it at the end.

Let's see how this might look in Perl:

join("Take one down and pass it around",map{@c=(@b=(99-$_,bottle.'s'x!+/98/,of,beer),on,the,wall);", @c.
@c, @b.
"}0..98)=~/
/;print$'."Go to the store and buy some more$`"

What about Python?
Alas, Python places many obstacles in the way of this approach:

Python does not have a short 0..98 range operator. The best you can do is range(99), which generates the sequence 0..98.

Unlike Perl and Ruby, regexes are not built into the Python language, usually making them too long for golf.

While map in Perl and Ruby takes a block/closure, Python map takes a function or lambda (both too long for golf) while list comprehensions/generator expressions take an expression, which nicely encourages side-effect-free functional purity, while being an utter nuisance for golfers.

Finally, and worst of all, notice that assignment is an operator in Perl and Ruby and may therefore be used as part of larger expressions. Not so in Python, where assignment is a statement and cannot be used as part of a larger expression. This cruel design decision has inflicted incalculable pain on Python golfers over a period of many years.

In any case, I couldn't make this approach short in Python.
For example, though this one does work:

r="Take one down and pass it around".join(", %s.\n\n"%c+c+", %s.\n"%c[+:-12]for c in[`99-z`+" bottle"+"s of beer on the wall"[z/98:]for z in+ range(99)])
print r[35:]+"Go to the store and buy some more"+r[:34]

Though admittedly two strokes better than my original function-based entry,
this solution is a gaping eleven strokes behind the lead, 182 strokes,
held by Norwegian teetotaler "hallvabo" -- who I contend has nowadays taken over
the mantle of No. 1 Python golfer from Mark Byers.

In desperation, I tried a completely different line-at-a-time
function-free approach in Python:

c=198
while c:y=`c/2or 99`+" bottle"+"s of beer on the wall"[3/c%3:];print[y+,"Take one down and pass it around","Go to the store and buy some mor+e"][1/c+c%2]+",",[y[:-12]+".",y+".\n"][c%2];c-=1

Note that the three stroke 198 above is routinely replaced by
the two stroke ?ascii-char-with-ord-198 when golfing in Ruby.

Bottle Golf Tip No 2: Consider counting from 1 up to 99 not 99 down to 1

Though counting down from 99 to 1 seems "natural", golfers should always
experiment with switching things around, to see if doing so shortens the code.

General golfing tip: Look for the part of your solution that
makes you pull a face and try to shorten it.

With the possible exception of Python, all the above attempts at solving
the crucial "1 bottle" versus "2-99 bottles" plural inflection
problem have caused me to pull a face.
Here is the parade of horrors seen so far:

where $x is the empty string for n==1 and "s" for n>1.
Can this be achieved?
Well, in languages where uninitialized variables display an empty string,
it's easily pulled off simply by counting upwards from 1 to 99 ... so long
as you can find a short way to set $x to "s" right after the first
iteration.
Of course, you'd need to build the output string in a loop
and emit it at the end, yet the regex solutions described above
already do that, courtesy of the $' and $` special
variables.

Instead of $x, how about applying Mtv's law yet again
and (indirectly) exploit a regex variable?
As is common in golf, once I'd thought of the basic idea,
a short solution materialized pretty quickly:

@c=(@b=(++$n,bottle.$&,of,beer),on,the,wall),s/^/Take one down and pas+s it around, @c.
@c, @b.
/,/s/for($_)x99;/,.*
/;print$'."Go to the store and buy some more$&"

Here we're building the string from the end to the beginning, from 1 to 99,
in $_ by using the regex substitution s/^/.../.
We're also exploiting a starting value of zero for the uninitialized $n.
Finally, note that we're further exploiting an aliasing quirk of the perl
for loop by building a single $_ value via a ($_)x99 list.
I remembered this surprising trick from the 2002 Cantor game in TPR03
(see Mtv's pdf book of Golf),
where a winning Cantor solution was:

Note that the /, 99.*\n\n/ expression serves a dual purpose
in that, in addition to terminating the until loop,
this regex sets the $' and $& special variables
to the desired values.
Note further that if leading whitespace were allowed
(as it is at phpgolf.org), this regex
can be shortened by two strokes to /, 99.*/.

Further 162-stroke variations are:

/s/until@c=($b=++$n." bottle$& of beer",on,the,wall),s/^/Take one down+ and pass it around, @c.
@c, $b.
/,/, 99.*
/;print$'."Go to the store and buy some more$&"

I have an uneasy feeling that this solution is not the end of the road
and that a future Perl golfer may further shorten it.

Can we translate this approach into Ruby?
Yes. It's not as effective as the Perl version because Ruby
lacks Perl's built-in s/^/.../ substitution operator.
But it still shaves two strokes off our previous best Ruby solution:

1.upto(99){|n|~/s/;$_="Take one down and pass it around, #{c="#{b=n," +bottle#$& of beer"} on the wall"}.
#{c}, #{b}.
#$_"}
~/,.*
/;puts$'+"Go to the store and buy some more"+$&

The need for a space before until is unfortunate.
As is the need for the n=0 initialization, which is not required in Perl.

As already discussed, I saw no hope of translating this
approach into Python, where short "special variables" (e.g. $_, $&)
do not exist and where regexes are not built into the language.

Bottle Golf Tip No 3: Unearth language-specific tactical tricks

My previous golfing articles focused mostly
on the dark art of magic formulae.
As you may have noticed above, magic formulae hardly feature in this game.
You must rely instead on old fashioned classical golf technique,
especially language-specific tactical tricks.

Of course. The true&tested method of "Can't possibly work, let's try it anyway."

-- Eugene van der Pijll

One of the best ways to find tactical tricks in the dusty corners
of a programming language is to simply try ridiculous things and see
what happens. Modern languages are so large and complex that it's
not practical to precisely specify every little detail in the core
language and libraries ... which offers opportunities for golfers
to exploit implementation quirks.

Desperate to save a stroke or two, I experimented with how
the % printf-like operator behaves when given more
arguments than expected:

produces the same result as Ruby.
That is, Ruby and Perl silently ignore extra arguments to printf.
They also automatically "flatten" the array.
Python does not.
Python also checks the number of printf arguments more strictly;
that is, this Python program: