@@ -10,42 +10,36 @@ object Day17:
10
10
Set (Point (0 , 0 ), Point (0 , 1 ), Point (0 , 2 ), Point (0 , 3 )),
11
11
Set (Point (0 , 0 ), Point (1 , 0 ), Point (0 , 1 ), Point (1 , 1 )))
12
12
13
- case class Point (x : Int , y : Int ):
14
- def + (other : Point ): Point = Point (x + other.x, y + other.y)
13
+ extension (shape : Set [Point ])
14
+ def move (dx : Int , dy : Int ): Set [Point ] = shape.map(p => Point (p.x + dx, p.y + dy))
15
+ def canMove (grid : Set [Point ]): Boolean = shape.forall(p => p.x > 0 && p.x < 8 && ! grid.contains(p))
15
16
16
- case class State (grid : Set [Point ], wind : String , shapeIndex : Int , windIndex : Int , height : Int )
17
+ case class Point (x : Int , y : Int )
18
+ case class State (grid : Set [Point ], shapeIndex : Int , jetIndex : Int , height : Int )
17
19
18
20
@ tailrec
19
- def fall (grid : Set [Point ], shape : Set [Point ], wind : String , windIndex : Int ): (Int , Set [Point ]) =
20
- var next = shape
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 )
21
27
22
- val gust = wind(windIndex % wind.size)
23
- val shift = if gust == '>' then Point (1 , 0 ) else Point (- 1 , 0 )
24
- var test = shape.map(_ + shift)
25
- if test.forall(p => p.x > 0 && p.x < 8 && ! grid.contains(p)) then next = test
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))
26
33
27
- test = next.map(_ + Point ( 0 , - 1 ))
28
- if test.exists(grid.contains) then (windIndex + 1 , next) else fall(grid, test, wind, windIndex + 1 )
29
- end fall
34
+ 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)
30
37
31
- def step (state : State ): State =
32
- val State (grid, wind, shapeIndex, windIndex, height) = state
33
- val initial = Point (3 , height + 4 )
34
- val next = shapes(shapeIndex % shapes.size).map(_ + initial)
35
- val (nextWindIndex, foo) = fall(grid, next, wind, windIndex)
36
-
37
- State (grid ++ foo, wind, shapeIndex + 1 , nextWindIndex, height.max(foo.map(_.y).max))
38
- end step
39
-
40
- def simulate (input : String ): Iterator [State ] =
41
- val initial = State (Set .tabulate(8 )(Point (_, 0 )), input, 0 , 0 , 0 )
42
- Iterator .iterate(initial)(step)
43
-
44
- def part1 (input : String ): Int = simulate(input).drop(2022 ).next().height
38
+ def part1 (input : String ): Int = simulate(input).drop(2022 ).next()
45
39
46
40
def part2 (input : String ): Long =
47
41
val guess = 1000
48
- val height = simulate(input).drop( 1 ).take( 10 * guess).map(_.height ).toSeq
42
+ val height = simulate(input).slice( 1 , 10 * guess).toSeq
49
43
val delta = height.sliding(2 ).map { case Seq (a, b) => b - a }.toSeq
50
44
val index = delta.lastIndexOfSlice(delta.takeRight(guess), delta.size - guess - 1 )
51
45
val cycleHeight = height(delta.size - guess) - height(index)
0 commit comments