時代遅れひとりFizzBuzz祭り、前回のGDBに引き続き今回もライトなキワモノネタでいこうと思う――いやキワモノというほどでもないか。具体的にはbcとかbcとかbcだ。
bcは任意精度の数値演算を行える対話型の計算ツールで、POSIX 1に含まれるので大抵のUnix系OSにはデフォルトで入っているのではないかと思う。起源はUNIX V6みたいだ*1。多分インストールベースではメジャーなツールなはずなのに、個人的にどうにもマイナー感が拭えない。awkの方がよほどメジャーな印象があるのだけど、気のせいだろうか? この辺りは単に所属する文化圏の違いなだけで、実はbcがメジャーな文化圏の方が大きいのだけど私が知らないだけなのかなあ。
bcにはPOSIX版とGNU版がある。手元の処理系はGnuWin32のbc 1.06(Windows用バイナリ)なのだけど、ここは拡張機能を使わないPOSIX版でも動作するだろう移植性のある(と思われる)FizzBuzzを書いてみた。
/* #!/usr/bin/bc -q -s */ define p (n) { auto f f = 0 if (n % 3 == 0) { "Fizz" f = 1 } if (n % 5 == 0) { "Buzz" f = 1 } if (f == 1) { " " return } n } for (i = 1; i <= 100; i++) { t = p(i) } quit
思ったよりは苦心の作だ。POSIX版bcはC言語スタイルのコメントしか受け付けない。変数や関数名は [a-z] の1文字だ(2文字以上は「移植性の無い拡張機能」らしい)。elseやcontinueは拡張機能になってしまうので、これらを使わないとなるとforループ内にFizzBuzzの判定を直接記述することができない。そこで関数 p として定義した上で途中でreturnさせている。そして関数 p の戻り値を表示させないように変数 t に代入している。
GNU拡張有りならshebangが使えるし、コードも少し見やすくなる。
#!/usr/bin/bc -q define pfizzbuzz (n) { auto f f = 0 if (n % 3 == 0) { "Fizz" f = 1 } if (n % 5 == 0) { "Buzz" f = 1 } if (f == 1) { " " } else { n } } for (i = 1; i <= 100; i++) { tmp = pfizzbuzz(i) } quit
それにしても電子計算機の上でOSと計算ツールを動かして、しかも計算ツールなのに数値演算以外の処理を行うだなんて、ともすれば無意味な階層化だよなあ。ハードウェア資源が乏しかった頃なら「電子計算機なんだから直接計算してしまえばいいのに」と諭されたのだろうな。