Skip to content

Commit 17ba4f3

Browse files
committed
Add day06 solution
1 parent deb6d74 commit 17ba4f3

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

2024/06.livemd

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Advent of Code 2024 - Day 06
2+
3+
```elixir
4+
Mix.install([
5+
{:req, "~> 0.5"},
6+
{:benchee, "~> 1.3"}
7+
])
8+
```
9+
10+
## Input
11+
12+
```elixir
13+
opts = [headers: [{"cookie", "session=#{System.fetch_env!("LB_AOC_SESSION")}"}]]
14+
puzzle_input = Req.get!("https://adventofcode.com/2024/day/6/input", opts).body
15+
```
16+
17+
```elixir
18+
grid =
19+
String.split(puzzle_input, "\n", trim: true)
20+
|> Enum.map(fn row ->
21+
String.codepoints(row)
22+
|> Enum.with_index()
23+
|> Enum.map(fn {char, index} -> {index, char} end)
24+
|> Map.new()
25+
end)
26+
|> Enum.with_index()
27+
|> Enum.map(fn {char, index} -> {index, char} end)
28+
|> Map.new()
29+
```
30+
31+
## Grid
32+
33+
```elixir
34+
defmodule Grid do
35+
def rotate_dir_90({0, -1}), do: {1, 0}
36+
def rotate_dir_90({1, 0}), do: {0, 1}
37+
def rotate_dir_90({0, 1}), do: {-1, 0}
38+
def rotate_dir_90({-1, 0}), do: {0, -1}
39+
40+
def move_dir({col_modifier, row_modifier} = _dir, {col, row} = _pos) do
41+
{col + col_modifier, row + row_modifier}
42+
end
43+
44+
def find(grid, char) do
45+
Enum.reduce_while(grid, nil, fn {row_i, row_value}, _acc ->
46+
case Enum.find(row_value, fn {_k, v} -> v == char end) do
47+
{col_i, _col_value} -> {:halt, {col_i, row_i}}
48+
nil -> {:cont, nil}
49+
end
50+
end)
51+
end
52+
53+
def update(grid, {col, row} = _pos, value) do
54+
Map.update!(grid, row, fn r ->
55+
Map.put(r, col, value)
56+
end)
57+
end
58+
59+
def at(grid, {col, row} = _pos) do
60+
get_in(grid, [row, col]) || ""
61+
end
62+
end
63+
```
64+
65+
## Puzzle 1
66+
67+
```elixir
68+
defmodule Puzzle1 do
69+
def count_visited(grid, current_pos, dir, visited) do
70+
facing_pos = Grid.move_dir(dir, current_pos)
71+
facing_obstacle = Grid.at(grid, facing_pos)
72+
73+
case facing_obstacle do
74+
"" -> visited |> Enum.uniq() |> Enum.count()
75+
"." -> count_visited(grid, facing_pos, dir, [facing_pos | visited])
76+
"#" -> count_visited(grid, current_pos, Grid.rotate_dir_90(dir), visited)
77+
end
78+
end
79+
end
80+
81+
puzzle_1 = fn ->
82+
start_pos = Grid.find(grid, "^")
83+
grid = Grid.update(grid, start_pos, ".")
84+
85+
Puzzle1.count_visited(grid, start_pos, {0, -1}, [start_pos])
86+
end
87+
88+
puzzle_1.()
89+
```
90+
91+
## Puzzle 2
92+
93+
```elixir
94+
defmodule Puzzle2 do
95+
def loop?(grid, current_pos, dir, visited \\ []) do
96+
facing_pos = Grid.move_dir(dir, current_pos)
97+
facing_obstacle = Grid.at(grid, facing_pos)
98+
99+
cond do
100+
{current_pos, dir} in visited ->
101+
1
102+
103+
facing_obstacle == "#" ->
104+
loop?(grid, current_pos, Grid.rotate_dir_90(dir), [{current_pos, dir} | visited])
105+
106+
facing_obstacle == "." ->
107+
loop?(grid, facing_pos, dir, [{current_pos, dir} | visited])
108+
109+
true ->
110+
0
111+
end
112+
end
113+
end
114+
115+
puzzle_2 = fn ->
116+
start_pos = Grid.find(grid, "^")
117+
grid = Grid.update(grid, start_pos, ".")
118+
119+
row_range = Map.keys(grid) |> length()
120+
col_range = Map.get(grid, 0) |> Map.keys() |> length()
121+
122+
positions_to_check =
123+
for row <- 0..(row_range - 1), col <- 0..(col_range - 1) do
124+
{col, row}
125+
end
126+
|> Enum.filter(fn pos ->
127+
Grid.at(grid, pos) != "#" and pos != start_pos
128+
end)
129+
130+
positions_to_check
131+
|> Task.async_stream(fn pos ->
132+
Grid.update(grid, pos, "#")
133+
|> Puzzle2.loop?(start_pos, {0, -1})
134+
end)
135+
|> Enum.reduce(0, fn {:ok, result}, acc -> acc + result end)
136+
end
137+
138+
puzzle_2.()
139+
```
140+
141+
<!-- livebook:{"offset":3190,"stamp":{"token":"XCP.ZIz-v6sUQcM1Lm_PpVOn6JmIUrVushSMizvoGpA0ASgugGV3iX9504iqHEPT6lx7CVjDB33joZgNM--Z_4f-u3PVhnailJyoaVn_WO5E9GRgdskIDzY","version":2}} -->

0 commit comments

Comments
 (0)