競技プログラミングPythonまとめ

久しぶりの記事になってしまいました。AtCoderの過去問を解きながらPythonを勉強しています。多少の知識が纏まってきたので、ここを棚卸しに活用します。ほぼ単なるメモです。

いつもお世話になっている参照先

Python基礎文法の整理

変数名 = 変数
関数()  # ()は関数が処理する内容。データ。
[]  # コンテナ型。複数のデータを収めてるもの。
変数名.関数(コンテナ名[]) とかも出来る。

入力

文字列を一つだけ受け取る
a = input()

空白を空けて複数の文字列を受け取る
a, b = input().split()

数値を一つだけ受け取る
n = int(input()) 

数値を複数受け取る 「A B」のように空白で区切る入力のとき
a, b = map(int, input().split())

リスト入力 「a1 a2 a3 ...」のように入力数が決まっていない場合
s = list(map(int, input().split()))

リスト入力の別解。内包表記は何かと便利なので慣れるべき。
s = [int(i) for i in input().split()]

複数入力を受け取る、かつ入力行数指定のとき(例はn=行数)
n = int(input())
p = [int(input()) for _ in range(n)]

複数入力を受け取る(行列の形)
n, m = map(int,input().split()) 
p = [list(map(int,input().split())) for i in range(m)]
print(type(P), P)

2 3
1 32
2 63
1 12

[[1, 32], [2, 63], [1, 12]]

空の繰り返しを与えて行列を作る場合(ABC050B)
n = int(input())
t = list(map(int, input().split()))
m = int(input())
for _ in range(m):
   p, x = map(int, input().split())
   print(sum(t)-t[p-1]+x)
 
5
7 2 3 8 5
3
4 2
1 7
4 13
 
19
25
30

出力

基本。{}に対応するformat()を出力。  ※3.6以降はf"{}"で書いた方が楽。
print("{} {}".format(a+b+c, s))

0.3644 小数点第4位に丸めることもできる。
print("{:.4f}".format(a))

左詰め  python---------
print("python".ljust(15,'-'))

中央寄せ  -----python----
print("python".center(15,'-'))

右詰め  ---------python
print("python".rjust(15,'-'))

10桁ゼロ埋め  0000000029
print(str(29).rjust(10,'0'))

リストのアンパック出力
print(*c)

二次元リストで間を詰めたもの
for i in [['#','.','#'],['#','#','#']]:print(*i, sep='')
#.#
###

よくある処理

= よくある処理(三項演算子)= print(三項演算子)みたいに一行で書ける。
条件式が真のときに評価される式 if 条件式 else 条件式が偽のときに評価される式
条件式が真のときに返す値 if 条件式 else 条件式が偽のときに返す値

= よくある処理(リスト) =
len(lst)  リストの全要素数を取得
lst.count('a')  リストの特定要素の出現回数を取得
lst.index('a')  リストのインデックス取得
1 in lst  リストに数値の1がいるか否か

リストに数値を入力してそれを計算したいとき。
リストをソートして変数へアンパックし代入。便利。
a, b, c = list(map(int, input().split()))
s = a, b, c
l = sorted(s)
x, y, z = l

リストに含まれる全ての値が条件に合致するか。
allをanyに変えるといずれかの要素が条件に合致するか、に変更できる。
lst = [0, 1, 2, 3, 4]
print(all([i > 2 for i in lst]))

# リストの各要素に特定の条件(処理)を与えたい場合
a = [int(x) for x in input().split()]  
for x in a:
    if
        break
    else        # breakするならelse不要
print

= よくある処理(文字列) =
eval('1 + 2')  文字列を式として実行
s.replace(' ', '-')  文字列の置換
''.join(lst)  リストの全要素の結合
'abc123def'[:]  # すべての文字列が取れる
'abc123def'[-1:]  # 終端文字がとれる
'abc123def'[:-1]  # 最後の1文字以外のものがとれる。
'abc123def'[::-1]  # 文字が逆転する

= よくある処理(数値) =
//  小数点切り捨ての割り算
sum(lst)  リストに含まれる要素の合計
  # 文字列不可,[:-1]とすれば最後の値を除きsum
sum(int(i) for i in lst)  上述と等価
abs(x)  絶対値(0からの距離)の取得

内包表記

内包表記でリストを作成するとき。
変数名=[式 for 任意の変数名 in イテラブルオブジェクト if 条件式]
入力数nまでの、3515の倍数を「除く」リストを生成の例
lst = [i for i in range(1, n+1) if i % 3 != 0 and i % 5 != 0]
入力数nまでの、3515の倍数「だけ」のリストを生成の例
lst = [i for i in range(1, n+1) if i % 3 == 0 or i % 5 == 0]

条件式が真のときに評価される式 if 条件式 else 条件式が偽のときに評価される式
l = [i * 10 if i % 2 == 0 else i for i in range(10)]
# [0, 1, 20, 3, 40, 5, 60, 7, 80, 9]

二次元配列入力
s = [list(map(int,list(input()))) for i in range(h)]

九九を一つのリストに入力
s = [x*y for x in range(1, 10) for y in range(1, 10)]
[1, 2, 3, 4, 5, 6, 7, 8, 9,
 2, 4, 6, 8, 10, 12, 14, 16, 18,
 3, 6, 9, 12, 15, 18, 21, 24, 27,
 4, 8, 12, 16, 20, 24, 28, 32, 36,
 5, 10, 15, 20, 25, 30, 35, 40, 45,
 6, 12, 18, 24, 30, 36, 42, 48, 54,
 7, 14, 21, 28, 35, 42, 49, 56, 63,
 8, 16, 24, 32, 40, 48, 56, 64, 72,
 9, 18, 27, 36, 45, 54, 63, 72, 81]

九九を二次元配列で入力
s = [[x*y for x in range(1, 10)] for y in range(1, 10)]
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
 [2, 4, 6, 8, 10, 12, 14, 16, 18],
 [3, 6, 9, 12, 15, 18, 21, 24, 27],
 [4, 8, 12, 16, 20, 24, 28, 32, 36],
 [5, 10, 15, 20, 25, 30, 35, 40, 45],
 [6, 12, 18, 24, 30, 36, 42, 48, 54],
 [7, 14, 21, 28, 35, 42, 49, 56, 63],
 [8, 16, 24, 32, 40, 48, 56, 64, 72],
 [9, 18, 27, 36, 45, 54, 63, 72, 81]]

全探索の基礎

ABC136B 範囲条件に合致する数値をカウント
n = int(input())
ans = 0
for i in range(1, n+1):
   if 0 < i < 10 or 99 < i < 1000 or 9999 < i < 100000:
       ans += 1
print(ans)

ABC051B 複数の要素x,y,zを組み合わせ、条件sに合致すればカウント+1
k, s = map(int, input().split())
ans = 0
for x in range(k+1):
   for y in range(k+1):
       for z in range(k+1):
           if x+y+z == s:
               ans += 1
print(ans)

ABC051B(計算量を減らした解法)
k, s = map(int, input().split())
ans = 0
for x in range(k+1):
   for y in range(k+1):
       z = s-x-y
       if 0 <= z <= k and x+y+z == s:
           ans += 1
print(ans)
 
ABC130B カウント要素2つをコントロールする事例
N, X = map(int, input().split())
L = list(map(int, input().split()))
distance = 0
cnt = 1
for i in range(N):
   distance += L[i]
   if distance <= X:
       cnt += 1
print(cnt)

itertoolsまとめ

順列(重複を含む、異なる複数の要素の組み合わせ)
import itertools
lst = ['a', 'b', 'c', 'd']
print(list(itertools.permutations(lst, 2)))
[('a', 'b'), ('a', 'c'), ('a', 'd'),
 ('b', 'a'), ('b', 'c'), ('b', 'd'),
 ('c', 'a'), ('c', 'b'), ('c', 'd'),
 ('d', 'a'), ('d', 'b'), ('d', 'c')]

組み合わせ(重複を除く、異なる複数の要素の組み合わせ)
import itertools
lst = ['a', 'b', 'c', 'd']
print(list(itertools.combinations(lst, 2)))
[('a', 'b'), ('a', 'c'), ('a', 'd'),
 ('b', 'c'), ('b', 'd'), ('c', 'd')]

重複順列(1つ(同一内容)のリストからマトリクス状に組み合わせを生成)
import itertools
lst = ['a', 'b', 'c', 'd']
print(list(itertools.product(lst, repeat=2)))
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'),
 ('b', 'a'), ('b', 'b'), ('b', 'c'), ('b', 'd'),
 ('c', 'a'), ('c', 'b'), ('c', 'c'), ('c', 'd'),
 ('d', 'a'), ('d', 'b'), ('d', 'c'), ('d', 'd')]

直積(デカルト積)(2つ(異なる内容)のリストからマトリクス状に組み合わせを生成)
import itertools
lst = ['a', 'b', 'c', 'd']
num = [1, 2, 3, 4]
print(list(itertools.product(lst, num)))
[('a', 1), ('a', 2), ('a', 3), ('a', 4),
 ('b', 1), ('b', 2), ('b', 3), ('b', 4),
 ('c', 1), ('c', 2), ('c', 3), ('c', 4),
 ('d', 1), ('d', 2), ('d', 3), ('d', 4)]

計算事例① 順列の前者後者を全て足したもの ※アンパックしてるから
import itertools
num = [1, 2, 3, 4]
data = list(itertools.permutations(num, 2))
print([sum(x) for x in zip(*data)])
#  [(1, 2), (1, 3), (1, 4), (2, 1), (2, 3), (2, 4),
    (3, 1), (3, 2), (3, 4), (4, 1), (4, 2), (4, 3)]
[30, 30]  

計算事例② 順列をそれぞれ足したもの
import itertools
num = [1, 2, 3, 4]
data = list(itertools.permutations(num, 2))
print([sum(x) for x in (data)])
[3, 4, 5, 3, 5, 6, 4, 5, 7, 5, 6, 7]  

計算事例③ 順列を全部足したもの
import itertools
num = [1, 2, 3, 4]
data = list(itertools.permutations(num, 2))
print(sum([sum(x) for x in (data)]))
#  60

高速化のおまじない

とりあえずPypyで提出すれば何とかなる(かもしれない)。

import sys
input = sys.stdin.readline # コードの最初に追加。2〜10倍も違うらしい。

雑記

A問題はifで場合分けを全て書けば解ける。
B問題はforで解く。「どのような解法があるか」を考えるより「どのようにforを回すか」で考えた方が答えに近づくように思う。
C問題もforありきで「全通り」を調べ上げるのが基本。ただし計算量の制約に応じて記述を工夫しないとTLE。
D問題はこれから。

//end

いいなと思ったら応援しよう!