1
0
Fork 0
advent-of-code/2015/lib/2015/9.ex
2022-09-21 09:19:53 -04:00

72 lines
2.2 KiB
Elixir

import AOC
aoc 2015, 9 do
def parse_line(line) do
[from, _, to, _, distance] = String.split(line, " ")
{from, to, String.to_integer(distance)}
end
def p1 do
graph =
input_stream()
|> Stream.map(&parse_line/1)
|> Enum.reduce(Graph.new(type: :undirected), fn {v1, v2, weight}, graph ->
Graph.add_edge(graph, v1, v2, weight: weight)
end)
for start <- Graph.vertices(graph), reduce: :infinity do
shortest_so_far -> find_shortest_path_to_all_vertices(graph, start) |> min(shortest_so_far)
end
end
def find_shortest_path_to_all_vertices(graph, start, distance \\ 0)
def find_shortest_path_to_all_vertices(%{vertices: v}, _, distance) when map_size(v) == 1,
do: distance
def find_shortest_path_to_all_vertices(graph, start, distance) do
for neighbor <- Graph.neighbors(graph, start), reduce: :infinity do
shortest_path_distance ->
%{weight: distance_to_neighbor} = Graph.edge(graph, start, neighbor)
find_shortest_path_to_all_vertices(
Graph.delete_vertex(graph, start),
neighbor,
distance_to_neighbor + distance
)
|> min(shortest_path_distance)
end
end
def p2 do
graph =
input_stream()
|> Stream.map(&parse_line/1)
|> Enum.reduce(Graph.new(type: :undirected), fn {v1, v2, weight}, graph ->
Graph.add_edge(graph, v1, v2, weight: weight)
end)
for start <- Graph.vertices(graph), reduce: 0 do
longest_so_far -> find_longest_path_to_all_vertices(graph, start) |> max(longest_so_far)
end
end
def find_longest_path_to_all_vertices(graph, start, distance \\ 0)
def find_longest_path_to_all_vertices(%{vertices: v}, _, distance) when map_size(v) == 1,
do: distance
def find_longest_path_to_all_vertices(graph, start, distance) do
for neighbor <- Graph.neighbors(graph, start), reduce: 0 do
longest_path_distance ->
%{weight: distance_to_neighbor} = Graph.edge(graph, start, neighbor)
find_longest_path_to_all_vertices(
Graph.delete_vertex(graph, start),
neighbor,
distance_to_neighbor + distance
)
|> max(longest_path_distance)
end
end
end