3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

配列を偶数番目と奇数番目で分けてみた

Last updated at Posted at 2019-10-29

###初投稿

普段自分で勉強していて、自分の書いたソースや、
他人の参考にしたソースの内容をすぐに忘れてしまう、
次似たようなものが来ても、思い出せない、と
全く自分の知識となっていないように感じたため、
アウトプットの場として、ここを利用していこうと思います。


###AtCoderをやっていて
では、早速昨日AtCoderで以下の問題をやっていた時のこと。
[AtCoder Beginner Contest 141 B-Tap Dance]
(https://atcoder.jp/contests/abc141/tasks/abc141_b)

ある文字列の偶数番目と奇数番目に現れる文字が、
特定の文字であるか否かを判定し、
それに応じて出力する文字列を変えるというような問題。

私は、文字列を偶数番目用と奇数番目用の配列に分けて、
その中に、指定された特定の文字があるかの判定をしようと、考えました。

oddeven.rb
#当初のイメージ
s = gets.chomp.split('')
#以下でsを奇数番目にと偶数番目に分ける。
odd = []
even = []
if odd.include?('指定の文字') || even.include?('指定の文字')
  puts 'No'
else
 puts 'Yes'
end

そこでググって見たら見つかったのが、以下の記事でした。
Ruby | 配列の奇数番目と偶数番目を取り出す方法

もうこれじゃないかと、そのままコピペしてできたコードがこちら。

oddeven.rb
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の配列の中に入ってしまっていました。


###解決策

それでは、どうやって私が解いたのか、というと、
このようにしました。

oddeven.rb
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で割り切れるか否かで、
奇数番目なのか偶数番目なのかを特定し、
新たに配列を作った後に、特定の文字が含まれるか否かを判定する、
という流れを作りました。


###更に推敲

出力は正しかったものの、長い・処理時間が若干長い、ということもあったので、
他の人の回答も参考にしながら、私の中でわかりやすかった回答を新たに作ってみました。
それが、こちら。

oddeven.rb
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'

わざわざ、奇数用と偶数用に配列を作らなくとも、
繰り返し処理を行って、その回数が奇数回目なのか。偶数回目なのかを確認すれば、
配列の中を確認せずとも、一文字一文字条件に合うかを確認できて、
簡潔に書くことができました。


###最後に

と、いうようにまだまだ簡単な処理を書くことだけでも、
精一杯の状態ではありますが、
日々自分の書いたソース・参考にしたソースの何がうまくいなかなったのか、
どうやって解決したのか、ということをここに残していければと思います。

勉強がんばります!

3
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?