85 lines
2.5 KiB
Python
85 lines
2.5 KiB
Python
from tools.aoc import AOCDay
|
|
from typing import Any
|
|
|
|
|
|
def get_available_steps(steps: dict) -> list:
|
|
return [x for x in steps if len(steps[x]) == 0]
|
|
|
|
|
|
class Day(AOCDay):
|
|
inputs = [
|
|
[
|
|
("CABDFE", "input7_test"),
|
|
("JMQZELVYXTIGPHFNSOADKWBRUC", "input7"),
|
|
],
|
|
[
|
|
(15, "input7_test"),
|
|
(1133, "input7"),
|
|
]
|
|
]
|
|
|
|
def get_step_blocker(self) -> dict:
|
|
steps = {}
|
|
for line in self.getInput():
|
|
tmp = line.split(" ")
|
|
step_done, step_begin = tmp[1], tmp[7]
|
|
if step_begin not in steps:
|
|
steps[step_begin] = []
|
|
if step_done not in steps:
|
|
steps[step_done] = []
|
|
|
|
steps[step_begin].append(step_done)
|
|
|
|
return steps
|
|
|
|
def part1(self) -> Any:
|
|
steps = self.get_step_blocker()
|
|
step_order = ""
|
|
while next_steps := get_available_steps(steps):
|
|
next_step = min(next_steps)
|
|
step_order += next_step
|
|
del steps[next_step]
|
|
for x in steps:
|
|
if next_step in steps[x]:
|
|
steps[x].remove(next_step)
|
|
|
|
return step_order
|
|
|
|
def part2(self) -> Any:
|
|
steps = self.get_step_blocker()
|
|
second = 0
|
|
time_add = 0 if self._current_test_file.endswith("test") else 60
|
|
worker_count = 2 if self._current_test_file.endswith("test") else 5
|
|
step_order = ""
|
|
current_work = []
|
|
while second == 0 or current_work:
|
|
new_work = []
|
|
for work in current_work:
|
|
if work[1] - 1 == 0:
|
|
step_order += work[0]
|
|
for x in steps:
|
|
if work[0] in steps[x]:
|
|
steps[x].remove(work[0])
|
|
else:
|
|
new_work.append([work[0], work[1] - 1])
|
|
|
|
current_work = new_work
|
|
second += 1
|
|
|
|
if len(current_work) < worker_count:
|
|
available_worker = worker_count - len(current_work)
|
|
avaiable_work = get_available_steps(steps)
|
|
while avaiable_work and available_worker:
|
|
next_step = min(avaiable_work)
|
|
del steps[next_step]
|
|
avaiable_work.remove(next_step)
|
|
current_work.append([next_step, ord(next_step) - 64 + time_add])
|
|
available_worker -= 1
|
|
|
|
return second - 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
day = Day(2018, 7)
|
|
day.run(verbose=True)
|