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 c1b7129

Browse files
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)

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