-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: prepare for interactive 2024 solution (#729)
* build: setup for 2024 * feat(2024): day 13
- Loading branch information
Showing
3 changed files
with
76 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package day13 | ||
|
||
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/day13") | ||
|
||
case class Claw(ax: Long, ay: Long, bx: Long, by: Long, x: Long, y: Long): | ||
def solve: Option[Long] = for | ||
b <- (x * ay - y * ax) safeDiv (bx * ay - by * ax) | ||
a <- (x - b * bx) safeDiv ax | ||
yield a * 3 + b | ||
|
||
object Claw: | ||
def parse(xs: Seq[String]): Option[Claw] = xs match | ||
case Seq( | ||
s"Button A: X+${L(ax)}, Y+${L(ay)}", | ||
s"Button B: X+${L(bx)}, Y+${L(by)}", | ||
s"Prize: X=${L(x)}, Y=${L(y)}", | ||
) => | ||
Some(Claw(ax, ay, bx, by, x, y)) | ||
case _ => None | ||
|
||
def parse(input: String): Seq[Claw] = | ||
input.split("\n+").toSeq.grouped(3).flatMap(Claw.parse).toSeq | ||
|
||
extension (a: Long) | ||
infix def safeDiv(b: Long): Option[Long] = | ||
Option.when(b != 0 && a % b == 0)(a / b) | ||
|
||
object L: | ||
def unapply(s: String): Option[Long] = s.toLongOption | ||
|
||
def part1(input: String): Long = | ||
parse(input).flatMap(_.solve).sum | ||
|
||
def part2(input: String): Long = | ||
val diff = 10_000_000_000_000L | ||
parse(input) | ||
.map(c => c.copy(x = c.x + diff, y = c.y + diff)) | ||
.flatMap(_.solve) | ||
.sum |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] |