直積の列挙
itertools.product
を用いることが出来ます。
python
1>>> from itertools import product
2>>> list(product(lst, repeat=2))
3[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
itertools --- 効率的なループ実行のためのイテレータ生成関数 — Python 3.8.2 ドキュメント
和のiterableにする
やり方の候補はいくつかあります。
for
ループを書く
- 内包表記を書く
map
とsum
で書く
どれにしろロジックとしては同じで、各要素ごとの合計のiterableが最終的にできればいいでしょう。
python
1>>> list(map(sum, product(lst, repeat=2)))
2[0, 1, 2, 1, 2, 3, 2, 3, 4]
数える
collections.Counter
とかでやってみます。
python
1>>> Counter(map(sum, product(lst, repeat=2)))
2Counter({2: 3, 1: 2, 3: 2, 0: 1, 4: 1})
collections --- コンテナデータ型 — Python 3.8.2 ドキュメント
割合にする
Counter
の値の総和で割るだけなので楽勝です。
python
1>>> cnt = Counter(map(sum, product(lst, repeat=2)))
2>>> total = sum(cnt.values())
3>>> proportions = {k:v/total for k ,v in cnt.items()}
4>>> proportions
5{0: 0.1111111111111111, 1: 0.2222222222222222, 2: 0.3333333333333333, 3: 0.2222222222222222, 4: 0.1111111111111111}
6
グラフにする
作った割合の辞書のキーの最小値と最大値の区間で棒グラフを描くだけなので、これもまた簡単です。
どんなグラフを意図しているのかよくわからなかったので、とりあえず棒グラフにしました。
python
1>>> sorted_props = sorted(proportions.items())
2>>> x, y = zip(*sorted_props)
3>>> x
4(0, 1, 2, 3, 4)
5>>> y
6(0.1111111111111111, 0.2222222222222222, 0.3333333333333333, 0.2222222222222222, 0.1111111111111111)
7>>> import matplotlib.pyplot as plt
8>>> plt.bar(x, y, align="center")
9<Container object of 5 artists>
10>>> plt.show()
11
matplotlib.pyplot.bar — Matplotlib 3.1.0 documentation
あとは適切な入出力処理のあるプログラムにまとめて細かい挙動や見た目の調整をすれば完成です