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