はじめに
Ruby学習の一環として「アルゴリズム実技検定」に挑戦します。
そのための学習の中で学んだことをアウトプットしていきます。
今回は「第一回アルゴリズム実技検定」の六問目(DoubleCamelCase Sort)より。
第一回アルゴリズム実技検定 過去問
今回は、参考になった解答をもとに学ぶことが出来た内容をまとめていきたいと思います。
問題
文字列 S が与えられる。
これは、1 つ以上の単語を (間に空白などを挟まずに) 連結したものである。
ここで、各単語は 2 文字以上であり、最初の文字と最後の文字のみが英大文字、それ以外の文字は全て英小文字である。
制約
・S は長さ 2 以上 100,000 以下の文字列である。
・S の各文字は英大文字または英小文字である。
・S は問題文で述べたような単語の連結である。
入力は以下の形で与えられる。
S
入力例
FisHDoGCaTAAAaAAbCAC
出力例
=> AAAaAAbCACCaTDoGFisH
解答
今回参考にさせて頂く解答はこちらです。
puts gets.scan(/[A-Z][a-z]*[A-Z]/).sort_by(&:upcase).join
受け取った文字列に対して、単語ごとに要素としてまとめて配列化。
sort_byメソッドを使って並び替えた後、joinメソッドを使って配列の要素全てを連結して出力という流れ。
それぞれのメソッドについてや、正規表現での表現について以下にまとめていきます。
scanメソッド
オブジェクトに対し、()内に指定したパターンを繰り返しマッチし、マッチした部分文字列を配列として返します。
p "test".scan(/../)
#=> ["te", "st"]
p "test".scan("t")
#=> ["t"]
p "testet".scan(/te./)
#=> ["tes", "tet"]
大文字で始まり、大文字で終わる単語を取り扱う今回のようなケースでは最適なメソッドですね。
正規表現部分
今回取り扱う単語を正規表現で表現すると以下のようになります。
/[A-Z][a-z]*[A-Z]/
/ /
//で囲むことで正規表現オブジェクトを生成することが出来ます。
つまり、「//で囲まれたものが正規表現だよ」という宣言になります。
[ ]
角括弧[ ]で挟まれた部分を文字クラスと言います。
1個以上の文字を列挙したもので、いずれかの1文字にマッチします(上記では0から9のうち1文字)。
[A-Z]
1文字の大文字英字を表しています。
[a-z]
1文字の小文字英字を表しています。
直前の表現を0回以上繰り返すという意味のメタ文字になります。
今回の場合は小文字英字が0回以上繰り返されるという意味になり、
3文字以上の英単語が示される際、大文字の間に挟まれるのは必ず小文字、という意味になります。
これで、問題の指定に沿った単語にマッチ出来るようになりました。
sort_byメソッド
配列の中身を比較して並び替え、並び替えた状態の配列を新たに作ってくれます。
()内にて、正しく比較をするためにupcaseメソッドを各要素に当て、全て大文字にしてから比較しています。
※そのままだとabcという順番よりも、大文字ABC...小文字abc...という順番で並び替えてしまうため。
p ["AA", "AC", "AaA"].sort_by(&:upcase)
#=>["AA", "AaA", "AC"]
joinメソッド
配列の要素を括弧()内に指定した区切り文字を挟んで連結した文字列を返します。
()を記述しなかった場合は、区切り文字なしで連結されます。
p ["AA", "AaA", "AC"].join(",")
#=>AA,AaA,AC
p ["AA", "AaA", "AC"].join
#=>AAAaAAC
最後に
以上、「第一回アルゴリズム実技検定」の六問目(DoubleCamelCase Sort)で学んだメソッドについてまとめました。
正規表現や様々なメソッドを使って、今回参考にさせて頂いた解答のように簡潔で分かりやすい解答が出来るようにしていきたいものです。
もし間違いなどございましたら、ご指摘いただけると嬉しいです。