From 40b37fcb3b8f9802580eaa0c1a2abdaba6755178 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 6 Dec 2025 22:39:20 +0900 Subject: [PATCH] feat(2025): day 06 source code --- 2025/project.scala | 3 +++ 2025/src/day06.scala | 39 +++++++++++++++++++++++++++++++++++++++ 2025/src/inputs.scala | 9 +++++++++ 2025/src/locations.scala | 19 +++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 2025/project.scala create mode 100644 2025/src/day06.scala create mode 100644 2025/src/inputs.scala create mode 100644 2025/src/locations.scala diff --git a/2025/project.scala b/2025/project.scala new file mode 100644 index 000000000..f6cb19794 --- /dev/null +++ b/2025/project.scala @@ -0,0 +1,3 @@ +//> using scala 3.7.4 +//> using option -Wunused:all +//> using test.dep org.scalameta::munit::1.2.1 diff --git a/2025/src/day06.scala b/2025/src/day06.scala new file mode 100644 index 000000000..d7060d6d0 --- /dev/null +++ b/2025/src/day06.scala @@ -0,0 +1,39 @@ +package day06 + +import locations.Directory.currentDir +import inputs.Input.loadFileSync + +@main def part1: Unit = + println(s"The solution is ${part1(loadInput())}") + +@main def part2: Unit = + println(s"The solution is ${part2(loadInput())}") + +def loadInput(): String = loadFileSync(s"$currentDir/../input/day06") + +extension [A](xs: IterableOnce[A]) + inline def splitBy(sep: A) = + val (b, cur) = (Vector.newBuilder[Vector[A]], Vector.newBuilder[A]) + for e <- xs.iterator do + if e != sep then cur += e else { b += cur.result(); cur.clear() } + (b += cur.result()).result() + +extension (xs: Iterator[(symbol: String, nums: IterableOnce[String])]) + def calculate: Long = xs.iterator.collect { + case ("*", nums) => nums.iterator.map(_.toLong).product + case ("+", nums) => nums.iterator.map(_.toLong).sum + }.sum + +def part1(input: String): Long = input.linesIterator.toVector + .map(_.trim.split(raw"\s+")) + .transpose + .iterator + .map { col => (col.last, col.view.init) } + .calculate + +def part2(input: String): Long = + val lines = input.linesIterator.toVector + val ops = lines.last.split(raw"\s+").iterator + val xss = lines.init.transpose.map(_.mkString.trim).splitBy("") + + (ops zip xss).calculate diff --git a/2025/src/inputs.scala b/2025/src/inputs.scala new file mode 100644 index 000000000..1d41e4738 --- /dev/null +++ b/2025/src/inputs.scala @@ -0,0 +1,9 @@ +package inputs + +import scala.util.Using +import scala.io.Source + +object Input: + + def loadFileSync(path: String): String = + Using.resource(Source.fromFile(path))(_.mkString) diff --git a/2025/src/locations.scala b/2025/src/locations.scala new file mode 100644 index 000000000..986d2a3bb --- /dev/null +++ b/2025/src/locations.scala @@ -0,0 +1,19 @@ +package locations + +import scala.quoted.* + +object Directory: + + /** The absolute path of the parent directory of the file that calls this method + * This is stable no matter which directory runs the program. + */ + inline def currentDir: String = ${ parentDirImpl } + + private def parentDirImpl(using Quotes): Expr[String] = + // position of the call to `currentDir` in the source code + val position = quotes.reflect.Position.ofMacroExpansion + // get the path of the file calling this macro + val srcFilePath = position.sourceFile.getJPath.get + // get the parent of the path, which is the directory containing the file + val parentDir = srcFilePath.getParent().toAbsolutePath + Expr(parentDir.toString) // convert the String to Expr[String]