【競技プログラミングの第一歩】Pythonでのさまざまな標準入力

はじめに

今回はPythonでの標準入力の受け取り方について紹介します。

この競技プログラミングで最初の関門になるのが標準入力です。
ここでつまづいてしまうと競技プログラミングでの面白さを体感する前に挫折してしまいます。
なので必要なメソッドに関しては初学者向けに丁寧に解説します。

競技プログラミングに挑戦してみたい方はこの機会に是非マスターしましょう。

目次

標準入力について

標準入力とは、アプリやコマンド側での入力を受け取ることです。
標準入力は普通のWebアプリの開発などでは使われないので、見たことのある人は少ないかもしれません。

ただし、特にこの標準入力が必須になる部分があります。
それが先に紹介した競技プログラミングです。

競技プログラミングとは出題された問題の仕様通りのプログラムを組んで、いかに速く正確に答えを出せるかを競うものです。
日本ではさまざまな競技プログラミングが毎日のように行われています。

AtCoderは日本最大の競技プログラミングサイトです。
週に1回、主に土曜日にコンテストを行っています。

atcoder


AtCoder:AtCoderは、オンラインで参加できるプログラミングコンテスト(競技プログラミング)のサイトです。リアルタイムのコンテストで競い合ったり、約2000問のコンテストの過去問にいつでも挑戦することが出来ます。

他には転職サービスと並行して行っている企業もあります。

paiza

paiza:paiza(パイザ)のプログラミングスキルチェックは、コードを書いて書類選考なしで面接可能な求人がわかる、IT/Webエンジニア、プログラマのための新しいカタチの転職サービスです。

競技プログラミングは問題を解けたときの達成感はもちろん、日々の努力も正解数やレートという形で表示してくれるので非常に楽しみながらプログラミングを勉強できます。
その第一歩として、まずは標準入力をできるようになりましょう。

いろいろなパターンの標準入力

ここではさまざまなパターンでの標準入力を紹介します。
これらをマスターすればほとんどの標準入力はできるようになるので頑張りましょう。

1つの文字を受け取る

これがすべての基本になります。
単純にinput()を使っています。

a
s = input()
# a

1つの数値を受け取る

input()で標準入力を受け取ると文字列になります。
なので、数値が欲しい場合はint()を使いましょう。

12
i = int(input())
# 12

1行複数の文字を受け取る

split()を使うとそれぞれの入力を分裂して受け取ることができます。
今回はs1とs2の間にスペースがあるのでそこを境に2つの値を分けています。

split()の引数には分断する目印を取りますが、split()はデフォルトでsplit(' ') と同じ意味です。

s1 s2
a, b = input().split()

1行複数の数値を受け取る

上記のように受け取った場合の値それぞれに関数を適応する場合にはmap()を使います。
この関数は引数を2つ取り、map(適応する関数, iterableなオブジェクト)です。

iterableとは__iter__特殊メソッドが定義されている(もしくは、__getitem__特殊メソッドが定義されている)オブジェクトです。
ただし難しいので、現状はfor文で取り出せるものと認識しておいてください。

1 2
a, b = map(int, input().split())

1行複数の数値をリストにいれる

以下のような出力をリストで受け取りたい場合はlist()を使いましょう。

1 2
ls = list(map(int, input().split()))
# [1, 2]

1行のつながった文字をばらばらでリストに入れる

for文を使い、受け取った入力を1文字ずつリストに入れています。

abcdefg
ls = [s for s in input()]
# ['a', 'b', 'c', 'd', 'e', 'f']

複数行の数値を受け取る(最初の数値は行数)

競技プログラミングでは最初に受け取る行数が指定されることがほとんどなので、その数値を受け取ってデータを複数行受け取ります。
for文で行数分のinput()を行うことで受け取ることができます。

3
1
2
3
n = int(input())
l = [int(input()) for _ in range(n)]

# [1, 2, 3]

for文を使うとき、取り出した変数を使わない場合は_とするのが良いと思います。
文字列の場合はint()を外すだけです。

複数行の複数の数値を受け取りながら何らかの処理を行いたい場合

複数行の複数の数値を使って何らかの処理を行いたい場合は、for文で受け取りながら行います。
受け取り方は複数1行の数字を受け取る方法と同じです。

3
1 2
3 4
5 6
n = int(input())
for _ in range(n):
  a, b = map(int, input().split())
  # 何らかの処理

複数行の複数の数値を二次元リストに格納する

今までの応用です。
上記の処理をlist()で内包記法として実行するだけです。
使用頻度は高くないですが、参考に載せます。

3
1 2
3 4
5 6
n = int(input())
ls = [list(map(int, input().split())) for _ in range(n)]
# [[1, 2], [3, 4], [5, 6]]

競技プログラミングの問題に挑戦しよう

AtCoderのABC(AtCoder Beginer Contest)のA問題は標準入力さえできれば解けてしまう問題が多数あります。

せっかくですので、今回学んだ標準入力を使って競技プログラミングの問題を解いてみましょう。

ABC 094 a

A – Cats and Dogs

問題文

猫と犬が合わせて A+B 匹います.
このうち A 匹は猫であることがわかっていますが,残りの B 匹は猫と犬のどちらであるかわかっていません.

この A+B 匹の中に,猫がちょうど X 匹いるということはありうるかどうか判定してください.

制約

  • 1≤A≤100
  • 1≤B≤100
  • 1≤X≤200
  • 入力はすべて整数

入力

入力は以下の形式で標準入力から与えられる。

A B X

出力

猫がちょうど X 匹いるということがありうるならば YES を,ありえないならば NO を出力せよ.

入力例 1

3 5 4

出力例 1

YES

B=5 匹のうち,猫が 1 匹,犬が 4 匹であれば,猫の数は合計で X=4 匹になります.

競技プログラミングでは上記のように入力が与えられます。
これを標準入力し、求められている値を出力できれば正解となります。

1行複数の数値を受け取るのはどのようにやるか思い出せるでしょうか。
受け取れれば後は文章力の問題です。
猫の匹数は、最小でA匹、最大でA+B匹になるのでこの数の中に当てはまればYES、そうでなければNOと出力するように条件分岐させましょう。

正解の1例は以下のようになります。

a, b, x = map(int, input().split())
print('YES' if a <= x <= b+a else 'NO')

皆さん解けたでしょうか。
このように標準入力さえわかっていれば、すんなり解けてしまいます。

ちなみにif文はprint()に内包記法という形で書いています。
通常通り外に書くこともできるのですが、内包記法の方が見た目がスッキリしており処理速度も速いのでこちらの方が好まれます。

入力を受け取りながら何らかの処理を行う問題にも挑戦してみましょう。

ABC 121 b

B – Can you solve this?

問題文

N 個のソースコードがあり、i 個目のソースコードの特徴は Ai1,Ai2,…,AiM の M 個の整数で表されます。

また、整数 B1,B2,…,BM と 整数 C が与えられます。

Ai1B1+Ai2B2+…+AiMBM+C>0 のときに限り、i 個目のソースコードはこの問題に正答するソースコードです。

N 個のソースコードのうち、この問題に正答するソースコードの個数を求めてください。

制約

  • 入力は全て整数である。
  • 1≤N,M≤20
  • −100≤Aij≤100
  • −100≤Bi≤100
  • −100≤C≤100

入力

入力は以下の形式で標準入力から与えられる。

N M C
B1 B2 ... BM
A11 A22 ... A1M
...
AN1 AN2 ... ANM

出力

N 個のソースコードのうち、この問題に正答するソースコードの個数を出力せよ。

入力例 1

2 3 -10
1 2 3
3 2 1
1 2 2

出力例 1

1

以下のように 2 個目のソースコードのみがこの問題に正答します。

  • 3×1+2×2+1×3+(−10)=0≤0 なので 1 個目のソースコードはこの問題に正答しません。
  • 1×1+2×2+2×3+(−10)=1>0 なので 2 個目のソースコードはこの問題に正答します。

この問題は先程よりも少し複雑です。
Bと対応するそれぞれの行のAとの値の積を計算する必要があります。
この場合、入力を最初にすべて受け取らず、3行目からのAの行を1行ずつ読み込みながら処理を行います。

つまり、複数行の複数の数値を受け取りながら何らかの処理を行いたい場合の手法が使えます。
正解の1例はこのようになります。

n, m, c = map(int, input().split())
B = list(map(int, input().split()))

num = 0

for _ in range(n):
    A = list(map(int, input().split()))
    ans = [a*b for (a, b) in zip(A, B)]
    if sum(ans)+c > 0:
        num += 1

print(num)

A行が始まる3行目からはfor文で1行ずつ読み込み、Aと対応するBとの積をリストに入れsum()で合計を出しています。

このように難しい問題は標準入力ができることが大前提なので、まずは自分の思うように値を受け取れるようにしてください。

まとめ

今回はさまざまな標準入力を紹介しました。
これで競技プログラミングの基本的な問題は挑戦できるはずです。

実はinput()よりも早く動く標準入力のプログラムはあります。
ただそれはどんどんレベルアップして興味が湧いてきたら学ぶと良いでしょう。

本気でプログラミングを身につけるならCodeShip

CodeShipは業界内で唯一「無償延長保証制度」によるスキル修得を保証しているプログラミングスクールです。
独学での挫折や未経験からでも、スタートアップベンチャーや日系・外資の大手WEB系企業まで幅広くエンジニアを輩出する教育実績を残しています。

勉強目的ごとに用意された6つの学習コース&オリジナルのポートフォリオ開発実戦経験豊富な現役エンジニアキャリアコンサルタントがあなたの「開発スキル修得」と「キャリアプランニング」をサポートします

さらに、期間内であれば選択した以外のコースのカリキュラムを受講可能。
同じ値段で、頑張った分だけ勉強できる「勉強し放題」はCodeShipだけ。

まずはご自身のプログラミング学習やキャリアプランについて、無料個別相談会にてお気軽にご相談ください。


おすすめ記事