From 7d5f3501c09b6a892441dd0bf1d84c280632acb4 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Thu, 6 Dec 2018 20:12:31 -0500 Subject: [PATCH] Day 6 --- lib/day6/day6.ex | 132 +++++++++++++++++++++++++++++++++++++++++++++ lib/day6/input.txt | 50 +++++++++++++++++ test/day6_test.exs | 4 ++ 3 files changed, 186 insertions(+) create mode 100644 lib/day6/day6.ex create mode 100644 lib/day6/input.txt create mode 100644 test/day6_test.exs diff --git a/lib/day6/day6.ex b/lib/day6/day6.ex new file mode 100644 index 0000000..6fb0e08 --- /dev/null +++ b/lib/day6/day6.ex @@ -0,0 +1,132 @@ +defmodule Day6 do + + @doc """ + Parses a node from a string. + + ## Examples + + iex> Day6.parse_node("1, 6") + {1, 6} + + """ + def parse_node(s) do + [x, y] = String.split(s, ", ") + { + x |> String.to_integer(), + y |> String.to_integer() + } + end + + @doc """ + Distance between two coordinates. + + ## Examples + + iex> Day6.distance({0, 0}, {3, 7}) + 10 + """ + def distance({x1, y1}, {x2, y2}) do + abs(x2 - x1) + abs(y2 - y1) + end + + @doc """ + + ## Examples + + iex> Day6.nearest_node({0, 0}, [{-1, -1}, {1, 2}, {0, 1}, {3, 4}]) + {0, 1} + iex> Day6.nearest_node({0, 0}, [{0, -1}, {1, 0}]) + nil + """ + def nearest_node(point, all) do + nearest = + all + |> Enum.map(fn other -> {other, distance(point, other)} end) + + {min_pt, min_dist} = nearest |> Enum.min_by(fn {_pt, dist} -> dist end) + + case Enum.count(nearest, fn {_pt, dist} -> dist == min_dist end) do + 1 -> min_pt + _ -> nil + end + end + + def largest_region(nodes, grid_size \\ 1000) do + {areas, infinite_area_nodes} = + 0..grid_size + |> Enum.reduce({%{}, []}, fn y, acc -> + 0..grid_size + |> Enum.reduce(acc, fn x, {areas, infinite_area_nodes} -> + pt = {x, y} + case nearest_node(pt, nodes) do + nil -> + {areas, infinite_area_nodes} + nearest -> + if x == 0 or y == 0 or x == grid_size or y == grid_size do + { + areas, + [nearest | infinite_area_nodes] + } + else + { + Map.update(areas, nearest, 1, &(&1 + 1)), + infinite_area_nodes + } + end + end + end) + end) + + areas + |> Enum.reject(fn {node, _area} -> node in infinite_area_nodes end) + |> Enum.max_by(fn {_node, area} -> area end) + end + + @doc """ + Sums the distance between the point and each of the nodes. + + ## Examples + + iex> Day6.total_distances({0, 0}, [{0, 2}, {-2, 0}, {3, 5}]) + 12 + """ + def total_distances(pt, nodes) do + nodes + |> Enum.map(fn node -> distance(pt, node) end) + |> Enum.sum() + end + + def region_near_most(nodes, grid_size \\ 1000, max_dist \\ 10000) do + 0..grid_size + |> Enum.reduce([], fn y, acc -> + 0..grid_size + |> Enum.reduce(acc, fn x, acc -> + pt = {x, y} + cond do + total_distances(pt, nodes) < max_dist -> + [pt | acc] + true -> + acc + end + end) + end) + end + + def parse_input() do + File.read!("lib/day6/input.txt") + |> String.split("\n", trim: true) + |> Enum.map(&parse_node/1) + end + + def part1() do + parse_input() + |> largest_region() + end + + def part2() do + parse_input() + |> region_near_most() + |> Enum.count() + end + +end \ No newline at end of file diff --git a/lib/day6/input.txt b/lib/day6/input.txt new file mode 100644 index 0000000..fb5384c --- /dev/null +++ b/lib/day6/input.txt @@ -0,0 +1,50 @@ +227, 133 +140, 168 +99, 112 +318, 95 +219, 266 +134, 144 +306, 301 +189, 188 +58, 334 +337, 117 +255, 73 +245, 144 +102, 257 +255, 353 +303, 216 +141, 167 +40, 321 +201, 50 +60, 188 +132, 74 +125, 199 +176, 307 +204, 218 +338, 323 +276, 278 +292, 229 +109, 228 +85, 305 +86, 343 +97, 254 +182, 151 +110, 292 +285, 124 +43, 223 +153, 188 +285, 136 +334, 203 +84, 243 +92, 185 +330, 223 +259, 275 +106, 199 +183, 205 +188, 212 +231, 150 +158, 95 +174, 212 +279, 97 +172, 131 +247, 320 diff --git a/test/day6_test.exs b/test/day6_test.exs new file mode 100644 index 0000000..51a7be2 --- /dev/null +++ b/test/day6_test.exs @@ -0,0 +1,4 @@ +defmodule Day6Test do + use ExUnit.Case + doctest Day6 +end \ No newline at end of file