99 Bottles Of Beer Challenge With Least Amount Of Characters ?

Started by
95 comments, last by rip-off 9 years, 2 months ago

Yup, that was a great suggestion, thank you.

Modifying the raw source as follows, I managed to bring it down to 181 characters:


for($r=99;$r;--$r){$s=$r==1?:"s";echo "$r bottle$s of beer on the wall, $r bottle$s of beer.
Take one and pass it around, ",$r-1," bottle$s of beer on the wall.

";}echo "
No more bottles of beer on the wall, no more bottles of beer. 
Go to the store and buy some more, 99 bottles of beer on the wall.";

Basically, this tries to give the dictionary compressor a few more opportunities to match. That's harder to get right (and less intuitive, longer text sometimes compresses to smaller output!) than it sounds. Not only is the compression result a bit hard to predict from the editor, but also better compression may be larger in the end due to escaping.

Advertisement

Well, you don't need to escape all those characters (you can probably store tabs as-is, and \" shouldn't need to be escaped since you're using the other kind of quote). Also remember gzdeflate can take a level parameter which determines how much it will try to compress (you may want to push it to the maximum, which is 9).

Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.

The level parameter won't change anything, the to-be-compressed string is far too short for that to have any effect (not that I didn't initially try a brute-force packer that chose the smallest of every possible level anyway, but that turned out a complete waste of time rolleyes.gif ).

As for not escaping all those characters, this was my first thought, too. Actually I thought that escaping \0 as well as single and double quotation marks should be enough. Then it occurred to me that backslash probably needed to be escaped, too. Turned out that still isn't enough, gzinflate will choke on tab and $ as well.

Further, there is indeed at least one character that I'm not escaping although I should to be "formally correct" (I didn't bother to find out which, as the result was longer than the best match anyway -- probably it's the backspace character or some other weird control code?).

I discovered this when trying to rename the loop variable to something that gives more matches than "$n". My first idea was "$e", seeing how e is the most frequent character in English. That was too naive and didn't work out (first, in this particular text, "o" is the most common character, and second it doesn't suffice to be frequent, you also need surrounding characters to match -- which made "r" being the most frequent end-of-word character the best candidate), But what's worst, it broke the decompressor.

Now "r" saved 2 bytes, which is nice, so I stuck with that. And incidentially, it works fine with the small subset of escaped characters, too.

Now "r" saved 2 bytes, which is nice, so I stuck with that. And incidentially, it works fine with the small subset of escaped characters, too.

Micro-optimizing data pre-compression.

Folks, that is a true coding horror.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

The brackets are need around the ternary operator since it's in a macro.


#include <iostream>
#define a(i) << " bottle" << (i-1?"s":"") << " of beer" << 
#define w " on the wall" <<

int main()
{   
    for(int i=100;i-->1;)
      std::cout << i a(i) w ", " << i a(i) ".\nTake one down and pass it around, " << i-1 a(i-1) w ".\n\n";
    std::cout << "No more" a() w ", no more" a() ".\nGo to the store and buy some more, 99" a() w ".";
}

After some tweaking 273 now

Sadly, it fails for 1 bottle of beer.

C# 230 characters

class B
{
static void Main()
{
for(int i=100;i-->1;)
System.Console.WriteLine("{0} {6}{1} {2} {5}, {0} {6}{1} {2}.\nTake 1 down, pass it around {3} {6}{4} {2} {5}.",i,i>1?"s":"","of beer",i==1?"no more":(i-1).ToString(),i==2?"":"s","on the wall","bottle");
}
}

C# 230 characters

class B
{
static void Main()
{
for(int i=100;i-->1;)
System.Console.WriteLine("{0} {6}{1} {2} {5}, {0} {6}{1} {2}.\nTake 1 down, pass it around {3} {6}{4} {2} {5}.",i,i>1?"s":"","of beer",i==1?"no more":(i-1).ToString(),i==2?"":"s","on the wall","bottle");
}
}

You missed the last verse, where you have to go to the store and buy some more.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

Who gets the award for "hardest to read code" ?

I cannot remember the books I've read any more than the meals I have eaten; even so, they have made me.

~ Ralph Waldo Emerson

I just discovered this: http://esolangs.org/wiki/Var%27aq

klingon programming language with 99 bears implemented:


~ bottles { 
  latlh 1 rap'a' "" tam 
    { woD "s" } ghobe'chugh 
  " bottle" tam tlheghrar tam woD 
  " of beer" tlheghrar 
} pong

~ print-verse { 
  latlh latlh bottles tlheghrar " on the wall" tlheghrar cha'
  latlh latlh bottles tlheghrar cha'
  "Take one down and pass it around" cha'
  wa'boqHa' latlh latlh  { "No" } ghobe'chugh latlh bottles tlheghrar " on the wall" tlheghrar cha' 
  "" cha' 
  latlh { print-verse } HIja'chugh
} pong

99 print-verse
Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.


klingon programming language with 99 bears implemented:

Fixed for you:

~ bottles { 
  latlh 1 rap'a' "" tam 
    { woD "s" } ghobe'chugh 
  " bottle" tam tlheghrar tam woD 
  " of bear" tlheghrar 
} pong
 
~ print-verse { 
  latlh latlh bottles tlheghrar " on the wall" tlheghrar cha'
  latlh latlh bottles tlheghrar cha'
  "Take one down and pass it around" cha'
  wa'boqHa' latlh latlh  { "No" } ghobe'chugh latlh bottles tlheghrar " on the wall" tlheghrar cha' 
  "" cha' 
  latlh { print-verse } HIja'chugh
} pong
 
99 print-verse

This topic is closed to new replies.

Advertisement