Solution to problem 7 in Python

This commit is contained in:
David Doblas Jiménez 2022-03-15 14:33:14 +01:00
parent 7c688d4162
commit 1613813d7a

View File

@ -60,6 +60,8 @@
# In what order should the steps in your instructions be completed?
from string import ascii_uppercase
import networkx as nx
with open("files/P7.txt") as f:
@ -76,5 +78,86 @@ def part_1() -> None:
print(f"The correct order will be {order}")
# --- Part Two ---
# As you're about to begin construction, four of the Elves offer to help. "The
# sun will set soon; it'll go faster if we work together." Now, you need to
# account for multiple people working on steps simultaneously. If multiple
# steps are available, workers should still begin them in alphabetical order.
# Each step takes 60 seconds plus an amount corresponding to its letter: A=1,
# B=2, C=3, and so on. So, step A takes 60+1=61 seconds, while step Z takes
# 60+26=86 seconds. No time is required between steps.
# To simplify things for the example, however, suppose you only have help from
# one Elf (a total of two workers) and that each step takes 60 fewer seconds
# (so that step A takes 1 second and step Z takes 26 seconds). Then, using the
# same instructions as above, this is how each second would be spent:
# Second Worker 1 Worker 2 Done
# 0 C .
# 1 C .
# 2 C .
# 3 A F C
# 4 B F CA
# 5 B F CA
# 6 D F CAB
# 7 D F CAB
# 8 D F CAB
# 9 D . CABF
# 10 E . CABFD
# 11 E . CABFD
# 12 E . CABFD
# 13 E . CABFD
# 14 E . CABFD
# 15 . . CABFDE
# Each row represents one second of time. The Second column identifies how many
# seconds have passed as of the beginning of that second. Each worker column
# shows the step that worker is currently doing (or . if they are idle). The
# Done column shows completed steps.
# Note that the order of the steps has changed; this is because steps now take
# time to finish and multiple workers can begin multiple steps simultaneously.
# In this example, it would take 15 seconds for two workers to complete these
# steps.
# With 5 workers and the 60+ second step durations described above, how long
# will it take to complete all of the steps?
def part_2() -> None:
G = nx.DiGraph()
for step in steps:
parent, child = step[5:6], step[36:37]
G.add_edge(parent, child)
n_workers = 5
# Add amount of work for each node
for node in G.nodes:
G.nodes[node]["work"] = 61 + ord(node) - ord("A")
time = 0
while G.nodes:
# Find nodes available for work
available_nodes = [node for node in G.nodes if G.in_degree(node) == 0]
# Sort available nodes: Work on nodes with least remaining work
available_nodes.sort(key=lambda node: G.nodes[node]["work"])
# Reduce remaining work for n_workers of the available nodes
for worker, node in zip(range(n_workers), available_nodes):
G.nodes[node]["work"] -= 1
# Remove finished nodes
if G.nodes[node]["work"] == 0:
G.remove_node(node)
time += 1
print(f"Finishing all the work took {time} seconds")
if __name__ == "__main__":
part_1()
part_2()