Pythonの辞書内包表記でオイラー関数を計算する
Pythonである整数の約数に対するオイラー関数の和がある整数になることを確認しました。
ここで、ある整数以下の数値を、その整数との最小公倍数で分類する辞書を作成し、これに対し、補約数をキーとつつ、値のリストを最大公約数で割るような計算をしました。
# 約数のオイラー関数の和が元の数に戻る
num=18
divisor = {1: [1, 5, 7, 11, 13, 17], 2: [2, 4, 8, 10, 14, 16], 3: [3, 15], 6: [6, 12], 9: [9], 18: [18]}
complement = {}
irreducible = {}
for i in divisor.keys():
irreducible[i] = list(map(lambda x: int(x/i), divisor[i]))
j = int(num/i)
complement[j] = irreducible[i]
print(irreducible)
print(complement)
#{1: [1, 5, 7, 11, 13, 17], 2: [1, 2, 4, 5, 7, 8], 3: [1, 5], 6: [1, 2], 9: [1], 18: [1]}
#{18: [1, 5, 7, 11, 13, 17], 9: [1, 2, 4, 5, 7, 8], 6: [1, 5], 3: [1, 2], 2: [1], 1: [1]}
せっかく作ったのですが、いかにもどんくさい感じです。そこで、辞書内包表記を使い、一気に計算する方法を考えました。
complement={int(num/key):[int(value/key) for value in value_list] for (key,value_list) in divisor.items()}
print(complement)
#{18: [1, 5, 7, 11, 13, 17], 9: [1, 2, 4, 5, 7, 8], 6: [1, 5], 3: [1, 2], 2: [1], 1: [1]}
辞書:divisorの中身をitems()で受け、キーの部分をkey,値の部分をvalue_listに代入します。新しく作成する辞書:complementのキーの部分はint(num/key)と単純に計算できますが、値の部分はさらにリストになっているので、リスト内包表記を使い、リストの用ををkeyの値で割り返したリストに再構築しています。
一気にできるのはとても気持ちが良いのですが、やはり可読性に欠けており、1か月後に見たら作った本人も何のことやらわからなくなってしまいそうです。