Solution to problem 7 in Python
This commit is contained in:
parent
7c688d4162
commit
1613813d7a
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user