Giới thiệu
Trong một cuộc tổng tuyển cử, người ta muốn tính một mức giá không đổi trên mỗi ghế quốc hội. Điều này có nghĩa là N >= 0
để phân bổ số ghế và danh sách ns
phiếu bầu cho mỗi bên, chúng tôi muốn tìm một số d
sao cho
sum(floor(n/d) for n in ns) == N
Để làm cho mọi thứ thú vị (và giống như thế giới thực hơn), chúng tôi thêm hai sự thật nữa:
Hai bên có thể tập hợp thành một "liên minh", để các ghế được trao cho "liên minh" bằng tổng số phiếu bầu cho tất cả các bên trong đó. Sau đó, các ghế mà 'liên minh' có được được phân chia giữa các bên theo kiểu tương tự (tìm ước số, v.v.)
Một bên không vượt qua một tỷ lệ phiếu nhất định (ví dụ 3,25%) sẽ tự động nhận được 0 ghế và phiếu bầu của họ không được tính cho một "liên minh".
Thử thách
Bạn đã được nhận :
- Một danh sách các danh sách, mỗi danh sách lồng nhau chứa các số nguyên (số phiếu) và có độ dài 1 cho một bên hoặc chiều dài 2 cho một "liên minh".
- Tỷ lệ phiếu bầu tối thiểu (còn gọi là "bar" cho "barrage") để có chỗ ngồi, dưới dạng phân số (vì vậy 3,25% được đưa ra là 0,0325)
- Tổng số ghế được phân phối giữa tất cả các bên (số nguyên)
Bạn phải in ra cấu trúc danh sách lồng nhau, với số phiếu được thay thế bằng ghế quốc hội.
Người chiến thắng là mã có số lượng byte nhỏ nhất.
Trường hợp góc:
- Có thể (và thường sẽ có) nhiều hơn một ước số có thể. Vì nó không có trong đầu ra, nên nó không thực sự quan trọng.
- Hãy tưởng tượng
N=10
vàns = [[1]]
, vì vậy số chia có thể là 0,1 (không phải là số nguyên) - Một số trường hợp không thể giải quyết, ví dụ
ns=[[30],[30],[100]]
,bar=0
,N=20
. Có một ranh giớid=7.5
trong đó tổng các giá trị thả nổi nhảy từ 19 đến 21. Bạn không cần phải giải quyết các trường hợp này. (cảm ơn thành viên cộng đồng Arnauld đã chỉ ra trường hợp này)
Ví dụ đầu vào và đầu ra
Một ví dụ Python3 không được tối ưu hóa:
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))
Ví dụ đầu vào:
l = [[190970, 156473],
[138598, 173004],
[143666, 193442],
[1140370, 159468],
[258275, 249049],
[624, 819],
[1125881],
[152756],
[118031],
[74701]]
bar = 0.0325
N = 120
Và đầu ra của nó:
[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]
Một số ví dụ đầu ra:
Nếu bar=0.1
chúng tôi có một cuộc đối thoại thú vị giữa hai bên vì không có bên nào trong số các bên nhỏ hơn được tính vào:
[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]
Và nếu N=0
(trường hợp góc) thì tất nhiên không ai nhận được gì:
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]
d=7.5
bạn có một bước nhảy từ 19 chỗ ngồi lên 21 chỗ ngồi.