Skip to content

Commit c1b7129

Browse files
committed
Tidy
1 parent 9befde1 commit c1b7129

File tree

2 files changed

+44
-93
lines changed

2 files changed

+44
-93
lines changed
Lines changed: 42 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,48 @@
11
package AdventOfCode2022
22

33
object Day24:
4-
case class Point(x: Int, y: Int, z: Int):
5-
def +(other: Point): Point = Point(x + other.x, y + other.y, z + other.z)
6-
7-
def part1(input: Seq[String]): Int = 123
8-
9-
def part2(input: Seq[String]): Int = 456
10-
11-
def parse(input: Seq[String]): (Set[Point], Set[Point], Set[Point], Set[Point], Set[Point]) =
12-
val right = for y <- input.indices; x <- input.head.indices if input(y)(x) == '>' yield Point(x, y, 0)
13-
val down = for y <- input.indices; x <- input.head.indices if input(y)(x) == 'v' yield Point(x, y, 0)
14-
val left = for y <- input.indices; x <- input.head.indices if input(y)(x) == '<' yield Point(x, y, 0)
15-
val up = for y <- input.indices; x <- input.head.indices if input(y)(x) == '^' yield Point(x, y, 0)
16-
val wall = for y <- input.indices; x <- input.head.indices if input(y)(x) == '#' yield Point(x, y, 0)
17-
(right.toSet, down.toSet, left.toSet, up.toSet, wall.toSet)
4+
val moves = Seq(Point(0, 0), Point(1, 0), Point(-1, 0), Point(0, 1), Point(0, -1))
5+
6+
case class Point(x: Int, y: Int):
7+
def +(other: Point): Point = Point(x + other.x, y + other.y)
8+
def neighbours: Seq[Point] = moves.map(_ + this)
9+
10+
def parse(input: Seq[String]): (Point, Point, (Set[Point], Point, Int) => Int) =
11+
val width = input.head.size - 2
12+
val height = input.size - 2
13+
14+
def mod(a: Int, m: Int): Int =
15+
val remainder = (a - 1) % m
16+
if remainder < 0 then remainder + m + 1 else remainder + 1
17+
18+
def valid(time: Int)(point: Point): Boolean =
19+
val Point(x, y) = point
20+
input.indices.contains(y)
21+
&& input(y)(x) != '#'
22+
&& input(y)(mod(x + time, width)) != '<'
23+
&& input(y)(mod(x - time, width)) != '>'
24+
&& input(mod(y + time, height))(x) != '^'
25+
&& input(mod(y - time, height))(x) != 'v'
26+
27+
def simulate(points: Set[Point], end: Point, time: Int): Int =
28+
if points.contains(end) then time else
29+
val next = points.flatMap(_.neighbours).filter(valid(time + 1))
30+
simulate(next, end, time + 1)
31+
32+
(Point(1, 0), Point(width, height + 1), simulate)
33+
end parse
34+
35+
def part1(input: Seq[String]): Int =
36+
val (start, end, simulate) = parse(input)
37+
simulate(Set(start), end, 0)
38+
39+
def part2(input: Seq[String]): Int =
40+
val (start, end, simulate) = parse(input)
41+
val time1 = simulate(Set(start), end, 0)
42+
val time2 = simulate(Set(end), start, time1)
43+
simulate(Set(start), end, time2)
1844

1945
def main(args: Array[String]): Unit =
20-
// val data = sample
21-
// val minX = 1
22-
// val maxX = 6
23-
// val minY = 1
24-
// val maxY = 4
25-
2646
val data = io.Source.fromResource("AdventOfCode2022/Day24.txt").getLines().toSeq
27-
val minX = 1
28-
val maxX = 120
29-
val minY = 1
30-
val maxY = 25
31-
32-
val points = collection.mutable.Set[Point]()
33-
var (right, down, left, up, wall) = parse(data)
34-
wall = wall + Point(1, -1, 0)
35-
points ++= right
36-
points ++= down
37-
points ++= left
38-
points ++= down
39-
points ++= wall
40-
41-
for _ <- 1 to 1000 do // Guess max z value
42-
right = right.map { cur =>
43-
if cur.x == maxX then Point(minX, cur.y, cur.z + 1) else Point(cur.x + 1, cur.y, cur.z + 1)
44-
}
45-
left = left.map { cur =>
46-
if cur.x == minX then Point(maxX, cur.y, cur.z + 1) else Point(cur.x - 1, cur.y, cur.z + 1)
47-
}
48-
up = up.map { cur =>
49-
if cur.y == minY then Point(cur.x, maxY, cur.z + 1) else Point(cur.x, cur.y - 1, cur.z + 1)
50-
}
51-
down = down.map { cur =>
52-
if cur.y == maxY then Point(cur.x, minY, cur.z + 1) else Point(cur.x, cur.y + 1, cur.z + 1)
53-
}
54-
wall = wall.map { cur =>
55-
Point(cur.x, cur.y, cur.z + 1)
56-
}
57-
points ++= right
58-
points ++= down
59-
points ++= left
60-
points ++= up
61-
points ++= wall
62-
end for
63-
64-
def bfs(start: Point, end: Point): Int =
65-
val todo = collection.mutable.Queue(start)
66-
val cost = collection.mutable.Map(start -> 0)
67-
68-
while todo.nonEmpty do
69-
val cur = todo.dequeue()
70-
71-
if cur.x == end.x && cur.y == end.y then return cost(cur)
72-
73-
val neighbours = Seq(
74-
Point(cur.x, cur.y, cur.z + 1),
75-
Point(cur.x - 1, cur.y, cur.z + 1),
76-
Point(cur.x + 1, cur.y, cur.z + 1),
77-
Point(cur.x, cur.y - 1, cur.z + 1),
78-
Point(cur.x, cur.y + 1, cur.z + 1),
79-
)
80-
81-
neighbours.filterNot(cost.contains).filterNot(points.contains).foreach { next =>
82-
todo += next
83-
cost(next) = cost(cur) + 1
84-
}
85-
end while
86-
87-
-1
88-
end bfs
89-
90-
val time1 = bfs(Point(1, 0, 0), Point(maxX, maxY + 1, 0))
91-
println(time1)
92-
val time2 = bfs(Point(maxX, maxY + 1, time1), Point(1, 0, 0))
93-
println(time2)
94-
val time3 = bfs(Point(1, 0, time1 + time2), Point(maxX, maxY + 1, 0))
95-
println(time3)
96-
println(time1 + time2 + time3)
97-
end main
47+
println(part1(data))
48+
println(part2(data))

src/test/scala/AdventOfCode2022/Day24Suite.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ class Day24Suite extends AnyFunSuite:
1212
"######.#")
1313

1414
test("Part 1 should handle sample input correctly") {
15-
assert(Day24.part1(sample) == 123)
15+
assert(Day24.part1(sample) == 18)
1616
}
1717

1818
test("Part 2 should handle sample input correctly") {
19-
assert(Day24.part2(sample) == 456)
19+
assert(Day24.part2(sample) == 54)
2020
}

0 commit comments

Comments
 (0)