1
1
Fork 0
aoc2018/day6.exs

95 lines
3.0 KiB
Elixir

defmodule DaySix do
def part_one(input) do
coords = parse_input(input)
corners = find_corners(coords)
distances = distances(corners, coords)
legal = filter_infinite(distances, corners)
# IO.puts "Total: #{length distances} Legal: #{length legal}"
length = Enum.group_by(legal, fn {_, coord} -> coord end)
|> Enum.map(fn {_key, list} -> length list end)
|> Enum.max
length
end
def part_two(input) do
coords = parse_input(input)
{maxx, maxy, _minx, _miny} = find_corners(coords)
field = gen_field({maxx * 2, maxy * 2, 0, 0})
filter_below(field, coords, 10000) |> length
end
def parse_input(input) do
lines = String.split(input, "\n")
|> Enum.filter(&(&1 != ""))
lines
|> Enum.map(&(String.split(&1, ", ")))
|> Enum.map(fn [x, y] -> {String.to_integer(x), String.to_integer(y)} end)
end
def find_corners(coords) do
{maxx, _} = Enum.max_by(coords, fn {x, _} -> x end)
{_, maxy} = Enum.max_by(coords, fn {_, y} -> y end)
{minx, _} = Enum.min_by(coords, fn {x, _} -> x end)
{_, miny} = Enum.min_by(coords, fn {_, y} -> y end)
{maxx, maxy, minx, miny}
end
def gen_field({maxx, maxy, minx, miny}) do
Enum.map(minx..maxx, fn i ->
Enum.map(miny..maxy, fn j ->
{i, j}
end)
end) |> List.flatten
end
def distances({maxx, maxy, minx, miny}, coords) do
Enum.map(minx..maxx, fn i ->
Enum.map(miny..maxy, fn j ->
distances = Enum.map(coords, fn {x, y} ->
{{x, y}, abs(i - x) + abs(j - y)}
end)
{{x, y}, distance} = Enum.min_by(distances, fn {_, distance} -> distance end)
if length(Enum.filter(distances, fn {_, d} -> distance == d end)) > 1 do
[]
else
{{i, j}, {x, y}}
end
end)
end)
|> List.flatten
# |> Map.new
end
def is_border({maxx, maxy, minx, miny}, {x, y}) when x == maxx or x == minx or y == maxy or y == miny, do: true
def is_border(_, _), do: false
def filter_infinite(distances, corners) do
is_infinite = Enum.map(distances, fn {{i, j}, {x, y}} -> {{x, y}, is_border(corners, {i, j})} end)
|> Enum.group_by(fn {coord, _} -> coord end)
|> Enum.map(fn {coord, list} -> {coord, Enum.map(list, fn {_, inf} -> inf end)} end)
# IO.inspect is_infinite
infinites = is_infinite
|> Enum.filter(fn {_, list} -> Enum.member?(list, true) end)
|> Enum.map(fn {coord, _} -> coord end)
# IO.puts "Infinites: #{length infinites}"
Enum.filter(distances, fn {_, coord} -> not Enum.member?(infinites, coord) end)
end
def total_distance({i, j}, points) do
Enum.map(points, fn {x, y} -> abs(x - i) + abs(y - j) end) |> List.foldl(0, &+/2)
end
def filter_below(coords, points, under) do
total_distances = Enum.map(coords, fn coord -> {coord, total_distance(coord, points)} end)
Enum.filter(total_distances, fn {_, dist} -> dist < under end)
end
end
{:ok, content} = File.read("input6.txt")
IO.puts("Part 1: #{DaySix.part_one(content)}")
IO.puts("Part 2: #{DaySix.part_two(content)}")