2019-06-02
Ruby手習い(正規表現)
アウトプットのネタに困ったらこれ!?Ruby 初心者向けのプログラミング問題を集めてみた(全 10 問) - give IT a try
上記記事のカラオケマシーン問題。
自分で書いたコード
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
「CodeIQ ベストコード発表会 ~最もエレガントにカラオケマシン問題を解いた挑戦者は誰だ!?~」を放送しました #sg_study - give IT a try
学んだこと
- 正規表現全然知らなかったがちょっと知った。
- 最初 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
カコイイ…