tuneoの日記: なつやすみのじゆうけんきゅう:ふぃずばず 4
世にあまたあるFizzBuzzプログラムを見ていてイマイチぐっと来ない点が「なんで剰余を2回計算してんねん」というところだったりする。
- 整数nが3の倍数だったら文字列Fizzを表示する
- 整数nが5の倍数だったら文字列Buzzを表示する
- 整数nが3の倍数かつ5の倍数だったら文字列FizzBuzzを表示する
- 整数nがそれ以外の場合は何も表示しない
と言われて、
msg = ""
if (n % 3 == 0) and (n % 5 == 0):
msg = "FizzBuzz"
elif n % 3 == 0:
msg = "Fizz"
elif n % 5 == 0:
msg = "Buzz"
print(msg)
と書くのって、控えめに言ってもバカっぽくない?整数の剰余計算なら繰り返してもそれほど困らない(し、言語処理系によってはオプティマイザが鼻歌交じりに最適化してくれる)が、例えば「ファイルの中を全文検索して云々」とか言われたらやっとれんだろうに。計算結果は再利用してなんぼ。
mod3 = n % 3
mod5 = n % 5
msg = ""
if mod3 == 0 & mod5 == 0:
msg = "FizzBuzz"
elif mod3 == 0:
msg = "Fizz"
elif mod5 == 0:
msg = "Buzz"
print(msg)
少なくともこれぐらいはやりたいが、これも剰余と0の比較が2回あるのが好かない。
isMultipleOf3 = (n % 3) == 0
isMultipleOf5 = (n % 5) == 0
msg = ""
if isMultipleOf3 and isMultipleOf5:
msg = "FizzBuzz"
elif isMultipleOf3:
msg = "Fizz"
elif isMultipleOf5:
msg = "Buzz"
print(msg)
こんな感じか。Pythonに特化すると、タプルはイミュータブルなシーケンスなので辞書のキーになれることを利用して
fizzbuzz = { (False, False) : "", (True, False) : "Fizz", (False, True) : "Buzz", (True, True) : "FizzBuzz" }
print(fizzbuzz[(n % 3 == 0, n % 5 == 0)])
と書いてしまうこともできるな。
なお、3の倍数でFizz、5の倍数でBuzz、3と5の公倍数ならそれらを連結したもの、と考えれば、文字列連結で手抜きができる。
msg = ""
if n % 3 == 0:
msg += "Fizz"
if n % 5 == 0:
msg += "Buzz"
print(msg)
一行で
print("".join(("Fizz" if n % 3 == 0 else "", "Buzz" if n % 5 == 0 else "")))
なんてのも。ただし、例えば3の倍数でfoo,5の倍数でbar,3と5の公倍数でbazを表示しろ、なんて仕様だと破綻するけどw
ちなみにこのFizzBuzz、剰余演算子を使わないで倍数の判定をやる、という縛りを入れることもあるんだとか。5の倍数の判定は十進表記の1の位が「0」か「5」になるから簡単だけど、3の倍数はどういう性質があったかな。3の倍数は全桁の数字の和も3の倍数になる、というのはかろうじて覚えてるんで、10未満になるまで各桁の数字を繰り返し足して、3/6/9のどれかだったら3の倍数、ってことになるのか。美しくない。
余剰演算子を使わないだけなら (スコア:1)
3や5で割った結果が整数か否かで判定しても良いんですよね。
整数性を判定する関数があるならそれを使う。
速度をまったく気にしなくても良いなら(コードゴルフとか)、いったん文字列に変換して小数点が含まれるか否かを調べる。
数値→文字列の暗黙の変換があって正規表現リテラルのある言語だと簡潔に書けます。JavaScriptとか。
Re:余剰演算子を使わないだけなら (スコア:1)
それも考えなくはなかったのですが、いかんせんPythonではダメなのですねー。
という具合に、余り0でかっきり割り切れても、割った結果はfloat型になるのです。
# Python3の場合は、ですが。
……と、ここまで書いて気が付きましたが、Python3でもb = n // aと書けば「n >= a * bを満足する最大の整数bを求める」ので、b = n // aで除算してからn == a * bなら割り切れたと判定できるんでしたorz。
Re:余剰演算子を使わないだけなら (スコア:1)
is_integer() はだめなんでしょうか?
Re:余剰演算子を使わないだけなら (スコア:1)
そんな関数がいつの間に!……って、聞くところによると2.6だそうですね。
Python知識がずいぶんと穴だらけなことを露呈して自由研究が終わりましたorz。