はじめに
Rubyおよびアルゴリズムの学習の一環として競技プログラミングに参加しています。
ここでは、そのための学習の中で学んだことをアウトプットしていきます。
今回は、これまで問題を解く中で使った「標準入力の受け取り方」をまとめておきたいと思います。
ひとつの要素を受け取る
文字列
入力例
Ruby
s = gets.chomp
# print s
# => Ruby
chompメソッドは、文字列の末尾から改行コードを取り除いた文字列を返します。
受け取りたい文字列のみをしっかり受け取る為に付けておくと安心です。
整数
入力例
64
s = gets.to_i
# print s
# => 64
getsメソッドで受け取った標準入力は、String(文字列)型として受け取られます。
to_iメソッドを後ろに付けることで受け取った文字列をInteger(整数)型に変換します。
この場合は、chompメソッドは必要ありません。
ひとつの要素を任意の形に分割する
問題によっては、要素を分解することで解答に近づけるケースが結構あります。
ここではその例のいくつかを紹介します。
文字列を一文字ずつに分割し、配列にする
入力例
Ruby
ary = gets.split("")
ary = gets.split(//) #正規表現
# print ary
# => ["R", "u", "b", "y"]
splitメソッドは、文字列を分割して配列にしてくれるメソッドです。
()内の第一引数に区切り文字を指定することが出来ます。
一文字ずつ分割したい場合は("")もしくは(//)で可能です。
文字列を任意の規則で分割し、配列にする
入力例
RubyRuby
ary = gets.scan(/../) #①
ary = gets.scan("R") #②
ary = gets.scan(/Ru./) #③
# print ary
#① => ["Ru", "by", "Ru", "by"]
#② => ["R", "R"]
#③ => ["Rub", "Rub"]
scanメソッドは引数に指定したパターンを繰り返しマッチし、マッチした部分文字列を配列として返します。
なので、入力を一定の規則に従って分割して扱いたい時に使えます。
その規則を正規表現などで表現するのが慣れるまではちょっと難しいかもです。
一行から複数の要素を受け取る
半角スペースで区切られた、複数の要素を一度に受け取るパターンです。
###配列として受け取る(文字列)
入力例
Ruby PHP
ary = gets.split(" ")#ダブルコロンの間の空白は半角スペース
# print ary
# => ["Ruby", "PHP"]
splitメソッドの第一引数に上記のように半角スペースを指定することで、
半角スペースで区切られた複数の要素を一度に受け取ることが出来ます。
###変数に受け取る(文字列)
入力例
Ruby PHP
a,b = gets.split(" ")
# print a
# => "Ruby"
# print b
# => "PHP"
受け取る要素の数が限られている場合は、それぞれ変数に入れて受け取った方が便利な場合もあります。
そのような場合は上記のように、変数を「,」で区切ることで、それぞれ受け取ることが出来ます。
###整数を受け取る
入力例
123 456
ary = gets.split(" ").map(&:to_i) #①配列で受け取る
a,b = gets.split(" ").map(&:to_i) #②変数で受け取る
# print ary
# => [123, 456]
# print a
# => 123
# print b
# => 456
mapメソッドは、配列の要素の数だけブロック内の処理を繰り返し、結果として作られた配列を返します。
各要素にメソッドを適用したい(今回は全ての要素を整数型に変換したい)時は、
&を使って上記のように省略して書けます。
複数行に渡る要素をまとめて受け取る
timesメソッド
競技プログラミングの問題では、
最初に「その後に与えられる要素の数」が入力され、
次の行から「解答に必要な要素」が与えられるというパターンの問題が多いです。
その場合は、timesメソッドを使って要素をまとめて受け取ることが出来ます。
入力例
3 #この後に与えられる要素の数
4 8
8 2
5 2
#整数型で受け取る時
n = gets.to_i #1行目で与えられる要素の数
ary = n.times.map{gets.split.map(&:to_i)}
# print ary
# => [[2, 2], [8, 2], [5, 2]]
#文字列型として受け取る時
n = gets.to_i
ary = n.times.map{gets.split}
# print ary
# => [["2", "2"], ["8", "2"], ["5", "2"]]
timesメソッドとmapメソッドの組み合わせで
入力を二次元配列としてまとめられ、様々な判定を行うのに便利です。
最後に
以上、よく使う標準入力の受け取り方でした。
問題を解く中で他の方法に出会ったら、その都度追加していきたいと思います。
もし間違いなどございましたら、ご指摘いただけると嬉しいです。