[Python]競プロ覚書


はじめに

身内に情報共有するくらいのノリで書いているので、競プロの山に住まうムキムキ競プロ仙人の方にはツッコミどころが多いかと思われます。ご了承ください。

この記事はPythonで競プロを行ううえで思ったことをまとめただけの記事です。
使いそうな標準入力や、実装してるときに考えてることとかを書いてます。

標準入力

思いつく限り載せておきます。
変数名はお好みで。

一行の文字列

s = input()

複数行の文字列

Pythonのリスト内包表記を使うと簡単です。

# nは入力回数
strArr = [input() for i in range(n)]

スペース区切りの文字列

split関数を使います。
区切り文字がスぺースじゃない場合はsplit関数に区切り文字を引数として渡せばOK。

strArr = input().split()

複数行でスペース区切りされた文字列

a b c
e d
f

みたいなの。
上記の内容をぱぱっと合わせて一行でまとまります。

# nは入力回数
strArr = [input().split() for i in range(n)]

一行の文字列を一文字ずつ

ynnyyynn

みたいな入力を一文字ずつ処理する問題が稀によくあるので。

charList = list(input())

listの引数に文字列を指定すると一文字ずつ切り取って配列にしてくれます。便利。
要素の型はcharではなくstrです。そこだけ注意。

一行の数

int, float関数で文字列を数に変換します。

# 整数
n = int(input())

# 浮動小数点数
n = float(input())

以降は明記がない限り整数のみの入力で説明します。

スペース区切りの数

split関数...だと一気に一行で処理できません。
map関数とlist関数を使います。

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

他に比べ少し難解なので補足。

map関数は「配列の要素にそれぞれ同じ処理を施す関数」、list関数は「配列を作成する関数」。
順に処理内容をまとめると、

input().split()で入力された文字列を空白ごとに区切る

map関数でその要素それぞれにint化する処理を行う

map関数はリストではない形で値を返す(扱いづらい)ため、list関数でリストにする

というかんじ。

複数行の数

リスト内包表記をつかうだけ。

# nは入力回数
numArr = [int(input()) for i in range(n)]

複数行でスペース区切りされた数

これも上記内容でどうにかなります。

# nは入力回数
numArr = [list(map(int, input().split())) for i in range(n)]

汎用性の高いものだけ挙げました。
ほかに何かあればコメントまで。

実装時に考えてること

ここ一番書きたかった。

処理は関数で分けよう

ある程度難易度が高くなってくると、

「どこでどの処理を書いたかわからん!😢」

みたいなことが起こり、最終的に自分で書いたコードが読めずにあえなく断念することが割と多いです。

そういったことを回避するのが関数
極端な例ですが、

# 1からnの総和を出力する
def main():
  n = int(input())
  ans = 0
  for i in range(1, n+1):
    ans += i

  print(ans)


if __name__ == "__main__":
  main()

より、

# 1からnまでの総和を出力する

def main():
    n = int(input())
    print(totalSum(0, n))


def totalSum(min, max):
    ans = 0
    for i in range(min+1, max+1):
        ans += i

    return ans


if __name__ == "__main__":
    main()

としたほうがデバッグがしやすくて楽です。

筆者はこれに加えて、

問題を見て必要な実装を考える

先に実装部分だけ関数で作っておく

main関数を記述

デバッグ

という工程を加えることで、安全に手早く、先を見通しながらコードを書くことを意識しています。
結構簡単に意識できてわかりやすくコードが改善されるポイントなので、初心者にはオススメ。

関数は処理内容に名前を付けて保存することとでも思うといいと思います。

変数・関数名はそれなりにちゃんと書こう

整数値をnum1n1とかで済ませるのは早期にやめたほうがいいです。

競プロはたかが一問20分くらいだと思って変数や関数名を適当につけると、5分後には地獄を見ることもしばしば。

しっかり「変数の持つ意味」を考えながら書きましょう。

といっても命名に一つ数分も取られるのは億劫なので、筆者は悩んだらこんなのを使ってます。

変数ネーム: https://codic.jp

日本語を書き込めば、プログラマの世界で使われてきた「暗黙の了解」のような命名規則にのっとって変数を命名してくれます。
とりあえず再度コードを見たときにわからなくなることを防ぐのには役立つのでオススメ。

検索技術を高めよう

プログラミングでは、コーディング技術と同等かそれ以上に検索する能力が必要になってきます。
エントリーするイベントごとに制約はありますが、許可されている場合は心置きなくググりましょう。

また、Qiitaなどで普段からいろんな実装やアルゴリズムについての記事を見たり、参考になりそうなサイトをある程度ブックマークしておいたりすると役立つこともありますのでオススメです。

コーディング環境は整えよう

Pythonの場合、JetBrains社がリリースしているPyCharmが一番のおススメですが、学割がつかえない場合有料となってしまいます。

個人的にはVSCodeやAtomに拡張要素を入れて使いやすくするなどがお金もかからずオススメですが、「それだと重くて動かないよ😢」という鉄の塊のようなパソコンをお使いの方はSublime Textがおすすめです。

よくある実装はアーカイブ化するのもアリ

「よく同じような実装をするけど複数行にまたいじゃう」といった場合は、関数をまとめるファイルを作ってそこにアーカイブとして残すのもアリです。
同じような内容を毎回実装していると手間ですしミスも増えますし。

ただ、独自ライブラリのimportは環境によってはできないことに気を付けてください。
実際に使う際はコピペが多いと思います。

練習としてアルゴリズムを関数化するのもよさそう。