1
1
package AdventOfCode2022
2
2
3
- import scala .annotation .tailrec
4
-
5
3
object Day17 :
6
4
val shapes = Seq (
7
5
Set (Point (0 , 0 ), Point (1 , 0 ), Point (2 , 0 ), Point (3 , 0 )),
@@ -10,44 +8,45 @@ object Day17:
10
8
Set (Point (0 , 0 ), Point (0 , 1 ), Point (0 , 2 ), Point (0 , 3 )),
11
9
Set (Point (0 , 0 ), Point (1 , 0 ), Point (0 , 1 ), Point (1 , 1 )))
12
10
11
+ case class Point (x : Int , y : Int )
12
+
13
13
extension (shape : Set [Point ])
14
14
def move (dx : Int , dy : Int ): Set [Point ] = shape.map(p => Point (p.x + dx, p.y + dy))
15
15
def canMove (grid : Set [Point ]): Boolean = shape.forall(p => p.x > 0 && p.x < 8 && ! grid.contains(p))
16
16
17
- case class Point (x : Int , y : Int )
18
- case class State (grid : Set [Point ], shapeIndex : Int , jetIndex : Int , height : Int )
19
-
20
- @ tailrec
21
- def fall (grid : Set [Point ], shape : Set [Point ], jets : String , jetIndex : Int ): (Set [Point ], Int ) =
22
- val jet = jets(jetIndex % jets.length)
23
- val first = if jet == '>' then shape.move(1 , 0 ) else shape.move(- 1 , 0 )
24
- val second = if first.canMove(grid) then first else shape
25
- val third = second.move(0 , - 1 )
26
- if third.canMove(grid) then fall(grid, third, jets, jetIndex + 1 ) else (second, jetIndex + 1 )
27
-
28
- def step (jets : String )(state : State ): State =
29
- val State (grid, shapeIndex, jetIndex, height) = state
30
- val initialShape = shapes(shapeIndex % shapes.size).move(3 , height + 4 )
31
- val (nextShape, nextJetIndex) = fall(grid, initialShape, jets, jetIndex)
32
- State (grid ++ nextShape, shapeIndex + 1 , nextJetIndex, height.max(nextShape.map(_.y).max))
17
+ case class State (jets : String , grid : Set [Point ], shapeIndex : Int , jetIndex : Int , height : Int ):
18
+ def step : State =
19
+ val initialShape = shapes(shapeIndex % shapes.size).move(3 , height + 4 )
20
+ val (nextShape, nextJetIndex) = fall(initialShape, jetIndex)
21
+ val nextHeight = height.max(nextShape.map(_.y).max)
22
+ State (jets, grid ++ nextShape, shapeIndex + 1 , nextJetIndex, nextHeight)
23
+
24
+ def fall (shape : Set [Point ], jetIndex : Int ): (Set [Point ], Int ) =
25
+ val jet = jets(jetIndex % jets.length)
26
+ val first = if jet == '>' then shape.move(1 , 0 ) else shape.move(- 1 , 0 )
27
+ val second = if first.canMove(grid) then first else shape
28
+ val third = second.move(0 , - 1 )
29
+ if third.canMove(grid) then fall(third, jetIndex + 1 ) else (second, jetIndex + 1 )
30
+ end State
33
31
34
32
def simulate (jets : String ): Iterator [Int ] =
35
- val initial = State (Set .tabulate(8 )(Point (_, 0 )), 0 , 0 , 0 )
36
- Iterator .iterate(initial)(step(jets) ).map(_.height)
33
+ val initial = State (jets, Set .tabulate(8 )(Point (_, 0 )), 0 , 0 , 0 )
34
+ Iterator .iterate(initial)(_. step).map(_.height)
37
35
38
36
def part1 (input : String ): Int = simulate(input).drop(2022 ).next()
39
37
40
38
def part2 (input : String ): Long =
41
39
val guess = 1000
42
- val height = simulate(input).slice(1 , 10 * guess).toSeq
43
- val delta = height.sliding(2 ).map { case Seq (a, b) => b - a }.toSeq
44
- val index = delta.lastIndexOfSlice(delta.takeRight(guess), delta.size - guess - 1 )
45
- val cycleHeight = height(delta.size - guess) - height(index)
46
- val cycleWidth = delta.size - guess - index
47
- val offset = 1000000000000L - 1 - index
40
+ val height = simulate(input).slice(1 , 5 * guess).toSeq
41
+ val delta = height.sliding(2 ).map(s => s.last - s.head).toSeq
42
+ val end = delta.size - guess
43
+ val start = delta.lastIndexOfSlice(delta.takeRight(guess), end - 1 )
44
+ val cycleHeight = height(end) - height(start)
45
+ val cycleWidth = end - start
46
+ val offset = 1000000000000L - 1 - start
48
47
val quotient = offset / cycleWidth
49
48
val remainder = offset % cycleWidth
50
- (quotient * cycleHeight) + height(index + remainder.toInt)
49
+ (quotient * cycleHeight) + height(start + remainder.toInt)
51
50
52
51
def main (args : Array [String ]): Unit =
53
52
val data = io.Source .fromResource(" AdventOfCode2022/Day17.txt" ).mkString.trim
0 commit comments