Skip to content

Instantly share code, notes, and snippets.

@ynonp
Last active December 11, 2020 12:47
Show Gist options
  • Save ynonp/89ace2253d8d74fe479564ba40221ff1 to your computer and use it in GitHub Desktop.
Save ynonp/89ace2253d8d74fe479564ba40221ff1 to your computer and use it in GitHub Desktop.
defmodule Day11 do
def read_input do
File.read!("input/day11.txt")
|> String.split("\n", trim: true)
|> Enum.map(&String.graphemes/1)
|> Enum.map(&Enum.with_index/1)
|> Enum.with_index
|> Enum.flat_map(fn {line, row} -> Enum.map(line, fn {el, col} -> {{row, col}, el } end) end)
|> Enum.into(%{})
end
def values_in_direction({ row, col }, { dy, dx }, matrix) do
Stream.unfold({ row + dy, col + dx }, fn { r, c } ->
cond do
Map.has_key?(matrix, { r, c }) -> {
Map.get(matrix, { r, c }),
{ r + dy, c + dx }
}
true -> nil
end
end)
end
def first_seat_in_direction(start, direction, matrix) do
values_in_direction(start, direction, matrix)
|> Enum.find(fn val -> val != "." end)
end
def visible(matrix, start) do
for i <- -1..1, j <- -1..1 do
{ i, j }
end
|> Enum.filter(&(&1 != {0, 0}))
|> Enum.map(&(first_seat_in_direction(start, &1, matrix)))
end
def adjacent(matrix, { row, col }) do
keys = for i <- row-1..row+1, j <- col-1..col+1, { i, j } != { row, col } do
{ i, j }
end
Map.take(matrix, keys)
end
def occupied(matrix) do
matrix
|> Enum.filter(fn
{ _k, v } -> v == "#"
val -> val == "#"
end)
end
def next_state({ key, value}, matrix, threshold, look_fn) do
occupied_neighbors_count = look_fn.(matrix, key)
|> occupied
|> Enum.count
{ key,
case value do
"L" -> if occupied_neighbors_count == 0, do: "#", else: "L"
"#" -> if occupied_neighbors_count >= threshold, do: "L", else: "#"
other -> other
end
}
end
def next_state(matrix, threshold, look_fn) do
Enum.map(matrix, fn kv -> next_state(kv, matrix, threshold, look_fn) end)
|> Map.new
end
def loop_until_stable(matrix, threshold, look_fn) do
if matrix == next_state(matrix, threshold, look_fn) do
matrix
else
loop_until_stable(next_state(matrix, threshold, look_fn), threshold, look_fn)
end
end
def part1 do
read_input()
|> loop_until_stable(4, &adjacent/2)
|> occupied
|> Enum.count
|> IO.inspect
end
def part2 do
read_input()
|> loop_until_stable(5, &visible/2)
|> occupied
|> Enum.count
|> IO.inspect
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment