diff --git a/2015/input/2015_9.txt b/2015/input/2015_9.txt new file mode 100644 index 0000000..a56f5e2 --- /dev/null +++ b/2015/input/2015_9.txt @@ -0,0 +1,28 @@ +AlphaCentauri to Snowdin = 66 +AlphaCentauri to Tambi = 28 +AlphaCentauri to Faerun = 60 +AlphaCentauri to Norrath = 34 +AlphaCentauri to Straylight = 34 +AlphaCentauri to Tristram = 3 +AlphaCentauri to Arbre = 108 +Snowdin to Tambi = 22 +Snowdin to Faerun = 12 +Snowdin to Norrath = 91 +Snowdin to Straylight = 121 +Snowdin to Tristram = 111 +Snowdin to Arbre = 71 +Tambi to Faerun = 39 +Tambi to Norrath = 113 +Tambi to Straylight = 130 +Tambi to Tristram = 35 +Tambi to Arbre = 40 +Faerun to Norrath = 63 +Faerun to Straylight = 21 +Faerun to Tristram = 57 +Faerun to Arbre = 83 +Norrath to Straylight = 9 +Norrath to Tristram = 50 +Norrath to Arbre = 60 +Straylight to Tristram = 27 +Straylight to Arbre = 81 +Tristram to Arbre = 90 diff --git a/2015/lib/2015/9.ex b/2015/lib/2015/9.ex new file mode 100644 index 0000000..5274b09 --- /dev/null +++ b/2015/lib/2015/9.ex @@ -0,0 +1,72 @@ +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 diff --git a/2015/lib/advent_of_code2015.ex b/2015/lib/advent_of_code2015.ex deleted file mode 100644 index 645ed7b..0000000 --- a/2015/lib/advent_of_code2015.ex +++ /dev/null @@ -1,18 +0,0 @@ -defmodule AdventOfCode2015 do - @moduledoc """ - Documentation for `AdventOfCode2015`. - """ - - @doc """ - Hello world. - - ## Examples - - iex> AdventOfCode2015.hello() - :world - - """ - def hello do - :world - end -end diff --git a/2015/mix.exs b/2015/mix.exs index 02415aa..853ea3f 100644 --- a/2015/mix.exs +++ b/2015/mix.exs @@ -23,6 +23,7 @@ defmodule AdventOfCode2015.MixProject do [ {:advent_of_code_utils, "~> 1.0"}, {:exla, "~> 0.1.0-dev", github: "elixir-nx/nx", sparse: "exla"}, + {:libgraph, "~> 0.13.3"}, {:nimble_parsec, "~> 1.0"}, {:nx, "~> 0.1.0-dev", github: "elixir-nx/nx", sparse: "nx", override: true} ] diff --git a/2015/mix.lock b/2015/mix.lock index 767627d..236fcce 100644 --- a/2015/mix.lock +++ b/2015/mix.lock @@ -2,6 +2,7 @@ "advent_of_code_utils": {:hex, :advent_of_code_utils, "1.0.0", "e9ce8be22988e095991168e9d2dde802afc213aaae64491e9fde84dd877db41c", [:mix], [], "hexpm", "1fa5217ccb95a38ce2312dd7ea6057b0d0002a3eba7490feab704df4b8a94038"}, "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"}, "exla": {:git, "https://github.com/elixir-nx/nx.git", "e23a678bf0ebcbbafe03f1b5ed78623f052ad486", [sparse: "exla"]}, + "libgraph": {:hex, :libgraph, "0.13.3", "20732b7bafb933dcf7351c479e03076ebd14a85fd3202c67a1c197f4f7c2466b", [:mix], [], "hexpm", "78f2576eef615440b46f10060b1de1c86640441422832052686df53dc3c148c6"}, "nimble_parsec": {:hex, :nimble_parsec, "1.2.0", "b44d75e2a6542dcb6acf5d71c32c74ca88960421b6874777f79153bbbbd7dccc", [:mix], [], "hexpm", "52b2871a7515a5ac49b00f214e4165a40724cf99798d8e4a65e4fd64ebd002c1"}, "nx": {:git, "https://github.com/elixir-nx/nx.git", "e23a678bf0ebcbbafe03f1b5ed78623f052ad486", [sparse: "nx"]}, "xla": {:hex, :xla, "0.2.0", "689887888afb22587168d461f0e9ff83d7b06040273ea7082dbf9ff7eca33dcc", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "a2e7b81413db49a159eabfb12dbd784a7c04b5c68c7b4057238d5ec9b110f2ec"}, diff --git a/2015/test/advent_of_code2015_test.exs b/2015/test/advent_of_code2015_test.exs deleted file mode 100644 index 5c9ee79..0000000 --- a/2015/test/advent_of_code2015_test.exs +++ /dev/null @@ -1,8 +0,0 @@ -defmodule AdventOfCode2015Test do - use ExUnit.Case - doctest AdventOfCode2015 - - test "greets the world" do - assert AdventOfCode2015.hello() == :world - end -end