時代遅れひとりFizzBuzz祭り bc編

時代遅れひとり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と計算ツールを動かして、しかも計算ツールなのに数値演算以外の処理を行うだなんて、ともすれば無意味な階層化だよなあ。ハードウェア資源が乏しかった頃なら「電子計算機なんだから直接計算してしまえばいいのに」と諭されたのだろうな。

*1:出展はFreeBSD 9.0-RELEASEの日本語man。