Advent of Code 2024
Mix.install([
{:req, "~> 0.3.2"}
])
Day 6
input =
"https://adventofcode.com/2024/day/6/input"
|> Req.get!(headers: [cookie: "session=#{System.get_env("AOC_COOKIE")}"])
|> Map.get(:body)
sample = """
....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...
"""
defmodule Day6 do
def parse(input) do
lines =
input
|> String.split("\n", trim: true)
|> Enum.map(&String.split(&1, "", trim: true))
for {row, y} <- Enum.with_index(lines),
{val, x} <- Enum.with_index(row),
into: %{},
do: {{x, y}, val}
end
def step({x, y}, :up), do: {x, y - 1}
def step({x, y}, :down), do: {x, y + 1}
def step({x, y}, :left), do: {x - 1, y}
def step({x, y}, :right), do: {x + 1, y}
def turn(:up), do: :right
def turn(:down), do: :left
def turn(:left), do: :up
def turn(:right), do: :down
end
import Day6
Part 1
grid =
input
|> parse()
{start, _} =
grid
|> Enum.find(fn {_k, v} -> v == "^" end)
visited = MapSet.new([start])
grid = Map.put(grid, start, ".")
guard_path =
Stream.iterate(1, &(&1 + 1))
|> Enum.reduce_while({start, :up, visited}, fn _, {pos, dir, visited} ->
next = step(pos, dir)
case Map.get(grid, next) do
"." ->
{:cont, {next, dir, MapSet.put(visited, next)}}
"#" ->
{:cont, {pos, turn(dir), visited}}
nil ->
{:halt, visited}
end
end)
guard_path
|> MapSet.size()
Part 2
# positions_to_try =
# grid
# |> Enum.filter(fn {_k, v} -> v == "." end)
# |> Enum.map(&elem(&1, 0))
visited = MapSet.new([start])
grid = Map.put(grid, start, ".")
# check all positions the guard normally walks
positions_to_try =
guard_path
|> MapSet.delete(start)
positions_to_try
|> Task.async_stream(fn position_to_block ->
grid = Map.put(grid, position_to_block, "#")
Stream.iterate(1, &(&1 + 1))
|> Enum.reduce_while({start, :up, Map.new()}, fn _, {pos, dir, visited} ->
next = step(pos, dir)
case Map.get(grid, next) do
"." ->
{:cont, {next, dir, visited}}
"#" ->
if Map.get(visited, pos, 0) > 1 do
{:halt, true}
else
{:cont, {pos, turn(dir), Map.update(visited, pos, 1, &(&1 + 1))}}
end
nil ->
{:halt, false}
end
end)
end)
|> Enum.count(&(&1 |> elem(1)))