Loki's Note

色々なことに手を出して迷子中の私のための記録

【Python】標準入力の処理【競プロ 初心者】

post-featured-image

競プロ(競技プログラミング)に挑戦したくて、paizaで練習問題をやり始めました。
どの問題でもまず必要になるのは標準入力の処理なので、忘れたときのためにカンペを作成しました。

目次

一覧

今の時点で必要になった入力を一覧にまとめておきます。

1行
形式 入力 取得方法 結果
文字列 python s = input() ‘python’
数値 123 n = int(input()) 123
複数文字列
空白区切り
単体変数
python c# s1, s2 = input().split() s1 = ‘python’
s2 = ‘c#’
複数数値
空白区切り
単体変数
12 34 n1, n2 = map(int, input().split()) n1 = 12
n2 = 34
複数文字列
空白区切り
リスト化
python c# l = input().split() [‘python’, ‘c#’]
複数数値
空白区切り
リスト化
12 34 l = list(map(int, input().split())) [12, 34]
文字列
1文字ずつリスト化
python l = [s for s in input()] [‘p’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’]
数値
1桁ずつリスト化
12345 l = [int(s) for s in input()] [1, 2, 3, 4, 5]
n行(既知の行数)
形式 入力 取得方法 結果
文字列
リスト化
python
c#
l = [input() for _ in range(n)] [‘python’, ‘c#’]
数値
リスト化
12
34
l = [int(input()) for _ in range(n)] [12, 34]
複数文字列
空白区切り
2次元リスト化
aa bb cc
dd ee ff
l = [input().split() for _ in range(n)] [[‘aa’, ‘bb’, ‘cc’],
[‘dd’, ‘ee’, ‘ff’]]
複数数値
空白区切り
2次元リスト化
12 34 56
78 98 76
l = [list(map(int, input().split())) for _ in range(n)] [[12, 34, 56],
[78, 98, 76]]
複数複合
2次元リスト化
1 python
2 c#
3 java
l = []
for _ in range(n):
x, y = input().split()
l.append([int(x), y])
[[1, ‘python’],
[2, ‘c#’],
[3, ‘java’]]
複数複合
辞書化
1 python
2 c#
3 java
l = {}
for _ in range(n):
k, v = input().split()
l[int(k)] = v
{1: ‘python’,
2: ‘c#’,
3: ‘java’}
全ての行(行数不明)
形式 入力 取得方法 結果
文字列
リスト化
python
c#
java
import sys
l = [s.rstrip() for s in sys.stdin]
[‘python’,
‘c#’,
‘java’]
数値
リスト化
12
34
56
import sys
l = [int(s.rstrip()) for s in sys.stdin]
[12,
34,
56]
複数文字列
2次元リスト化
aa bb cc
dd ee ff
import sys
l = [s.rstrip().split() for s in sys.stdin]
[[‘aa’, ‘bb’, ‘cc’],
[‘dd’, ‘ee’, ‘ff’]]
複数数値
2次元リスト化
11 22 33
44 55 66
77 88 99
import sys
l = [list(map(int, s.rstrip().split())) for s in sys.stdin]
[[11, 22, 33],
[44, 55, 66],
[77, 88, 99]]
その他
形式 入力 取得方法 結果
n行数値
リスト化
フィルタ
12
99
76
l = list(filter(lambda x: x <= 80, [int(input()) for i in range(n)])) [12, 76]
n行数値
総当たり
重複なし
(2つ選択)
1
2
3
4
from itertools import combinations
l = [list(c) for c in combinations([int(input()) for _ in range(n)], 2)]
[[1, 2], [1, 3], [1, 4],
[2, 3], [2, 4], [3, 4]]
n行数値
総当たり
重複あり
(2つ選択)
1
2
3
4
from itertools import combinations_with_replacement
l = [list(c) for c in combinations_with_replacement([int(input()) for _ in range(n)], 2)]
[[1, 1], [1, 2], [1, 3], [1, 4],
[2, 2], [2, 3], [2, 4],
[3, 3], [3, 4], [4, 4]]
n行数値
総当たり
重複なし
全通り
(2つ選択)
1
2
3
4
from itertools import permutations
l = [list(c) for c in permutations([int(input()) for _ in range(n)], 2)]
[[1, 2], [1, 3], [1, 4],
[2, 1], [2, 3], [2, 4],
[3, 1], [3, 2], [3, 4],
[4, 1], [4, 2], [4, 3]]

1行分の取得

単一文字列

1行の文字列を取得する場合は単純にinputで取得可能。
inputで取得すると数値であってもすべて文字列として処理される。

s = input()

もし不要な改行が含まれてしまう場合はrstripを使用する。
inputでは必要になったことはないが、念の為。

s = input().rstrip()
複数文字列

1行に空白区切りで複数の文字列が与えられた場合はsplitを使用する。
受け取る側をカンマ区切りで複数用意することで、それぞれを独立した変数に格納できる。

s1, s2 = input().split()
# 入力:apple orange
# 結果:s1 = 'apple' s2 = 'orange'

受け取る側を1つだけ用意すると、空白で区切られた文字列が1つのリストにまとめられる。

l = input().split()
# 入力:apple orange
# 結果:['apple', 'orange']
単一数値

数値として取得したい場合はintを使用する。

n = int(input())
複数数値

複数の文字列を数値として取得したい場合はmapを使用する。
mapを使用することで分割したそれぞれの値にintを適用することができる。

n1, n2 = map(int, input().split())

複数の数値を1つのリストにまとめる場合は単一の変数を用意し、上のmapに加えてlistを使用する。
listで囲わずにそのまま取得するとmapオブジェクトになってしまう。

l = list(map(int, input().split()))

複数行の取得

input関数は1行ずつ取得し、繰り返し使用することで次の行を取得していくことができる。
データの行数を始めに与えられることが多いので、大抵はfor 〜 in range(n)で1行取得する処理をn行分繰り返し呼び出して、データをリストに追加していく。

n行の文字列をリストへ

問題文でn行と指定されていたり、1行目で行数が与えられたりする場合の取得方法。
リスト内包表記で記述可能。n回inputを繰り返してリスト化する。

l = [input() for _ in range(n)]
n行の空白区切り複数文字列をリストへ

単一行で取得したものを、行数分繰り返すだけ。
リストの中に1行分のリストを追加していくので2次元リストになる。

l = [input().split() for _ in range(n)]
n行の数値をリストへ

1行取得の時と同じでintを使用し、行数分繰り返す。

l = [int(input()) for _ in range(n)]
n行の空白区切り複数数値をリストへ

こちらも1行取得の時と同じものを、行数分繰り返すだけ。
リストの中に1行分のリストを追加していくので文字列と同じく2次元リストになる。

l = [list(map(int, input().split())) for _ in range(n)]

データの行数が与えられていない時(sys.stdin)

行数がわからない場合や、または行数を指定されず全てを処理する場合は、何回繰り返せばいいか分からないため、上の方法は使えない。その場合はsys.stdinを使用する。
stdinを使用するためにはsysをimportする必要がある。
また、この方法を使用すると文字列の最後に改行文字がついてくるため、rstripが必須となる。
intに変換すると改行文字は消えるので、intにする場合はやらなくても問題なさそう。

全行の文字列を取得

for s in stdinとすることで入力が1行単位でsに代入されるので、あとはinputで取得した時と同じように処理できる。
改行を外すためにrstripをつけておく。

import sys
l = [s.rstrip() for s in sys.stdin]
全行の空白区切りの文字列を取得

上のものにsplitをつけただけ。

import sys
l = [s.rstrip().split() for s in sys.stdin]
全行の数値を取得

基本は前と同じで、intをつけるだけ。
rstripはつけなくても結果は変わらない。

import sys
l = [int(s.rstrip()) for s in sys.stdin]
全行の空白区切りの数値を取得

手順はinputの時と同じ。

import sys
l = [list(map(int, s.rstrip().split())) for s in sys.stdin]

文字列・数値の分解

1文字ずつに分解したい時がたまにある。
分解してそれぞれリストに代入する方法。

文字列を1文字ずつリストへ

for inで文字列を与えると1文字ずつ渡されることを利用してリストに入れる。

l = [s for s in input()]
数値を1文字ずつリストへ

分割した文字列にintを使うだけ。

l = [int(s) for s in input()]

データの加工

標準入力からは外れるが、ついでにメモ。

フィルターをかけて条件抽出(filter)

あらかじめ不要なデータを除いてリストに格納したいこともある。
基本の取得の方法は同じで、filter関数にラムダ式で条件を渡して抽出する。
そのままだとfilterオブジェクトになってしまうので、listでリスト化してあげる。
下の例ではn行の数値を取得し、80以下の数値のみリストに格納する。
listの部分をsortedにすることで、ソートもここで行える。

l = list(filter(lambda x: x &lt;= 80, [int(input()) for i in range(n)]))
様々な組み合わせを検証(itertools)

与えられた入力を総当たりで検証したいこともある。
itertoolsのcombinationsを使うと簡単に重複のない組み合わせを作成してくれる。
組み合わせはタプルで返ってくるので、 まとめてリストに入れておくとforで回して処理ができる。
下の例ではlistを用いてリストにしている。
combinationsの第2引数が1つの組み合わせにいくつ含まれるかの設定になる。3なら3つ選んで組み合わせる。

from itertools import combinations
l = [list(c) for c in combinations([int(input()) for _ in range(n)], 2)]
# 入力:1〜4 を改行区切り
# 出力: [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

itertoolsのその他の使い方

終わり

問題解いてる中で新しいものに出会ったら追記する予定。
AtCoderも近いうちに挑戦したい。