Advent of code day 08
Mix.install([
{:kino, "~> 0.5.0"}
])
Setup input
example = Kino.Input.textarea("Please paste your input example:")
input = Kino.Input.textarea("Please paste your real input:")
Parse
parsed =
example
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&(String.split(&1, "", trim: true) |> List.to_tuple()))
|> List.to_tuple()
rows = tuple_size(parsed) - 1
cols = tuple_size(elem(parsed, 0)) - 1
grid =
for l <- 0..rows, c <- 0..cols, into: %{} do
{{l, c}, elem(elem(parsed, l), c)}
end
Part 01
defmodule Solver do
def part01(antennas, {max_row, max_col}) do
Enum.reduce(antennas, MapSet.new(), fn {_k, coords}, set ->
crds = List.to_tuple(coords)
for r <- 0..(length(coords) - 1), c <- 1..(length(coords) - 1), c != r do
{{r1, c1}, _} = elem(crds, r)
{{r2, c2}, _} = elem(crds, c)
a = {2 * r1 - r2, 2 * c1 - c2}
b = {2 * r2 - r1, 2 * c2 - c1}
{a, b}
end
|> Enum.reduce(set, fn {a, b}, s ->
MapSet.put(s, a) |> MapSet.put(b)
end)
end)
|> Enum.reject(fn {row, col} ->
row < 0 or row > max_row or (col < 0 or col > max_col)
end)
end
def part02(antennas, {max_row, max_col}) do
Enum.reduce(antennas, MapSet.new(), fn {_k, coords}, ss ->
crds = List.to_tuple(coords)
for r <- 0..(length(coords) - 1), c <- 0..(length(coords) - 1), c != r do
{{r1, c1}, _} = elem(crds, r)
{{r2, c2}, _} = elem(crds, c)
dr = r2 - r1
dc = c2 - c1
rx = r1
cx = c1
0
|> Stream.iterate(&(&1 + 1))
|> Enum.reduce_while(%{set: MapSet.new(), r: rx, c: cx}, fn _, acc ->
set = MapSet.put(acc.set, {acc.r, acc.c})
r = acc.r + dr
c = acc.c + dc
cond do
acc.r < 0 or acc.r > max_row or (acc.c < 0 or acc.c > max_col) ->
{:halt, acc.set}
true ->
{:cont, %{acc | set: set, r: r, c: c}}
end
end)
end
|> Enum.reduce(ss, fn m, acc ->
MapSet.union(m, acc)
end)
end)
end
end
antennas = grid |> Enum.group_by(fn {_, v} -> v end ) |> Map.delete(".")
Solver.part01(antennas, {rows, cols}) |> Enum.uniq |> Enum.count
Part 02
Solver.part02(antennas, {rows, cols}) |> MapSet.size()