FizzBuzz 再燃
今更だけど FizzBuzz に制限をつけると面白かった。
元ネタ
【問題】
1から100までの数を表示するプログラムを書け。
ただし3の倍数のときは数の代わりに「Fizz」と表示。
5の倍数のときは「Buzz」と表示。
3と5両方の倍数の場合には「FizzBuzz」と表示すること。解答言語は PHP とする。
また、以下のテンプレートを使用すること。for($i=1;$i<=100;$i++){
echo ### FreeCode ###;
}### FreeCode ### 部分を三項演算子を用い、()を用いずにコーディングして解を示せ。
- -
つまり PHP で三項演算子を使って、()で優先順位付せずに解いてネ、ってこと。
http://d.hatena.ne.jp/levin_gsp/20080904/1220533204
表示部分を()を使わずにワンライナーで書くというのがキモ。
私は PHP を避けているので JavaScript で。ついでに三項演算子も無くしました。
(function(){ var s = []; for(var i=1;i<=100;i++){ s[i-1]=['',i][i%3*i%5*-1>>>31]+['Fizz',''][i%3*-1>>>31]+['Buzz',''][i%5*-1>>>31]; } alert(s); })()
紛らわしいのは「i%3*i%5」と「x*-1>>>31」の2点。
「i%3*i%5」は、「3 か 5 のどちらかで割り切れたら 0」という意味で、正確には「(i % 3) * (i % 5)」としたいところ。この式だと「%」も「*」も演算の優先順位は同じなので左から「*1。
正の整数( 3): 00000000 00000000 00000000 00000011 3 >>> 1: 00000000 00000000 00000000 00000001 3 >>> 31: 00000000 00000000 00000000 00000000 (0) 負の整数(-3): 11111111 11111111 11111111 11111101 -3 >>> 1: 01111111 11111111 11111111 11111110 -3 >>> 31: 00000000 00000000 00000000 00000001 (1)
x は「割り切れたら 0、そうでなければ正の整数」が入っています。この演算によって正の整数が「1」に変換され、つまりは「割り切れたら 0、そうでなければ 1」という意味になります。
*1:i % 3) * i) % 5)」と評価されちゃいます。 でもこれでも問題無し。例えば i が 5 で割り切れるとしたとき、「i = 5 * x」と表現できて、その時の i を 3 で割った余りを d とすると「d * 5 * x」=「5 * (x * d)」となり、結局 5 で割り切れます。 「x*-1>>>31」はビット演算。 JavaScript ではビット演算を行う場合に左辺を32ビットの整数にします。左辺が正の整数の場合は32ビット目が「0」、負の場合は「1」になっていますから、31ビット0埋め右シフトをすると、正の整数なら 0、負の整数なら 1 と評価されます((この Java プログラムで確認できます。http://gist.github.com/16208