Skip to content

Instantly share code, notes, and snippets.

@ynonp
Created December 17, 2020 21:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ynonp/2a1cbf88d8f3839c1004bd362d4b8f40 to your computer and use it in GitHub Desktop.
Save ynonp/2a1cbf88d8f3839c1004bd362d4b8f40 to your computer and use it in GitHub Desktop.
defmodule Day17 do
def read_input do
File.read!("input/day17.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, 0}, el } end) end)
|> Enum.into(%{})
end
def values_in_direction({ row, col, z }, { dy, dx, dz }, matrix) do
Stream.unfold({ row + dy, col + dx, z + dz }, fn { r, c, z } ->
cond do
Map.has_key?(matrix, { r, c, z }) -> {
Map.get(matrix, { r, c, z }),
{ r + dy, c + dx, z + dz }
}
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, k <- -1..1 do
{ i, j, k }
end
|> Enum.filter(&(&1 != {0, 0, 0}))
|> Enum.map(&(first_seat_in_direction(start, &1, matrix)))
end
def adjacent(matrix, { row, col, z }) do
keys = for i <- row-1..row+1, j <- col-1..col+1, k <- z-1..z+1, { i, j, k } != { row, col, z } do
{ i, j, k }
end
Map.new(keys, fn k -> { k, "." } end)
|> Map.merge(Map.take(matrix, keys))
end
def occupied(matrix) do
matrix
|> Enum.filter(fn
{ _k, v } -> v == "#"
val -> val == "#"
end)
end
def with_adjacent(matrix) do
matrix
|> occupied
|> Enum.flat_map(fn {k, _v} -> adjacent(matrix, k) end)
|> Enum.into(%{})
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
"#" -> if ((occupied_neighbors_count == 3) || (occupied_neighbors_count == 2)), do: "#", else: "."
"." -> if occupied_neighbors_count == 3, do: "#", else: "."
other -> other
end
}
end
def next_state(matrix, threshold, look_fn) do
matrix
|> with_adjacent
|> Enum.map(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()
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> occupied
|> Enum.count
|> IO.inspect
end
end
defmodule Day17_2 do
def read_input do
File.read!("input/day17.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, 0, 0}, el } end) end)
|> Enum.into(%{})
end
def adjacent(matrix, { row, col, z, w }) do
keys = for i <- row-1..row+1, j <- col-1..col+1, k <- z-1..z+1, l <- w-1..w+1, { i, j, k, l } != { row, col, z, w } do
{ i, j, k, l }
end
Map.new(keys, fn k -> { k, "." } end)
|> Map.merge(Map.take(matrix, keys))
end
def occupied(matrix) do
matrix
|> Enum.filter(fn
{ _k, v } -> v == "#"
val -> val == "#"
end)
end
def with_adjacent(matrix) do
matrix
|> occupied
|> Enum.flat_map(fn {k, _v} -> adjacent(matrix, k) end)
|> Enum.into(%{})
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
"#" -> if ((occupied_neighbors_count == 3) || (occupied_neighbors_count == 2)), do: "#", else: "."
"." -> if occupied_neighbors_count == 3, do: "#", else: "."
other -> other
end
}
end
def next_state(matrix, threshold, look_fn) do
matrix
|> with_adjacent
|> Enum.map(fn kv -> next_state(kv, matrix, threshold, look_fn) end)
|> Map.new
end
def part1 do
read_input()
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/2)
|> next_state(0, &adjacent/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