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