Jump to content

  • Log In with Google      Sign In   
  • Create Account

99 Bottles Of Beer Challenge With Least Amount Of Characters ?

  • You cannot reply to this topic
97 replies to this topic

#61 adam4813   Members   -  Reputation: 668

Like
0Likes
Like

Posted 19 July 2013 - 04:53 PM

After some more tweaking I brought it down to 274 could be 272 if you aren't required to have to line breaks after each round.

#include <iostream>
#define a(i) << " bottle" << (i!=1?"s":"") << " of beer" << (i>-1?" on the wall":".\n") <<


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

Edited by adam4813, 19 July 2013 - 04:57 PM.


Sponsor:

#62 adam4813   Members   -  Reputation: 668

Like
0Likes
Like

Posted 19 July 2013 - 05:38 PM

Last one, had an issue with 1 bottle

#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(0) w ", no more" a(0) ".\nGo to the store and buy some more, 99" a(9) w ".";
}

Characters w/o spaces: 277

Characters: 366



#63 Sik_the_hedgehog   Crossbones+   -  Reputation: 1833

Like
1Likes
Like

Posted 19 July 2013 - 08:50 PM


I wonder if one could make an end run around this by implicitly defining printf()? That's sort of legal C, right?

C doesn't require function declarations, yeah (though I think they were planning to change that in the latest revision).

 

Though now you got me wondering if there are any variants to printf (there's puts, but that one only allows printing strings as-is).


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.

#64 Paradigm Shifter   Crossbones+   -  Reputation: 5435

Like
1Likes
Like

Posted 20 July 2013 - 10:17 AM

#define a(i) << " bottle" << (i!=1?"s":"") << " of beer" <<

 

#define a(i) << " bottle" << (i-1?"s":"") << " of beer" <<

 

saves 1 character ;)

 

EDIT - do you actually need the brackets around the ternary operator? << has really low operator precedence?

 

EDIT:

I'm pretty sure you could change the for loop to for(int i = 99; --i; ) adjust the a(i) macro to test i instead, and use i+1 and i instead of i and i-1 in the loop too?

 

Not got a compiler to hand though...

 

EDIT2: You could also get rid of the std::cout outside the loop by doing << --i ? "" : /*output from outside the loop*/; at the end of the loop output line as well, also doing the loop decrementing on that line too, saves a few characters.


Edited by Paradigm Shifter, 20 July 2013 - 12:44 PM.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#65 adam4813   Members   -  Reputation: 668

Like
1Likes
Like

Posted 20 July 2013 - 09:57 PM

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


Edited by adam4813, 20 July 2013 - 10:13 PM.


#66 Sik_the_hedgehog   Crossbones+   -  Reputation: 1833

Like
1Likes
Like

Posted 21 July 2013 - 06:09 AM


EDIT - do you actually need the brackets around the ternary operator? << has really low operator precedence?

The ternary operator is right above assignment (= and variants) in terms of precedence. It's really low, much lower than << (makes sense, since it's supposed to have less precedence than conditions).


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.

#67 Cornstalks   Crossbones+   -  Reputation: 6991

Like
1Likes
Like

Posted 21 July 2013 - 03:02 PM

The #include <iostream> is eating up a ton of characters.

 

I wonder if one could make an end run around this by implicitly defining printf()? That's sort of legal C, right? smile.png

In C89, it is legal. In C99 (and later), it is illegal.

 

But if you use C89, you must put return 0;. If you use C99 (and later), you can omit return 0;. Also, if you use C99 (and later), then that for loop is fine; if you use C89, then i would have to be declared before it.


[ 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 ]

#68 swiftcoder   Senior Moderators   -  Reputation: 10364

Like
0Likes
Like

Posted 21 July 2013 - 04:30 PM

In C89, it is legal. In C99 (and later), it is illegal.
 
But if you use C89, you must put return 0;. If you use C99 (and later), you can omit return 0;. Also, if you use C99 (and later), then that for loop is fine; if you use C89, then i would have to be declared before it.

This is C/C++ we are talking about, though... the least standards-compliant languages of all time.

How about we go for the shortest version that will compile with GCC?

Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#69 Sik_the_hedgehog   Crossbones+   -  Reputation: 1833

Like
0Likes
Like

Posted 21 July 2013 - 09:54 PM


In C89, it is legal. In C99 (and later), it is illegal.

In C99 it's still legal, it has tripped me many times before (well, not so bad as the compiler screams warnings like crazy so I catch it before I even get to try the code, but it's still easy to forget to declare a function).

 

The main catch (and I think this is true in C89 too) is that the function prototype becomes whatever types you used in the first function call. This means that if you use the same function twice with different parameter types (implicit casting can completely screw you up here) you will end up with a compiling error (if I recall correctly) as the compiler now won't be able to tell which prototype is correct.


Edited by Sik_the_hedgehog, 21 July 2013 - 09:55 PM.

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.

#70 Cornstalks   Crossbones+   -  Reputation: 6991

Like
2Likes
Like

Posted 21 July 2013 - 09:59 PM

How about we go for the shortest version that will compile with GCC?

Did it in 1 character (including whitespace):
A
Compile with: gcc -DA='int printf(const char*, ...);int main(){int i;for (i = 99; i > 0; --i){printf("%d bottle%s of beer on the wall, %d bottle%s of beer.\nTake one down and pass it around, ",i, i > 1 ? "s" : "",i, i > 1 ? "s" : "");if (i > 1)printf("%d bottle%s of beer on the wall.\n\n",i - 1, i > 2 ? "s" : "");else printf("no more bottles of beer on the wall.\n\n");}printf("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.");return 0;}' a.c -o beer
Run with: ./beer

(assuming a.c is the source file). Compiles with GCC (even with -Wall -Wextra -pedantic (and -std=c99 or -std=c89)). Booyah.
 
And yes, I'm being cheeky.
[ 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 ]

#71 Cornstalks   Crossbones+   -  Reputation: 6991

Like
0Likes
Like

Posted 21 July 2013 - 10:12 PM

In C89, it is legal. In C99 (and later), it is illegal.

In C99 it's still legal, it has tripped me many times before (well, not so bad as the compiler screams warnings like crazy so I catch it before I even get to try the code, but it's still easy to forget to declare a function).

Nope, it's not legal in C99. I actually was curious about this when I was doing my attempt so I asked about it on StackOverflow and I got a couple great responses that pointed out the following:
 
Rationale for International Standard — Programming Languages — C, section 6.5.2.2 (page 62, starting on line 23):
"A new feature of C99: The rule for implicit declaration of functions has been removed in C99. The effect is to guarantee the production of a diagnostic that will catch an additional category of programming errors. After issuing the diagnostic, an implementation may choose to assume an implicit declaration and continue translation in order to support existing programs that exploited this feature."

 
The section that allowed implicit function declaration in C89 was section 3.3.2.2 (paragraph 4). This section was moved to the 6.5.2.2 section in C99, and removed the paragraph that defined implicit function declaration (paragraph 4 in C89).
[ 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 ]

#72 Sik_the_hedgehog   Crossbones+   -  Reputation: 1833

Like
0Likes
Like

Posted 21 July 2013 - 10:53 PM

 

How about we go for the shortest version that will compile with GCC?

Did it in 1 character (including whitespace):
A
Compile with: gcc -DA='int printf(const char*, ...);int main(){int i;for (i = 99; i > 0; --i){printf("%d bottle%s of beer on the wall, %d bottle%s of beer.\nTake one down and pass it around, ",i, i > 1 ? "s" : "",i, i > 1 ? "s" : "");if (i > 1)printf("%d bottle%s of beer on the wall.\n\n",i - 1, i > 2 ? "s" : "");else printf("no more bottles of beer on the wall.\n\n");}printf("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.");return 0;}' a.c -o beer
Run with: ./beer

(assuming a.c is the source file). Compiles with GCC (even with -Wall -Wextra -pedantic (and -std=c99 or -std=c89)). Booyah.
 
And yes, I'm being cheeky.

 

You're never going to beat smr.c =P


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.

#73 Aether_plus   Members   -  Reputation: 103

Like
0Likes
Like

Posted 23 July 2013 - 03:38 PM

I totally cheated but here's a go with C gets it done in 187 characters

 

You have to pass in the correct strings to get it to work

#include<stdio.h>
int main(int c, char** a){
    for(c=99;c>0;--c)
        printf("%d %s %s, %d %s. %s, %d %s %s\n",c,(c==1)?a[4]:a[1],a[2],c,(c==1)?a[4]:a[1],a[3],c-1,((c-1)==1)?a[4]:a[1],a[2]);
    printf("%s",a[5]);
}

"bottles of beer" "on the wall" "Take one down pass it around" "bottle of beer" "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."


Edited by Aether_plus, 23 July 2013 - 03:46 PM.


#74 Paradigm Shifter   Crossbones+   -  Reputation: 5435

Like
0Likes
Like

Posted 23 July 2013 - 05:56 PM

If cheating is allowed you could just pass the entire text in on the command line and do a puts().


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#75 samoth   Crossbones+   -  Reputation: 5033

Like
0Likes
Like

Posted 24 July 2013 - 10:20 AM

274 characters PHP (no "cheating" in a sense of printing the contents of an URL or such)  smile.png

<?eval(gzuncompress(base64_decode('eJx9zsEKgkAQBuD7PMWPLFiwSh3N1GO3Tr3AmiNFuhO7KxHRu6fS0brMYfjmn78Vt1K2yLJc2XIzjiRZ04uUL6Z1sV1XcbyLfZwTny+CSFnUEkLHykNa1MwOYhEujIfpOo0FkNLJ3HhkDGMb3I33uAYYJ4NtNCI9ft3q6G9wShTl9K5KOgp6cfzVP1rYZZSCDoIgs/RhElOjenjCS8/zjUaW/QtP99UH7qth3w==')));?>

The executed code (can probably still be tweaked to take less space) is as follows:

for($n=99;$n>0;$n--)
{
$s=($n==1)?'':'s';
echo "$n bottle$s of beer on the wall, $n bottle$s of beer.
Take one and pass it around, ",$n-1," bottle$s 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, 99 bottles of beer on the wall.<?


#76 Sik_the_hedgehog   Crossbones+   -  Reputation: 1833

Like
0Likes
Like

Posted 24 July 2013 - 11:44 AM

I think you're better off skipping the base64 part and escaping the few bytes you can't put as-is (PHP strings are purely byte-based after all, so no codepage shenanigans).

 

EDIT: also may want to take a look at gzinflate, that may or may not help (at least the function name is shorter!).


Edited by Sik_the_hedgehog, 24 July 2013 - 11:47 AM.

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.

#77 swiftcoder   Senior Moderators   -  Reputation: 10364

Like
0Likes
Like

Posted 24 July 2013 - 01:43 PM

274 characters PHP (no "cheating" in a sense of printing the contents of an URL or such)  smile.png

<?eval(gzuncompress(base64_decode('eJx9zsEKgkAQBuD7PMWPLFiwSh3N1GO3Tr3AmiNFuhO7KxHRu6fS0brMYfjmn78Vt1K2yLJc2XIzjiRZ04uUL6Z1sV1XcbyLfZwTny+CSFnUEkLHykNa1MwOYhEujIfpOo0FkNLJ3HhkDGMb3I33uAYYJ4NtNCI9ft3q6G9wShTl9K5KOgp6cfzVP1rYZZSCDoIgs/RhElOjenjCS8/zjUaW/QtP99UH7qth3w==')));?>

I just tried to apply this to dmatter's 207-character Python solution, and the damn thing grew 150 characters sad.png
import zlib, uu
exec(zlib.decompress('eJwljrFuwzAMRHd/xS0GZcgp5GwxoAxZunXqlmqQYRYRKkuJpcDo35dxOT2CxL27wCL6ZZo9kqVE\nI6hHWzDlWiML5G9MzCtyQr0xNh8joYVSoR2M6ZOmjCWvTN01WGtcDyr0wmF0XcMST29fiZogdDo1\n2y1ERsDZwowNZB5yuCj6kIDj6KBl6a7jYTg6zbIpes+oeZeXKiL4NGN6/qLkhf/V4vz0PywdGXPe\n0v5y96UgVPg1P9P8qoczjNudAQeLYcf7GlJVDy1Wzd0fdlNKWA==\n'.decode('base64')))

Edited by swiftcoder, 24 July 2013 - 01:45 PM.

Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#78 samoth   Crossbones+   -  Reputation: 5033

Like
0Likes
Like

Posted 24 July 2013 - 01:48 PM

So far, I got the PHP version down to 259 characters, with gzinflate being the best available compressor of the 4 different ones I tried (the others are 4 or 8 bytes larger, respectively, because of checksums and headers added). Will try if I can replace base64 with something more compact.

 

207 characters are a challenge, though...



#79 samoth   Crossbones+   -  Reputation: 5033

Like
1Likes
Like

Posted 24 July 2013 - 02:34 PM

186 characters! biggrin.png

 

Run php pack.php to generate beer.php from beer-src.php.

 

beer-src.php

for($n=99;$n>0;$n--){$s=$n==1?:'s';echo"$n bottle$s of beer on the wall, $n bottle$s of beer.
Take one and pass it around, ",$n-1," bottle$s 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, 99 bottles of beer on the wall.<?

pack.php

<?
function encode($in)
{
	$out = '';
	foreach(str_split($in) as $c)
	{
			switch($c)
			{
				case '\0'  : $c = '\0'; break;
				case '"'  : $c = '\"'; break;
				case '\''  : $c = '\''; break;
				case '\n'  : $c = '\n'; break;
				case '\$'  : $c = '\$'; break;
				case '\t'  : $c = '\t'; break;
				case '\\'  : $c = '\\'; break;
			}
		$out .= $c;
	}

	return $out;
}

$src    = file_get_contents("beer-src.php");
$src_gz = encode(gzdeflate($src));

$output=<<<xxx
<?eval(gzinflate("$src_gz"));?>
xxx;

echo strlen($output)." characters\n\n";
echo $output;

$f = fopen("beer.php", "w");
fwrite($f, $output);
fclose($f);

beer.php (186 bytes)

<?eval(gzinflate("}α‚0à½Oñ‡4A“ÒȈŒnN¾@‘#¡gÚcŒï.Gd¹áòÝËn#m‘e¹´ånI²}K_Œ»\"­ö±sº\9’5‡Ð‘ôà5‘[„+áiºNahq6wÁØã=nÆñ`…HßR­k!¢üS•âÄèÙÑÿ)a—‘†82ÏÒ‡IL…êáÏ=Í7
Y¶®Õ"));?>


#80 Sik_the_hedgehog   Crossbones+   -  Reputation: 1833

Like
0Likes
Like

Posted 24 July 2013 - 09:45 PM

Why are you passing Perl to gzinflate? *runs*

 

Serious though, this is why I suggested trying to encode the strings directly instead of using base64, because base64 is a massive overhead: three bytes get encoded as four characters, and code like this doesn't compress that well, so that most likely ends up countering the compression. Besides, if we're aiming for the smallest code then anything that can shrink the size should be attempted, right? =P


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.





PARTNERS