AtCoderでよく使いそうな関数メモ

# この記事は何？
AtCoderでよく使いそうな関数たちをまとめた記事です。

# 記事を作成した背景
AtCoder挑戦時に毎回検索して時間を使っているなぁ。。。
-> 関数をまとめて記事にしておいたら自分に必要な関数だけ参照できるのでは？
-> 関数まとめた記事を書いて、辞書みたいに使おう！

# 入力を受け取りたい
AtCoderの入力パターンは下記かな、という認識です。
1. 入力値が1つだけある
    - `10`など
1. 入力値がスペース区切りで複数ある
    - `1 2 3`など

## 1. 入力値が1つだけある
### 例：文字列として入力を取得
```python: 入力に「test」が与えられる
x = input()
print(x)
# -> test
```
### 例：数値として入力を取得
```python: 入力に「10」が与えられる
# intで型変換をする
x = int(input())
print(x)
# -> 10
```

## 2. 入力値がスペース区切りで複数ある
### 例：文字列として入力を取得
```python: 入力に「test case」が与えられる
x = input().split()
print(x)
# -> [test, split]
```
### 例：数値として入力を取得
```python: 入力に「1 2 3」が与えられる
# intで型変換をする
x = list(map(int, input().split()))
print(x)
# -> [1, 2, 3]
```
# 複数データを操作したい
AtCoderではほとんどの場合、複数の入力が与えられます。
- 例：[AtCoder ABC124 B - Great Ocean View](https://atcoder.jp/contests/abc124/tasks/abc124_b)
![B_-_Great_Ocean_View.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146452/03087fb0-d967-c157-ba46-940a3107fcac.png)

ここでは複数の入力を受け取ってゴニョゴニョ処理したい時に利用する関数を記載します。
## List
複数情報を保持する際に、最も利用するデータ型です。
以下の特徴があります。（主観）
- 各要素に1つのデータを保持できる
- 要素の追加/変更が可能
- 保持しているデータから、特定値を探す場合には向かない
    - ループの回数を削る工夫をしないとTLEが乱発するイメージあります

### 1. 最初/最後の要素を取得したい
取得した値を残したいかどうかで利用する関数が変わります。
#### 元データはそのままにして取得
インデックスを指定して実現できます。
```python: 最初/最後の値を取得する
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`関数を利用して実現できます。
```python: 最初/最後の値を取得して削除する
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
```
- [5.1. リスト型についてもう少し](https://docs.python.org/ja/3/tutorial/datastructures.html?highlight=pop#more-on-lists)

## Dictionary
Key,Valueで保持できるデータ型です。
以下の特徴があります。（主観)
- 各要素にKey,Valueの2つのデータを保持できる
- 要素の追加/変更が可能
- 特定の値（Key）を探索するのがめちゃくちゃ早い

### 1. 値を追加したい
`dict[key] = value`のようにして値を追加できます。
```python
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を基準にする
```python
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を基準にする
```python
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)]
```

<!--
## Set
-->

# ループ
各種ループ方法についてまとめます。

## 特定の範囲でループしたい
特定の範囲を決めるときには`range`関数を使うことが多いです。
例：`range(1,5)`
　　-> **1以上5未満**の値を**順に**戻してくれる
```python: 1~3のインデックス範囲でループ
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
```
- [組み込み型 range](https://docs.python.org/ja/3/library/stdtypes.html#ranges)

## 要素を全てループしたい
ループしたいリストなどを`in`の後に配置すれば、ループ内で最初から順にアクセスできます。
```python: testに格納された要素全ての値を取得
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`を使って配列にインデックスアクセスしなくても良いので便利 :smiley: 
```python: testに格納された要素全ての値とインデックスを取得
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
```
- [組み込み関数 enumerate](https://docs.python.org/ja/3/library/functions.html#enumerate)
## 特定の条件を満たすまでループしたい
`while`を使ってループしましょう :muscle: 
```python: 条件を満たす限りループ 
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`を使ってスキップしましょう :mans_shoe: 
```python: 偶数の数字は出力しない
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](https://atcoder.jp/contests/typical90/tasks/typical90_bo)

ありがたいことにPythonには基数変換メソッドがあります :snake: 
```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分岐は減らしたほうが良いです。
（分岐の不等号を間違えたりしてバグが発生したりします。。。）

## 計算した値が小さい場合に更新する
```python: リストの中で最小値を表示する
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
```

## 計算した値が大きい場合に更新する
```python: リストの中で最大値を表示する
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
```