aboutsummaryrefslogtreecommitdiff
path: root/day7/solve.py
blob: 93ae801e3eea7028b1b35abc41d89b9230ba5c92 (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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from collections import defaultdict

from commons import get_input, remove_empty


def get_requirement(line):
    return line[5], line[36]


def fill_requirements():
    for line in lines:
        needs, gives = get_requirement(line)
        requirements[gives].append(needs)
        _ = requirements[needs]  # to insert all steps, even the ones without gives/needs


def find_available_steps(known, done):
    return [
        gives for gives, needs in requirements.items()
        if gives in known or all(need in done for need in needs)
    ]


def find_order():
    done = set()
    available = set()
    steps = []
    while True:
        available = set(find_available_steps(available, done))
        found = available - set(steps)
        if len(found) == 0:
            break
        step = sorted(found)[0]
        steps.append(step)
        done.add(step)
    return steps


def process_order():
    done = set()
    available = set()
    time = 0
    steps = []
    worker = []

    while True:
        print(time)
        available = set(find_available_steps(available, done))
        found = available - set(steps) - set(map(lambda w: w[0], worker))
        if len(worker) == 0 and len(found) == 0:
            break
        for i in range(len(worker)):
            job, passed = worker[i]
            worker[i] = job, passed + 1

        finished = list(filter(lambda w: w[1] >= ord(w[0]) - ord('A') + 60, worker))
        for d in finished:
            done.add(d[0])
            steps.append(d[0])
        worker = list(filter(lambda w: w[1] < ord(w[0]) - ord('A') + 60, worker))

        for job in list(found)[:5 - len(worker)]:
            worker.append((job, 0))
        time += 1
    return time


lines = remove_empty(get_input(7).splitlines(keepends=False))
requirements = defaultdict(list)
fill_requirements()

if __name__ == '__main__':
    print('first:', ''.join(find_order()))
    print('second:', process_order())