Skip to content

Instantly share code, notes, and snippets.

@hallski
Last active December 17, 2020 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hallski/d008696327bbb7b59530eaff4dc2ad8f to your computer and use it in GitHub Desktop.
Save hallski/d008696327bbb7b59530eaff4dc2ad8f to your computer and use it in GitHub Desktop.
Advent of Code: Day 17
defmodule AdventOfCode.Day17 do
def run(input) do
input
|> parse()
|> simulate(6)
|> Kernel.map_size()
end
def simulate(pocket, 0), do: pocket
def simulate(pocket, iterations) do
new_pocket =
pocket
|> simulate_one()
|> Enum.filter(fn {_, state} -> state == "#" end)
|> Enum.into(%{})
simulate(new_pocket, iterations - 1)
end
def simulate_one(pocket) do
[x_range, y_range, z_range, w_range] = simulation_space(pocket)
for x <- x_range,
y <- y_range,
z <- z_range,
w <- w_range do
coordinate = {x, y, z, w}
{coordinate, new_state(pocket, coordinate)}
end
end
def simulation_space(pocket) do
x_range = pocket |> Enum.map(fn {{x, _, _, _}, _} -> x end) |> Enum.min_max()
y_range = pocket |> Enum.map(fn {{_, y, _, _}, _} -> y end) |> Enum.min_max()
z_range = pocket |> Enum.map(fn {{_, _, z, _}, _} -> z end) |> Enum.min_max()
w_range = pocket |> Enum.map(fn {{_, _, _, w}, _} -> w end) |> Enum.min_max()
sim_range = fn {min, max} -> (min - 1)..(max + 1) end
[x_range, y_range, z_range, w_range] |> Enum.map(sim_range)
end
def new_state(pocket, coordinate) do
state = Map.get(pocket, coordinate, ".")
active_neighbours = get_active_neighbours(pocket, coordinate)
state(state, active_neighbours)
end
def state("#", neighbors) when neighbors in 2..3, do: "#"
def state(".", 3), do: "#"
def state(_, _), do: "."
def get_active_neighbours(pocket, {x, y, z, w}) do
check_range = fn n -> (n - 1)..(n + 1) end
for(
xp <- check_range.(x),
yp <- check_range.(y),
zp <- check_range.(z),
wp <- check_range.(w),
{x, y, z, w} != {xp, yp, zp, wp},
do: Map.get(pocket, {xp, yp, zp, wp}, ".")
)
|> Enum.filter(fn state -> state == "#" end)
|> Enum.count()
end
def parse(data) do
data
|> String.split("\n", trim: true)
|> Enum.with_index()
|> Enum.flat_map(fn {data, y} ->
String.split(data, "", trim: true)
|> Enum.with_index()
|> Enum.filter(fn {state, _} -> state == "#" end)
|> Enum.map(fn {state, x} -> {{x, y, 0, 0}, state} end)
end)
|> Map.new()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment