-1. はじめに&前口上
この記事は、私のはてなブログに掲載している記事とほぼ同一です。
最近話題になってる、競技プログラミングをしています(激弱コーダーなので探さないでください……泣)。
C++だったら、std::cin
の後に>>
をひたすらつなげておけばいいんですけど(偏見)、Pythonはそうもいかないので、標準入力を受け取る方法をいくつかまとめてみます。
以下に挙げるコードはPython 3.7.3
で動作確認済みです。
間違い等ありましたら、教えてください!!
0. 目次
競技プログラミング基準で、どうしても整数中心の説明になっていますが、整数を受け取る場合も文字列を受け取る場合も、基本的な構造は変わらないと思います。
-
input()
の動作 -
標準入力(1行)を受け取る
-
入力が1つの文字(列)
-
入力が1つの整数
-
入力が複数の整数
-
-
標準入力(複数行)を受け取る
-
各行に1つの整数(行数指定あり)
-
各行に複数の整数(行数列数指定あり)
-
各行に1つの整数(行数指定無し)
-
-
標準入力に関して書いておきたいこと
-
終わりに
1. input()
の動作
input([prompt])
引数 prompt が存在すれば、それが末尾の改行を除いて標準出力に書き出されます。次に、この関数は入力から 1 行を読み込み、文字列に変換して (末尾の改行を除いて) 返します。 EOF が読み込まれたとき、 EOFError が送出されます。
(^o^)…………へぇ。
とりあえず競プロをするうえで押さえるべきは、
-
入力からの1行を読み込む
-
文字列に変換して返す
の2つだと思います。これを頭に入れて、実際の使用例を見ていきます。
2. 標準入力(1行)を受け取る
例1. 入力が1つの文字(列)
入力
apple
コード1
s = input()
print(s)
出力1
apple
変数s
の型は、もちろんstr
型。
一文字ずつリストに入れたい場合は、
コード2
s = list(input())
print(s)
出力2
['a', 'p', 'p', 'l', 'e']
変数s
の型は、list
型。
例2. 入力が1つの整数
入力
334
コード3
n = int(input())
print(n)
出力3
334
input()
でstr
型の334
が返るので、それをint
で括っています。
したがって、変数n
の型は、int
型。
もちろん入力が数字であっても、文字列のように扱いたい場合は、上述のコード1, 2のように書けばOK。
例3. 入力が複数の整数
競プロでは圧倒的に使用頻度が高いです。map
という関数を使います。
入力(それぞれの数字は半角スペース区切り)
334 -334 364
コード4
a, b, c = map(int, input().split())
print(a, b, c)
出力4
334 -334 364
何やってるか記しておくと、
-
input().split()
で、半角スペースで区切られたそれぞれの整数を要素とした、リストが返ります(上の例でいうと、['334', '-334', '364']
)。「整数を要素とした」と書きましたが、Pythonに言わせればこれらはまだ文字列のリストです。 -
map
は、簡単に言うと、リスト(とか)のすべての要素に同じ処理を適用する関数です。ここで、文字列として扱われている整数たちを、int
型に変換します。 -
それぞれの要素を変数
a
b
c
にぶち込みます。
コード4では、変数を3つ用意してそれぞれにぶちこみましたが、もちろんリストにすることもできます。
コード5
a = list(map(int, input().split()))
print(a)
出力5
[334, -334, 364]
ひとつ注意したいのは、list
で囲んで、list
型に変換しなければならない点です。map
の返り値はリストではなく、mapオブジェクトとかいうクソザコプログラマには理解しがたい何かだからです。
複数の文字列を受け取るときも、コード4, 5とほぼ同じです。ただし、int
のままだとValueError
を吐くのでちゃんとstr
にしましょう。
(2019/12/31追記)複数の文字列を受け取る時は、map
からlist
にせずとも、単にinput().split()
で良いです。
3. 標準入力(複数行)を受け取る
基本的に、上述した方法を行の数ぶん繰り返すだけなので、forループにぶち込んでぶん回せばいいです。
ここでは、内包表記を使った方法などを記します。
例1. 各行に1つの整数(行数指定あり)
競プロでは、最初に入力の行数を与えてくれることがほとんどなので、ここでもそれに従った入力の方法を紹介します。
入力
5
441
484
529
576
625
※ただし1行目は続く入力の行数をあらわす。
コード6
n = int(input())
l = [int(input()) for i in range(n)]
print(n, l)
出力6
5 [441, 484, 529, 576, 625]
input()
を括っているint
を外せば、もちろん文字列にも使えます。
最近Twitterで回ってきた方法(リンク)がこれ↓
コード7
n, *l = map(int, open(0))
ただ、ローカル環境とかでテストするときに、プログラムを走らせてから標準入力する場合は、うまくできない可能性大です。正直何やってるのかよくわからないので、コード7への言及はこれくらいにしておきます。浅学がバレる……(既にバレている)。
例2. 各行に複数の整数(行数列数指定あり)
2次元平面上の問題や、登場するものが複数の要素をもっている問題の入力で使いそうです。
コード5をリスト内包表記でぶん回します。
入力
5 9
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
※ただし、1行目は順に、行数、列数をあらわす。
コード8
n, m = map(int, input().split())
l = [list(map(int, input().split())) for i in range(n)]
print(n, m, l)
出力8
5 9 [[1, 2, 3, 4, 5, 6, 7, 8, 9], [2, 4, 6, 8, 10, 12, 14, 16, 18], [3, 6, 9, 12, 15, 18, 21, 24, 27], [4, 8, 12, 16, 20, 24, 28, 32, 36], [5, 10, 15, 20, 25, 30, 35, 40, 45]]
見にくくて申し訳ないですが、変数l
に2次元のリストが入っていることがわかります。列数は、Pythonでは使いません。やったね。
例3. 各行に1つの整数(行数指定無し)
これは、競プロというより実務的な側面の方が大きいかと思います。
入力
441
484
529
576
625
コード9
import sys
array = []
for i in sys.stdin.readlines():
array.append(int(i.rstrip()))
print(array)
出力9
[441, 484, 529, 576, 625]
白状してしまうと、競プロで使わないので、今考えて書きました。果たして合っているのでしょうか……?
コード9も、ローカル環境などにおいて、プログラムを走らせてから標準入力する場合はうまくできない可能性大です。
4. 標準入力に関して書いておきたいこと
-
input()
と、sys.stdin.readline()
の大きな違いは、末尾の改行文字が含まれるか否かです。input()
は末尾の改行文字が除かれますが、sys.stdin.readline()
は改行文字が含まれます。そのためsys.stdin.readline()
を使う際は、しばしばrstrip()
で改行文字を取り除きます(詳しくはググろう)。 -
forループを書くのとリスト内包表記を用いるのでは、リスト内包表記の方が速いそうです(参考記事: https://qiita.com/intermezzo-fr/items/43f90e07e4cebe63aeb6 )
5. 終わりに
ダラダラ書いてたら意外と長くなりました。冒頭でも書きましたが、間違いなどありましたら是非教えてください!