Skip to content

Commit

Permalink
2024 day 18 part 2 successful optimization
Browse files Browse the repository at this point in the history
Use binary search to narrow down where the first byte that causes a failure is

Way too much time spent debugging off-by-one errors in the search though...
  • Loading branch information
sevenseacat committed Dec 18, 2024
1 parent d7197e2 commit 64a118c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 21 deletions.
4 changes: 2 additions & 2 deletions lib/y2024/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ day 15, part 1 5.06 197.80 ms ±0.60% 197.59 ms 201.
day 16, part 1 12.91 77.43 ms ±5.49% 77.14 ms 86.71 ms
day 16, part 2 13.07 76.51 ms ±5.00% 76.09 ms 85.69 ms
day 17, part 1 45.64 K 21.91 μs ±15.81% 21.17 μs 37.50 μs
day 18, part 1 22.34 0.0448 s ±5.84% 0.0449 s 0.0516 s
day 18, part 2 0.0329 30.44 s ±0.00% 30.44 s 30.44 s
day 18, part 1 22.53 44.38 ms ±5.11% 44.48 ms 48.54 ms
day 18, part 2 4.04 247.58 ms ±3.18% 247.68 ms 260.90 ms
```
54 changes: 37 additions & 17 deletions lib/y2024/day18.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,42 @@ defmodule Y2024.Day18 do
alias Advent.PathGrid

def part1(bytes, size \\ 70, byte_num \\ 1024) do
empty_grid({0, 0}, {size, size})
|> get_path(bytes, byte_num, size)
|> length()
|> Kernel.-(1)
end

def part2(bytes, size \\ 70) do
max_bytes = length(bytes)
empty_grid = empty_grid({0, 0}, {size, size})

# Binary search this thing.
{row, col} = run_binary_search(empty_grid, bytes, 0, max_bytes, size)
"#{row},#{col}"
end

defp run_binary_search(_grid, bytes, val, val, _), do: Enum.at(bytes, val - 1)

defp run_binary_search(grid, bytes, min, max, size) do
at = min + div(max - min, 2)

if get_path(grid, bytes, at, size) do
run_binary_search(grid, bytes, at + 1, max, size)
else
run_binary_search(grid, bytes, min, at, size)
end
end

defp get_path(grid, bytes, byte_num, size) do
fallen = Enum.take(bytes, byte_num)

graph =
Enum.reduce(fallen, empty_grid({0, 0}, {size, size}), fn coord, graph ->
Enum.reduce(fallen, grid, fn coord, graph ->
PathGrid.add_wall(graph, coord)
end)

length(Graph.get_shortest_path(graph, {0, 0}, {size, size})) - 1
end

def part2(bytes, size \\ 70) do
Enum.reduce_while(bytes, empty_grid({0, 0}, {size, size}), fn {row, col}, graph ->
graph = PathGrid.add_wall(graph, {row, col})

if Graph.get_shortest_path(graph, {0, 0}, {size, size}) == nil do
{:halt, "#{row},#{col}"}
else
{:cont, graph}
end
end)
Graph.get_shortest_path(graph, {0, 0}, {size, size})
end

@doc """
Expand All @@ -49,9 +65,13 @@ defmodule Y2024.Day18 do

[{row - 1, col}, {row, col - 1}]
|> Enum.reduce(graph, fn neighbour, graph ->
graph
|> Graph.add_edge({row, col}, neighbour)
|> Graph.add_edge(neighbour, {row, col})
if Graph.has_vertex?(graph, neighbour) do
graph
|> Graph.add_edge({row, col}, neighbour)
|> Graph.add_edge(neighbour, {row, col})
else
graph
end
end)
end)
end)
Expand Down
2 changes: 0 additions & 2 deletions test/y2024/day18_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ defmodule Y2024.Day18Test do
end

test "verification, part 1", do: assert(Day18.part1_verify() == 436)

@tag timeout: :infinity
test "verification, part 2", do: assert(Day18.part2_verify() == "61,50")

def test_data(), do: File.read!("test/y2024/input/day18/sample.txt")
Expand Down

0 comments on commit 64a118c

Please sign in to comment.