変形Fizz-Buzz問題
Posted feedbacks - Ruby
1 2 3 4 5 6 7 8 9 10 11 | def fizzbuzz(n)
(1..20).each do |i|
printf("%2d:", i)
print "Fizz" if i % 3 == 0
print "Buzz" if i % 5 == 0
print "hoge" if (i % 3) * (i % 5) != 0
puts
end
end
fizzbuzz(20)
|
こんな感じ? プレビューのハイライトが間違っている気がする… “else”は論理の否定を取ってしまうと普通に書けてしまうので, 条件分岐の条件を数以外で行うことと, “return”で飛んでみるという変形をしました. ""はStringと+について単位元なので, 9行目を変えれば“7の倍数の時は…” とか別の変形に応用できそうですね.
1 2 3 4 5 6 7 8 9 10 | class String
def hoge
return "hoge" if self.empty?
self
end
end
1.upto(99) {|i| ## とりあえず99まで
puts("%2d:%s"%[i,((["Fizz"]+[""]*2)[i%3]+(["Buzz"]+[""]*4)[i%5]).hoge])
}
|
ああ,なるほど,もしかしたら, 出題者の意図としてはこっちのコードの方が合っているかもしれないな. 他の方のコードをいくつか見て思った.
1 | 1.upto(20){|i|puts("%2d:%s"%[i,(["FizzBuzz"]+["hoge"]*2+["Fizz","hoge","Buzz","Fizz"]+["hoge"]*2+["Fizz","Buzz","hoge","Fizz"]+["hoge"]*2)[i%15]])}
|
すでに同じネタ出てるか確認してないのですが。 周期の全部書けばいいじゃん、みんな大げさだなあ、ということで。
1 2 3 4 5 6 7 | a = ['hoge', 'hoge', 'Fizz', 'hoge', 'Buzz',
'Fizz', 'hoge', 'hoge', 'Fizz', 'Buzz',
'hoge', 'Fizz', 'hoge', 'hoge', 'FizzBuzz']
100.times{|i|
printf("%2d:%s\n", i+1, a[i%a.size])
}
|
1 2 3 4 5 6 7 8 9 10 11 12 | def fizzbuzz(n)
a=[["FizzBuzz","Fizz"],["Buzz","hoge"],[3,5]]
(1..n).each {|i|
printf("%2d:%s\n",i,
a[-1].inject(a) {|r,j|r=r[i**(j-1)%j]}
)
}
end
if __FILE__ == $0
fizzbuzz(20)
end
|
安直に書いてみました
1 2 3 4 5 6 7 | (1 .. 20).each do |i|
out = ''
out << 'Fizz' if (i % 3) == 0
out << 'Buzz' if (i % 5) == 0
out = 'hoge' if out.empty?
puts "%2d:%s" % [i, out]
end
|
条件分岐無し,剰余演算子無し,ループ無し. ループ無しという割には,イテレータ付きgsubを 使っているあたりが反則っぽいけど.
1 2 3 4 5 6 7 8 | i = 0
print ('o' * 20).gsub(/./) {
i += 1
"%2d:%s\n" % [i, '-' * i + ',' + '=' * i]
}.gsub(/:(---)+,/, ':Fizz,').
gsub(/,(=====)+$/, 'Buzz').
gsub(/[-=,]/, '').
gsub(/:$/, ':hoge')
|
出遅れたけど,こんなのどうか。
1 2 3 4 5 6 | fizzbuzz = { true => { true => "FizzBuzz", false => "Fizz" },
false => { true => "Buzz", false => "hoge" } }
1.upto(20) do |x|
printf("%2d:%s\n", x, fizzbuzz[x%3==0][x%5==0])
end
|
完璧に出遅れで題意に従っているかあやしいのですが書いてみました。オブジェクト指向 (笑) という感じです。
言語組みこみの if/else を使わないという解釈です。
else にみえるのは、メソッドの名前なので hoge でも fuga でもよく、名前はこのさいどうでもいいと思ったので else のままにしてあります。
cycle を使っているので ruby1.9 です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class True
def then
yield
self
end
def else
self
end
end
class False
def then
self
end
def else
yield
end
end
t = True.new
f = False.new
(1..20).zip([f, f, t].cycle, [f, f, f, f, t].cycle).each do |i, i3, i5|
t = ""
i3.then {
i5.then {
t = "FizzBuzz"
}.else {
t = "Fizz"
}
}.else {
i5.then {
t = "Buzz"
}.else {
t = "hoge"
}
}
puts "%2d:%s" % [i, t]
end
|
せっかく Ruby なので、もうすこし踏みこんで 1.8 系でも動くようにしました。
TrueClass/FalseClass は true/false のクラスで、それを拡張しています。.result を付けくわえたのは if 文 (のようにみえるもの) が値を持つようにみせかけたかったからです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!ruby -Ku
require "pp"
class TrueClass
def then
@ret = yield
self
end
def else
self
end
def result
@ret
end
end
class FalseClass
def then
self
end
def else
@ret = yield
self
end
def result
@ret
end
end
(1..20).each do |i|
puts "%2d:%s" % [i,
(i % 3 == 0).then {
(i % 5 == 0).then {
"FizzBuzz"
}.else {
"Fizz"
}.result
}.else {
(i % 5 == 0).then {
"Buzz"
}.else {
"hoge"
}.result
}.result
]
end
|
見掛け上は条件分岐を使わず, かつ, FizzとBuzzがコード中に一回ずつしか出現しないようにしてみました.
1 2 3 4 | 1.upto(20){|i|
puts({0 => "#{i}: hoge", i%5 => "#{i}: ", i%3 => "#{i}: Fizz"}.
merge({i%5 => 'Buzz'}){|k,a,b| "#{a}#{b}"}[0])
}
|





raynstard
#3758()
Rating0/2=0.00
[ reply ]