Bye bye sbt
This commit is contained in:
19
aoc/src/main/scala/dev/ctsk/aoc/Main.scala
Normal file
19
aoc/src/main/scala/dev/ctsk/aoc/Main.scala
Normal file
@@ -0,0 +1,19 @@
|
||||
package dev.ctsk.aoc
|
||||
|
||||
import dev.ctsk.aoc.days._
|
||||
|
||||
val solvers = Map[Int, Solver](
|
||||
1 -> Day01,
|
||||
2 -> Day02
|
||||
)
|
||||
|
||||
@main def main(day: String, input: String): Unit =
|
||||
solvers.get(day.toInt) match
|
||||
case Some(solver) =>
|
||||
val (timings, solution) = solver.run(input)
|
||||
println(f"Preprocessing: ${timings.prep}%24s μs")
|
||||
println(f"Part 1: ${solution.p1}%15s ${timings.p1}%15s μs")
|
||||
println(f"Part 2: ${solution.p2}%15s ${timings.p2}%15s μs")
|
||||
|
||||
case None =>
|
||||
println(s"Day $day not solved")
|
||||
15
aoc/src/main/scala/dev/ctsk/aoc/Solution.scala
Normal file
15
aoc/src/main/scala/dev/ctsk/aoc/Solution.scala
Normal file
@@ -0,0 +1,15 @@
|
||||
package dev.ctsk.aoc
|
||||
|
||||
case class Timings(prep: Long, p1: Long, p2: Long)
|
||||
|
||||
case class Solution(p1: Object, p2: Object)
|
||||
|
||||
abstract class Solver(day: Int):
|
||||
def run(input: String): (Timings, Solution)
|
||||
|
||||
def timed[A](solution: => A): (Long, A) =
|
||||
val start = System.nanoTime()
|
||||
val result = solution
|
||||
val end = System.nanoTime()
|
||||
|
||||
((end - start) / 1000, result)
|
||||
33
aoc/src/main/scala/dev/ctsk/aoc/days/Day01.scala
Normal file
33
aoc/src/main/scala/dev/ctsk/aoc/days/Day01.scala
Normal file
@@ -0,0 +1,33 @@
|
||||
package dev.ctsk.aoc.days
|
||||
|
||||
import dev.ctsk.aoc._
|
||||
|
||||
object Day01 extends Solver(1):
|
||||
type Input = (Array[Int], Array[Int])
|
||||
|
||||
def pre(input: String): Input =
|
||||
io.Source
|
||||
.fromFile(input)
|
||||
.getLines()
|
||||
.map { case s"$i $j" => (i.toInt, j.toInt) }
|
||||
.toArray
|
||||
.unzip match { case (left, right) => (left.sorted, right.sorted) }
|
||||
|
||||
def part1(input: Input): Int =
|
||||
input match
|
||||
case (left, right) => left.zip(right).map(_ - _).map(_.abs).sum
|
||||
|
||||
def part2(input: Input): Int =
|
||||
val (left, right) = input;
|
||||
val counts = right.groupMapReduce(identity)(identity)(_ + _)
|
||||
left.map(n => counts.getOrElse(n, 0)).sum
|
||||
|
||||
def run(input: String): (Timings, Solution) =
|
||||
val (pre_time, pre_input) = timed { pre(input) }
|
||||
val (p1_time, p1_solution) = timed { part1(pre_input) }
|
||||
val (p2_time, p2_solution) = timed { part2(pre_input) }
|
||||
|
||||
(
|
||||
Timings(pre_time, p1_time, p2_time),
|
||||
Solution(Int.box(p1_solution), Int.box(p2_solution))
|
||||
)
|
||||
36
aoc/src/main/scala/dev/ctsk/aoc/days/Day02.scala
Normal file
36
aoc/src/main/scala/dev/ctsk/aoc/days/Day02.scala
Normal file
@@ -0,0 +1,36 @@
|
||||
package dev.ctsk.aoc.days
|
||||
|
||||
import dev.ctsk.aoc._
|
||||
|
||||
object Day02 extends Solver(2):
|
||||
def pre(input: String): List[List[Int]] =
|
||||
io.Source
|
||||
.fromFile(input)
|
||||
.getLines()
|
||||
.map(line => line.split(" ").map(_.toInt).toList)
|
||||
.toList
|
||||
|
||||
def safe(list: List[Int]): Boolean =
|
||||
list.length < 2 || list
|
||||
.sliding(2)
|
||||
.collect { case List(a, b) => b - a }
|
||||
.forall(1 to 3 contains _)
|
||||
|
||||
def safeWithGap(list: List[Int]): Boolean =
|
||||
list.indices.exists(i => safe(list.take(i) ++ list.drop(i + 1)))
|
||||
|
||||
def part1(lists: List[List[Int]]): Int =
|
||||
lists.count(list => safe(list) || safe(list.reverse))
|
||||
|
||||
def part2(lists: List[List[Int]]): Int =
|
||||
lists.count(list => safeWithGap(list) || safeWithGap(list.reverse))
|
||||
|
||||
def run(input: String): (Timings, Solution) =
|
||||
val (pre_time, pre_input) = timed { pre(input) }
|
||||
val (p1_time, p1_solution) = timed { part1(pre_input) }
|
||||
val (p2_time, p2_solution) = timed { part2(pre_input) }
|
||||
|
||||
(
|
||||
Timings(pre_time, p1_time, p2_time),
|
||||
Solution(Int.box(p1_solution), Int.box(p2_solution))
|
||||
)
|
||||
Reference in New Issue
Block a user