Tatehitoの技術メモ

ソフトウェアエンジニアです。いろいろ書きます。

【Rubyで競プロ】よく使う、標準入力を扱う方法あれこれ

最初はRubyの勉強のために始めた競技プログラミング(以下競プロ)ですが、最近はほぼ趣味として取り組んでいます。いずれは競プロに適しているとされる、コンパイル言語のC++で取り組んでみたいとは思っているものの、まだRuby学習中の身なのでしばらくはRubyでやっていこうと思っています。

僕の競プロ歴はAtCoderのABCに4回出場、実力は3完できるくらいの初心者ではありますが、Rubyで競プロを行う上で役に立つTipsをブログに書き溜めていきたいと思い立ち、この記事を書いています。

競プロのRuby情報は多くないと思いますので、誰かの役に立てれば幸いです。

ということで、今回は競プロでは必須の「標準入力を扱う方法」についてです。

getsメソッドで標準入力を取得できる

Rubyでは、getsで標準入力を取得できます。ただし、getsで取得した文字列は改行コード付きのため、競プロにおいてはgets単独ではほとんど使いません。

<標準入力>
sample
x = gets
=> "sample\n" # 末尾に改行コード

文字列を扱う場合

入力を文字列で扱う場合は、chompを使って末尾の改行コードを取り除きます。

これをしないと、パッと見正しい出力ができていても、オンラインジャッジで誤答と判定される場合があるので注意です。このことを知らず、「明らかに正しい出力が得られているのにACにならない。なぜ。。。」とドツボにはまったことがありました。

ちなみに、入力を数値で扱う場合はchompは必要ありません。chompを付けると処理速度の低下につながるようなので、文字列を扱う場合のみ付けるようにしましょう。

<参考> leokun0210.hatenablog.com

<標準入力>
sample
x = gets.chomp 
=> "sample"

文字列を1文字ずつ分けて配列に格納する

入力の文字列を、1文字ずつ扱いたい場合はcharsを使って分割し配列に格納できます。

<標準入力>
sample
x = gets.chomp.chars 
=> ["s", "a", "m", "p", "l", "e"]

数値を扱う場合

整数として取得する

getsは文字列を返すので、数値として扱いたい場合はto_iで整数に変換します。

<標準入力>
32
x = gets.to_i 
=> 32

数値を文字列として扱いたい場合はgets.chompを使います。

x = gets.chomp
=> "32"

浮動小数点数として取得する

入力値を小数で扱いたい場合はto_fを使います。

<標準入力>
32
x = gets.to_f
=> 32.0

スペース区切りの数値を取得する

競プロでよくあるのがスペース区切りで数値が並んでいる入力です。この場合は、splitを使って各数値を分割します。

<標準入力>
5 3 12 1
x = gets.split.map(&:to_i)
=> [5, 3, 12, 1]

たまにsplit(' ')と引数に区切り文字の半角スペースを指定している人を見かけますが、splitは引数を省略すると半角スペースで区切ってくれるので、結果は変わりません。

x = gets.split(' ').map(&:to_i)
=> [5, 3, 12, 1]

各数値を配列でなく、独立した変数に格納したい場合は多重代入を使います。

a, b, c, d = gets.split.map(&:to_i)
=> [5, 3, 12, 1]

p a
=> 5

p c
=> 12

縦に並んだ数値を取得する

縦に数値がならんだ入力を扱う方法です。

最初に「数値の数」が入力として与えられ、以降、縦に数値が並ぶケースが多いです。

以下の例だと、数値の数「4」が与えられ、以降、4つの数値が縦に並びます。この場合は、4回gets.to_iを繰り返せばOKです。

<標準入力>
4
5
3
12
1
n = gets.to_i
=> 4

n.times.map { gets.to_i } 
=> [5, 3, 12, 1]