|
| 1 | +package AdventOfCode2022 |
| 2 | + |
| 3 | +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) |
| 18 | + |
| 19 | + 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 | + |
| 26 | + 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 |
0 commit comments