2019-07-07
ビンゴカード作成問題を解いてみた
問題はこちら。
最初に書いたコード
class Bingo
SIZE = 5
def generate_card
format_a_row = Proc.new do |array|
array.map {|f| f.to_s.rjust(3)}.join(' |')
end
header = format_a_row("BINGO".chars)
rows = (1..SIZE).map do |i|
(1..SIZE).map {rand((i-1)*15+1..i*15)}
end.transpose
rows[(SIZE-1)/2][(SIZE-1)/2] = ""
rows.map! {|r| format_a_row(r)}
puts [header, *rows].join("\n")
end
end
Bingo.new.generate_card
出力結果は以下。
B | I | N | G | O
9 | 21 | 40 | 46 | 74
9 | 29 | 45 | 59 | 67
6 | 22 | | 56 | 61
12 | 18 | 34 | 51 | 66
7 | 28 | 36 | 47 | 62
transpose すぐ発想できたのはよかった。
ん…?数字重複してるじゃん!これじゃだめだ。
修正したコード
解答例もみる。
あと考えたら header と body の整形まとめた方がいいな。
class Bingo
SIZE = 5
FORMAT = Array.new(5, '%3s').join(' |')
def generate_card
rows = (1..SIZE)
.map {|i| [*((i-1)*15-1..i*15)].sample(5)}
.transpose.tap {|t| t[(SIZE-1)/2][(SIZE-1)/2] = ""}
puts rows.unshift("BINGO".chars).map {|r| FORMAT % r}.join("\n")
end
end
Bingo.new.generate_card
tap ってこうやってつかうんやな…すっきりやな…。
学んだこと
String#%(args)
sprintf 的なフォーマットができる。リファレンス
> "--%s--" % "hoge" # => "--hoge--"
# 引数に配列もわたせる
> "--%s--%s--" % ["hoge", "fuga"] # => "--hoge--fuga--"
# 幅も指定できる(右寄せになる)
> "--%10s--" % "hoge" # => "-- hoge--"
ランダムな値
をとるときには、重複を許容する/しないを意識すべし。