Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

In my opinion, its simplicity and directness reflects the basic nature of existence. Eventually, we all will have passed around 99 bottles of beer and there will be no more bottles on the wall.

-- Modern Drunkard Magazine (broken link - top 86 alcohol songs of all time, featuring 99 bottles of beer at #1)

🥴 🍻

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

-- The Complexity of Songs by Donald Knuth (1977)

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
to "save mailing list bandwidth". It snowballed from there until today we can now choose from more than 1400 programming language variations.

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 vast hordes of really awful bottle golf solutions 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:

sub b{[@b=(abs||No,bottle."s"x!!++$_,of,beer),on,the,wall]}print "@{+b},\n@b,\nTake one down, pass it around,\n@{+b}.\n" for-pop||-99..-1

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

Rules of the game

In this 99 Bottles of Beer challenge, your program takes no input and must emit the entire lyrics of the song to stdout as follows:

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.

Getting Started

🏌 🍺

The five times this game has been played here at Perl Monks:

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
and:
sub b{@b=(-$_++||99,bottl.($_?es:e),of,beer);"@b on the wall"}print+b, +", @b. ",$_?"Take one down and pass it around, ":"Go to the store and buy som +e 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:

@{sub b{[@b=(abs||No,bottle.'s'x!!++$_,of,beer),on,the,wall]}b}
This saves a single stroke because the first +b in the original is replaced by a bald b.

I then stared at the kldp solution, looking for anything unsightly. Well, that -99..-1 is an eyesore ... so I just hacked it out, reducing this solution from 174 to 168 strokes:

print"@{sub b{[@y=($n||=99,bottle.'s'x1!~$n,of,beer),on,the,wall]}b}, +@y. $_, @{b--$n}. "for("Take one down and pass it around")x98,"Go to the store and buy s +ome more"
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())
string slices are employed, which is almost mandatory when golfing in Python.

Though my first Ruby attempt:

def z "#{N<1?99:N} bottle#{'s'if N!=1} of beer"end (N=99).times{puts"%s, %s. "*2%[z+w=" on the wall",z,1>(N-=1)?"Go to the store and buy some more" +:"Take one down and pass it around",z+w],""}
is ungainly in the extreme, notice the curious expression:
z+w=" on the wall"
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$`"
Hmmm, 173 strokes. Not bad for a first attempt!

Regexes always win (Mtv's law of golf)

As you can see, the regex "side-effect variables", $' and $`, look very promising in this game -- as they so often are in golf.

It seems that Mtv's law applies to Ruby too, because this algorithm is actually better suited to Ruby than Perl due to some quirky Ruby syntactic sugar. You see, in Ruby:

somearray.join("string")
can be equivalently expressed as:
somearray*"string"
So, in Ruby, this new function-free approach effortlessly shaved eleven strokes from my earlier function-based solution:
"Go to the store and buy some more"+(-99..-1).map{|n|", #{c="#{b=-n," +bottle"+"s of beer"[1/-n,9]} on the wall"}. #{c}, #{b}. "}*"Take one down and pass it around"=~/ /;puts$'+$`
180 strokes! Though hardly the shortest, this is one of my favourite solutions because it directly expresses the (circular) idea of putting the last line first.

Update: Much later I reduced this by three strokes to 177:

"Go to the store and buy some more"+(-99..-1).map{|n|", #{b=-n," bottl +es"[0,6-n]+" of beer"," on the wall"}. #{b}, %s%s. "%b}*"Take one down and pass it around"=~/ /;puts$'+$`

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]
it's 207 strokes in length. Ouch. Of course, it's perfectly possible that I've overlooked some more golfish Python list comprehension syntax here. If so, please respond away.

After giving up on a functional approach, the shortest way I could find to implement this idea in Python was the following 193-stroker:

n=99 y="Go to the store and buy some more" while n:c=`n`+" bottle"+"s of beer on the wall"[1/n:];y+=", %s.\n\n"%c ++c+", %s.\nTake one down and pass it around"%c[:-12];n-=1 print y[68:-32]+y[:66]
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
To my enormous frustration, this solution, in addition to being unspeakably ugly, turned out to have exactly the same score, 193 strokes. No improvement. At all. Aaargh!

The 187-stroke Ruby translation below is presented as an example of an accepted solution that "cleanly terminates" by dividing by zero:

n=198 loop{$><<[y=[n/2%-99+99," bottle"+"s of beer"[3/n%3,9]," on the wall"] +,"Take one down and pass it around","Go to the store and buy some mor +e"][j=1/n+1&~n-=1]<<", #{y[0,2+j]}. "+$/*j}
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:

bottle."s"x!!++$_,of,beer # Perl bottl.($_?es:e),of,beer # Perl bottle.'s'x1!~$n,of,beer # Perl bottle.'s'x!/98/,of,beer # Perl "bottle#{'s'if N!=1} of beer" # Ruby " bottle"+"s of beer"[1/-n,9] # Ruby " bottles"[0,6-n]+" of beer" # Ruby "bottle"+"s of beer"[3/n%3,9] # Ruby "bottle"+"s of beer"[1/n:] # Python

As you might expect, I was eager to eliminate all this inflective claptrap, replacing it with something simple and short like:
"bottle$x of beer"
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$&"
165 strokes! Caught 0xF at last!

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:

s/./$& $&/gfor($_="- ")x pop;print

After a further period of shuffling things around, I finally tied for the lead at 162 strokes by replacing for with until like so:

/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$&"
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$&"
and:
/s/until@c=(++$n." bottle$& of beer",on,the,wall),s/^/Take one down an +d pass it around, @c. @c, $c[0]. /,/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"+$&
178 strokes. And here's an alternative 178-stroker using until:
n=0 ~/s/ until/, 99.* /=~$_="Take one down and pass it around, #{c="#{b=n+=1," 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:

b=[99," bottles of beer"," on the wall"] print "%s%s\n"%b
Running this little test program produces:
99 bottles of beer
in Ruby, but:
TypeError: not enough arguments for format string
in Python.

In case you're interested, running this little test program in Perl:

@b=(99," bottles of beer"," on the wall"); printf "%s%s\n",@b;
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:
b=[99," bottles of beer"," on the wall"] print "%s%s\n"%tuple(b)
fails with:
TypeError: not all arguments converted during string formatting
whereas this one:
b=[99," bottles of beer"," on the wall"] print "%s%s%s\n"%tuple(b)
works, printing:
99 bottles of beer on the wall

I was able to exploit Ruby's printf behaviour, described above, to shave two precious strokes and so move into outright second place, three strokes behind "Ruby golfing god", flagitious:

1.upto(99){|n|~/s/;$_="Take one down and pass it around, #{c=n," bottl +e#$& of beer"," on the wall"}. #{c}, %s%s. #$_"%c} ~/,.* /;puts$'+"Go to the store and buy some more"+$&
176 strokes! Cheers! Staggering into second place in Ruby was a pleasant surprise after languishing twenty strokes behind the leaders early in this game.

I hope you've enjoyed my long journey through this game. It's time for me to sober up now and give the game of golf a rest for a while.

Leaderboards, May 2011

All languages (1237 entries):

1st 162 rhebus Perl 2nd 162 eyepopslikeamosquito Perl 3rd 165 0xF Perl 4th 166 dgzj001 Perl 5th 167 shinh Perl 6th 170 komondorok Perl 7th 170 ySas Perl 8th 171 flagitious Perl 9th 171 o0lit3 Perl 10th 171 gorash Perl

Perl (273 entries):

1st 162 rhebus 2nd 162 eyepopslikeamosquito 3rd 165 0xF 4th 166 dgzj001 5th 167 shinh 6th 170 komondorok 7th 170 ySas 8th 171 flagitious 9th 171 o0lit3 10th 171 gorash 11th 173 jgoon 12th 173 volte 13th 174 g.allen 14th 174 terjek 15th 174 bearstearns 16th 174 raymundo 17th 174 ott 18th 174 ozy4dm 19th 174 sixmen 20th 174 Aidy 21st 174 szeryf 22nd 174 Shuman 23rd 174 stressedlemming 24th 175 Ciaran 25th 175 arpad 26th 175 ergasun 27th 175 Nisse 28th 176 jojo 29th 176 Zeithase 30th 177 moq 31st 177 olivier 32nd 178 leus 33rd 179 kounoike 34th 179 yojeb 35th 180 Bryan 36th 181 lima1 37th 181 agenticarus 38th 181 pace_t_zulu 39th 181 zkhr 40th 182 fluffle ... 60th 193 grizzley 65th 195 Jasper 89th 204 chargrill 98th 209 yanick

Ruby (338 entries):

1st 173 flagitious 2nd 176 eyepopslikeamosquito 3rd 177 eban 4th 177 bitsweat 5th 177 leonid 6th 180 tal 7th 180 emiltin 8th 181 yowa 9th 182 oxy4dm 10th 182 shinh 11th 182 noop 12th 182 J-_-L 13th 183 kik 14th 183 yvl 15th 184 tobyaw 16th 185 ksk 17th 186 jojo 18th 186 carldr 19th 186 pace_t_zulu 20th 187 adel

Python (423 entries):

1st 182 hallvabo 2nd 183 logan 3rd 183 uli 4th 189 Mark Byers 5th 190 hiro.suzuki 6th 192 primo 7th 193 eyepopslikeamosquito 8th 195 recursive 9th 195 tryeng 10th 195 etaronis 11th 196 kt3k 12th 197 gtalpo 13th 197 ProfessorO 14th 198 lifthrasiir 15th 198 Jay 16th 198 SergeantPepper 17th 199 hirose 18th 199 max 19th 200 Dilb 20th 200 yonilevy

PHP (264 entries):

1st 172 ToastyX 2nd 173 eyepopslikeamosquito 3rd 175 alab 4th 175 Morgil 5th 178 jln 6th 178 cms 7th 179 hamori 8th 180 hiro.suzuki 9th 183 eyepopper 10th 185 Leafy 11th 186 carldr 12th 191 shinh 13th 193 heavyware 14th 197 Shadlan 15th 198 davidpogson 16th 198 lxlh 17th 199 echofish 18th 200 phoe 19th 201 underdonges 20th 203 Theory

References

Added later:

Update: As described in detail in a three part series Compression in Golf: Part I, this 160-stroke Perl solution was later whittled to around 150 strokes, by using pack u compression.


In reply to Drunk on golf: 99 Bottles of Beer by eyepopslikeamosquito

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2024-03-28 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found