問題を解く以前に、入力をどう取り扱ったらいいかイマイチ良く分からない、あるいは入力を取得するコードを書くところで悩んで時間を食ってしまう……という人向けの記事。
慣れれば誰でも簡単に書けるようになるので、一応それらしいパターンをまとめつつ、どうしてこういう書き方になるのか、ちょっとした解説をつけてみようと思う。
最初に一連のコード例を。
# A: 一行の文字列を受け取る # abcde string = input() # B: 一行の整数を受け取る # 12345 integer = int(input()) # C: 一行の小数を受け取る # 1.2345 float_number = float(input()) # D: 最初の行に要素数Nが指定され、次行のスペースで区切られた整数列を受け取る # 5 # 1 2 3 4 5 N = int(input()) integer_list = list(map(int, input().split())) # D': スペースで区切られた2つの整数N, Mを受け取る # 3 4 N, M = map(int, input().spilt()) # E: 最初に要素数Nが指定され、続くN行の整数を受け取る # 3 # 1 # 2 # 3 N = int(input()) integer_list = [int(input()) for _ in range(N)] # F: 最初に要素数N、行数Mが指定され、続くM行の整数列(要素数N)を受け取る # 2 3 # 1 2 # 3 4 # 5 6 N, M = map(int, input().split()) integer_matrix = [list(map(int, input().split())) for _ in range(M)]
Pythonでは、とりあえずinput()を使用することで標準入力を「文字列として」一行分受け取ることができる。実に簡単だ。
文字列ならばそのまま受け取ればいいし、整数ならint(input())、小数ならfloat(input())と型変換をしてやればいい。(例A~C)
# D: 最初の行に要素数Nが指定され、次行のスペースで区切られた整数列を受け取る # 5 # 1 2 3 4 5 N = int(input()) integer_list = list(map(int, input().split()))
例Dは、細かく書いていくと次のような処理を行っている。一行目で要素数を受け取りはするが、この中では使用されない。
N = int(input()) input_string = input() # "1 2 3 4 5" splitted_string = input_string.split() # ["1", "2", "3", "4", "5"] map_object = map(int, splitted_string) # map_object(1, 2, 3, 4, 5) integer_list = list(map_object) # [1, 2, 3, 4, 5]
mapは関数とリストを引数に取る少し特殊な関数で、大まかにいうと次のような感じの処理を行ってくれる。
# map(function, list)とした場合 result = [] for item in list: result.append(function(item)) return result
今回の例でいうと、リストの各要素(文字列)にint()を適用し、整数に変換してくれたものを取得できるということだ。[a, b, c]→[int(a), int(b), int(c)]といったイメージである。
ただし、map()の返り値は実はリストそのものではなく、map objectという繰り返し処理可能(イテラブル)な特殊オブジェクトのため、そのままでは扱いにくい(特に、インデックスが使えない)。そこで、最後にlist()を用いてリストに変換してやるようにする。
# D': スペースで区切られた2つの整数N, Mを受け取る # 3 4 N, M = map(int, input().spilt())
対して、複数の変数に一度に代入を行っている(アンパック代入と呼ばれる)例D’では、右辺のmap objectは自動的に展開(アンパック)されるため、listを使用する必要はない。もちろんリストに変換しても動作するが、わずかに無駄な書き方になる。
# E: 最初に要素数Nが指定され、続くN行の整数を受け取る # 3 # 1 # 2 # 3 N = int(input()) integer_list = [int(input()) for _ in range(N)]
例Eでは、リスト内包表記を使用している。この部分を、forを用いて分かりやすい形に書き下すと、次のようなものになる。
integer_list = [] for i in range(M): n = int(input()) integer_list.append(n)
リスト内包表記は非常に強力で、また、慣れると書くのも早いので、一般的な使い方も覚えておくと便利だ。
そして、これらを組み合わせて入力を扱ったのが例Fということになる。このパターンでは、2次元リストとして入力を受け取ることになる。
# F: 最初に要素数N、行数Mが指定され、続くM行の整数列(要素数N)を受け取る # 2 3 # 1 2 # 3 4 # 5 6 N, M = map(int, input().split()) integer_matrix = [list(map(int, input().split())) for _ in range(M)]
以上のパターンが理解できれば、これらを組み合わせることで、基本的な入力については問題なく取り扱えるだろう。