Proper solution for 2023 Day8 part 2
This commit is contained in:
parent
bf6fa2af47
commit
fb8ea486cc
1 changed files with 17 additions and 16 deletions
23
2023/day8.exs
Normal file → Executable file
23
2023/day8.exs
Normal file → Executable file
|
@ -1,3 +1,4 @@
|
|||
#!/usr/bin/env elixir
|
||||
defmodule Day8 do
|
||||
def part1({instructions, network}) do
|
||||
instructions
|
||||
|
@ -8,24 +9,24 @@ defmodule Day8 do
|
|||
end)
|
||||
end
|
||||
|
||||
# Runs forever.
|
||||
# Need a better answer. Start at the end and validate can get there or something?
|
||||
def part2({instructions, network}) do
|
||||
starting_nodes =
|
||||
# Following the algorithm from the question naively seems to take too long, so we need to
|
||||
# find a shortcut.
|
||||
# It seems that each ghost runs in a cycle, so we can solve the number of steps for each
|
||||
# ghost's path, and then find the lowest common multiple of those lengths, which will
|
||||
# be the first time they arrive at the final spaces together.
|
||||
network
|
||||
|> Map.keys()
|
||||
|> Enum.filter(&match?(<<_::binary-2, "A">>, &1))
|
||||
|
||||
|> Enum.map(fn start ->
|
||||
instructions
|
||||
|> Stream.cycle()
|
||||
|> Enum.reduce_while({starting_nodes, 0}, fn side, {current_nodes, count} ->
|
||||
if Enum.all?(current_nodes, &match?(<<_::binary-2, "Z">>, &1)) do
|
||||
{:halt, count}
|
||||
else
|
||||
next_nodes = Enum.map(current_nodes, fn node -> elem(network[node], side) end)
|
||||
{:cont, {next_nodes, count + 1}}
|
||||
end
|
||||
|> Enum.reduce_while({start, 0}, fn
|
||||
_side, {<<_::binary-2, "Z">>, count} -> {:halt, count}
|
||||
side, {node, count} -> {:cont, {elem(network[node], side), count + 1}}
|
||||
end)
|
||||
end)
|
||||
|> Enum.reduce(fn a, b -> div(a * b, Integer.gcd(a, b)) end)
|
||||
end
|
||||
|
||||
def input do
|
||||
|
|
Loading…
Reference in a new issue