ドント方式

政党0,1,2,3がそれぞれ1000,650,200,150票を得た。10人当選させるには,各政党から何人ずつ選べばよいか。

import numpy as np

r = 10  # 当選数
n = a = np.array([1000, 650, 200, 150]) # 得票数
for i in range(2, r + 1):
    a = np.append(a, n / i)

a
array([1000.        ,  650.        ,  200.        ,  150.        ,
        500.        ,  325.        ,  100.        ,   75.        ,
        333.33333333,  216.66666667,   66.66666667,   50.        ,
        250.        ,  162.5       ,   50.        ,   37.5       ,
        200.        ,  130.        ,   40.        ,   30.        ,
        166.66666667,  108.33333333,   33.33333333,   25.        ,
        142.85714286,   92.85714286,   28.57142857,   21.42857143,
        125.        ,   81.25      ,   25.        ,   18.75      ,
        111.11111111,   72.22222222,   22.22222222,   16.66666667,
        100.        ,   65.        ,   20.        ,   15.        ])

この上位 r 人を選べばよい。

o = np.argsort(-a)
np.bincount((o % 4)[:r])
array([6, 3, 1])

この場合,最後の 0 は出力されない。なお,タイがない(a[o][r-1]a[o][r] が等しくない)ことも確認しなければならない。

別解:

r = 10  # 当選数
n = np.array([1000, 650, 200, 150]) # 得票数
h = np.zeros_like(n)  # 配分(最初はすべて0)
for _ in range(r):
    a = n / (h + 1)
    h[np.argmax(a)] += 1

h
array([6, 3, 1, 0])

この場合,タイを検出するには,最後の np.argmax(a) が一意であることを示せばよい。例えば:

if np.argmax(a) != len(a) - 1 - np.argmax(a[::-1]):
    print("タイです")

あるいは

i, = (a == a.max()).nonzero()
if len(i) > 1:
    print("タイ:", i)

Last modified: