1
0
Fork 0
advent-of-code/2015/lib/2015/18.ex
2022-09-21 09:19:53 -04:00

105 lines
2.3 KiB
Elixir

import AOC
aoc 2015, 18 do
def input() do
lists =
input_string()
|> String.split("\n", trim: true)
|> Enum.map(fn line ->
line
|> String.split("", trim: true)
|> Enum.map(&decode_state/1)
|> Enum.with_index(1)
end)
|> Enum.with_index(1)
for {row, i} <- lists, {cell, j} <- row, into: %{} do
{{i, j}, cell}
end
end
def decode_state("#"), do: :on
def decode_state("."), do: :off
def encode_state(:on), do: "#"
def encode_state(:off), do: :off
def n({i, j}), do: {i - 1, j}
def e({i, j}), do: {i, j + 1}
def s({i, j}), do: {i + 1, j}
def w({i, j}), do: {i, j - 1}
def ne(pos), do: pos |> n() |> e()
def se(pos), do: pos |> s() |> e()
def sw(pos), do: pos |> s() |> w()
def nw(pos), do: pos |> n() |> w()
def neighbors(map, pos) do
[&n/1, &ne/1, &e/1, &se/1, &s/1, &sw/1, &w/1, &nw/1]
|> Enum.map(&apply(&1, [pos]))
|> Enum.map(&Map.get(map, &1, :off))
|> Enum.frequencies()
end
def tick(map) do
for {pos, cell} <- map, into: %{} do
next_cell =
case {cell, neighbors(map, pos)} do
{:on, %{on: on}} when on in [2, 3] -> :on
{:on, _} -> :off
{:off, %{on: 3}} -> :on
{:off, _} -> :off
end
{pos, next_cell}
end
end
def tick_with_corners_on(map) do
for {pos, cell} <- map, into: %{} do
if pos in [{1, 1}, {1, 100}, {100, 1}, {100, 100}] do
{pos, :on}
else
next_cell =
case {cell, neighbors(map, pos)} do
{:on, %{on: on}} when on in [2, 3] -> :on
{:on, _} -> :off
{:off, %{on: 3}} -> :on
{:off, _} -> :off
end
{pos, next_cell}
end
end
end
def p1 do
start = input()
finish =
for _ <- 1..100, reduce: start do
curr -> tick(curr)
end
finish
|> Map.values()
|> Enum.count(&(&1 == :on))
end
def p2 do
start =
input()
|> Map.put({1, 1}, :on)
|> Map.put({1, 100}, :on)
|> Map.put({100, 1}, :on)
|> Map.put({100, 100}, :on)
finish =
for _ <- 1..100, reduce: start do
curr -> tick_with_corners_on(curr)
end
finish
|> Map.values()
|> Enum.count(&(&1 == :on))
end
end