summaryrefslogtreecommitdiff
path: root/17/main.py
blob: d3013341ffaedabd1f8490b6cc61b0f4451e4fbb (plain)
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
#!/usr/bin/python



def find_combos(sizes, taken, avail, remaining):
    result = set()

    # For each container we haven't used yet
    for i in avail:
        # If its capacity is less than what we need, recurse to find
        # containers for the remaining liquid, which might not succeed.
        if sizes[i] < remaining:
            _taken = taken | {i}
            _avail = avail - {i}
            _remaining = remaining - sizes[i]
            for c in find_combos(sizes, _taken, _avail, _remaining):
                result |= {frozenset([i]) | c}
        # If its capacity is exactly what we need, we've found an option
        elif sizes[i] == remaining:
            result |= {frozenset([i])}
        # If its capacity is too large, this isn't an option; continue

    return result



def solve_partn(partn, combos):
    if partn == 1:
        options = combos
    else: # partn == 2
        lengths = map(len, combos)
        min_len = min(lengths)
        options = {c for c in combos if len(c) == min_len}
    return len(options)



def main():
    # Read container volumes from the input text file
    with open("input.txt", "r") as f:
        sizes = list(map(int, f.read().splitlines()))

    # Extremely expensive (takes several minutes), so do it once up front
    combos = find_combos(sizes, set(), set(range(len(sizes))), 150)

    print("Part 1 solution:", solve_partn(1, combos)) # 1304 for me
    print("Part 2 solution:", solve_partn(2, combos)) #   18 for me



if __name__ == "__main__":
    main()