diff --git a/2020/day11/day11.ex b/2020/day11/day11.ex new file mode 100644 index 0000000..27cb65b --- /dev/null +++ b/2020/day11/day11.ex @@ -0,0 +1,93 @@ +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()