-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path24_It_Hangs_in_the_Balance.py
80 lines (64 loc) · 2.21 KB
/
24_It_Hangs_in_the_Balance.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from aoc import *
from itertools import groupby
import math
def has_subset_sum(values, expected):
subset = {(i, 0) for i in range(len(values)+1)}
for i in range(1, len(values)+1):
for j in range(1, expected+1):
if j < values[i-1] and (i-1, j) in subset:
subset.add((i, j))
if j <= values[i-1] and (i-1, j) in subset or (i-1, j-values[i-1]) in subset:
subset.add((i, j))
return (len(values), expected) in subset
def find_subsets(values, expected):
dp = [[False] * (expected+1) for j in range(len(values))]
for i in range(len(values)):
dp[i][0] = True
if values[0] <= expected:
dp[0][values[0]] = True
for i in range(1, len(values)):
for j in range(1, expected+1):
if values[i] > j:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = dp[i-1][j] or dp[i-1][j-values[i]]
if not dp[len(values)-1][expected]:
print('LALALA')
subsets = []
def find_recursive(i, j, p):
if j == 0:
subsets.append(list(p))
return
elif i == 0 and dp[i][j]:
p.append(values[i])
subsets.append(list(p))
p.pop()
return
if dp[i-1][j]:
find_recursive(i-1, j, p)
if j >= values[i] and dp[i-1][j-values[i]]:
p.append(values[i])
find_recursive(i-1, j-values[i], p)
p.pop()
find_recursive(len(values)-1, expected, [])
return subsets
def subset_score(s):
return (len(s), math.prod(s))
def has_non_overlaping_subsets(front, subsets, expected):
count = 0
for s in subsets:
if not (s & front):
count += 1
if count == expected:
return True
return False
def find_optimal_front(presents, n):
expected = sum(presents) // n
subsets = [set(x) for x in find_subsets(presents, expected)]
subsets.sort(key=subset_score)
for front in subsets:
if has_non_overlaping_subsets(front, subsets, n-1):
return front
presents = read()
print('Star 1:', math.prod(find_optimal_front(presents, 3)))
print('Star 1:', math.prod(find_optimal_front(presents, 4)))