blog.jnito.comやってみました。
カレンダー作成問題
ここで似たようなことをやっているので省略。(ただし、Date クラスは使っていません。)
カラオケマシン問題
class KaraokeMachine
Key = %w(C C# D D# E F F# G G# A A# B)
def initialize(melody)
@scaned = melody.scan(/C#|D#|F#|G#|A#|C|D|E|F|G|A|B| |\|/)
end
def transpose(n)
@scaned.map do |k|
idx = Key.index(k)
idx ? Key[(idx + n) % Key.size] : k
end.join
end
end
ビンゴカード作成問題
stock = 5.times.map {|i| (i * 15 + 1..(i + 1) * 15).to_a.shuffle}
table = 5.times.map do
5.times.map {|i| stock[i].shift}
end
table[2][2] = ""
table = ([%w(B I N G O)] + table).map do |row|
row.map {|x| "%2s" % x}.join(" | ")
end
puts table
出力例。
B | I | N | G | O
15 | 28 | 32 | 58 | 68
8 | 27 | 35 | 49 | 73
12 | 18 | | 47 | 64
1 | 21 | 42 | 56 | 62
3 | 25 | 38 | 52 | 75
ボーナスドリンク問題
class BonusDrink
def self.total_count_for(amount)
drink = ->(left, drinked) {
return drinked if left.zero?
i = left / 3
d = i.zero? ? left : i * 3
drink.(left - d + i, drinked + d)
}
drink.(amount, 0)
end
end
puts BonusDrink.total_count_for(100)
再帰で解いています。
残りが3本より少なければそのまま飲みます。3本以上なら、3の倍数本だけ飲めるだけ飲んで、(いま飲んだ本数÷3)本だけ追加します。残り0本ならば終了します。
電話帳作成問題
class NameIndex
ADan = %w(ア カ サ タ ナ ハ マ ヤ ラ ワ ン)
def self.create_index(names)
table = Hash.new([])
names.each do |name|
ADan.each_cons(2) do |be, ed|
table[be] += [name] if (be...ed).include?(name[0])
end
end
table.each_value {|v| v.sort!}
table.map {|k, v| [k, v]}.sort
end
end
NameIndex.create_index(['キシモト', 'イトウ', 'ババ', 'カネダ', 'ワダ', 'ハマダ'])
行単位、列単位で合計値を求めるプログラム
module SumMatix
extend self
def output(input)
result = calc(input)
length = result.last.map {|x| x.to_s.size}
result.map do |row|
row.map.with_index {|x, i| x.to_s.rjust(length[i])}.join("| ")
end
end
def calc(input)
tmp = input.map {|row| row + [row.sum]}
last = tmp.first.each_index.map do |i|
tmp.map {|row| row[i]}.sum
end
tmp + [last]
end
end
実行例。
input = [
[ 9, 85, 92, 20],
[68, 25, 80, 55],
[43, 96, 71, 73],
[43, 19, 20, 87],
[95, 66, 73, 62]
]
puts SumMatix.output(input)
9| 85| 92| 20| 206
68| 25| 80| 55| 228
43| 96| 71| 73| 283
43| 19| 20| 87| 169
95| 66| 73| 62| 296
258| 291| 336| 297| 1182
module KeitaiMessage
Allocation = [%W(. , ! ? #{" "}), %W(a b c), %W(d e f), %W(g h i), %W(j k l),
%W(m n o), %W(p q r s), %W(t u v), %W(w x y z)]
def self.key_in(input)
result = ""
input.chars.chunk_while {|i, j| i == j}.reject {|x| x[0] == "0"}.each do |line|
group = Allocation[line.first.to_i - 1]
result += group[(line.size - 1) % group.size]
end
result = result[0...-1] if input[-1] != "0"
result
end
end
puts KeitaiMessage.key_in("440330555055506660")
正しく問題のとおりにするなら、入力が例えば "5" の場合、何も出力されてはいけませんが、ここではじつは空文字列が出力されます。ただ元の仕様は美しくないので、まあいいかということにしてしまいました。正しく修正するなら、メソッドの外ですることになります。
Enumerable#chunk_while は見たことがないという人もいるかもしれませんが、意外と有用なメソッドだと思います。
終りに
「国民の祝日.csv パースプログラム」と「値札分割問題」は問題の定義がわかりにくかったので解いていません。
全体的にそんなにむずかしくはないですね。すなおな回答を心がけました。