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
カコイイ…