Giriş
Genel seçimlerde kişi meclis koltuğu başına sabit bir fiyat hesaplamak ister. Bu, N >= 0
dağıtılacak koltukların ve ns
parti başına oyların bir listesi için d
,
sum(floor(n/d) for n in ns) == N
İşleri ilginç hale getirmek (ve gerçek dünya gibi) için iki gerçek daha ekliyoruz:
İki taraf bir 'koalisyon' içinde toplanabilir, böylece koltuklar içindeki tüm tarafların oylarının toplamı ile “koalisyona” verilir. Daha sonra 'koalisyon'un' sahip olduğu koltuklar benzer bir şekilde taraflar arasında bölünür (bölen, vb. Bulun)
Oyların belirli bir yüzdesini (ör.% 3,25) geçmeyen bir taraf otomatik olarak 0 sandalye alır ve oyları 'koalisyon' için sayılmaz.
Meydan okuma
Size verilenler:
- Bir liste listesi, iç içe listelerin her biri tamsayıları (oy sayısı) içerir ve tek bir parti için 1 veya bir 'koalisyon' için 2 uzunluğundadır.
- En az oy yüzdesi ("baraj" için "bar" olarak da bilinir), kesir olarak (yani% 3.25, 0.0325 olarak verilir)
- Tüm taraflar arasında dağıtılacak toplam koltuk sayısı (tam sayı)
Aynı iç içe liste yapısını, parlamento koltuklarıyla değiştirilen oy sayısı ile yazdıracaksınız.
Kazanan, en az bayt içeren koddur.
Köşe kutuları:
- Birden fazla olası bölen olabilir (ve genellikle de olacaktır). Çıktıda olmadığı için, gerçekten önemli değil.
- Düşünün
N=10
vens = [[1]]
bölen 0,1 (tamsayı değil) olabilir - Bazı durumlarda, örneğin çözülemez
ns=[[30],[30],[100]]
,bar=0
,N=20
.d=7.5
Katlanmış değerlerin toplamının 19'dan 21'e atladığı bir sınır var . Bu durumları çözmeniz beklenmiyor. (bu davayı dile getirdiği için topluluk üyesi Arnauld'a teşekkürler)
Örnek Giriş ve Çıkış
Optimize edilmemiş bir Python3 örneği:
from math import floor
def main(_l, bar, N):
# sum all votes to calculate bar in votes
votes = sum(sum(_) for _ in _l)
# nullify all parties that didn't pass the bar
_l = [[__ if __ >= bar * votes else 0 for __ in _] for _ in _l]
# find divisor for all parliament seats
divisor = find_divisor([sum(_) for _ in _l], N)
# find divisor for each 'coalition'
divisors = [find_divisor(_, floor(sum(_)/divisor)) for _ in _l]
# return final results
return [[floor(___/_) for ___ in __] for _, __ in zip(divisors, _l)]
def find_divisor(_l, N, _min=0, _max=1):
s = sum(floor(_ / _max) for _ in _l)
if s == N:
return _max
elif s < N:
return find_divisor(_l, N, _min, (_max + _min) / 2)
else:
return find_divisor(_l, N, _max, _max * 2)
print(main(l, bar, N))
Örnek girdi:
l = [[190970, 156473],
[138598, 173004],
[143666, 193442],
[1140370, 159468],
[258275, 249049],
[624, 819],
[1125881],
[152756],
[118031],
[74701]]
bar = 0.0325
N = 120
Ve çıktısı:
[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]
Bazı örnek çıktılar:
Eğer bar=0.1
biz küçük partilerin hiçbirinin iki taraf arasında ilginç bir standby kurtulmak sayılır:
[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]
Ve eğer N=0
(köşe davası) o zaman hiç kimse bir şey almazsa:
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]
d=7.5
19 koltuktan 21 koltuğa bir sıçrama yapıyorsunuz.