Day 17 Part 1
This commit is contained in:
parent
acbd4a0237
commit
34d4dea789
1 changed files with 165 additions and 0 deletions
165
2020/day17/day17.ex
Normal file
165
2020/day17/day17.ex
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
defmodule Day17 do
|
||||||
|
defp read_input do
|
||||||
|
Path.expand('input', Path.dirname(__ENV__.file))
|
||||||
|
|> File.read!()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp test_input do
|
||||||
|
"""
|
||||||
|
.#.
|
||||||
|
..#
|
||||||
|
###
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_space(text) do
|
||||||
|
String.split(text, "\n", trim: true)
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.reduce(%{}, fn {line, y}, map ->
|
||||||
|
String.codepoints(line)
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.reduce(map, fn {char, x}, map ->
|
||||||
|
Map.put(map, {x, y, 0}, char_to_content(char))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp char_to_content(char) do
|
||||||
|
case char do
|
||||||
|
"." -> :inactive
|
||||||
|
"#" -> :active
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp state_char(char) do
|
||||||
|
case char do
|
||||||
|
:inactive -> "."
|
||||||
|
:active -> "#"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp expand_range(lo..hi, val) do
|
||||||
|
cond do
|
||||||
|
val < lo -> val..hi
|
||||||
|
val > hi -> lo..val
|
||||||
|
true -> lo..hi
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_bounds(space) do
|
||||||
|
Enum.reduce(space, %{x: 0..0, y: 0..0, z: 0..0}, fn {{x, y, z}, state}, bounds ->
|
||||||
|
case state do
|
||||||
|
:inactive ->
|
||||||
|
bounds
|
||||||
|
|
||||||
|
:active ->
|
||||||
|
%{
|
||||||
|
x: expand_range(bounds.x, x),
|
||||||
|
y: expand_range(bounds.y, y),
|
||||||
|
z: expand_range(bounds.z, z)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp show(space) do
|
||||||
|
bounds = get_bounds(space)
|
||||||
|
|
||||||
|
for z <- bounds.z do
|
||||||
|
IO.puts("z = #{z}")
|
||||||
|
|
||||||
|
for y <- bounds.y do
|
||||||
|
for x <- bounds.x do
|
||||||
|
state = Map.get(space, {x, y, z}, :inactive)
|
||||||
|
IO.write(state_char(state))
|
||||||
|
end
|
||||||
|
|
||||||
|
IO.write("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
IO.write("\n\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
space
|
||||||
|
end
|
||||||
|
|
||||||
|
defp populate(space) do
|
||||||
|
Enum.reduce(space, %{}, fn {cell, state}, counts ->
|
||||||
|
if state == :inactive do
|
||||||
|
counts
|
||||||
|
else
|
||||||
|
neighbors(cell)
|
||||||
|
|> Enum.reduce(counts, fn neighbor, counts ->
|
||||||
|
Map.put(counts, neighbor, 1 + Map.get(counts, neighbor, 0))
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp tick(space) do
|
||||||
|
populate(space)
|
||||||
|
|> Enum.reduce(%{}, fn {cell, count}, new_space ->
|
||||||
|
new_state =
|
||||||
|
case Map.get(space, cell, :inactive) do
|
||||||
|
:active ->
|
||||||
|
if count == 2 or count == 3 do
|
||||||
|
:active
|
||||||
|
else
|
||||||
|
:inactive
|
||||||
|
end
|
||||||
|
|
||||||
|
:inactive ->
|
||||||
|
if count == 3 do
|
||||||
|
:active
|
||||||
|
else
|
||||||
|
:inactive
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
case new_state do
|
||||||
|
:active -> Map.put(new_space, cell, :active)
|
||||||
|
:inactive -> new_space
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp neighbors(cell = {x, y, z}) do
|
||||||
|
for dx <- -1..1,
|
||||||
|
dy <- -1..1,
|
||||||
|
dz <- -1..1 do
|
||||||
|
{x + dx, y + dy, z + dz}
|
||||||
|
end
|
||||||
|
|> Enum.reject(&(&1 == cell))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp run(space, 0) do
|
||||||
|
space
|
||||||
|
end
|
||||||
|
|
||||||
|
defp run(space, cycles) do
|
||||||
|
IO.puts("cycles = #{cycles}")
|
||||||
|
show(space)
|
||||||
|
|
||||||
|
tick(space)
|
||||||
|
|> run(cycles - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def part1 do
|
||||||
|
read_input()
|
||||||
|
|> parse_space()
|
||||||
|
|> run(6)
|
||||||
|
|> show()
|
||||||
|
|> Enum.count(fn {_cell, state} -> state == :active end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def debug do
|
||||||
|
test_input()
|
||||||
|
|> parse_space()
|
||||||
|
|> tick()
|
||||||
|
|
||||||
|
# neighbors(%{}, {0, 0, 0})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Day17.part1() |> IO.inspect()
|
||||||
|
# Day17.debug() |> IO.inspect()
|
||||||
Loading…
Reference in a new issue