入社試験でよく出題されると巷で話題?のFizzBuzz問題を
一行で記述するとどのようなコードになるのか。
調べてみました。
一行で書けたからといって入社試験に合格するとは限りません。(たぶん)
目次
1.FizzBuzzとは?
Fizz Buzz(フィズ・バズ、Bizz BuzzやBuzzとも呼ばれる)は英語圏で長距離ドライブ中や飲み会の時に行われる言葉遊びである。
Wikipedia参照:https://ja.wikipedia.org/wiki/Fizz_Buzz
英語圏で流行していたプログラミングとは全く関係のない言葉遊びだったようです。
なぜ、プログラミング問題として流行するようになったのか?
このゲームをコンピュータ画面に表示させるプログラムとして作成させることで、コードが書けないプログラマ志願者を見分ける手法をJeff AtwoodがFizzBuzz問題 (FizzBuzz Question) として提唱した。その提唱はインターネットの様々な場所で議論の対象になっている。
Wikipedia参照:https://ja.wikipedia.org/wiki/Fizz_Buzz
Jeff Atwood氏が提唱したことが事の始まりだそうです。
世界の敏腕プログラマー達がこぞって挑戦し、
さらに縛りルールを加えて自らのプログラミング力を腕試しする人が増えていったのですね。
1-1.ゲームルール
さて、本題のゲームルールです。
本家のルールは下記です。
プレイヤーは円状に座る。最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、3で割り切れる場合は「Fizz」(Bizz Buzzの場合は「Bizz」)、5で割り切れる場合は「Buzz」、両者で割り切れる場合(すなわち15で割り切れる場合)は「Fizz Buzz」(Bizz Buzzの場合は「Bizz Buzz」)を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。
Wikipedia参照:https://ja.wikipedia.org/wiki/Fizz_Buzz
プログラミングに例えると下記のようになります。
1から100までの数字(範囲は任意)を1ずつカウントアップし、
3の倍数で「Fizz」と出力
5の倍数で「Buzz」と出力
15の倍数で「Fizz Buzz」と出力
上記に該当しない場合は数字を出力
といったルールになります。
2.模範解答
1 2 3 4 5 6 7 8 9 |
for i in range(1, 101): if i % 15 == 0: print("FizzBuzz") elif i % 3 == 0: print("Fizz") elif i % 5 == 0: print("Buzz") else: print(i) |
Python組込関数のrange()で1-100までの整数を生成し、
for文でループしながら処理分けをしています。
何の変哲もない一般的な解答で、一番可読性が高いと思います。
ですが、本日は「PythonでFizzBuzz問題を一行で書いてみた。」というお題なので、
Pythonらしく、コード量に着目してみます。
3.一行で書いてみた
1 |
print('\n'.join(['Fizz'*(n%3==0) + 'Buzz'*(n%5==0) or str(n) for n in range(1,101)])) |
3-1.解説
可読性の「可」の字もないほど読みにくいですね。
部品毎に紐解いて解説していきます。
まずは、
‘\n’.join()
join()はPython組込関数です。リストなどの値結合がたったの一行で出来てしまう便利関数です。
この例では、リストの値間に改行を入れて結合させています。
その次ですが、まずは大きく見てみます。
[‘Fizz’*(n%3==0) + ‘Buzz’*(n%5==0) or str(n) for n in range(1,101)]
これはリストを内包表記で生成しています。
内包表記とはリストを生成する方法の一つで、コード量を大幅に削減できる表記法です。
Pythonといえば、内包表記といったイメージがあります。
さらに中身を噛み砕いて、見ていきます。
for n in range(1,101)
内包表記では、まずfor文から評価されます。
for文の内容については、通常と同様で、
この場合、nに1-100までの整数が順に代入されます。
‘Fizz’*(n%3==0) + ‘Buzz’*(n%5==0) or str(n)
for文の処理が始まり、nに1が代入された次に上記の処理が開始されます。
まずはじめに疑問に思うのは、‘Fizz’*(n%3==0) でしょう。
文字列とブール型を乗算しています。
僕も最初は意味がわかりませんでした。
これは、ブール型が True == 1, False == 0 としても評価されるという仕様を上手く利用しています。
そのため、nに1が代入された場合は、
‘Fizz’*0 となります。
そしてここでも文字列演算の仕様を上手く利用しています。
Pythonでは文字列に0を乗算すると、空文字列になるという仕様があります。
なので、‘Fizz’*(n%3==0) はn==1の時、結果的に空文字となるのです。
ここまで理解が出来れば、‘Buzz’*(n%5==0) も分かると思います。
最後も紐解いてみましょう。
or str(n)
str()は、これまたPython組込関数です。
数値などを文字列に変換することができる関数です。
気になるのは、 or ですね。
if文で利用する or演算子です。
if文を記述しなくとも or演算子のみで利用ができるという代物です。
まとめてみると、下記のようになります。
n==1の場合、
” + ” or ‘1’
空文字列 + 空文字列 or ‘1’となります。
この場合、or演算子で空文字列と’1’が評価され、’1’がTrueとなり、生き残ります。
これの繰り返しで1-100までの整数分繰り返し出力していくといった処理となっています。
4.まとめ
入社試験においては、どの記述方法が正解かは分かりません。
知識力を見られるのか、
リーダブル(可読性)なコーディング力を見られるのか、
企業や面接官によって変わると思います。
一つ確実に言えることは、
僕はこんな記述をする人とは一緒に開発をしたくない!!!ということです。
以上、tigerでした。