Pythonで標準入力を受け取るまとめ

最近話題になってる(?)、競技プログラミングをしています(激弱コーダーなので探さないでください……泣)。

C++だったら、std::cin の後に>>をひたすらつなげておけばいいんですけど(偏見)、Pythonはそうもいかないので、標準入力を受け取る方法をいくつかまとめてみます。

以下に挙げるコードはPython 3.7.3で動作確認済みです。

間違い等ありましたら、教えてください!!

0. 目次

競技プログラミング基準で、どうしても整数中心の説明になっていますが、整数を受け取る場合も文字列を受け取る場合も、基本的な構造は変わらないと思います。

  • input()の動作

  • 標準入力(1行)を受け取る

    • 入力が1つの文字(列)

    • 入力が1つの整数

    • 入力が複数の整数

  • 標準入力(複数行)を受け取る

    • 各行に1つの整数(行数指定あり)

    • 各行に複数の整数(行数列数指定あり)

    • 各行に1つの整数(行数指定無し)

  • 標準入力に関して書いておきたいこと

  • 終わりに

1. input()の動作

input([prompt])

引数 prompt が存在すれば、それが末尾の改行を除いて標準出力に書き出されます。次に、この関数は入力から 1 行を読み込み、文字列に変換して (末尾の改行を除いて) 返します。 EOF が読み込まれたとき、 EOFError が送出されます。

引用元:Python 3.7.4 ドキュメント

(^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

何やってるか記しておくと、

  1. input().split()で、半角スペースで区切られたそれぞれの整数を要素とした、リストが返ります(上の例でいうと、['334', '-334', '364'])。「整数を要素とした」と書きましたが、Pythonに言わせればこれらはまだ文字列のリストです。

  2. mapは、簡単に言うと、リスト(とか)のすべての要素に同じ処理を適用する関数です。ここで、文字列として扱われている整数たちを、int型に変換します。

  3. それぞれの要素を変数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にしましょう。

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))

出力6と同様になります。

f:id:kingofwhiterock:20190828134358p:plain
コード7の実行結果
ただ、ローカル環境とかでテストするときに、プログラムを走らせてから標準入力する場合は、うまくできない可能性大です。正直何やってるのかよくわからないので、コード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]

f:id:kingofwhiterock:20190828151854p:plain
コード9の実行結果

白状してしまうと、競プロで使わないので、今考えて書きました。果たして合っているのでしょうか……?

コード9も、ローカル環境などにおいて、プログラムを走らせてから標準入力する場合はうまくできない可能性大です。

4. 標準入力に関して書いておきたいこと

  • input()と、sys.stdin.readline()の大きな違いは、末尾の改行文字が含まれるか否かです。input()は末尾の改行文字が除かれますが、sys.stdin.readline()は改行文字が含まれます。そのためsys.stdin.readline()を使う際は、しばしばrstrip()で改行文字を取り除きます(詳しくはググろう)。

  • forループを書くのとリスト内包表記を用いるのでは、リスト内包表記の方が速いそうです(参考記事: Pythonのリスト内包表記の速度 - Qiita )

5. 終わりに

ダラダラ書いてたら意外と長くなりました。冒頭でも書きましたが、間違いなどありましたら是非教えてください!