競プロ用チートシートのPython版です。一般的な競技プログラミングで不要と思われる内容は割愛されています。例えば、クラスの詳細、モジュール、ファイル関係など。
テンプレート
テンプレート
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# ・スニペット登録して呼び出す方が合理的かもしれません。要検討。 # ・1行目のimportは該当する機能を使わない場合は削除してください。 #import bisect,collections,copy,heapq,itertools,math,numpy,string from sys import stdin # 1行の整数 N = int(stdin.readline()) # 整数 X, Y, Z = map(int, stdin.readline().split()) # 複数の整数 A = list(map(int, stdin.readline().split())) # リスト A = [int(t) - 1 for t in stdin.readline().split()] # 0始まりにリスト # 複数行の整数 A = [int(stdin.readline()) for i in range(N)] # 整数 V = [list(map(int, stdin.readline().split())) for _ in range(N)] # 複数/複数行の整数を2次元リスト # 1行の文字列 S = stdin.readline().rstrip() # 文字列 A = list(stdin.readline().rstrip()) # 文字にバラしてリスト A = stdin.readline().rstrip().split() # 空白区切りでリストに A = stdin.readline().rstrip().split(',') # カンマ区切りでリストに # 複数行の文字列 A = [stdin.readline().rstrip() for _ in range(N)] # 全体をリストに A = [list(stdin.readline().rstrip()) for _ in range(N)] # 1文字ずつバラして2次元リストに # 文字列が複数書かれた複数行(全体を2次元リストに) A = [list(stdin.readline().rstrip().split()) for _ in range(N)] ans = 0 print(ans) |
文法
コメント・インデント
1 2 3 4 5 6 7 8 9 10 |
''' 複数行を まとめてコメント ''' # 1行コメント if True: # インデントはPEP8(*)に従い、半角スペース4つ print('Hello world') |
数値演算
1 2 3 4 |
print( 17 // 3 ) # 切り下げ除算は小数点以下を切り捨てる print( 17 % 3 ) # 剰余 print( 2 ** 6 ) # 2の6乗 print( round(3.1415926535, 2) ) # 小数点以下を2桁で丸める |
スライス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# スライスとは、[最初のインデックス:最後のインデックス] (ただし、0始まり) V = ['a','b','c','d','e','f','g'] print(V[1:4]) # 1番目から(4-1)番目まで print(V[:4]) # 先頭から(4-1)番目まで print(V[3:]) # 3番目から最後まで print(V[-1:]) # 最後のデータ print(V[-2:]) # 最後の2文字 print(V[:-1]) # 最後の1つ前まで print(V[1::2]) # 1番目から最後まで2つ飛ばし print(V[::-1]) # 反転 S = 'abcdefg' print(S[1:4]) # 文字列も扱える |
range()
1 2 3 4 5 6 7 8 9 10 |
# range(start, stop, step)関数はrange型のオブジェクトを返す r = range(5) print(r) print(type(r)) # リストで表示 print(list( r )) # [0, 1, 2, 3, 4] print(list( range(2,5) )) # [2, 3, 4 print(list( range(4,1,-1) )) # [4, 3, 2] (逆順) print(list( range(4,10,2) )) # [4, 6, 8] (2つ飛ばし) |
for文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# for ループ変数 in 反復可能オブジェクト: # ブロック # 注意: C言語はブロック内でループ変数の値を変更してループ制御することもできるが、 # Pythonはそのようなことはできない。 # 3回繰り返す for _ in range(3): # ループ変数を参照しないなら_を使う print('A') # 5回繰り返す for i in range(5): print(i, end=',' if i < 4 else '\n') # 最後だけ改行する方法 # リストの要素で繰り返す for i in [2, 5, 7]: print(i, end=',' if i != 7 else '\n') # 文字列の各文字で繰り返す for ch in 'Hello Python': print(ch, end=',') print() # for文のelseは、ループの最後(breakしなかった場合)に実行される #for c in ['A', 'B', 'C', 'D']: # 'C'が見つかる for c in ['A', 'B', 'X', 'D']: if c == 'C': print('Cが見つかりました。') break else: print('Cは見つかりませんでした。') |
while文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# while 条件式: # ブロック # 3回繰り返す i = 0 while i < 3: print(i) i += 1 i = 0 while True: # 無限ループ if i == 3: break # 条件でループを抜ける print(i) i += 1 else: # while文のelseは、ループの最後(breakしなかった場合)に実行される print('ループ終了') |
整数の入力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# input()は遅いので基本的に使わない from sys import stdin # 整数が1つ書かれた行 A = int(stdin.readline()) print(A) # 整数が複数書かれた1行 x,y,z = map(int, stdin.readline().split()) # 各変数へ print(x, y, z) xyz = list(map(int, stdin.readline().split())) # リストへ print(xyz) xyz = [int(t) - 1 for t in stdin.readline().split()] # 0始まりに変換してリストへ print(xyz) # 整数が1つ書かれたN行(リストへ) N = 3 B = [int(stdin.readline()) for i in range(N)] print(B) # 整数が複数書かれたN行(1行ずつ処理) N = 3 for _ in range(N): x, y, z = map(int, stdin.readline().split()) # 整数が複数書かれたN行(2次元リストに格納) N = 3 V = [list(map(int, stdin.readline().split())) for _ in range(N)] print(V) # データが何行あるかわからない場合 while True: try: A = int(stdin.readline()) except: break |
文字列の入力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# inputは遅いので基本的に使わない from sys import stdin # 文字列が1つ書かれた行 S = stdin.readline().rstrip() # 1つの文字列 print('"'+S+'"') V = list(stdin.readline().rstrip()) # 1文字ずつバラしてリストに print(V) # 文字列が複数書かれた1行 A = stdin.readline().rstrip().split() # 空白区切りでリストに print(A) B = stdin.readline().rstrip().split(',') # カンマ区切りでリストに print(B) # 文字列が1つ書かれたN行(1行ずつ逐次処理) N = 3 for _ in range(N): S = stdin.readline().rstrip() print('"'+S+'"') # 文字列が1つ書かれたN行(全体をリストに) S1 = [stdin.readline().rstrip() for _ in range(N)] print(S1) # 文字列が1つ書かれたN行(1文字ずつバラして全体を2次元リストに) S2 = [list(stdin.readline().rstrip()) for _ in range(N)] print(S2) # 文字列が複数書かれた複数行(全体を2次元リストに) S3 = [list(stdin.readline().rstrip().split()) for _ in range(N)] print(S3) |
出力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# 文字列 S = 'hoge' T = "hage" print(S) print(S,end='') # 改行しない print() # 改行のみ print(S+T) # 文字列を繋げる print(S, T) # 1つずつスペースを空けて print(S, T, sep='') # スペースを空けない print(S, T, sep=',') # カンマで区切る # 複数行の出力(「"""」で囲む) print(""" line1 line2 line3 """) # 改行せずに複数行の出力(「"""」で囲む) print("""\ line1\ line2 line3\ """) # 数値 A=1 B=2 print(A/B) print(str(A/B)+'くらいかな') # 文字列に変換してから繋げる # %を使った古い書式の書き方 print("%f" % (A/B)) # 浮動小数点(小数点以下6桁) print("%.1f" % (A/B)) # 浮動小数点(小数点以下1桁) # format()を使った新しい書式の書き方 n = 123 f = 2.54 s = 'hoge' print('{:.3f}'.format(f)) # 書式指定 print('{0} {1} {2}'.format(n, f, s)) # 複数の引数(数字は引数の番号) print('{0} {2} {1}'.format(n, f, s)) # 順番を入れ替える print('{0:5d} {1:5f} {2}'.format(n, f, s)) # 書式指定 print('{0:5} {1:5} {2:5}'.format(n, f, s)) # 桁揃え(右寄せ) print('{:#x}'.format(255)) # 16進数 # 幅寄せ print("python".ljust(15,'-')) # 左詰め python--------- print("python".center(15,'-'))# 中央寄せ -----python---- print("python".rjust(15,'-')) # 右詰め ---------python # 先頭ゼロ埋め print(str(29).rjust(10,'0')) #10桁ゼロ埋め 0000000029 |
データ型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# 明示的な型宣言 num: int = 1 name: str = 'Tanaka' li: list = [1, 2, 3] print(num, name, li) # 型変換 num = 2.3 print(num, type(num)) i = int(num) # 整数へ print(i, type(i)) s = str(num) # 文字列へ print(s, type(s)) # 文字を数値に変換 s = '12.3' f = float(s) print(f, type(f)) s = '12' i = int(s) print(i, type(i)) s = '12.3' try: i = int(s) print(i, type(i)) except: print('少数点付き数値文字列の、intへの変換は失敗しました') # 数値を文字に変換 i = 97 s = str(i) print(s, type(s)) # 文字をユニコード数値に変換 s = 'a' i = ord(s) print('{:#x}'.format(i), type(i)) # ユニコードを文字に変換 i = 97 c = chr(i) print(c, type(c)) i = 0x1F600 c = chr(i) print(c, type(c)) |
2/8/16進数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# 2/8/16進表記 bin_num = 0b10 # 2進数 oct_num = 0o10 # 8進数 hex_num = 0x10 # 16進数 # 型はintとして扱われる print(bin_num, type(bin_num)) # 2 <class 'int'> print(oct_num, type(oct_num)) # 8 <class 'int'> print(hex_num, type(hex_num)) # 16 <class 'int'> # 大文字でも同じ Bin_num = 0B10 # 2進数 Oct_num = 0O10 # 8進数 Hex_num = 0X10 # 16進数 # Python3.6以降、アンダースコアが使えるようになった(見やすさ向上のため) print(0b_1000_0000) # 128 # 数値を2/8/16進表記の文字列に変換 print( bin(16) ) print( oct(16) ) print( hex(16) ) print( str(16) ) # 10進数は普通にstr() # 2/8/16進表記の文字列を数値に変換 print( int('10', 2) ) print( int('10', 8) ) print( int('10', 16) ) print( int('10') ) # 10進数は普通にint() |
リスト
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
l = [1, 2, 3, 4, 5] print(l) # リストの要素の取得 print(l[0]) print(l[-1]) # スライス print(l[:3]) print(l[:]) # 全要素 # リストの結合 l2 = [6, 7, 8, 9, 10] print(l + l2) # リストの要素の変更 l[2] = 300 print(l) |
タプル
タプルは “変更できないリスト”(リストはmutable、タプルはimmutable)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# タプルの宣言 t1 = (1, 2, 3, 4, 5) print(t1) t2 = 1, 2, 3 # カッコなしでもタプルとして認識される print(t2) t3 = 1, # 要素が1つのタプルと認識 print(t3) # タプルの結合 print(t1 + t2) # タプルの要素の取得 t = (1, 2, 3, 4, 5) print(t[0]) print(t[-1]) print(t[:3]) # スライス print(t[:]) # スライスで全要素 # タプルの要素の変更 try: t[2] = 300 print(t) except: print("タプルの要素は変更できません") # タプルにリストを格納し、そのリストの値は変更可能 t = ([1, 2, 3], [4, 5, 6]) t[0][0] = 100 print(t) # リストに変換 l = list(t) print(l) # タプルを変数に代入 t = (1, 2, 3) x, y, z = t print(x, y, z) # タプルを使って変数の値を交換 X = 100 Y = 200 print(X, Y) X, Y = Y, X print(X, Y) |
辞書型(dict型)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# 辞書型の宣言① d = {'x': 10, 'y': 20, 'z': 30} print(d) # 辞書型(ディクショナリ型)の宣言② d2 = dict(a=100, b=200, c=300) print(d2) # キーから値を取得 print(d['y']) # キーと値を追加 d['a'] = 40 print(d) # キーの削除 del d['a'] print(d) # キーリストの取得 print( d.keys() ) print( list(d.keys()) ) # 辞書型の(値の更新または追加) print(d) d3 = {'x': 100, 'a': 200, 'b': 300} d.update(d3) print(d) # 特定のキーの値を取得 print( d.get('x') ) # 特定のキーの値を取得し、同時に削除 print( d.pop('a') ) print( d.pop('b') ) print(d) # キーの有無 print( 'x' in d ) |
集合(set型・frozenset型)
集合は要素の重複を許さず、要素の順番を保持しない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# set型 s = {'note', 'notebook', 'pen'} print(s, type(s)) # 重複要素は排除される s = {'note', 'notebook', 'pen', 'pen', 'note'} print(s) # 要素の追加 s.add('book') print(s) # 要素の削除 s.remove('pen') print(s) # 要素を取り出して、同時に削除(順序がない為、取り出される要素は不定) print(s.pop()) print(s) # 集合の操作 a = {'note', 'notebook', 'pen'} b = {'note', 'book', 'file'} # 和集合 print('和集合', a | b ) print('和集合', a.union(b) ) # 差集合 print('差集合', a - b ) print('差集合', a.difference(b)) # 積集合 print('積集合', a & b ) print('積集合', a.intersection(b)) # 対称差(XOR) print('対称差', a ^ b ) print('対称差', a.symmetric_difference(b)) # 部分集合か判定 print( {'note', 'pen'} <= a ) print( {'note', 'pen'}.issubset(a) ) # frozenset型 fs = frozenset(['note', 'notebook', 'pen']) print(fs, type(fs)) # frozenset型は変更できない try: fs.add('book') print(fs) except: print('追加できませんでした。') |
内包表記
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# for文を使ったリストの作成 numbers1 = [] for i in range(10): numbers1.append(str(i)) print(numbers1) # 内包表記を使ったリストの作成 numbers2 = [str(v) for v in range(10)] print(numbers2) # for文を使ったネストしたリストの作成 tuples1 = [] for x in [1, 2, 3]: for y in [4, 5, 6]: tuples1.append((x, y)) print(tuples1) # リスト内包表記を使ったネストしたリストの作成 tuples2 = [(x, y) for x in [1, 2, 3] for y in [4, 5, 6]] print(tuples2) # for文とif文を使ったリストの作成 even1 = [] for i in range(10): if i % 2 == 0: even1.append(i) print(even1) # for文とif文を使った内包表記 even2 = [x for x in range(10) if x % 2 == 0] print(even2) |
関数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
print('-- Part 1 -') ############################## # 関数の定義(引数なし) def say_hello(): print('Hello') say_hello() # Hello # 関数の定義(引数あり) def say_something(str): print(str) say_something('Good morning') # Good morning # 関数の定義(引数あり、デフォルト引数指定あり) def say_something2(str='Hi!'): print(str) say_something2() # Hi! say_something2('Hello') # Hello # 関数の定義(戻り値あり) def increment(num): return num + 1 print( increment(1) ) # 2 # 関数に型情報を付ける # def 関数名(arg1: arg1の型, arg2: arg2の型, ...) -> 戻り値の型: # 関数で実行したい処理 # return 戻り値 def say_something(name: str, age: int) -> str: print(name) print(age) return name print( say_something('Tom', 29) ) # 引数の順番で関数を呼び出す def add(num1, num2): return num1 + num2 print( add(2, 4) ) # 6 # 引数の名前を指定して呼び出す(順番は関係ない) def greeting(name, str): print(name + ', ' + str + '!') greeting(str='Hello', name='Tom') # Tom, Hello! # デフォルト引数(デフォルト値のある仮引数は、デフォルト値のない仮引数よりも後に記述する) def greeting(name, str='Hi'): print(name + ', ' + str + '!') greeting('Tom') # Tom, Hi! print('-- Part 2 -') ############################## # 可変長の位置引数(指定位置は、位置引数の最後で、デフォルト値のある引数よりも前) def say_something(name, *args): for str in args: print("I'm " + name + ". " + str + "!") say_something('Tom', 'Hello', 'Hi', 'Good morning') # 仮引数に割当てられなかったキーワード引数を辞書型で受け取る(指定位置は、一番最後) def print_birthday(family_name, **kwargs): print("Birthday of " + family_name + " family") for key, value in kwargs.items(): print(f'{key}: {value}') print_birthday('Smith', Nancy='1990/1/1', Tom='1993/1/1', Julia='2010/1/1') # 可変長の位置引数とキーワード引数(どのような引数の呼び出しにも対応可能) def say_something(*args, **kwargs): for s in args: print(s) for key, value in kwargs.items(): print(f'{key}: {value}') say_something('Hello', 'Hi', 'Bye', Nancy='29 years old', Tom='26 years old') print('-- Part 3 -') ############################## # リストに格納された値を引数に渡す def greeting(x, y, z): print(x) print(y) print(z) contents = ['Hello', 'Good morning', 'Bye'] # 関数呼び出し時に「*」演算子でリストから引数を展開する greeting(*contents) # 辞書に格納された値を引数に渡す def say_something(name, greeting): print(name) print(greeting) dict = {'greeting': 'Hello'} # 関数呼び出し時に「**」演算子で辞書から引数を展開する say_something('Julia', **dict) |
lambda式
lambda式を使うと、1行で無名関数を作成できる。
1 2 3 4 5 6 7 8 9 10 11 |
# lambda式の構文 # lambda 引数1, 引数2, 引数3, ...: 戻り値になる式 increment = lambda num1, num2: num1 + num2 print( increment(1, 2) ) # 3 # filter()関数に使う例 # 第1引数には関数、第2引数にはリストなどを指定 nums = ['one', 'two', 'three'] filterd = filter(lambda x: len(x) == 3, nums) print( list(filterd) ) # ['one', 'two'] |
クラスの基本
1 2 3 4 5 6 7 8 9 10 |
class Person(object): def __init__(self): # コンストラクタ print('Initialized.') def say_something(self): print('Hello!!!') # クラスをインスタンス化 person = Person() # Initialized. # インスタンスメソッドの呼び出し person.say_something() # Hello!!! |
string
宣言と参照(工事中)
編集(工事中)
操作(工事中)
正規表現
1 2 3 4 |
import re s='hoge6hoge21foo:bar' print( re.findall(r'[a-z]+',s) ) #['hoge', 'hoge', 'foo', 'bar'] print( re.findall(r'[a-z0-9]+',s) ) # ['hoge6hoge21foo', 'bar'] |
リスト
基本(工事中)
リストの操作
1 2 3 4 5 6 7 8 9 10 11 12 13 |
a = [3, 2, 5, 1, 4] b = [2, 1, 4, 5, 3] # list.sort()は自分自身を並べ替える a.sort() print(a) # [1, 2, 3, 4, 5] # sorted()は新しいリストを返す print( sorted(b) ) # [1, 2, 3, 4, 5] print(b) # [2, 1, 4, 5, 3] # reverse=Trueを指定すると逆順になる print( sorted(b, reverse=True) ) # [5, 4, 3, 2, 1] |
比較関数を使ったソート
1 2 3 4 5 6 7 8 9 10 11 12 |
from functools import cmp_to_key def cmptuple(a, b): if a[1] > b[1]: return 1 elif a[1] < b[1]: return -1 else: return 0 xs = [(4, 90), (-9, 12), (42, 12), (100, 12), (1, 1), (-123, 1)] print(sorted(xs, key=cmp_to_key(cmptuple))) # 2番目の要素でソート |
bisect(工事中)
C++ の upper_bouns()、lower_bound() みたいなことができます。
データ構造
pair(工事中)
stack と queue(工事中)
アルゴリズム
UnionFind(DSU)
ACLのUnionFindをPythonで書いた例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
class dsu: def __init__(self, n): self._n = n self.parent_or_size = [-1] * n def merge(self, a, b): assert 0 <= a < self._n assert 0 <= b < self._n x, y = self.leader(a), self.leader(b) if x == y: return x if -self.parent_or_size[x] < -self.parent_or_size[y]: x, y = y, x self.parent_or_size[x] += self.parent_or_size[y] self.parent_or_size[y] = x return x def same(self, a, b): assert 0 <= a < self._n assert 0 <= b < self._n return self.leader(a) == self.leader(b) def leader(self, a): assert 0 <= a < self._n if self.parent_or_size[a] < 0: return a self.parent_or_size[a] = self.leader(self.parent_or_size[a]) return self.parent_or_size[a] def size(self, a): assert 0 <= a < self._n return -self.parent_or_size[self.leader(a)] def groups(self): leader_buf = [self.leader(i) for i in range(self._n)] result = [[] for _ in range(self._n)] for i in range(self._n): result[leader_buf[i]].append(i) return [r for r in result if r != []] |
例題
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
(ここにdsuのライブラリを書く) N = 5 # 頂点の数 M = 3 # 辺の数 E = [[1, 2], [1, 3], [4, 5]] # 辺のリスト d = dsu(N) # 頂点数NのUnionFindを作成 for a, b in E: # 辺のリストを順に追加(0始まりに変換) d.merge(a-1, b-1) print(d.groups()) # 連結成分のリスト print(len(d.groups())) # 連結成分の数 for g in d.groups(): print("Leader", d.leader(g[0]), ": ") # この連結成分のリーダー for v in g: print(v) # この連結成分の頂点 print(d.size(0)) # 頂点0が含まれる連結成分のサイズ print(d.leader(0)) # 頂点0が含まれる連結成分のリーダー print(d.same(0, 1)) # 頂点0と頂点1が同じ連結成分に含まれるか |
bit全探索(工事中)
DFS(深さ優先探索) (工事中)
BFS(幅優先探索) (工事中)
ダイクストラ法(工事中)
DP(動的計画法)(工事中)
その他の関数
CPU時間の計測(工事中)
進数変換(工事中)
素数(工事中)
約数列挙(工事中)
最大公約数、最小公倍数(工事中)
素因数分解と、互いに素の個数(オイラーのφ関数)(工事中)
「aとbが互いに素」とは、「aとbの最大公約数が1」ということ。
等差級数(工事中)
組合せの数(工事中)
組合せで実行(工事中)
順列(工事中)
フィボナッチ数列とメモ化(工事中)
コメント