Solve 2018/07
This commit is contained in:
parent
5abd5ff140
commit
9ccaaa74a7
3 changed files with 223 additions and 0 deletions
101
2018/07/input.txt
Normal file
101
2018/07/input.txt
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
Step U must be finished before step A can begin.
|
||||
Step F must be finished before step Z can begin.
|
||||
Step B must be finished before step J can begin.
|
||||
Step O must be finished before step R can begin.
|
||||
Step H must be finished before step S can begin.
|
||||
Step T must be finished before step R can begin.
|
||||
Step L must be finished before step W can begin.
|
||||
Step M must be finished before step I can begin.
|
||||
Step Q must be finished before step K can begin.
|
||||
Step Z must be finished before step V can begin.
|
||||
Step C must be finished before step E can begin.
|
||||
Step W must be finished before step I can begin.
|
||||
Step K must be finished before step S can begin.
|
||||
Step I must be finished before step Y can begin.
|
||||
Step P must be finished before step V can begin.
|
||||
Step V must be finished before step X can begin.
|
||||
Step R must be finished before step E can begin.
|
||||
Step N must be finished before step E can begin.
|
||||
Step X must be finished before step J can begin.
|
||||
Step A must be finished before step J can begin.
|
||||
Step S must be finished before step G can begin.
|
||||
Step J must be finished before step E can begin.
|
||||
Step Y must be finished before step E can begin.
|
||||
Step D must be finished before step G can begin.
|
||||
Step E must be finished before step G can begin.
|
||||
Step K must be finished before step N can begin.
|
||||
Step B must be finished before step I can begin.
|
||||
Step X must be finished before step S can begin.
|
||||
Step V must be finished before step S can begin.
|
||||
Step U must be finished before step L can begin.
|
||||
Step N must be finished before step G can begin.
|
||||
Step O must be finished before step L can begin.
|
||||
Step X must be finished before step E can begin.
|
||||
Step V must be finished before step E can begin.
|
||||
Step Y must be finished before step G can begin.
|
||||
Step A must be finished before step Y can begin.
|
||||
Step M must be finished before step E can begin.
|
||||
Step F must be finished before step Q can begin.
|
||||
Step F must be finished before step X can begin.
|
||||
Step L must be finished before step C can begin.
|
||||
Step T must be finished before step L can begin.
|
||||
Step B must be finished before step C can begin.
|
||||
Step Q must be finished before step N can begin.
|
||||
Step T must be finished before step G can begin.
|
||||
Step R must be finished before step D can begin.
|
||||
Step I must be finished before step A can begin.
|
||||
Step B must be finished before step M can begin.
|
||||
Step H must be finished before step A can begin.
|
||||
Step F must be finished before step K can begin.
|
||||
Step U must be finished before step F can begin.
|
||||
Step R must be finished before step A can begin.
|
||||
Step J must be finished before step D can begin.
|
||||
Step V must be finished before step Y can begin.
|
||||
Step F must be finished before step J can begin.
|
||||
Step C must be finished before step K can begin.
|
||||
Step M must be finished before step C can begin.
|
||||
Step F must be finished before step E can begin.
|
||||
Step I must be finished before step E can begin.
|
||||
Step T must be finished before step A can begin.
|
||||
Step J must be finished before step Y can begin.
|
||||
Step R must be finished before step X can begin.
|
||||
Step W must be finished before step S can begin.
|
||||
Step V must be finished before step R can begin.
|
||||
Step U must be finished before step V can begin.
|
||||
Step C must be finished before step V can begin.
|
||||
Step F must be finished before step Y can begin.
|
||||
Step R must be finished before step G can begin.
|
||||
Step W must be finished before step N can begin.
|
||||
Step H must be finished before step N can begin.
|
||||
Step H must be finished before step Y can begin.
|
||||
Step B must be finished before step W can begin.
|
||||
Step M must be finished before step Z can begin.
|
||||
Step X must be finished before step A can begin.
|
||||
Step A must be finished before step G can begin.
|
||||
Step N must be finished before step A can begin.
|
||||
Step H must be finished before step J can begin.
|
||||
Step B must be finished before step O can begin.
|
||||
Step W must be finished before step A can begin.
|
||||
Step P must be finished before step N can begin.
|
||||
Step Z must be finished before step G can begin.
|
||||
Step W must be finished before step D can begin.
|
||||
Step D must be finished before step E can begin.
|
||||
Step W must be finished before step J can begin.
|
||||
Step N must be finished before step D can begin.
|
||||
Step C must be finished before step J can begin.
|
||||
Step B must be finished before step Y can begin.
|
||||
Step F must be finished before step P can begin.
|
||||
Step L must be finished before step P can begin.
|
||||
Step X must be finished before step G can begin.
|
||||
Step R must be finished before step Y can begin.
|
||||
Step K must be finished before step A can begin.
|
||||
Step M must be finished before step Y can begin.
|
||||
Step W must be finished before step Y can begin.
|
||||
Step F must be finished before step I can begin.
|
||||
Step L must be finished before step X can begin.
|
||||
Step R must be finished before step J can begin.
|
||||
Step V must be finished before step J can begin.
|
||||
Step V must be finished before step D can begin.
|
||||
Step H must be finished before step C can begin.
|
||||
Step O must be finished before step G can begin.
|
||||
Step P must be finished before step R can begin.
|
||||
115
2018/07/solve.py
Normal file
115
2018/07/solve.py
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import re
|
||||
import sys
|
||||
|
||||
# PART 1
|
||||
|
||||
STEP_RE = r"Step (\S+) must be finished before step (\S+) can begin.\n"
|
||||
|
||||
def load_steps(filename):
|
||||
steps = {}
|
||||
with open(filename, "r") as f:
|
||||
for line in f:
|
||||
match = re.fullmatch(STEP_RE, line)
|
||||
step, before = match.groups()
|
||||
steps[step] = steps.get(step, set()) | {before}
|
||||
|
||||
return steps
|
||||
|
||||
def reverse_steps(steps):
|
||||
reverse = {}
|
||||
for step, befores in steps.items():
|
||||
# Make sure that step exists in reverse
|
||||
reverse[step] = reverse.get(step, set())
|
||||
|
||||
for before in befores:
|
||||
reverse[before] = reverse.get(before, set()) | {step}
|
||||
|
||||
return reverse
|
||||
|
||||
def duration_of(step):
|
||||
return ord(step) - ord("A") + 61
|
||||
|
||||
class Tree:
|
||||
def __init__(self, steps, workers=1):
|
||||
self.workers = {i: None for i in range(workers)}
|
||||
self.steps = reverse_steps(steps) # Warning: Steps are reversed in Trees.
|
||||
self.result = []
|
||||
self.duration = 0
|
||||
|
||||
def working(self):
|
||||
return {worker: work for worker, work in self.workers.items() if work is not None}
|
||||
|
||||
def find_free(self):
|
||||
return {step for step, afters in self.steps.items() if len(afters) == 0}
|
||||
|
||||
def find_working(self):
|
||||
return {step for (step, _) in self.working().values()}
|
||||
|
||||
def find_available(self):
|
||||
return self.find_free() - self.find_working()
|
||||
|
||||
def remove_step(self, step):
|
||||
try:
|
||||
del self.steps[step]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
for s in self.steps.values():
|
||||
try:
|
||||
s.remove(step)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def update_workers(self):
|
||||
min_duration = min(duration for (_, duration) in self.working().values())
|
||||
self.duration += min_duration
|
||||
|
||||
finished_steps = set()
|
||||
|
||||
# Subtract min_duration from all workers
|
||||
for w, s in self.workers.items():
|
||||
if s is not None:
|
||||
step, duration = s
|
||||
duration -= min_duration
|
||||
|
||||
if duration <= 0:
|
||||
finished_steps.add(step)
|
||||
self.remove_step(step)
|
||||
self.workers[w] = None
|
||||
else:
|
||||
self.workers[w] = (step, duration)
|
||||
|
||||
self.result += list(finished_steps)
|
||||
|
||||
def distribute_jobs(self):
|
||||
available = list(reversed(sorted(self.find_available())))
|
||||
|
||||
for w, s in self.workers.items():
|
||||
if not available:
|
||||
break
|
||||
|
||||
if s is None:
|
||||
step = available.pop()
|
||||
duration = duration_of(step)
|
||||
self.workers[w] = (step, duration)
|
||||
|
||||
def run(self):
|
||||
while self.steps:
|
||||
self.distribute_jobs()
|
||||
self.update_workers()
|
||||
|
||||
def main(filename):
|
||||
print(f"Solutions for {filename}")
|
||||
steps = load_steps(filename)
|
||||
tree = Tree(steps, workers=1)
|
||||
tree.run()
|
||||
sequence = "".join(tree.result)
|
||||
print(f"Part 1: {sequence}")
|
||||
tree = Tree(steps, workers=5)
|
||||
tree.run()
|
||||
duration = tree.duration
|
||||
print(f"Part 2: {duration}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
for filename in sys.argv[1:]:
|
||||
main(filename)
|
||||
7
2018/07/test_input.txt
Normal file
7
2018/07/test_input.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Step C must be finished before step A can begin.
|
||||
Step C must be finished before step F can begin.
|
||||
Step A must be finished before step B can begin.
|
||||
Step A must be finished before step D can begin.
|
||||
Step B must be finished before step E can begin.
|
||||
Step D must be finished before step E can begin.
|
||||
Step F must be finished before step E can begin.
|
||||
Loading…
Add table
Add a link
Reference in a new issue