[https://blog.jnito.com/entry/2019/05/03/121235:title]
上記記事のカラオケマシーン問題。
自分で書いたコード
class KaraokeMachine
KEYS = %w(C C# D D# E F F# G G# A A# B)
def initialize(melody)
@melody = melody
end
def transpose(diff)
@melody.gsub(/[A-G]#?/) {|l| KEYS[(KEYS.index(l)+diff)%12]}
end
end
出題者による回答例
class KaraokeMachine
SCALE = %w(C C# D D# E F F# G G# A A# B).freeze
def initialize(melody)
@melody = melody
end
def transpose(amount)
converter = [SCALE, SCALE.rotate(amount)].transpose.to_h
@melody.gsub(/[A-G]#?/, converter)
end
end
[https://blog.jnito.com/entry/2014/07/10/091216:title]
学んだこと
- 正規表現全然知らなかったがちょっと知った。
- 最初gsubの第一引数を
Regexp.new(KEYS.join('|'))
でつくろうとして、F#
のF
の部分がヒットしてしまう問題に直面した。F
かF#
をヒットさせたければF#?
とすぐに発想できたかった。 - 定数がミュータブルなオブジェクトの場合、再代入は警告だすけど実行できてしまう。再代入できないようにするには
freeze
する必要あり。 - gsubの第二引数に文字列じゃなくてハッシュ渡せる!覚えておきたい。(ヒットした文字列をもとにあれこれ操作したい場合はブロックをつかう。)
-
Array#rotate(count)
配列の要素を回転させるみたいに動かせる。 -
Array#transpose
で行列の転置みたいな操作ができる。 -
converter = [SCALE, SCALE.rotate(amount)].transpose.to_h
カコイイ…