1
0
Fork 0

solve 2024 day 6

This commit is contained in:
sloane 2024-12-06 07:12:55 -05:00
parent a9dae7f820
commit db20c89051
Signed by: sloanelybutsurely
SSH key fingerprint: SHA256:8SBnwhl+RY3oEyQxy1a9wByPzxWM0x+/Ejc+sIlY5qQ
3 changed files with 129 additions and 2 deletions

View file

@ -2,7 +2,7 @@
| S | M | T | W | T | F | S |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| [1] | [2] | [3] | [4] | [5] | 6 | 7 |
| [1] | [2] | [3] | [4] | [5] | [6] | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | | | |
@ -12,3 +12,4 @@
[3]: ./lib/2024/3.ex
[4]: ./lib/2024/4.ex
[5]: ./lib/2024/5.ex
[6]: ./lib/2024/6.ex

126
2024/lib/2024/6.ex Normal file
View file

@ -0,0 +1,126 @@
import AOC
aoc 2024, 6 do
defmodule State do
@moduledoc false
defstruct [:pos, :dir, grid: %{}, visited: MapSet.new(), visited_pos_and_dir: MapSet.new(), looped?: false]
end
def p1(input) do
%State{} =
final_state =
input
|> read_state()
|> simulate()
MapSet.size(final_state.visited)
end
def p2(input) do
%State{} = state = read_state(input)
in_front_of_guard = forward(state).pos
for pos <- Map.keys(state.grid), pos != in_front_of_guard, not blocked?(state, pos), reduce: 0 do
sum ->
if (state
|> insert_obstacle(pos)
|> simulate()).looped? do
sum + 1
else
sum
end
end
end
defp insert_obstacle(%State{grid: grid} = state, pos), do: %State{state | grid: Map.put(grid, pos, "#")}
## simulation
defp simulate(%State{} = state) do
state
|> Stream.iterate(&step/1)
|> Stream.drop_while(&(in_bounds?(&1) and not &1.looped?))
|> Stream.take(1)
|> Enum.at(0)
end
defp step(%State{} = state) do
next = forward(state)
cond do
blocked?(next) ->
rotate_90(state)
MapSet.member?(state.visited_pos_and_dir, {next.pos, next.dir}) ->
%State{state | looped?: true}
true ->
visit(next)
end
end
defp in_bounds?(%State{grid: grid, pos: pos}), do: Map.has_key?(grid, pos)
defp blocked?(%State{pos: pos} = state), do: blocked?(state, pos)
defp blocked?(%State{grid: grid}, pos), do: Map.get(grid, pos) == "#"
defp forward(%State{dir: :up, pos: {i, j}} = state), do: %State{state | pos: {i, j - 1}}
defp forward(%State{dir: :down, pos: {i, j}} = state), do: %State{state | pos: {i, j + 1}}
defp forward(%State{dir: :left, pos: {i, j}} = state), do: %State{state | pos: {i - 1, j}}
defp forward(%State{dir: :right, pos: {i, j}} = state), do: %State{state | pos: {i + 1, j}}
defp rotate_90(%State{dir: :up} = state), do: %State{state | dir: :right}
defp rotate_90(%State{dir: :right} = state), do: %State{state | dir: :down}
defp rotate_90(%State{dir: :down} = state), do: %State{state | dir: :left}
defp rotate_90(%State{dir: :left} = state), do: %State{state | dir: :up}
defp visit(%State{pos: pos, dir: dir, visited: visited, visited_pos_and_dir: visited_pos_and_dir} = state) do
if in_bounds?(state) do
%State{
state
| visited: MapSet.put(visited, pos),
visited_pos_and_dir: MapSet.put(visited_pos_and_dir, {pos, dir})
}
else
state
end
end
## input
defp read_state(input) do
lines =
input
|> String.split("\n")
|> Enum.map(&String.graphemes/1)
for {line, y} <- Enum.with_index(lines),
{c, x} <- Enum.with_index(line),
reduce: %State{} do
%State{grid: grid, pos: nil, dir: nil} ->
dir =
case c do
"^" -> :up
">" -> :right
"<" -> :left
"v" -> :down
_ -> nil
end
if is_nil(dir) do
%State{grid: Map.put(grid, {x, y}, c)}
else
%State{
grid: Map.put(grid, {x, y}, "."),
dir: dir,
pos: {x, y},
visited: MapSet.new([{x, y}])
}
end
%State{grid: grid} = state ->
%State{state | grid: Map.put(grid, {x, y}, c)}
end
end
end

View file

@ -15,7 +15,7 @@
| [2021] | **43/50** 🌟 | Elixir |
| [2022] | **14/50** 🌟 | Elixir, Haskell |
| [2023] | **19/50** 🌟 | Elixir, Haskell |
| [2024] | **10/50** 🌟 | Elixir |
| [2024] | **12/50** 🌟 | Elixir |
| **Total** | **162** 🌟| |
[2015]: ./2015