競プロにおける標準入力
個人的な感想としては競技プログラミングにおいて標準入力を受け取るというのが最初にして最大の難関。
標準入力を受け取ってからそれに対していい感じの処理をしていくので、そもそも受け取れないとスタートラインに立てないという感じ。
僕も最初は全然わからなかったが、標準入力の受け取り方にもある程度パターンがあるのでやっていくうちに慣れる。
今回はAtCoderの例題と一緒に受け取り方を紹介する。
ちなみにタイトルにもある通りPythonです。
一行に一つだけ
最も簡単な標準入力の例。
特に工夫もいらないので紹介するまでもないかもしれないが、念のため紹介する。
#整数として受け取る
t = int(input())
標準入力で受け取ったものは数値だろうが文字列として扱われるので、数値に変換したい場合は変換する処理を書く必要がある。
今回の例だとtは整数で与えられるがinput()
だけだと文字列として扱われるので、問題に答えるためには整数に変換し直してあげる必要がある。
もちろん、与えられる入力が文字列の場合だったり、数値でも文字列として扱いたい場合には変換する必要はない。
一行に二つ
これもまだ簡単。
基本的に入力が一行の場合はよくわからなくても行ける気がする。
#整数のリストとして受け取る場合
z = list(map(int, input().split()))
#別々の変数として受け取る場合
x, y = map(int, input().split())
入力が二個の時に限った話ではないが、一つの行にスペースで入力が分けられている場合にはsplit()
を使えばスペースで分けてリストにしてくれるので、よく使うことになると思う。
ただ、今回みたいに一行に入力データが二個のときは別々の変数に入れるほうが使い勝手がいい気がする。
入力が二行
複数行の入力になると戸惑ってしまうかもしれないが、やることはそこまで変わらない。
#一行目のL,Rを別々の変数として受け取ってから
L, R = map(int, input().split())
#二行目のSを受け取る
S = input()
input()
は自動的に次の行を取り出してくれるので、二行目のSを受け取るときも上記のように書けばOK。
これを知らないと、「取り出す行を指定しなきゃ...」みたいに勘違いして進めなくなる。
僕は勘違いした。
ちなみにSは文字列なので、数値に変換する処理を書いてないです。
最初に行数が与えられて複数行の入力
このあたりからけっこう難しい気がする。
でも、ここまでの受け取り方を覚えてしまえばだいたいの標準入力は行けると思う。
#最初に行数を数値で受け取ってから
N = int(input())
#残りの複数行をリストにする
S = [input() for _ in range(N)]
前にも書いたがinput()
は実行されるたびに勝手に次の行の入力を受け取ってくれるので、何行目の入力を受け取るとかやる必要がない。
それを僕は知らず苦労したが、そういうものだと知ってしまえば与えられた行の数だけfor
でループを繰り返せばいい。
ちなみに、上の例でループの中での変数をアンダースコアでとっているが、これは変数として取らざるを得ないけどその変数を利用しないときの慣例的なものらしいので、普通にiとかjとかのよく見る形でとっても何も変わらないっぽい。
これも以前は知らなくて「そういう特別な書き方なのか」と困ったことの一つ。
最初に行数と一行あたりのデータ数が与えられて複数行の入力
このパターンも結構見る。
難易度が上がるにつれてこんな感じの入力が増える印象。
Nが行数で、Mが一行あたりの入力データ数を表している。
他の言語だとわからないが、前述したようにPythonだとsplit()
を使えば数に関係なく行をスペースで分けて一発でリストにできるので、Mを使わないことも多い。
#行数であるN, 行あたりのデータ数Mを整数で受け取ってから
N, M = map(int, input().split())
#残りの行を二次元配列にする
B = [list(map(int, input().split())) for _ in range(N)]
見ればわかるようにMを使っていない。
ただし、入力を受け取るときにMを使わないだけで問題を解く中では使うかもしれないので、Nと一緒に整数で取ってしまうといいと思う。
というかNだけ整数で受け取るほうが手間がかかる気がする。
おわりに
今回紹介した例ができれば、ほとんどの競技プログラミングの問題で標準入力を受け取れるようになるはず。たぶん。