Skip to content

Commit 0a09b49

Browse files
authored
feat: prepare for interactive 2024 solution (#729)
* build: setup for 2024 * feat(2024): day 13
1 parent b4e27f5 commit 0a09b49

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

2024/src/day13.scala

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package day13
2+
3+
import locations.Directory.currentDir
4+
import inputs.Input.loadFileSync
5+
6+
@main def part1: Unit =
7+
println(s"The solution is ${part1(loadInput())}")
8+
9+
@main def part2: Unit =
10+
println(s"The solution is ${part2(loadInput())}")
11+
12+
def loadInput(): String = loadFileSync(s"$currentDir/../input/day13")
13+
14+
case class Claw(ax: Long, ay: Long, bx: Long, by: Long, x: Long, y: Long):
15+
def solve: Option[Long] = for
16+
b <- (x * ay - y * ax) safeDiv (bx * ay - by * ax)
17+
a <- (x - b * bx) safeDiv ax
18+
yield a * 3 + b
19+
20+
object Claw:
21+
def parse(xs: Seq[String]): Option[Claw] = xs match
22+
case Seq(
23+
s"Button A: X+${L(ax)}, Y+${L(ay)}",
24+
s"Button B: X+${L(bx)}, Y+${L(by)}",
25+
s"Prize: X=${L(x)}, Y=${L(y)}",
26+
) =>
27+
Some(Claw(ax, ay, bx, by, x, y))
28+
case _ => None
29+
30+
def parse(input: String): Seq[Claw] =
31+
input.split("\n+").toSeq.grouped(3).flatMap(Claw.parse).toSeq
32+
33+
extension (a: Long)
34+
infix def safeDiv(b: Long): Option[Long] =
35+
Option.when(b != 0 && a % b == 0)(a / b)
36+
37+
object L:
38+
def unapply(s: String): Option[Long] = s.toLongOption
39+
40+
def part1(input: String): Long =
41+
parse(input).flatMap(_.solve).sum
42+
43+
def part2(input: String): Long =
44+
val diff = 10_000_000_000_000L
45+
parse(input)
46+
.map(c => c.copy(x = c.x + diff, y = c.y + diff))
47+
.flatMap(_.solve)
48+
.sum

2024/src/inputs.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package inputs
2+
3+
import scala.util.Using
4+
import scala.io.Source
5+
6+
object Input:
7+
8+
def loadFileSync(path: String): String =
9+
Using.resource(Source.fromFile(path))(_.mkString)

2024/src/locations.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package locations
2+
3+
import scala.quoted.*
4+
5+
object Directory:
6+
7+
/** The absolute path of the parent directory of the file that calls this method
8+
* This is stable no matter which directory runs the program.
9+
*/
10+
inline def currentDir: String = ${ parentDirImpl }
11+
12+
private def parentDirImpl(using Quotes): Expr[String] =
13+
// position of the call to `currentDir` in the source code
14+
val position = quotes.reflect.Position.ofMacroExpansion
15+
// get the path of the file calling this macro
16+
val srcFilePath = position.sourceFile.getJPath.get
17+
// get the parent of the path, which is the directory containing the file
18+
val parentDir = srcFilePath.getParent().toAbsolutePath
19+
Expr(parentDir.toString) // convert the String to Expr[String]

0 commit comments

Comments
 (0)