93 lines
1.7 KiB
Elixir
93 lines
1.7 KiB
Elixir
defmodule Day11 do
|
|
defp read_input do
|
|
Path.expand('input', Path.dirname(__ENV__.file))
|
|
|> File.read!()
|
|
end
|
|
|
|
defp parse_layout(text) do
|
|
String.split(text, "\n", trim: true)
|
|
|> Enum.with_index()
|
|
|> Enum.reduce(%{}, fn {line, r}, map ->
|
|
String.codepoints(line)
|
|
|> Enum.with_index()
|
|
|> Enum.reduce(map, fn {char, c}, map ->
|
|
Map.put(map, {r, c}, char_to_content(char))
|
|
end)
|
|
end)
|
|
end
|
|
|
|
defp char_to_content(char) do
|
|
case char do
|
|
"." -> :floor
|
|
"L" -> :empty
|
|
"#" -> :occupied
|
|
end
|
|
end
|
|
|
|
defp content(grid, cell) do
|
|
Map.get(grid, cell, :floor)
|
|
end
|
|
|
|
defp neighbors(grid, {r, c}) do
|
|
[
|
|
{r - 1, c - 1},
|
|
{r - 1, c},
|
|
{r - 1, c + 1},
|
|
{r, c - 1},
|
|
{r, c + 1},
|
|
{r + 1, c - 1},
|
|
{r + 1, c},
|
|
{r + 1, c + 1}
|
|
]
|
|
|> Enum.map(&content(grid, &1))
|
|
end
|
|
|
|
defp tick(grid) do
|
|
Enum.into(grid, %{}, fn {cell, state} ->
|
|
new_state =
|
|
case state do
|
|
:floor ->
|
|
:floor
|
|
|
|
:empty ->
|
|
if Enum.all?(neighbors(grid, cell), &(&1 != :occupied)) do
|
|
:occupied
|
|
else
|
|
:empty
|
|
end
|
|
|
|
:occupied ->
|
|
if Enum.count(neighbors(grid, cell), &(&1 == :occupied)) >= 4 do
|
|
:empty
|
|
else
|
|
:occupied
|
|
end
|
|
end
|
|
|
|
{cell, new_state}
|
|
end)
|
|
end
|
|
|
|
defp run(grid) do
|
|
new_grid = tick(grid)
|
|
|
|
if new_grid == grid do
|
|
grid
|
|
else
|
|
run(new_grid)
|
|
end
|
|
end
|
|
|
|
defp count_seated(grid) do
|
|
Map.values(grid) |> Enum.count(&(&1 == :occupied))
|
|
end
|
|
|
|
def part1 do
|
|
read_input()
|
|
|> parse_layout()
|
|
|> run()
|
|
|> count_seated()
|
|
end
|
|
end
|
|
|
|
Day11.part1() |> IO.inspect()
|