「情熱プログラマー」にあった、 99 bottles of beer を代入なしでコーディングするの巻

C++ の string クラスを連結につかい、ループは再帰呼び出し実現。関数型言語での常道を C++ に持ち込んだ一品です。
string オブジェクトを作っては廃棄し、廃棄しては作ってと、富豪プログラミング的側面も兼ね備えています。今回のように代入禁止縛りがなければ string オブジェクトを連結に代用せず ostringstream を使いたいところです。

なお「代入なし」という条件は、すべての変数を const で縛り、値を実行中に変えないことで満たしています。

#include <stdio.h>
#include <string>

static const char lyrics[] =
"99 bottles of beer on the wall, 99 bottles of beer.\n"
"Take one down and pass it around, 98 bottles of beer on the wall.\n"
"98 bottles of beer on the wall, 98 bottles of beer.\n"
"Take one down and pass it around, 97 bottles of beer on the wall.\n"
"97 bottles of beer on the wall, 97 bottles of beer.\n"
"Take one down and pass it around, 96 bottles of beer on the wall.\n"
"96 bottles of beer on the wall, 96 bottles of beer.\n"
"Take one down and pass it around, 95 bottles of beer on the wall.\n"
"95 bottles of beer on the wall, 95 bottles of beer.\n"
"Take one down and pass it around, 94 bottles of beer on the wall.\n"
"94 bottles of beer on the wall, 94 bottles of beer.\n"
"Take one down and pass it around, 93 bottles of beer on the wall.\n"
"93 bottles of beer on the wall, 93 bottles of beer.\n"
"Take one down and pass it around, 92 bottles of beer on the wall.\n"
"92 bottles of beer on the wall, 92 bottles of beer.\n"
"Take one down and pass it around, 91 bottles of beer on the wall.\n"
"91 bottles of beer on the wall, 91 bottles of beer.\n"
"Take one down and pass it around, 90 bottles of beer on the wall.\n"
"90 bottles of beer on the wall, 90 bottles of beer.\n"
"Take one down and pass it around, 89 bottles of beer on the wall.\n"
"89 bottles of beer on the wall, 89 bottles of beer.\n"
"Take one down and pass it around, 88 bottles of beer on the wall.\n"
"88 bottles of beer on the wall, 88 bottles of beer.\n"
"Take one down and pass it around, 87 bottles of beer on the wall.\n"
"87 bottles of beer on the wall, 87 bottles of beer.\n"
"Take one down and pass it around, 86 bottles of beer on the wall.\n"
"86 bottles of beer on the wall, 86 bottles of beer.\n"
"Take one down and pass it around, 85 bottles of beer on the wall.\n"
"85 bottles of beer on the wall, 85 bottles of beer.\n"
"Take one down and pass it around, 84 bottles of beer on the wall.\n"
"84 bottles of beer on the wall, 84 bottles of beer.\n"
"Take one down and pass it around, 83 bottles of beer on the wall.\n"
"83 bottles of beer on the wall, 83 bottles of beer.\n"
"Take one down and pass it around, 82 bottles of beer on the wall.\n"
"82 bottles of beer on the wall, 82 bottles of beer.\n"
"Take one down and pass it around, 81 bottles of beer on the wall.\n"
"81 bottles of beer on the wall, 81 bottles of beer.\n"
"Take one down and pass it around, 80 bottles of beer on the wall.\n"
"80 bottles of beer on the wall, 80 bottles of beer.\n"
"Take one down and pass it around, 79 bottles of beer on the wall.\n"
"79 bottles of beer on the wall, 79 bottles of beer.\n"
"Take one down and pass it around, 78 bottles of beer on the wall.\n"
"78 bottles of beer on the wall, 78 bottles of beer.\n"
"Take one down and pass it around, 77 bottles of beer on the wall.\n"
"77 bottles of beer on the wall, 77 bottles of beer.\n"
"Take one down and pass it around, 76 bottles of beer on the wall.\n"
"76 bottles of beer on the wall, 76 bottles of beer.\n"
"Take one down and pass it around, 75 bottles of beer on the wall.\n"
"75 bottles of beer on the wall, 75 bottles of beer.\n"
"Take one down and pass it around, 74 bottles of beer on the wall.\n"
"74 bottles of beer on the wall, 74 bottles of beer.\n"
"Take one down and pass it around, 73 bottles of beer on the wall.\n"
"73 bottles of beer on the wall, 73 bottles of beer.\n"
"Take one down and pass it around, 72 bottles of beer on the wall.\n"
"72 bottles of beer on the wall, 72 bottles of beer.\n"
"Take one down and pass it around, 71 bottles of beer on the wall.\n"
"71 bottles of beer on the wall, 71 bottles of beer.\n"
"Take one down and pass it around, 70 bottles of beer on the wall.\n"
"70 bottles of beer on the wall, 70 bottles of beer.\n"
"Take one down and pass it around, 69 bottles of beer on the wall.\n"
"69 bottles of beer on the wall, 69 bottles of beer.\n"
"Take one down and pass it around, 68 bottles of beer on the wall.\n"
"68 bottles of beer on the wall, 68 bottles of beer.\n"
"Take one down and pass it around, 67 bottles of beer on the wall.\n"
"67 bottles of beer on the wall, 67 bottles of beer.\n"
"Take one down and pass it around, 66 bottles of beer on the wall.\n"
"66 bottles of beer on the wall, 66 bottles of beer.\n"
"Take one down and pass it around, 65 bottles of beer on the wall.\n"
"65 bottles of beer on the wall, 65 bottles of beer.\n"
"Take one down and pass it around, 64 bottles of beer on the wall.\n"
"64 bottles of beer on the wall, 64 bottles of beer.\n"
"Take one down and pass it around, 63 bottles of beer on the wall.\n"
"63 bottles of beer on the wall, 63 bottles of beer.\n"
"Take one down and pass it around, 62 bottles of beer on the wall.\n"
"62 bottles of beer on the wall, 62 bottles of beer.\n"
"Take one down and pass it around, 61 bottles of beer on the wall.\n"
"61 bottles of beer on the wall, 61 bottles of beer.\n"
"Take one down and pass it around, 60 bottles of beer on the wall.\n"
"60 bottles of beer on the wall, 60 bottles of beer.\n"
"Take one down and pass it around, 59 bottles of beer on the wall.\n"
"59 bottles of beer on the wall, 59 bottles of beer.\n"
"Take one down and pass it around, 58 bottles of beer on the wall.\n"
"58 bottles of beer on the wall, 58 bottles of beer.\n"
"Take one down and pass it around, 57 bottles of beer on the wall.\n"
"57 bottles of beer on the wall, 57 bottles of beer.\n"
"Take one down and pass it around, 56 bottles of beer on the wall.\n"
"56 bottles of beer on the wall, 56 bottles of beer.\n"
"Take one down and pass it around, 55 bottles of beer on the wall.\n"
"55 bottles of beer on the wall, 55 bottles of beer.\n"
"Take one down and pass it around, 54 bottles of beer on the wall.\n"
"54 bottles of beer on the wall, 54 bottles of beer.\n"
"Take one down and pass it around, 53 bottles of beer on the wall.\n"
"53 bottles of beer on the wall, 53 bottles of beer.\n"
"Take one down and pass it around, 52 bottles of beer on the wall.\n"
"52 bottles of beer on the wall, 52 bottles of beer.\n"
"Take one down and pass it around, 51 bottles of beer on the wall.\n"
"51 bottles of beer on the wall, 51 bottles of beer.\n"
"Take one down and pass it around, 50 bottles of beer on the wall.\n"
"50 bottles of beer on the wall, 50 bottles of beer.\n"
"Take one down and pass it around, 49 bottles of beer on the wall.\n"
"49 bottles of beer on the wall, 49 bottles of beer.\n"
"Take one down and pass it around, 48 bottles of beer on the wall.\n"
"48 bottles of beer on the wall, 48 bottles of beer.\n"
"Take one down and pass it around, 47 bottles of beer on the wall.\n"
"47 bottles of beer on the wall, 47 bottles of beer.\n"
"Take one down and pass it around, 46 bottles of beer on the wall.\n"
"46 bottles of beer on the wall, 46 bottles of beer.\n"
"Take one down and pass it around, 45 bottles of beer on the wall.\n"
"45 bottles of beer on the wall, 45 bottles of beer.\n"
"Take one down and pass it around, 44 bottles of beer on the wall.\n"
"44 bottles of beer on the wall, 44 bottles of beer.\n"
"Take one down and pass it around, 43 bottles of beer on the wall.\n"
"43 bottles of beer on the wall, 43 bottles of beer.\n"
"Take one down and pass it around, 42 bottles of beer on the wall.\n"
"42 bottles of beer on the wall, 42 bottles of beer.\n"
"Take one down and pass it around, 41 bottles of beer on the wall.\n"
"41 bottles of beer on the wall, 41 bottles of beer.\n"
"Take one down and pass it around, 40 bottles of beer on the wall.\n"
"40 bottles of beer on the wall, 40 bottles of beer.\n"
"Take one down and pass it around, 39 bottles of beer on the wall.\n"
"39 bottles of beer on the wall, 39 bottles of beer.\n"
"Take one down and pass it around, 38 bottles of beer on the wall.\n"
"38 bottles of beer on the wall, 38 bottles of beer.\n"
"Take one down and pass it around, 37 bottles of beer on the wall.\n"
"37 bottles of beer on the wall, 37 bottles of beer.\n"
"Take one down and pass it around, 36 bottles of beer on the wall.\n"
"36 bottles of beer on the wall, 36 bottles of beer.\n"
"Take one down and pass it around, 35 bottles of beer on the wall.\n"
"35 bottles of beer on the wall, 35 bottles of beer.\n"
"Take one down and pass it around, 34 bottles of beer on the wall.\n"
"34 bottles of beer on the wall, 34 bottles of beer.\n"
"Take one down and pass it around, 33 bottles of beer on the wall.\n"
"33 bottles of beer on the wall, 33 bottles of beer.\n"
"Take one down and pass it around, 32 bottles of beer on the wall.\n"
"32 bottles of beer on the wall, 32 bottles of beer.\n"
"Take one down and pass it around, 31 bottles of beer on the wall.\n"
"31 bottles of beer on the wall, 31 bottles of beer.\n"
"Take one down and pass it around, 30 bottles of beer on the wall.\n"
"30 bottles of beer on the wall, 30 bottles of beer.\n"
"Take one down and pass it around, 29 bottles of beer on the wall.\n"
"29 bottles of beer on the wall, 29 bottles of beer.\n"
"Take one down and pass it around, 28 bottles of beer on the wall.\n"
"28 bottles of beer on the wall, 28 bottles of beer.\n"
"Take one down and pass it around, 27 bottles of beer on the wall.\n"
"27 bottles of beer on the wall, 27 bottles of beer.\n"
"Take one down and pass it around, 26 bottles of beer on the wall.\n"
"26 bottles of beer on the wall, 26 bottles of beer.\n"
"Take one down and pass it around, 25 bottles of beer on the wall.\n"
"25 bottles of beer on the wall, 25 bottles of beer.\n"
"Take one down and pass it around, 24 bottles of beer on the wall.\n"
"24 bottles of beer on the wall, 24 bottles of beer.\n"
"Take one down and pass it around, 23 bottles of beer on the wall.\n"
"23 bottles of beer on the wall, 23 bottles of beer.\n"
"Take one down and pass it around, 22 bottles of beer on the wall.\n"
"22 bottles of beer on the wall, 22 bottles of beer.\n"
"Take one down and pass it around, 21 bottles of beer on the wall.\n"
"21 bottles of beer on the wall, 21 bottles of beer.\n"
"Take one down and pass it around, 20 bottles of beer on the wall.\n"
"20 bottles of beer on the wall, 20 bottles of beer.\n"
"Take one down and pass it around, 19 bottles of beer on the wall.\n"
"19 bottles of beer on the wall, 19 bottles of beer.\n"
"Take one down and pass it around, 18 bottles of beer on the wall.\n"
"18 bottles of beer on the wall, 18 bottles of beer.\n"
"Take one down and pass it around, 17 bottles of beer on the wall.\n"
"17 bottles of beer on the wall, 17 bottles of beer.\n"
"Take one down and pass it around, 16 bottles of beer on the wall.\n"
"16 bottles of beer on the wall, 16 bottles of beer.\n"
"Take one down and pass it around, 15 bottles of beer on the wall.\n"
"15 bottles of beer on the wall, 15 bottles of beer.\n"
"Take one down and pass it around, 14 bottles of beer on the wall.\n"
"14 bottles of beer on the wall, 14 bottles of beer.\n"
"Take one down and pass it around, 13 bottles of beer on the wall.\n"
"13 bottles of beer on the wall, 13 bottles of beer.\n"
"Take one down and pass it around, 12 bottles of beer on the wall.\n"
"12 bottles of beer on the wall, 12 bottles of beer.\n"
"Take one down and pass it around, 11 bottles of beer on the wall.\n"
"11 bottles of beer on the wall, 11 bottles of beer.\n"
"Take one down and pass it around, 10 bottles of beer on the wall.\n"
"10 bottles of beer on the wall, 10 bottles of beer.\n"
"Take one down and pass it around, 9 bottles of beer on the wall.\n"
"9 bottles of beer on the wall, 9 bottles of beer.\n"
"Take one down and pass it around, 8 bottles of beer on the wall.\n"
"8 bottles of beer on the wall, 8 bottles of beer.\n"
"Take one down and pass it around, 7 bottles of beer on the wall.\n"
"7 bottles of beer on the wall, 7 bottles of beer.\n"
"Take one down and pass it around, 6 bottles of beer on the wall.\n"
"6 bottles of beer on the wall, 6 bottles of beer.\n"
"Take one down and pass it around, 5 bottles of beer on the wall.\n"
"5 bottles of beer on the wall, 5 bottles of beer.\n"
"Take one down and pass it around, 4 bottles of beer on the wall.\n"
"4 bottles of beer on the wall, 4 bottles of beer.\n"
"Take one down and pass it around, 3 bottles of beer on the wall.\n"
"3 bottles of beer on the wall, 3 bottles of beer.\n"
"Take one down and pass it around, 2 bottles of beer on the wall.\n"
"2 bottles of beer on the wall, 2 bottles of beer.\n"
"Take one down and pass it around, 1 bottle of beer on the wall.\n"
"1 bottle of beer on the wall, 1 bottle of beer.\n"
"Take one down and pass it around, no more bottles of beer on the wall.\n"
"No more bottles of beer on the wall, no more bottles of beer.\n" 
"Go to the store and buy some more, 99 bottles of beer on the wall.\n";

/* main
	checks make_lyrics routine correctly generate 99 bottles of beer lyrics.
*/
static std::string make_lyrics(unsigned n);
int main(void)
{
	puts(0 == strcmp(lyrics, make_lyrics(99u).c_str()) ? "OK" : "NG");
	return 0;
}

static std::string N_bottles(unsigned n);
static std::string n_bottles(unsigned n);
static std::string make_lyrics(unsigned n)
{
	static const char otw[] = " on the wall", eol[] = ".\n";
	return N_bottles(n) + otw + ", " + n_bottles(n) + eol + (0 < n
		? "Take one down and pass it around, " + n_bottles(n-1) + otw + eol + make_lyrics(n-1)
		: "Go to the store and buy some more, " + n_bottles(99u) + otw + eol);
}

static std::string N_bottles(unsigned n)
{
	return 0 == n ? "No more bottles of beer" : n_bottles(n);
}

static std::string to_string(unsigned n);
static std::string n_bottles(unsigned n)
{
	switch(n)
	{
	case 0: return "no more bottles of beer";
	case 1: return "1 bottle of beer";
	default: return to_string(n) + " bottles of beer";
	}
}

static std::string to_string_aux(unsigned n);
static std::string to_string(unsigned n)
{
	return 0 == n ? "0" : to_string_aux(n);
}

static std::string to_string_aux(unsigned n)
{
	static const char tbl[] = "0123456789";
	return 0 == n ? "" : to_string_aux(n/10) + tbl[n%10];
}