AoC 2015 Day 6
Mix.install([:kino])
defmodule Utils do
def split(line, sep \\ "") do
String.split(line, sep, trim: true)
end
def split_all_lines(text, sep \\ "") do
text
|> String.split("\n", trim: true)
|> Enum.map(&split(&1, sep))
end
def to_numbers(number) when is_binary(number) do
String.to_integer(number)
end
def to_numbers(numbers) when is_list(numbers) do
Enum.map(numbers, &to_numbers/1)
end
def to_matrix(text, sep \\ "") do
text
|> split_all_lines(sep)
|> then(fn data ->
for {row, r} <- Enum.with_index(data), {col, c} <- Enum.with_index(row) do
{{r, c}, col}
end
end)
|> Map.new()
end
end
Setup
import Utils
input = Kino.Input.textarea("Input:")
text = Kino.Input.read(input)
data = split_all_lines(text, " ")
num = fn c -> split(c, ",") |> to_numbers() end
data =
Enum.map(data, fn
[_, "on", c1, _, c2] -> {:on, num.(c1), num.(c2)}
[_, "off", c1, _, c2] -> {:off, num.(c1), num.(c2)}
["toggle", c1, _, c2] -> {:toggle, num.(c1), num.(c2)}
end)
P1
defmodule P1 do
def solve(input) do
input
|> Enum.reduce(:array.new(1000 * 1000, default: false), fn {op, [x1, y1], [x2, y2]}, arr ->
for x <- x1..x2, y <- y1..y2, reduce: arr do
arr ->
case op do
:on -> :array.set(x * 1000 + y, true, arr)
:off -> :array.set(x * 1000 + y, false, arr)
:toggle -> :array.set(x * 1000 + y, !:array.get(x * 1000 + y, arr), arr)
end
end
end)
end
end
:array.sparse_foldl(
fn
_, true, count -> count + 1
_, false, count -> count
end,
0,
P1.solve(data)
)
P2
defmodule P2 do
def solve(input) do
input
|> Enum.reduce(:array.new(1000 * 1000, default: 0), fn {op, [x1, y1], [x2, y2]}, arr ->
for x <- x1..x2, y <- y1..y2, reduce: arr do
arr ->
case op do
:on -> update(x * 1000 + y, 1, arr)
:off -> update(x * 1000 + y, -1, arr)
:toggle -> update(x * 1000 + y, 2, arr)
end
end
end)
end
def update(offset, change, arr) do
v = :array.get(offset, arr) + change
v = if v < 0, do: 0, else: v
:array.set(offset, v, arr)
end
end
:array.sparse_foldl(
fn _, n, b -> b + n end,
0,
P2.solve(data)
)