You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/2024/puzzles/day20.md
+253Lines changed: 253 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -2,16 +2,269 @@ import Solver from "../../../../../website/src/components/Solver.js"
2
2
3
3
# Day 20: Race Condition
4
4
5
+
by [@scarf005](https://github.com/scarf005)
6
+
5
7
## Puzzle description
6
8
7
9
https://adventofcode.com/2024/day/20
8
10
11
+
## Solution Summary
12
+
13
+
Both parts of the problem are essentially the same - they ask you to find the shortest 'cheated' path. The only difference is the duration you can cheat.
14
+
15
+
1. Parse the input into start point, end point, and path
16
+
2. For each step, collect a list of all possible cheated positions
17
+
3. Sum cheats that would save at least 100 picoseconds
18
+
19
+
## Data Structures
20
+
21
+
Let's define the core data structure first: `Pos`. It represents a `(x,y)` position in the grid. Since `Pos` will be used _extensively_, we should make it as performant as possible. It's defined as an [opaque type](https://docs.scala-lang.org/scala3/book/types-opaque-types.html), giving it the performance of `Int` while maintaining the ergonomics of a regular case object `Pos` with `x` and `y` fields.
22
+
23
+
```scala
24
+
opaquetypePos=Int// 1)
25
+
26
+
objectPos:
27
+
valup=Pos(0, -1)
28
+
valdown=Pos(0, 1)
29
+
valleft=Pos(-1, 0)
30
+
valright=Pos(1, 0)
31
+
valzero=Pos(0, 0)
32
+
inlinedefapply(x: Int, y: Int):Pos= y <<16| x // 2)
-`1)`: A new type `Pos` is declared that isn't interchangeable with `Int`.
44
+
-`2)`: An `Int` is 32 bits. The lower 16 bits store `x` and the upper 16 bits store `y`. This is safe as the width and height of the given map won't exceed 65536 tiles (2^16).
45
+
-`3)`: `AND`ing with `0xffff` (=`0x0000ffff`) keeps only the lower 16 bits, effectively extracting `x`.
46
+
47
+
:::info
48
+
49
+
To better illustrate how `Pos` works, here's the hexadecimal layout:
50
+
51
+
```
52
+
// 0x 00ff 0001
53
+
// hex y position x position
54
+
55
+
scala> 0x00ff0001
56
+
val res1: Int = 16711681
57
+
58
+
// bit-shift to extract the y poisition 0x00ff
59
+
scala> 0x00ff0001 >> 16
60
+
val res2: Int = 255
61
+
62
+
// AND it to extract the x position 0001
63
+
scala> 0x00ff0001 & 0x0000ffff
64
+
val res3: Int = 1
65
+
```
66
+
67
+
:::
68
+
69
+
The `Rect` case class marks the boundaries of the track.
70
+
71
+
```scala
72
+
extension (x: Int) inlinedef±(y: Int) = x - y to x + y // 1)
73
+
extension (x: Inclusive)
74
+
inlinedef&(y: Inclusive) = (x.start max y.start) to (x.end min y.end) // 2)
75
+
76
+
caseclassRect(x: Inclusive, y: Inclusive):
77
+
inlinedef&(that: Rect) =Rect(x & that.x, y & that.y) // 3)
78
+
79
+
defiterator:Iterator[Pos] =for// 4)
80
+
y <- y.iterator
81
+
x <- x.iterator
82
+
yieldPos(x, y)
83
+
```
84
+
85
+
-`1)`: Convenience method to create a range from `x-y` to `x+y`.
86
+
-`2)`: Convenience method to create a range from the intersection of two ranges.
87
+
-`3)`: Convenience method to create a new `Rect` from the intersection of two Rects.
88
+
-`4)`: `O(1)` space iterator to iterate over all positions in the `Rect`.
89
+
90
+
## Parsing
91
+
92
+
The input is a large maze with a **single path** from start to end.
93
+
Since the solution involves moving forward in the path frequently, storing the path as a set is more efficient.
-[Solution](https://github.com/rmarbeck/advent2024/blob/main/day20/src/main/scala/Solution.scala) by [Raphaël Marbeck](https://github.com/rmarbeck)
12
264
-[Solution](https://github.com/nikiforo/aoc24/blob/main/src/main/scala/io/github/nikiforo/aoc24/D20T2.scala) by [Artem Nikiforov](https://github.com/nikiforo)
13
265
-[Solution](https://github.com/aamiguet/advent-2024/blob/main/src/main/scala/ch/aamiguet/advent2024/Day20.scala) by [Antoine Amiguet](https://github.com/aamiguet)
14
266
-[Solution](https://github.com/merlinorg/aoc2024/blob/main/src/main/scala/Day20.scala) by [merlinorg](https://github.com/merlinorg)
267
+
-[Solution](https://github.com/scarf005/aoc-scala/blob/main/2024/day20.scala) by [scarf](https://github.com/scarf005)
15
268
-[Writeup](https://thedrawingcoder-gamer.github.io/aoc-writeups/2024/day20.html) by [Bulby](https://github.com/TheDrawingCoder-Gamer)
16
269
-[Solution](https://github.com/AvaPL/Advent-of-Code-2024/tree/main/src/main/scala/day20) by [Paweł Cembaluk](https://github.com/AvaPL)
0 commit comments