Day17
Setup
Mix.install([
{:kino, "~> 0.5.0"}
])
sample_text = Kino.Input.textarea("sample")
input_text = Kino.Input.textarea("input")
sample = Kino.Input.read(sample_text)
input = Kino.Input.read(input_text)
defmodule Shared do
def parse(text) do
text
|> String.replace("#", "1")
|> String.replace(".", "0")
|> String.split("\n", trim: true)
|> Enum.map(fn row ->
row
|> String.graphemes()
|> Enum.map(&String.to_integer/1)
end)
end
end
defmodule PartA do
def cube(array_of_array) do
size = length(array_of_array) - 1
null_array_of_array =
for _ <- 0..size do
for _ <- 0..size do
0
end
end
[null_array_of_array] ++
[array_of_array] ++
for _ <- 0..(size - 2) do
null_array_of_array
end
end
def grow(matrix) do
new_size = length(matrix)
for x <- -1..new_size do
for y <- -1..new_size do
for z <- -1..new_size do
access(matrix, x, y, z)
end
end
end
end
def access(matrix, x, y, z) do
size = length(matrix)
oob? = x < 0 || x >= size || y < 0 || y >= size || z < 0 || z >= size
if oob?, do: 0, else: matrix |> Enum.at(x) |> Enum.at(y) |> Enum.at(z)
end
def neighbors(matrix, i, j, k) do
for x <- -1..1, y <- -1..1, z <- -1..1, x != 0 || y != 0 || z != 0 do
access(matrix, i + x, j + y, k + z)
end
|> Enum.sum()
end
def cycle(matrix) do
grown_matrix = grow(matrix)
size = length(grown_matrix) - 1
for x <- 0..size do
for y <- 0..size do
for z <- 0..size do
case {access(grown_matrix, x, y, z), neighbors(grown_matrix, x, y, z)} do
{1, 2} -> 1
{1, 3} -> 1
{1, _} -> 0
{0, 3} -> 1
{0, _} -> 0
end
end
end
end
end
end
part a
input
|> Shared.parse()
|> PartA.cube()
|> PartA.cycle()
|> PartA.cycle()
|> PartA.cycle()
|> PartA.cycle()
|> PartA.cycle()
|> PartA.cycle()
|> Enum.concat()
|> Enum.concat()
|> Enum.sum()
part b
defmodule PartB do
def hypercube(array_of_array) do
cube = PartA.cube(array_of_array)
size = length(cube) - 1
null_cube =
for _ <- 0..size do
for _ <- 0..size do
for _ <- 0..size do
0
end
end
end
[null_cube] ++
[cube] ++
for _ <- 0..(size - 2) do
null_cube
end
end
def access(cube, x, y, z, w) do
size = length(cube)
oob? = x < 0 || x >= size || y < 0 || y >= size || z < 0 || z >= size || w < 0 || w >= size
if oob? do
0
else
cube |> Enum.at(x) |> Enum.at(y) |> Enum.at(z) |> Enum.at(w)
end
end
def grow(cube) do
new_size = length(cube)
for x <- -1..new_size do
for y <- -1..new_size do
for z <- -1..new_size do
for w <- -1..new_size do
access(cube, x, y, z, w)
end
end
end
end
end
def neighbors(cube, i, j, k, l) do
for x <- -1..1, y <- -1..1, z <- -1..1, w <- -1..1, x != 0 || y != 0 || z != 0 || w != 0 do
access(cube, i + x, j + y, k + z, l + w)
end
|> Enum.sum()
end
def cycle(cube) do
grown_cube = grow(cube)
size = length(grown_cube) - 1
for x <- 0..size do
for y <- 0..size do
for z <- 0..size do
for w <- 0..size do
case {access(grown_cube, x, y, z, w), neighbors(grown_cube, x, y, z, w)} do
{1, 2} -> 1
{1, 3} -> 1
{1, _} -> 0
{0, 3} -> 1
{0, _} -> 0
end
end
end
end
end
end
end
input
|> Shared.parse()
|> PartB.hypercube()
|> PartB.cycle()
|> PartB.cycle()
|> PartB.cycle()
|> PartB.cycle()
|> PartB.cycle()
|> PartB.cycle()
|> Enum.concat()
|> Enum.concat()
|> Enum.concat()
|> Enum.sum()