99 Bottles Of Beer Challenge With Least Amount Of Characters ?

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

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) ".";
}
Advertisement

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


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.

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

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

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


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.

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.

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

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. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


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.

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.

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

This topic is closed to new replies.

Advertisement