Advent of Code 2015 Day 18 Part 2
Mix.install([
{:kino_aoc, "~> 0.1"},
{:nx, "~> 0.9.2"}
])
Get Inputs
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2015", "18", System.fetch_env!("LB_SESSION"))
My answer
lights =
puzzle_input
|> String.split("\n")
|> Enum.map(fn row ->
row
|> String.codepoints()
|> Enum.map(fn light -> if light == "#", do: 1, else: 0 end)
end)
|> Nx.tensor()
tb_lights =
1..100
|> Enum.map(fn index -> if index == 1 or index == 100, do: 1, else: 0 end)
|> Nx.tensor()
|> Nx.new_axis(1)
inner_lights = Nx.broadcast(0, {100, 98})
corner_lights =
Nx.concatenate(
[tb_lights, inner_lights, tb_lights],
axis: 1
)
lights = Nx.logical_or(lights, corner_lights)
1..100
|> Enum.reduce(lights, fn _, acc_lights ->
around_on =
acc_lights
|> Nx.pad(0, [{1, 1, 0}, {1, 1, 0}])
|> Nx.window_sum({3, 3})
|> Nx.subtract(acc_lights)
current_on_next_on =
Nx.multiply(
acc_lights,
Nx.multiply(Nx.greater_equal(around_on, 2), Nx.less_equal(around_on, 3))
)
current_off_next_on =
Nx.multiply(
Nx.equal(acc_lights, 0),
Nx.equal(around_on, 3)
)
Nx.add(current_on_next_on, current_off_next_on)
|> Nx.logical_or(corner_lights)
end)
|> Nx.sum()