Loading [MathJax]/jax/output/HTML-CSS/config.js

競技プログラミングにおける、標準入力の取得例 in Python3

Share

問題を解く以前に、入力をどう取り扱ったらいいかイマイチ良く分からない、あるいは入力を取得するコードを書くところで悩んで時間を食ってしまう……という人向けの記事。

慣れれば誰でも簡単に書けるようになるので、一応それらしいパターンをまとめつつ、どうしてこういう書き方になるのか、ちょっとした解説をつけてみようと思う。

最初に一連のコード例を。

  1. # A: 一行の文字列を受け取る
  2. # abcde
  3. string = input()
  4.  
  5. # B: 一行の整数を受け取る
  6. # 12345
  7. integer = int(input())
  8.  
  9. # C: 一行の小数を受け取る
  10. # 1.2345
  11. float_number = float(input())
  12.  
  13. # D: 最初の行に要素数Nが指定され、次行のスペースで区切られた整数列を受け取る
  14. # 5
  15. # 1 2 3 4 5
  16. N = int(input())
  17. integer_list = list(map(int, input().split()))
  18.  
  19. # D': スペースで区切られた2つの整数N, Mを受け取る
  20. # 3 4
  21. N, M = map(int, input().spilt())
  22.  
  23. # E: 最初に要素数Nが指定され、続くN行の整数を受け取る
  24. # 3
  25. # 1
  26. # 2
  27. # 3
  28. N = int(input())
  29. integer_list = [int(input()) for _ in range(N)]
  30.  
  31. # F: 最初に要素数N、行数Mが指定され、続くM行の整数列(要素数N)を受け取る
  32. # 2 3
  33. # 1 2
  34. # 3 4
  35. # 5 6
  36. N, M = map(int, input().split())
  37. integer_matrix = [list(map(int, input().split())) for _ in range(M)]

Pythonでは、とりあえずinput()を使用することで標準入力を「文字列として」一行分受け取ることができる。実に簡単だ。

文字列ならばそのまま受け取ればいいし、整数ならint(input())、小数ならfloat(input())と型変換をしてやればいい。(例A~C)

  1. # D: 最初の行に要素数Nが指定され、次行のスペースで区切られた整数列を受け取る
  2. # 5
  3. # 1 2 3 4 5
  4. N = int(input())
  5. integer_list = list(map(int, input().split()))

例Dは、細かく書いていくと次のような処理を行っている。一行目で要素数を受け取りはするが、この中では使用されない。

  1. N = int(input())
  2. input_string = input() # "1 2 3 4 5"
  3. splitted_string = input_string.split() # ["1", "2", "3", "4", "5"]
  4. map_object = map(int, splitted_string) # map_object(1, 2, 3, 4, 5)
  5. integer_list = list(map_object) # [1, 2, 3, 4, 5]

mapは関数とリストを引数に取る少し特殊な関数で、大まかにいうと次のような感じの処理を行ってくれる。

  1. # map(function, list)とした場合
  2. result = []
  3. for item in list:
  4. result.append(function(item))
  5. return result

今回の例でいうと、リストの各要素(文字列)にint()を適用し、整数に変換してくれたものを取得できるということだ。[a, b, c]→[int(a), int(b), int(c)]といったイメージである。

ただし、map()の返り値は実はリストそのものではなく、map objectという繰り返し処理可能(イテラブル)な特殊オブジェクトのため、そのままでは扱いにくい(特に、インデックスが使えない)。そこで、最後にlist()を用いてリストに変換してやるようにする。

  1. # D': スペースで区切られた2つの整数N, Mを受け取る
  2. # 3 4
  3. N, M = map(int, input().spilt())

対して、複数の変数に一度に代入を行っている(アンパック代入と呼ばれる)例D’では、右辺のmap objectは自動的に展開(アンパック)されるため、listを使用する必要はない。もちろんリストに変換しても動作するが、わずかに無駄な書き方になる。

  1. # E: 最初に要素数Nが指定され、続くN行の整数を受け取る
  2. # 3
  3. # 1
  4. # 2
  5. # 3
  6. N = int(input())
  7. integer_list = [int(input()) for _ in range(N)]

例Eでは、リスト内包表記を使用している。この部分を、forを用いて分かりやすい形に書き下すと、次のようなものになる。

  1. integer_list = []
  2. for i in range(M):
  3. n = int(input())
  4. integer_list.append(n)

リスト内包表記は非常に強力で、また、慣れると書くのも早いので、一般的な使い方も覚えておくと便利だ。

そして、これらを組み合わせて入力を扱ったのが例Fということになる。このパターンでは、2次元リストとして入力を受け取ることになる。

  1. # F: 最初に要素数N、行数Mが指定され、続くM行の整数列(要素数N)を受け取る
  2. # 2 3
  3. # 1 2
  4. # 3 4
  5. # 5 6
  6. N, M = map(int, input().split())
  7. integer_matrix = [list(map(int, input().split())) for _ in range(M)]

以上のパターンが理解できれば、これらを組み合わせることで、基本的な入力については問題なく取り扱えるだろう。

Share

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です