###初投稿
普段自分で勉強していて、自分の書いたソースや、
他人の参考にしたソースの内容をすぐに忘れてしまう、
次似たようなものが来ても、思い出せない、と
全く自分の知識となっていないように感じたため、
アウトプットの場として、ここを利用していこうと思います。
###AtCoderをやっていて
では、早速昨日AtCoderで以下の問題をやっていた時のこと。
[AtCoder Beginner Contest 141 B-Tap Dance]
(https://atcoder.jp/contests/abc141/tasks/abc141_b)
ある文字列の偶数番目と奇数番目に現れる文字が、
特定の文字であるか否かを判定し、
それに応じて出力する文字列を変えるというような問題。
私は、文字列を偶数番目用と奇数番目用の配列に分けて、
その中に、指定された特定の文字があるかの判定をしようと、考えました。
#当初のイメージ
s = gets.chomp.split('')
#以下でsを奇数番目にと偶数番目に分ける。
odd = []
even = []
if odd.include?('指定の文字') || even.include?('指定の文字')
puts 'No'
else
puts 'Yes'
end
そこでググって見たら見つかったのが、以下の記事でした。
Ruby | 配列の奇数番目と偶数番目を取り出す方法
もうこれじゃないかと、そのままコピペしてできたコードがこちら。
s = gets.chomp.split('')
#以下でsを奇数番目にと偶数番目に分ける。
odd = s.each_slice(2).map(&:first)
even = s.each_slice(2).map(&:last)
if odd.include?('指定の文字') || even.include?('指定の文字')
puts 'No'
else
puts 'Yes'
end
こちら、each_slice(2)によって、配列の値を2つずつ取り出し、
oddでは、2つの値のうち最初の値を、
evenでは、最後、つまり2つ目の値を取得して来ています。
「これならいけるだろう」と、意気揚々と例題の値を入力し、
結果を確認すると、
Noと出力されるはずが、Yesと出力されてしまいました。
原因
なぜ、このようなことになったのか、原因を探ってみると、
入力した文字列が、奇数個の文字列であったことが原因であったようです。
each_slice(2)によって2つずつ値を取得しても、
奇数個であった場合、最後は1つの値しか取得できません。
1つの値だと、firstでもlastでも同じ値が取得されるので、
そこで想定とは違う値が、evenの配列の中に入ってしまっていました。
###解決策
それでは、どうやって私が解いたのか、というと、
このようにしました。
s = gets.chomp.split('')
odd = []
even = []
(0..s.length-1).each do |n|
if n%2 ==0
odd << s[n]
else
even << s[n]
end
end
if odd.include?('指定の文字') || even.include?('指定の文字')
puts 'No'
else
puts 'Yes'
end
結局配列の何番目かというのを、0..length-1によって取得し、
それが2で割り切れるか否かで、
奇数番目なのか偶数番目なのかを特定し、
新たに配列を作った後に、特定の文字が含まれるか否かを判定する、
という流れを作りました。
###更に推敲
出力は正しかったものの、長い・処理時間が若干長い、ということもあったので、
他の人の回答も参考にしながら、私の中でわかりやすかった回答を新たに作ってみました。
それが、こちら。
s = gets.chomp.split('')
s.length.times do |n|
if n.odd? &&s[n]=='指定の文字' || n.even? && s[n] == '指定の文字'
puts 'No'
exit
end
end
puts 'Yes'
わざわざ、奇数用と偶数用に配列を作らなくとも、
繰り返し処理を行って、その回数が奇数回目なのか。偶数回目なのかを確認すれば、
配列の中を確認せずとも、一文字一文字条件に合うかを確認できて、
簡潔に書くことができました。
###最後に
と、いうようにまだまだ簡単な処理を書くことだけでも、
精一杯の状態ではありますが、
日々自分の書いたソース・参考にしたソースの何がうまくいなかなったのか、
どうやって解決したのか、ということをここに残していければと思います。
勉強がんばります!