Skip to content

Commit e5b63e9

Browse files
committed
Add code for day 8
1 parent 2a24583 commit e5b63e9

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

2025/src/day08.scala

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package day08
2+
3+
import scala.util.boundary
4+
import scala.util.boundary.break
5+
6+
import locations.Directory.currentDir
7+
import inputs.Input.loadFileSync
8+
9+
def loadInput(): String = loadFileSync(s"$currentDir/../input/day08")
10+
11+
class Point(val x: Long, val y: Long, val z: Long, var circuit: Int):
12+
def distance(p: Point): Long =
13+
(x - p.x) * (x - p.x) + (y - p.y) * (y - p.y) + (z - p.z) * (z - p.z)
14+
15+
/** Parses comma-separated coordinates from the given `line` into a `Point`
16+
* with the given `circuit` ID.
17+
*/
18+
def point(line: String, circuit: Int): Point =
19+
val parts = line.split(",")
20+
Point(parts(0).toLong, parts(1).toLong, parts(2).toLong, circuit)
21+
22+
/** Parses the input file at `path`, returning a sequence of `Point`s and all
23+
* unique pairs of points sorted by distance.
24+
*/
25+
def load(input: String): (Seq[Point], Seq[(Point, Point)]) =
26+
val lines = input.linesIterator.filter(_.nonEmpty)
27+
val points = lines.zipWithIndex.map(point).toSeq
28+
val pairsByDistance = points.pairs.toSeq.sortBy((p1, p2) => p1.distance(p2))
29+
(points, pairsByDistance)
30+
31+
/** Sets all points in `points` with circuit `c2` to circuit `c1`. */
32+
def merge(c1: Int, c2: Int, points: Seq[Point]): Unit =
33+
for p <- points if p.circuit == c2 do p.circuit = c1
34+
35+
extension [T](self: Seq[T])
36+
/** Generates all unique pairs (combinations of 2) from given the sequence. */
37+
def pairs: Iterator[(T, T)] =
38+
self.combinations(2).map(pair => (pair(0), pair(1)))
39+
40+
@main def part1: Unit =
41+
println(s"The solution is ${part1(loadInput())}")
42+
43+
def part1(input: String): Int =
44+
val (points, pairsByDistance) = load(input)
45+
for (p1, p2) <- pairsByDistance.take(1000) if p1.circuit != p2.circuit do
46+
merge(p1.circuit, p2.circuit, points)
47+
val sizes = points.groupBy(_.circuit).values.map(_.size).toSeq.sortBy(-_)
48+
sizes.take(3).product
49+
50+
@main def part2: Unit =
51+
println(s"The solution is ${part2(loadInput())}")
52+
53+
def part2(input: String): Long =
54+
val (points, pairsByDistance) = load(input)
55+
var n = points.length
56+
boundary:
57+
for (p1, p2) <- pairsByDistance if p1.circuit != p2.circuit do
58+
merge(p1.circuit, p2.circuit, points)
59+
n -= 1
60+
if n <= 1 then
61+
break(p1.x * p2.x)
62+
throw Exception("Should not reach here")

0 commit comments

Comments
 (0)