94 lines
3 KiB
Elixir
94 lines
3 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)}")
|