Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a521eec

Browse files
Further tidy
1 parent 05a3aab commit a521eec

File tree

1 file changed

+57
-68
lines changed

1 file changed

+57
-68
lines changed

‎src/main/scala/AdventOfCode2022/Day22.scala

Lines changed: 57 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,105 +3,94 @@ package AdventOfCode2022
33
object Day22:
44
val (right, down, left, up) = (Point(1, 0), Point(0, 1), Point(-1, 0), Point(0, -1))
55

6+
type State = (Point, Point)
7+
68
enum Tile:
79
case Open, Solid, Wrap
8-
import Tile._
910

1011
case class Point(x: Int, y: Int):
1112
def +(other: Point): Point = Point(x + other.x, y + other.y)
1213
def clockwise: Point = Point(-y, x)
1314
def counterClockwise: Point = Point(y, -x)
1415

15-
case class State(position: Point, direction: Point)
16-
17-
def parse(input: Seq[String]): Map[Point, Tile] =
16+
def parse(input: Seq[String]): (Map[Point, Tile], String) =
1817
val points = for
1918
(row, y) <- input.dropRight(2).zipWithIndex
2019
(cell, x) <- row.zipWithIndex
2120
if cell != ' '
22-
yield Point(x, y) -> (if cell == '.' then Open else Solid)
23-
points.toMap.withDefaultValue(Wrap)
21+
yield Point(x, y) -> (if cell == '.' then Tile.Open else Tile.Solid)
22+
(points.toMap.withDefaultValue(Tile.Wrap), input.last)
2423

25-
def follow(points: Map[Point, Tile], path: String, handleWrap: State => State): Int =
24+
def follow(tiles: Map[Point, Tile], path: String, handleWrap: State => State): Int =
2625
val numbers = path.split("\\D+").map(_.toInt).toSeq
2726
val letters = path.split("\\d+").toSeq
2827
val moves = numbers.zip(letters)
2928

30-
val initial = State(Point(50, 0), Point(1, 0))
31-
val result= moves.foldLeft(initial) { case (state, (number, letter)) =>
29+
val initial = (Point(50, 0), Point(1, 0))
30+
val (position, direction) = moves.foldLeft(initial) { case ((position, direction), (number, letter)) =>
3231
val nextDirection = letter match
33-
case "L" => state.direction.counterClockwise
34-
case "R" => state.direction.clockwise
35-
case _ => state.direction
32+
case "L" => direction.counterClockwise
33+
case "R" => direction.clockwise
34+
case _ => direction
3635

37-
(1 to number).foldLeft(State(state.position, nextDirection)) { (state, _) =>
38-
val State(position, direction) = state
36+
(1 to number).foldLeft((position, nextDirection)) { case ((position, direction), _) =>
3937
val next = position + direction
40-
points(next) match
41-
case Open => State(next, direction)
42-
case Solid => state
43-
case Wrap => handleWrap(state)
38+
tiles(next) match
39+
case Tile.Open => (next, direction)
40+
case Tile.Solid => (position, direction)
41+
case Tile.Wrap =>
42+
val (wrapPosition, wrapDirection) = handleWrap(position, direction)
43+
if tiles(wrapPosition) == Tile.Open then (wrapPosition, wrapDirection) else (position, direction)
4444
}
4545
}
4646

47-
val facing = Seq(right, down, left, up)
48-
1000 * (result.position.y + 1) + 4 * (result.position.x + 1) + facing.indexOf(result.direction)
47+
1000 * (position.y + 1) + 4 * (position.x + 1) + Seq(right, down, left, up).indexOf(direction)
4948
end follow
5049

5150
def part1(input: Seq[String]): Int =
52-
val tiles = parse(input)
53-
54-
val valid = tiles.filterNot((k, v) => v == Wrap).keySet
55-
val minX = valid.groupMapReduce(_.y)(_.x)(_ min _)
56-
val maxX = valid.groupMapReduce(_.y)(_.x)(_ max _)
57-
val minY = valid.groupMapReduce(_.x)(_.y)(_ min _)
58-
val maxY = valid.groupMapReduce(_.x)(_.y)(_ max _)
59-
60-
def handleWrap(state: State): State =
61-
val State(position, direction) = state
62-
val nextPosition = direction match
63-
case `right` => Point(minX(position.y), position.y)
64-
case `left` => Point(maxX(position.y), position.y)
65-
case `down` => Point(position.x, minY(position.x))
66-
case `up` => Point(position.x, maxY(position.x))
67-
if tiles(nextPosition) == Open then State(nextPosition, direction) else state
68-
69-
follow(tiles, input.last, handleWrap)
51+
val (tiles, path) = parse(input)
52+
53+
val minX = tiles.keys.groupMapReduce(_.y)(_.x)(_ min _)
54+
val maxX = tiles.keys.groupMapReduce(_.y)(_.x)(_ max _)
55+
val minY = tiles.keys.groupMapReduce(_.x)(_.y)(_ min _)
56+
val maxY = tiles.keys.groupMapReduce(_.x)(_.y)(_ max _)
57+
58+
def handleWrap(position: Point, direction: Point): State = direction match
59+
case `right` => position.copy(x = minX(position.y)) -> right
60+
case `left` => position.copy(x = maxX(position.y)) -> left
61+
case `down` => position.copy(y = minY(position.x)) -> down
62+
case `up` => position.copy(y = maxY(position.x)) -> up
63+
64+
follow(tiles, path, handleWrap)
7065
end part1
7166

7267
def part2(input: Seq[String]): Int =
73-
val tiles = parse(input)
74-
75-
def handleWrap(state: State): State =
76-
val State(position, direction) = state
68+
// Cube faces:
69+
// BA
70+
// C
71+
// ED
72+
// F
73+
def handleWrap(position: Point, direction: Point): State =
7774
val (cubeX, cubeY) = (position.x / 50, position.y / 50)
7875
val (modX, modY) = (position.x % 50, position.y % 50)
79-
80-
// Cube faces:
81-
// BA
82-
// C
83-
// ED
84-
// F
85-
val (nextPosition, nextDirection) = (cubeX, cubeY, direction) match
86-
case (2, 0, `up`) => Point(modX, 199) -> up // A to F
87-
case (2, 0, `down`) => Point(99, 50 + modX) -> left // A to C
88-
case (2, 0, `right`) => Point(99, 149 - modY) -> left // A to D
89-
case (1, 0, `up`) => Point(0, 150 + modX) -> right // B to F
90-
case (1, 0, `left`) => Point(0, 149 - modY) -> right // B to E
91-
case (1, 1, `left`) => Point(modY, 100) -> down // C to E
92-
case (1, 1, `right`) => Point(100 + modY, 49) -> up // C to A
93-
case (1, 2, `down`) => Point(49, 150 + modX) -> left // D to F
94-
case (1, 2, `right`) => Point(149, 49 - modY) -> left // D to A
95-
case (0, 2, `up`) => Point(50, 50 + modX) -> right // E to C
96-
case (0, 2, `left`) => Point(50, 49 - modY) -> right // E to B
97-
case (0, 3, `down`) => Point(100 + modX, 0) -> down // F to A
98-
case (0, 3, `left`) => Point(50 + modY, 0) -> down // F to B
99-
case (0, 3, `right`) => Point(50 + modY, 149) -> up // F to D
100-
101-
if tiles(nextPosition) == Open then State(nextPosition, nextDirection) else state
102-
end handleWrap
103-
104-
follow(tiles, input.last, handleWrap)
76+
(cubeX, cubeY, direction) match
77+
case (2, 0, `up`) => Point(modX, 199) -> up // A to F
78+
case (2, 0, `down`) => Point(99, 50 + modX) -> left // A to C
79+
case (2, 0, `right`) => Point(99, 149 - modY) -> left // A to D
80+
case (1, 0, `up`) => Point(0, 150 + modX) -> right // B to F
81+
case (1, 0, `left`) => Point(0, 149 - modY) -> right // B to E
82+
case (1, 1, `left`) => Point(modY, 100) -> down // C to E
83+
case (1, 1, `right`) => Point(100 + modY, 49) -> up // C to A
84+
case (1, 2, `down`) => Point(49, 150 + modX) -> left // D to F
85+
case (1, 2, `right`) => Point(149, 49 - modY) -> left // D to A
86+
case (0, 2, `up`) => Point(50, 50 + modX) -> right // E to C
87+
case (0, 2, `left`) => Point(50, 49 - modY) -> right // E to B
88+
case (0, 3, `down`) => Point(100 + modX, 0) -> down // F to A
89+
case (0, 3, `left`) => Point(50 + modY, 0) -> down // F to B
90+
case (0, 3, `right`) => Point(50 + modY, 149) -> up // F to D
91+
92+
val (tiles, path) = parse(input)
93+
follow(tiles, path, handleWrap)
10594
end part2
10695

10796
def main(args: Array[String]): Unit =

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /