Day 7
This commit is contained in:
parent
f677b1326e
commit
3203eeb9c3
|
@ -0,0 +1,113 @@
|
|||
defmodule Day7 do
|
||||
|
||||
def get_requirement(str) do
|
||||
[_, requirement, step] = Regex.run(~r/Step (\w) must be finished before step (\w) can begin./, str)
|
||||
{step, requirement}
|
||||
end
|
||||
|
||||
def all_nodes(requirements) do
|
||||
requirements
|
||||
|> Enum.reduce([], fn {step, req}, acc ->
|
||||
[step | [req | acc]]
|
||||
end)
|
||||
|> Enum.uniq
|
||||
end
|
||||
|
||||
def create_graph(requirements) do
|
||||
Enum.reduce(requirements, %{}, fn {step, req}, acc ->
|
||||
Map.update(acc, step, [req], &([req | &1]))
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Topological sort implemented using Kahn's algorithm: https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
|
||||
"""
|
||||
def kahn(_nodes, sorted, _graph, []), do: Enum.reverse(sorted)
|
||||
def kahn(nodes, sorted, graph, no_incoming_edges) do
|
||||
# sort no_incoming_edges lexicographically as per AoC problem
|
||||
[n | rest_no_incoming_edges] = no_incoming_edges |> Enum.sort()
|
||||
sorted = [n | sorted]
|
||||
{graph, no_incoming_edges} =
|
||||
nodes
|
||||
|> Enum.filter(fn m -> n in Map.get(graph, m, []) end)
|
||||
|> Enum.reduce({graph, rest_no_incoming_edges}, fn m, {graph, no_incoming_edges} ->
|
||||
new_dependencies_of_m = graph |> Map.get(m) |> List.delete(n)
|
||||
new_graph = graph |> Map.put(m, new_dependencies_of_m)
|
||||
{
|
||||
new_graph,
|
||||
case new_dependencies_of_m do
|
||||
[] -> [m | no_incoming_edges]
|
||||
_ -> no_incoming_edges
|
||||
end
|
||||
}
|
||||
end)
|
||||
kahn(nodes, sorted, graph, no_incoming_edges)
|
||||
end
|
||||
|
||||
def kahn(nodes, graph) do
|
||||
no_incoming_edges = Enum.filter(nodes, fn node -> !Map.has_key?(graph, node) end)
|
||||
kahn(nodes, [], graph, no_incoming_edges)
|
||||
end
|
||||
|
||||
def step_time(nil), do: 0
|
||||
def step_time(<<c::utf8, _rest::binary>>) do
|
||||
# step - ?A + 1 + extra
|
||||
c - ?A + 60
|
||||
end
|
||||
|
||||
def tick(workers, nodes, graph, done \\ [], time \\ 0) do
|
||||
{workers, {done, nodes}} =
|
||||
Enum.map_reduce(workers, {done, nodes}, fn {current_step, remaining}, {done, nodes} ->
|
||||
case remaining do
|
||||
0 ->
|
||||
new_done = case current_step do
|
||||
nil -> done
|
||||
_ -> [current_step | done]
|
||||
end
|
||||
next_step =
|
||||
nodes
|
||||
|> Enum.find(fn node ->
|
||||
Enum.all?(Map.get(graph, node, []), fn dep -> dep in new_done end)
|
||||
end)
|
||||
new_nodes = List.delete(nodes, next_step)
|
||||
{{next_step, step_time(next_step)}, {new_done, new_nodes}}
|
||||
|
||||
n when n > 0 ->
|
||||
{{current_step, n - 1}, {done, nodes}}
|
||||
end
|
||||
end)
|
||||
|
||||
IO.inspect(nodes)
|
||||
IO.inspect(done)
|
||||
IO.inspect(workers)
|
||||
|
||||
if length(nodes) == 0 and Enum.all?(workers, fn {step, _} -> step == nil end) do
|
||||
time - 1
|
||||
else
|
||||
tick(workers, nodes, graph, done, time + 1)
|
||||
end
|
||||
end
|
||||
|
||||
def parse_input() do
|
||||
File.read!("lib/day7/input.txt")
|
||||
|> String.split("\n", trim: true)
|
||||
|> Enum.map(&get_requirement/1)
|
||||
end
|
||||
|
||||
def part1() do
|
||||
requirements = parse_input()
|
||||
nodes = all_nodes(requirements)
|
||||
graph = create_graph(requirements)
|
||||
kahn(nodes, graph)
|
||||
|> Enum.join()
|
||||
end
|
||||
|
||||
def part2() do
|
||||
requirements = parse_input()
|
||||
nodes = all_nodes(requirements)
|
||||
graph = create_graph(requirements)
|
||||
workers = for _ <- 1..5, do: {nil, 1}
|
||||
tick(workers, nodes, graph)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,101 @@
|
|||
Step T must be finished before step C can begin.
|
||||
Step V must be finished before step C can begin.
|
||||
Step Y must be finished before step H can begin.
|
||||
Step R must be finished before step U can begin.
|
||||
Step B must be finished before step J can begin.
|
||||
Step Q must be finished before step O can begin.
|
||||
Step W must be finished before step O can begin.
|
||||
Step S must be finished before step X can begin.
|
||||
Step I must be finished before step N can begin.
|
||||
Step X must be finished before step H can begin.
|
||||
Step M must be finished before step L can begin.
|
||||
Step A must be finished before step F can begin.
|
||||
Step G must be finished before step P can begin.
|
||||
Step U must be finished before step E can begin.
|
||||
Step Z must be finished before step E can begin.
|
||||
Step H must be finished before step L can begin.
|
||||
Step P must be finished before step C can begin.
|
||||
Step K must be finished before step F can begin.
|
||||
Step O must be finished before step C can begin.
|
||||
Step C must be finished before step F can begin.
|
||||
Step D must be finished before step L can begin.
|
||||
Step L must be finished before step F can begin.
|
||||
Step N must be finished before step E can begin.
|
||||
Step J must be finished before step F can begin.
|
||||
Step F must be finished before step E can begin.
|
||||
Step I must be finished before step A can begin.
|
||||
Step Z must be finished before step J can begin.
|
||||
Step I must be finished before step P can begin.
|
||||
Step T must be finished before step E can begin.
|
||||
Step R must be finished before step F can begin.
|
||||
Step U must be finished before step H can begin.
|
||||
Step K must be finished before step E can begin.
|
||||
Step D must be finished before step N can begin.
|
||||
Step U must be finished before step C can begin.
|
||||
Step D must be finished before step J can begin.
|
||||
Step N must be finished before step F can begin.
|
||||
Step C must be finished before step J can begin.
|
||||
Step U must be finished before step J can begin.
|
||||
Step A must be finished before step O can begin.
|
||||
Step H must be finished before step N can begin.
|
||||
Step P must be finished before step O can begin.
|
||||
Step I must be finished before step E can begin.
|
||||
Step G must be finished before step F can begin.
|
||||
Step O must be finished before step J can begin.
|
||||
Step Q must be finished before step F can begin.
|
||||
Step G must be finished before step J can begin.
|
||||
Step X must be finished before step E can begin.
|
||||
Step S must be finished before step D can begin.
|
||||
Step R must be finished before step P can begin.
|
||||
Step K must be finished before step L can begin.
|
||||
Step R must be finished before step Q can begin.
|
||||
Step L must be finished before step N can begin.
|
||||
Step Q must be finished before step C can begin.
|
||||
Step C must be finished before step D can begin.
|
||||
Step C must be finished before step N can begin.
|
||||
Step O must be finished before step E can begin.
|
||||
Step W must be finished before step F can begin.
|
||||
Step K must be finished before step D can begin.
|
||||
Step T must be finished before step H can begin.
|
||||
Step M must be finished before step D can begin.
|
||||
Step Y must be finished before step Z can begin.
|
||||
Step J must be finished before step E can begin.
|
||||
Step S must be finished before step F can begin.
|
||||
Step G must be finished before step U can begin.
|
||||
Step V must be finished before step S can begin.
|
||||
Step Y must be finished before step F can begin.
|
||||
Step G must be finished before step H can begin.
|
||||
Step T must be finished before step Q can begin.
|
||||
Step S must be finished before step U can begin.
|
||||
Step V must be finished before step D can begin.
|
||||
Step W must be finished before step M can begin.
|
||||
Step M must be finished before step E can begin.
|
||||
Step A must be finished before step H can begin.
|
||||
Step B must be finished before step F can begin.
|
||||
Step B must be finished before step N can begin.
|
||||
Step D must be finished before step F can begin.
|
||||
Step W must be finished before step K can begin.
|
||||
Step P must be finished before step E can begin.
|
||||
Step B must be finished before step X can begin.
|
||||
Step Q must be finished before step U can begin.
|
||||
Step Q must be finished before step X can begin.
|
||||
Step X must be finished before step N can begin.
|
||||
Step M must be finished before step Z can begin.
|
||||
Step G must be finished before step Z can begin.
|
||||
Step S must be finished before step G can begin.
|
||||
Step P must be finished before step F can begin.
|
||||
Step I must be finished before step O can begin.
|
||||
Step R must be finished before step A can begin.
|
||||
Step L must be finished before step J can begin.
|
||||
Step B must be finished before step I can begin.
|
||||
Step C must be finished before step E can begin.
|
||||
Step B must be finished before step W can begin.
|
||||
Step P must be finished before step N can begin.
|
||||
Step H must be finished before step C can begin.
|
||||
Step K must be finished before step J can begin.
|
||||
Step Y must be finished before step M can begin.
|
||||
Step Z must be finished before step P can begin.
|
||||
Step I must be finished before step K can begin.
|
||||
Step V must be finished before step E can begin.
|
||||
Step Y must be finished before step P can begin.
|
||||
Step T must be finished before step R can begin.
|
|
@ -0,0 +1,4 @@
|
|||
defmodule Day7Test do
|
||||
use ExUnit.Case
|
||||
doctest Day7
|
||||
end
|
Loading…
Reference in New Issue