67 lines
1.5 KiB
Elixir
67 lines
1.5 KiB
Elixir
defmodule AOC.Day21 do
|
|
# use AOC.Day, day: 21, input: "example"
|
|
use AOC.Day, day: 21
|
|
|
|
def parse_input(lines) do
|
|
map =
|
|
lines
|
|
|> Enum.with_index()
|
|
|> Enum.flat_map(fn {line, y} ->
|
|
line
|
|
|> String.to_charlist()
|
|
|> Enum.with_index()
|
|
|> Enum.map(fn {tile, x} -> {{y, x}, tile} end)
|
|
end)
|
|
|> Enum.into(%{})
|
|
|
|
start_position =
|
|
map
|
|
|> Enum.find(fn {_, tile} -> tile == ?S end)
|
|
|> elem(0)
|
|
|
|
{Map.put(map, start_position, ?.), start_position}
|
|
end
|
|
|
|
def walk(map, start_position, steps) do
|
|
map
|
|
|> do_walk(start_position, steps)
|
|
|> Enum.count()
|
|
end
|
|
|
|
def do_walk(map, position, _) when not is_map_key(map, position), do: []
|
|
def do_walk(map, position, _) when :erlang.map_get(position, map) == ?#, do: []
|
|
def do_walk(_map, position, 0), do: [position]
|
|
|
|
def do_walk(map, {y, x} = position, steps_left) do
|
|
case :ets.lookup(:steps_memo, {position, steps_left}) do
|
|
[] ->
|
|
reachable =
|
|
[{y - 1, x}, {y, x + 1}, {y + 1, x}, {y, x - 1}]
|
|
|> Enum.flat_map(fn neighbor_position ->
|
|
do_walk(map, neighbor_position, steps_left - 1)
|
|
end)
|
|
|> Enum.uniq()
|
|
|
|
:ets.insert(:steps_memo, {{position, steps_left}, reachable})
|
|
|
|
reachable
|
|
|
|
[{_, reachable}] ->
|
|
reachable
|
|
end
|
|
end
|
|
|
|
def part1({map, start_position}) do
|
|
:ets.new(:steps_memo, [:named_table])
|
|
|
|
map
|
|
|> walk(start_position, 64)
|
|
|> IO.inspect()
|
|
|
|
"TODO"
|
|
end
|
|
|
|
def part2(_input) do
|
|
"TODO"
|
|
end
|
|
end
|