転職活動中(未経験)にコーディングテストがあり、解答した答えを備忘録として残しました
実力不足で色々試行錯誤して出した答えのため、修正・解説いただけると嬉しいです
この他にも何問かあったので、追って記事にする予定です
問題1.回文部分の文字列を出力
PalindromString(str)でstrには文字列が入ります。
この文字列内で部分的に最長となる回文文字列を取得するメソッドを作るという問題です。
例 str="abracecars"の場合、racecarを返す必要があります。
strの入力は小文字英字のみで、3文字以上の回文文字列がない場合はnoneを返すようにしてください。
自分の回答
1.変数wordに文字列内で連続した文字のすべての組み合わせを取り出す
2.reverseメソッドを用いてword == word.reverseを満たしかつ3文字以上のwordを配列に代入する
3.配列内で最長となるwordを出力する
といった処理を記述したつもりです
以下が全体のコードです
def PalindromString(str)
# code goes here
num = 1
str_size = str.length
array = []
# 調べるwordの全組み合わせについて回文になっているか確認する
while num <= (str_size - 1)
while 2 <= (str_size - 1)
word = str.slice(num..str_size - 1)
str_size = str_size - 1
# 回文になっている、かつ文字数が2文字以上のものをarrayに代入
if (word == word.reverse) && (word.length > 2)
array << word
end
end
str_size = str.length
num = num + 1
end
# arrayにwordが入っている時に最初に回文になっている最大文字数のものを表示する
unless array.empty?
puts array.max_by{|w| w.size}
else
puts "none"
end
end
1.変数wordに文字列内で連続した文字のすべての組み合わせを取り出す
連続した文字のすべての組み合わせを取り出すというのは
例えばstr = "abcdefg"
の場合には下記の組み合わせになります
ab, abc, abcd,..,abcdefg
b,bc,bcd,..,bcdefg
c,cd,cde,.,cdefg
d,..,defg
e,ef,efg
f,fg
これらを全部取り出し、それぞれにreverseメソッドを使って回文になるものを探そうとしました
すべての組み合わせを取り出す処理は以下です
def PalindromString(str)
num = 0
str_size = str.length
while num <= (str_size - 1)
while 2 <= (str_size -1)
word = str.slice(num..str_size - 1)
str_size = str_size - 1
end
num = num + 1
end
end
変数について
変数num
は文字列を開始する場所の指定に使っています
sliceメソッドで文字列を切り取るときには0からカウントがスタートするため、num = 0
から始めています
str_size
は入力する文字列str
の文字数です
word
は入力された文字列から任意の範囲で切り取った単語です
①開始位置の記述
while num <= (str_size - 1)
num = num + 1
end
while~end内で最初の処理が行われるたびにnumの値が1ずつ増えるので、開始位置がずれていくといった記述です
②終了位置の記述
while 2 <= (str_size - 1)
word = str.slice(num..str_size - 1)
str_size = str_size - 1
end
ここではwhile~end内の処理が行われるたびに終了位置が左にずれていくといった記述です
処理の流れ
①で開始位置を決めます
②で開始位置が固定された状態で終了位置が変わりながらすべての組み合わせを取り出します
②の処理が終わると①で開始位置が変わり、固定されます
②の処理で開始位置が固定された状態で終了位置が変わりながらすべての組み合わせを取り出します
str = "abcdefg"
の場合
abcdefg,abcdef,abcde,abcd,abc,ab,a
bcdefg,bcdef,bcde,bcd,bc
cdefg,cdef,cde,cd
...
といったように繰り返し、すべての組み合わせを取得します
2.reverseメソッドを用いてword == word.reverseを満たしかつ3文字以上のwordを配列に代入する
while 2 <= (str_size - 1)
word = str.slice(num..str_size - 1)
str_size = str_size - 1
if (word == word.reverse) && (word.length > 2)
array << word
end
end
1で取り出したwordに条件式でword.reverseと一致するものかつwordの長さが2以上のものがあればarrayに代入するという記述です
3.配列内で最長となるwordを出力する
表示は2パターンあります
回文になっているwordが存在し、最長のものを表示するパターン
回文になっているwordが存在せず、noneと表示するパターン
これらを条件式を使って表示させるようにしました
unless array.empty?
puts array.max_by{|w| w.size}
else
puts "none"
end
条件式unlessでarrayが空でない場合には文字数が最大のものを出力し、空の場合は"none"が出力されます
max_byメソッド
では条件式を付け加え、その条件で最大となるものを取得することができます
ここではw.size
で要素の文字数で最大になるものということになります
気づき
簡単なケースではうまく動作しても、複雑化するとうまく動いていない場合が多くありそうだと感じた
動作確認のために問題と一緒に与えられた文字列ではうまく動作したが、うまくいかなそうなケースを自分で考えて処理を行ってみたいと思った
→例えば、最大のものが複数あった場合にはmax_byメソッド
で最初に見つけたものしか出力されなかった
(問題には複数表示できるようにといったことは書いてなかったので、このまま提出した)
このうまくいかなそうなケースを想定するにはどうしたら・・・?