やるだけPython競プロ日誌

競プロの解説をPythonでやっていきます。できるだけ初心者に分かりやすいように『やるだけ』とかは言わないようにします。コメントについては必ず読んでいます。どんなに細かいことでもいいのでコメントくださればうれしいです。

Pythonでenumerateを賢く使う。

enumerateって?

英語で『数え上げる』という意味です。この関数の引数にイテレータを与えると、何回そのイテレータを呼び出したかを数える数と、そのイテレータ自身を返します。
例えば

for i, j in enumerate(range(5, 0, -1)):
    print(i, j)
"""
0 5
1 4
2 3
3 2
4 1
"""

rangeの特異な使い方については、こちらをご覧ください
delta114514.hatenablog.jp


となります。 i には 呼び出し回数が、j にはイテレータ(今回は、特にジェネレータです)の値が入っています。

ちなみに、enumerateは引数を二つ取ります。二つ目は、1番初めの番号を決めます。

for i, j in enumerate(range(5, 0, -1), start=5):
    print(i, j)
"""
5 5
6 4
7 3
8 2
9 1
"""

これを使うと、AtCoderのこのC問題なら2行で解くことができます。
C - 背の順

問題文

高橋学級には N 人の生徒がいます。 生徒は 1 から N まで出席番号が振られています。 i 番目の生徒の身長は a_i です。 a_i はすべて相異なります。
高橋先生は N 人の生徒を背の高い方から順に並べました。 N 人の生徒の出席番号を背の高い方から順に出力してください。

制約

2≦N≦10^5
ai は整数である。
1≦a_i≦10^9
a_i はすべて相異なる。

部分点

30 点分のテストケースでは、N≦1000 を満たす。

入力

入力は以下の形式で標準入力から与えられる。

N
a_1 a_2 … a_N

出力

N 行出力せよ。 i 行目には、i 番目に背の高い生徒の出席番号を出力せよ。

はい。
愚直にやると

n = int(input())
individuals = list(map(int, input().split()))
for i in range(n):
    tallest = max(individuals)
    number = individuals.index(tallest)  # tallestを直に入れても良いです
    print(number + 1)
    individuals[number] = 0

背の高い人を毎回割り出して、その番号を返し、身長をブラックホール圧縮することでカウントしないようにしています。


ですが、こちら、TLEしてしまいました。


悲しいなぁ…

ですが、このenumerateを使う方法ならTLEせずに解けます。

n=int(input())
for i in sorted(enumerate(list(map(int, input().split())), start=1), key = lambda x :x[1], reverse = True):
    print(i[0])

lambdaについては 
delta114514.hatenablog.jp
をご覧ください
わかりやすくすると

def getsecond(n):  # lambdaの明示化
    return n[1]
 
n = int(input())
individuals = list(map(int, input().split()))  # 入力
enumerated_individuals = list(enumerate(individuals, start=1))  # enumerateされたlistを作る
enumerated_individuals.sort(key=getsecond, reverse=True)  # 身長でsortする
for i in enumerated_individuals:
    print(i[0])

です。つまり、身長と、入力された順番で対応したlistを作り、身長でsort(番号はくっついたまま)することにより、上から取り出すことで、番号のみを取り出すことができます。

各実行ごとでは

def getsecond(n):  # lambdaの明示化
    return n[1]
 
n = int(input())
individuals = list(map(int, input().split()))  # 入力
# individuals == [[160, 120, 150, 170]]

enumerated_individuals = list(enumerate(individuals, start=1))  # enumerateされたlistを作る
#enumerated_individuals == [(1, 160), (2, 120), (3, 150), (4, 170)]

enumerated_individuals.sort(key=getsecond, reverse=True)  # 身長でsortする
#enumerated_individuals == [(4, 170), (1, 160), (3, 150), (2, 120)]

for i in enumerated_individuals:
    print(i[0])

となります。

いいでしょ~、enumerate!!

それではみなさん、よいPythonLifeを!

宣伝…