LoginSignup
10
14

More than 5 years have passed since last update.

初心者による超初心者のための競プロの基礎的な入出力(Python3)

Last updated at Posted at 2018-03-20

注意

 この記事は、プログラミング自体が初めてというレベルの人向けにかかれています。中級者、上級者はもちろん、少しでもプログラミングに慣れている方も、何も得られない可能性があります。ご了承ください。
入出力と書きましたが、入力がメインになってしまっています…すみません…

はじめに

 競プロをプログラミングの勉強のため始めようとしたところ、プログラミング自体がほぼ初めてであった私が最初に何よりも困ったのが入出力でした。入出力がうまくできないと、本質的ではない部分で詰まっているように感じ、あまりおもしろくなかったものです。(入出力を憶えるというところも、1つの本質であるかもしれませんが)。

 競プロのサイトの方で、基本例なんかは用意してくださっているのですが、なんとなくそれを写してとやっていると、よくわからないまま扱っているので、ちょっと入力の形が変わると対応できないなど、なかなかに苦労しました。この部分で苦労して、よく触る前に競プロが嫌になる人もいるのではないかなと少し感じます。

そこで、競プロの、特に簡単めな問題ではよく見る形式の入出力についての記事を書こうと思いました。言語をPython3としたのは、単純に私が入出力を書ける言語であるというのに加えて、やはりプログラミング初心者にも書きやすい言語であるからです。C++のこの形の記事も、後ほど諸々を鑑みて、可能であれば書きたいと思っています。

この記事では、初心者の方が、後に自分でもある程度応用できるよう、まず使用するパーツ(関数など)を説明してから、具体的な組み合わせに入って行きたいと思います。

使うパーツ(関数など)たち

引数は種類を日本語で書いています(私は最初の頃リファレンスとかの形式での引数表記を読むのが大変だったので、日本語にしてみました)。また、引数はこの記事で主に使う形で書いていますので、正確性を欠くところが多々多々あります。初心者の方はプログラミングになれてきたらリファレンスとかを見てください。

読み込むパーツ

input()

基礎的な入力を受け取る関数です。”文字列”が返ります。

分割するパーツ

.split(文字列)

"文字列"が持っている、自分を()内に書かれた文字列をしきりとして見て、分割する機能です。()内に何も書かないと、空白で区切ってくれます。

型を変換するパーツ

int(文字列etc)

型の変換を行います。今回の主な使用法としては、文字列を整数に変えます。(他に小数以下を切り捨てるときに使えたりもします。)

map(関数名,リスト)

リストの全てに対して関数の操作を行います。返り値はそのままだとよくわからないのが返ってきます(map型)。ここでは関数名と書きましたが、ここは特に正確性を欠く表現なのですが、他の言い方が思いつきませんでした…すみません…

分割時補助パーツ

list(よくわからないもの)

listが返ってくると思ったのに、返ってこないときはこの関数の()に入れると大抵いい感じにlistにして返してくれます。map→listの変換に主に使います。

出力パーツ

print(なんでも)

()内にあるものを出力します。だいたい何を入れても出力してくれます。改行なしに出力したい場合はprint(出力したい物,end="区切り文字")の形でできます。

print_test.py
array = [1,2,3]

print("str")
print(1)
print(array)
print("a",end="")
print("b",end=" ")
print("c",end=",")
print("d")
str
1
[1, 2, 3]
ab c,d

以上が使うパーツになります。
読み込み
分割
型変換
map補助
出力
の順にパーツを考えて、あとはforを組み合わせるだけで、基礎的な入出力はだいたい受けることができます。

入力具体例

数字が一つ

5

みたいな入力のときです。このときは、
読み込み→必要
分割→いらない
型変換→必要
map補助→mapないのでいらない
なので、順に適用していくと

num_single.py
s = input()
s = int(s)

print(s)
5

また、まとめれば

s = int(input())

で入力を受けられます。

数字が複数行で最初に行数

3
2
5
11

みたいなときです。これは、最初にループ回数を取得して、その後は数字一つの時の処理をforの中に入れればいいです。

num_multi.py
N = int(input())
a = []
for i in range(N):
    a.append(int(input()))
print(a)
[2, 5, 11]

今回はリストに入れましたが、その場で処理して出力したり、ディクショナリに入れることもあります。本題からそれるので今回は割愛しますが…

数字がスペース区切りで横一列にいっぱい

1 1 2 3 5

みたいなときです。
このときは、
入力→必要
分割→必要
型変換→必要
map補助→必要
なので

num_space.py
s = input()
s = s.split()
s = map(int,s)
s = list(s)

print(s)
[1, 1, 2, 3, 5]

まとめちゃうと

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

で一気に受けられます。
今回は整数型に変換しましたがlist(map(float,input().split()))で小数を受けたり、自作の関数をmapに渡すことでもうちょっと高度な処理ができます(ほとんど使わない気はしますが)

最初に入力行数、そのあとスペース区切りの数字列が複数行

3
1 2 3
4 5 6
7 8 9

もしくはこれの変形で列数もあたえられた

3 3
1 2 3
4 5 6
7 8 9

こんなパターンですね。これはスペース区切りで横一列の入力ををループするだけになります。
列数が与えられていてもpythonでは特に気にすることなく捨てて問題無いことが多いです。

列がないときは

N = int(input())
a = []
for i in range(N):
    a.append(list(map(int,input().split())))

print(a)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

列があるときは

N = int(input())

N = list(map(int,input().split()))[0]

として分割、変換後最初の要素だけとってくるように変更すれば問題ないです。

文字列+数字(複数行)

あまり見ない形ではあるのですが、応用として入れました。

3
Takashi 80
Naomi 76
Kenya 91

みたいな形を想定しています(テストの点数など)。
このときは
入力→必要
分割→必要
型変換→後の部分のみ
map補助→mapないのでいらない
ということになるので、

N = int(input())
a = {}

for i in range(N):
    s = input().split()
    a[s[0]] = int(s[1])

print(a)
{'Takashi': 80, 'Naomi': 76, 'Kenya': 91}

と以上のようにパーツをうまく組み合わせると、大体の入力を受けられます。

番外編

文字列、それを一文字ずつ処理したい

このパターンはpythonで正直に処理すると、間に合わない問題も多いのですが、一応。
例えば

aabbcdeaf

なんて文字列のときに出てくるaの数を数えたいとなれば、一番単純なのは一つづつ見て、数えていくというものになりますが、このときの分割はどうすれば良いでしょうか…

正解としてはまさかの分割の必要すらないということになります。

s = input()
sum = 0
for char in s:
    if char == "a":
        sum+=1

print(sum)
3

当然といえば当然なのですが(C言語でも似たような形で処理できるくらいプリミティブです)、意外と見落としがちなので…

文字を数字として扱う

これもたまにしか必要では無いですし、入出力から少し離れているように見えますが、一応。アルファベット全部のリストを作ったり、アルファベット以外の文字で処理をするなんて場面で訳に立つことがあります。
ord("文字")で文字コードに変換、chr(文字コード)で逆に文字に戻せます。
具体例を見てみましょう

print(ord("a"))
print(ord("z"))
print(ord("!"))

print(chr(97))
print(chr(122))
print(chr(33))
97
122
33
a
z
!

97-122はアルファベットが連番で収まっていて、入力で分割したあと、mapでordを全体にかけて、その値が97-122に収まっているかを判断することで、アルファベット以外の文字を見つけたときの分岐が書きやすくなります。

終わりに

すでに腐るほど溢れている情報なので、需要はあるのだろうかと心配になりながらも、応用に繋げることを意識して書いてみました。一応差別化はしたつもりです。リスト内包表記、mapにlambda式を渡す等々、実はもっと簡潔に書く方法は存在するのですが、初心者のうちはコードを短くすることよりも、一つ一つちゃんと手順とpythonでできることを把握するのが良いのでは無いのかなと思いこのような形にしました。
説明の丁寧さがちぐはぐな部分があるかもしれません…気力があれば修正していきたいと思います。

参考記事

Pythonで競技プログラミングする時に知っておきたいtips(入出力編)
https://qiita.com/lethe2211/items/6cbade2bc547649bc040

Python Snippets 文字→ascii。ascii→文字 ord, chr
https://python.civic-apps.com/char-ord/

AtCoder practice contest A:はじめてのあっとこーだー
https://practice.contest.atcoder.jp/tasks/practice_1

10
14
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
14