diff --git a/aoc/resources/day15Input.txt b/aoc/resources/day15Input.txt new file mode 100644 index 0000000..d4c562b --- /dev/null +++ b/aoc/resources/day15Input.txt @@ -0,0 +1,25 @@ +Sensor at x=251234, y=759482: closest beacon is at x=-282270, y=572396 +Sensor at x=2866161, y=3374117: closest beacon is at x=2729330, y=3697325 +Sensor at x=3999996, y=3520742: closest beacon is at x=3980421, y=3524442 +Sensor at x=3988282, y=3516584: closest beacon is at x=3980421, y=3524442 +Sensor at x=3005586, y=3018139: closest beacon is at x=2727127, y=2959718 +Sensor at x=3413653, y=3519082: closest beacon is at x=3980421, y=3524442 +Sensor at x=2900403, y=187208: closest beacon is at x=2732772, y=2000000 +Sensor at x=1112429, y=3561166: closest beacon is at x=2729330, y=3697325 +Sensor at x=3789925, y=3283328: closest beacon is at x=3980421, y=3524442 +Sensor at x=3991533, y=3529053: closest beacon is at x=3980421, y=3524442 +Sensor at x=3368119, y=2189371: closest beacon is at x=2732772, y=2000000 +Sensor at x=2351157, y=2587083: closest beacon is at x=2727127, y=2959718 +Sensor at x=3326196, y=2929990: closest beacon is at x=3707954, y=2867627 +Sensor at x=3839244, y=1342691: closest beacon is at x=3707954, y=2867627 +Sensor at x=2880363, y=3875503: closest beacon is at x=2729330, y=3697325 +Sensor at x=1142859, y=1691416: closest beacon is at x=2732772, y=2000000 +Sensor at x=3052449, y=2711719: closest beacon is at x=2727127, y=2959718 +Sensor at x=629398, y=214610: closest beacon is at x=-282270, y=572396 +Sensor at x=3614706, y=3924106: closest beacon is at x=3980421, y=3524442 +Sensor at x=3999246, y=2876762: closest beacon is at x=3707954, y=2867627 +Sensor at x=3848935, y=3020496: closest beacon is at x=3707954, y=2867627 +Sensor at x=123637, y=2726215: closest beacon is at x=-886690, y=3416197 +Sensor at x=4000000, y=3544014: closest beacon is at x=3980421, y=3524442 +Sensor at x=2524955, y=3861248: closest beacon is at x=2729330, y=3697325 +Sensor at x=2605475, y=3152151: closest beacon is at x=2727127, y=2959718 \ No newline at end of file diff --git a/aoc/src/Day15.scala b/aoc/src/Day15.scala new file mode 100644 index 0000000..a9a4041 --- /dev/null +++ b/aoc/src/Day15.scala @@ -0,0 +1,76 @@ +import scala.io.Source +import scala.util.chaining.* + +object Day15 extends App: + + val input = Source + .fromURL(getClass.getResource("day15Input.txt")) + .mkString + .split('\n') + .map( + _.drop(12) + .split(": closest beacon is at x=") + .map(_.split(", y=").map(_.toInt)) + ).map { case Array(Array(sX, sY), Array(bX, bY)) => + ((sX, sY), (bX, bY)) + }.toMap + + type Point = (Int, Int) + + extension (point: Point) + def x = point._1 + def y = point._2 + + def manhattanDistance(to: Point): Int = (x - to.x).abs + (y - to.y).abs + + val beacons = input.values.toList + + val sensorsWithDistance = input.map { case ((sX, sY), (bX, bY)) => + ((sX, sY), (sX, sY).manhattanDistance(bX, bY)) + }.toMap + + val xMin = sensorsWithDistance.map { case ((x, _), distance) => x - distance }.min + val xMax = sensorsWithDistance.map { case ((x, _), distance) => x + distance }.max + val yMin = sensorsWithDistance.map { case ((_, y), distance) => y - distance }.min + val yMax = sensorsWithDistance.map { case ((_, y), distance) => y + distance }.max + + val part1 = (for x <- xMin to xMax yield (x, 2000000)) + .filterNot(beacons.contains) + .filter(point => + sensorsWithDistance.exists { case (sensor, distance) => + point.manhattanDistance(sensor) <= distance + } + ).length + + println("Part 1:") + println(part1) + + val part2Bound = 4000000 + + val posiblePosition = LazyList.iterate((0, 0))(point => + if point.x >= part2Bound then (0, point.y + 1) + else + sensorsWithDistance + .find { case (sensor, distance) => + point.manhattanDistance(sensor) <= distance + }.map { case (sensor, distance) => + ( + point.x + (sensor.x - point.x) + (distance + 1) - ((sensor.y - point.y).abs), + point.y + ) + }.getOrElse((point.x + 1, point.y)) + ) + + val beaconPosition = posiblePosition + .filter(point => point.x < part2Bound && point.y < part2Bound) + .filterNot(point => + sensorsWithDistance.exists { case (sensor, distance) => + point.manhattanDistance(sensor) <= distance + } + ) + .head + + val part2 = beaconPosition.x * 4000000L + beaconPosition.y + println("Part 2:") + println(part2) +end Day15