🍻99本のビール rosettaさんいらっしゃい~#3
どうかしている。しかし、なぜかこの詩は一部では有名だ。愚直に数がデクリメントしていって、他の歌詞はかわらないため、プログラミングの入門に良いと古来からされてきたが、知ってる人に会ったことはない。
もちろん我らが味方rosetta codeにもたっぷりある。
https://rosettacode.org/wiki/99_bottles_of_beer
文字列の出力と減算ができれば参加できるため、300言語以上のエントリがある。珍しく先にアルゴリズムを紹介する。
どうももともとは、たいてい苦笑いとなり1ミリも笑えない「ジョークアーティクル」が発端となっているようだ。
ヒヒヒ(爆笑してるつもり)
Helloと初めてコンピューターが喋る(表示する)喜びと学習工数のトレードオフがつりあうのがHello,Wolrdだとすると、ループによってもたらされる大量の文字列と学習工数のトレードオフがつりあうというのか、しかし、Hello.Wolrdのことはみんな知っていても、99 Bottles of Beerのことはあまり知られていないし、これでループをマスターした人も知らない。Hello.Wolrdのことが嫌いでも99 Bottles of Beerの事は嫌いにならないでほしい。C#でのサンプルがのっていた
for (int bottleNumber = 100; 1 <= bottleNumber; bottleNumber--)
{
Console.WriteLine("{0} bottles of beer on the wall, {0} bottles of beer", bottleNumber);
Console.WriteLine($"Take one down and pass it around, {bottleNumber - 1} bottles of beer on the wall");
}
ループするだけだが、これって最後の一本になったときだけ単数形になるという条件式が入るというものではなかったか、気のせいか。
C#、Unityで5秒くらいしか使ったことないが、どうも展開式なのか、Cのフォーマットみたいな使い方があるみたいだ。前置きは以上として、わだば言語を見ていきたい。今回はカテゴリーからやる
夏休みの宿題派
ソースが一緒なので、名乗りだけあげて他の欄に集約されているもの。BASICに顕著でした。
グラフィック・ジョーク
比較的貧しい感じの笑いで、テキストアートめいたものでお茶を濁すもの。AAと一緒でたいてい笑えない。これは晒していこう。
超短い
ゴリゴリの本格派で、なぜこんなに短いのかもよくわからない。APL系で多いのが他のサンプル見ても分かってきた。しかし、可読性が低いから、保守を考えると、短いだけで理解に長い時間がかかる。
bob ← { (⍕⍵), ' bottle', (1=⍵)↓'s of beer'}
bobw ← {(bob ⍵) , ' on the wall'}
beer ← { (bobw ⍵) , ', ', (bob ⍵) , '; take one down and pass it around, ', bobw ⍵-1}
↑beer¨ ⌽(1-⎕IO)+⍳99
コードっていうか昔の電子掲示板みたいだ。猫がボトルを追っかけているように見える。
LISPも短くてきれい
(let ((i 99))
(while (> i 0)
(princ-list i " bottles of beer on the wall" "\n Take one down, pass it around")
(setq i (1- i))))
再帰ック
意味なく再帰する。意味なくといったらあれだが、こないだ勉強した。外部回転だか内部回転だかで、内部回転するやつということだろう。言語で傾向があるとは思えないので、掲載者の趣味でそうなると思われる。
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc == 99)
return 99;
if(argv[0] != NULL){
argv[0] = NULL;
argc = 0;
}
argc = main(argc + 1, argv);
printf("%d bottle%c of beer on the wall\n", argc, argc == 1?'\0': 's');
printf("%d bottle%c of beer\n", argc, argc == 1?'\0': 's');
printf("Take one down, pass it around\n");
printf("%d bottle%c of beer on the wall\n\n", argc - 1, (argc - 1) == 1?'\0': 's');
return argc - 1;
}
この発想は無かった、mainの再帰でC
ワンライナー部門
こちらも、必要性は感じないのと、最近つぶやきのほうで短い締まったコードを魅せられているので、特に心が動かなかった
[296,{3/)}%-1%["No more"]+[" bottles":b]294*[b-1<]2*+[b]+[" of beer on the wall\n".8<"\nTake one down, pass it around\n"+1$n+]99*]zip
timesっぽいの使えますぜ部門
ここぞとばかりtimes系
99.to 2 { n |
p "#{n} bottles of beer on the wall, #{n} bottles of beer!"
p "Take one down, pass it around, #{n - 1} bottle#{true? n > 2 's' ''} of beer on the wall."
}
p "One bottle of beer on the wall, one bottle of beer!"
p "Take one down, pass it around, no more bottles of beer on the wall."
こちらはbratというrubyに影響受けた言語
とにかくジェイ
へっぽこ研究所ではもはや一ジャンルとなっている畳一畳サイズ言語J、今回も短く鈍く光っている
bob =: ": , ' bottle' , (1 = ]) }. 's of beer'"_
bobw=: bob , ' on the wall'"_
beer=: bobw , ', ' , bob , '; take one down and pass it around, ' , bobw@<:
beer"0 >:i.-99
99 Bottles of Beer協会認定ソース
やはり記憶通り、1本になったときは単数にする、というルールのようだ。言っておくが競プログラミングにはでない。
/* 99 Bottles, in Jsish */
function plural(n:number):string { return (bottles == 1) ? "" : "s"; }
function no(n:number):string { return (bottles == 0) ? "No" : n.toString(); }
var bottles = 99;
do {
printf("%d bottle%s of beer on the wall\n", bottles, plural(bottles));
printf("%d bottle%s of beer\n", bottles, plural(bottles));
puts("Take one down, pass it around");
bottles--;
printf("%s bottle%s of beer on the wall\n\n", no(bottles), plural(bottles));
} while (bottles > 0);
こちらはECMA系列のJsish