この記事は何?
AtCoderでよく使いそうな関数たちをまとめた記事です。
記事を作成した背景
AtCoder挑戦時に毎回検索して時間を使っているなぁ。。。
-> 関数をまとめて記事にしておいたら自分に必要な関数だけ参照できるのでは?
-> 関数まとめた記事を書いて、辞書みたいに使おう!
入力を受け取りたい
AtCoderの入力パターンは下記かな、という認識です。
- 入力値が1つだけある
-
10
など
-
- 入力値がスペース区切りで複数ある
-
1 2 3
など
-
1. 入力値が1つだけある
例:文字列として入力を取得
x = input()
print(x)
# -> test
例:数値として入力を取得
# intで型変換をする
x = int(input())
print(x)
# -> 10
2. 入力値がスペース区切りで複数ある
例:文字列として入力を取得
x = input().split()
print(x)
# -> [test, split]
例:数値として入力を取得
# intで型変換をする
x = list(map(int, input().split()))
print(x)
# -> [1, 2, 3]
複数データを操作したい
AtCoderではほとんどの場合、複数の入力が与えられます。
ここでは複数の入力を受け取ってゴニョゴニョ処理したい時に利用する関数を記載します。
List
複数情報を保持する際に、最も利用するデータ型です。
以下の特徴があります。(主観)
- 各要素に1つのデータを保持できる
- 要素の追加/変更が可能
- 保持しているデータから、特定値を探す場合には向かない
- ループの回数を削る工夫をしないとTLEが乱発するイメージあります
1. 最初/最後の要素を取得したい
取得した値を残したいかどうかで利用する関数が変わります。
元データはそのままにして取得
インデックスを指定して実現できます。
test = [1,2,3,4,5]
print("list", test, "value", test[0])
# -> list [1, 2, 3, 4, 5] value 1
print("list", test, "value", test[4])
# -> list [1, 2, 3, 4, 5] value 5
# 最後の要素は-1でも取得可能
print("list", test, "value", test[-1])
# -> list [1, 2, 3, 4, 5] value 5
取得した要素を元データから消す
pop
関数を利用して実現できます。
test = [1,2,3,4,5]
# 最初の要素を取得するときはインデックスで指定する必要がある
print("list", test, "value", test.pop(0))
# -> list [2, 3, 4, 5] value 1
# 引数なしだと、デフォルトで最後の要素が対象となる
print("list", test, "value", test.pop())
# -> list [2, 3, 4] value 5
Dictionary
Key,Valueで保持できるデータ型です。
以下の特徴があります。(主観)
- 各要素にKey,Valueの2つのデータを保持できる
- 要素の追加/変更が可能
- 特定の値(Key)を探索するのがめちゃくちゃ早い
1. 値を追加したい
dict[key] = value
のようにして値を追加できます。
dict = {'a': 3, 'c':1, 'b': 2}
print(dict)
# -> {'a': 3, 'c': 1, 'b': 2}
dict['d'] = 4
print(dict)
# -> {'a': 3, 'c': 1, 'b': 2, 'd': 4}
2. ソートしたい
dictionary
をソートするには、items()
を利用して型変換を行う必要があるので注意して下さい。
Keyを基準にする
dict = {'a': 3, 'c':1, 'b': 2}
# items()で[(),()]の形式にデータを変換する
dict_items = dict.items()
# キーでの昇順ソート
print(sorted(dict_items))
# -> [('a', 3), ('b', 2), ('c', 1)]
# キーでの降順ソート
print(sorted(dict_items, reverse=True))
# -> [('c', 1), ('b', 2), ('a', 3)]
Valueを基準にする
dict = {'a': 3, 'c':1, 'b': 2}
# items()で[(),()]の形式にデータを変換する
dict_items = dict.items()
print(dict_items)
# -> dict_items([('a', 3), ('c', 1), ('b', 2)])
# items()でdictionaryがtupleになっているので、キーとして明示的にインデックス1を指定する
# 値での昇順ソート
print(sorted(dict_items, key=lambda x:x[1]))
# -> [('c', 1), ('b', 2), ('a', 3)]
# 値での降順ソート
print(sorted(dict_items, key=lambda x:x[1], reverse=True))
# -> [('a', 3), ('b', 2), ('c', 1)]
ループ
各種ループ方法についてまとめます。
特定の範囲でループしたい
特定の範囲を決めるときにはrange
関数を使うことが多いです。
例:range(1,5)
-> 1以上5未満の値を順に戻してくれる
test = [1,2,3,4,5]
for i in range(1,4):
print("index", i, "value", test[i])
# 出力結果
# index 1 value 2
# index 2 value 3
# index 3 value 4
要素を全てループしたい
ループしたいリストなどをin
の後に配置すれば、ループ内で最初から順にアクセスできます。
test = [1,2,3,4,5]
for t in test:
print("value", t)
# 出力結果
# value 1
# value 2
# value 3
# value 4
# value 5
要素全てをループしつつ、ループしているインデックスの要素も取得したい
Listではインデックスを取得してのループはできないので、enumerate
オブジェクトに変換してループします。
全リストのループでインデックスも欲しいとき、range
を使って配列にインデックスアクセスしなくても良いので便利
test = [1,2,3,4,5]
# enumerate関数を利用することで、インデックスと一緒に値が取得できる
for i, t in enumerate(test):
print("index", i, "value", t)
# 出力結果
# index 0 value 1
# index 1 value 2
# index 2 value 3
# index 3 value 4
# index 4 value 5
特定の条件を満たすまでループしたい
while
を使ってループしましょう
test = [1,2,3,4,5]
i = 0
# iが3未満の場合はループ
while i < 3:
print("index", i, "value", test[i])
i += 1
# 出力結果
# index 0 value 1
# index 1 value 2
# index 2 value 3
特定の条件だけ処理を行いたくない
continue
を使ってスキップしましょう
test = [1,2,3,4,5]
i = 0
for t in test:
# 偶数の場合は処理をスキップ
if t % 2 == 0:
continue
print("value", t)
# 出力結果
# value 1
# value 3
# value 5
値変換
色々な値変換をまとめます。
基数変換
AtCoderは基数変換が求められる問題が多いです!(競プロ典型問題にも登録されています)
-> 067 - Base 8 to 9
ありがたいことにPythonには基数変換メソッドがあります
# 10進数の10が。。。
x = 10
# 2進数
print(bin(x))
# -> 0b1010
# 8進数
print(oct(x))
# -> 0o12
# 16進数
print(hex(x))
# -> 0xa
# 基数変換後にはPrefixがつくので、値だけ欲しい場合はスライスする必要があります
print(bin(x)[2::]) # "0b"が消える
# -> 1010
print(oct(x)[2::]) # "0o"が消える
# -> 12
print(hex(x)[2::]) # "0x"が消える
# -> a
IF分岐を減らす
IF分岐が多いほどバグが混入しやすいので、なるべくIF分岐は減らしたほうが良いです。
(分岐の不等号を間違えたりしてバグが発生したりします。。。)
計算した値が小さい場合に更新する
test = [3,2,4,5,1]
# ifを使った条件分岐
result = 2 ** 30 # 十分に大きい値を最大値とする
for i in test:
if i < result: # 不等号間違えるかも。。。
result = i
print(result)
# -> 1
# minを使った条件分岐
result = 2 ** 30 # 十分に大きい値を最大値とする
for i in test:
result = min(i, result)
print(result)
# -> 1
計算した値が大きい場合に更新する
test = [3,2,4,5,1]
# ifを使った条件分岐
result = 0
for i in test:
if result < i: # 不等号間違えるかも。。。
result = i
print(result)
# -> 5
# maxを使った条件分岐
result = 0
for i in test:
result = max(i, result)
print(result)
# -> 5