mirror of
https://github.com/mx42/aoc2024.scala.git
synced 2026-01-14 05:49:51 +01:00
feat: basic wrapper + days 1 to 3
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -32,3 +32,5 @@ metals.sbt
|
||||
/.worksheet/
|
||||
|
||||
.direnv
|
||||
|
||||
src/main/resources
|
||||
|
||||
2
.scalafmt.conf
Normal file
2
.scalafmt.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
version = "3.7.15"
|
||||
runner.dialect = scala3
|
||||
@@ -1,8 +1,8 @@
|
||||
## sbt project compiled with Scala 3
|
||||
## Advent of Code 2024
|
||||
|
||||
### Usage
|
||||
|
||||
This is a normal sbt project. You can compile code with `sbt compile`, run it with `sbt run`, and `sbt console` will start a Scala 3 REPL.
|
||||
- Put input in `src/main/resources/days/dayXX.txt`
|
||||
- Run SBT `sbt`
|
||||
- In SBT shell, run day: `run XX`
|
||||
|
||||
For more information on the sbt-dotty plugin, see the
|
||||
[scala3-example-project](https://github.com/scala/scala3-example-project/blob/main/README.md).
|
||||
|
||||
@@ -5,8 +5,7 @@ lazy val root = project
|
||||
.settings(
|
||||
name := "AOC2024",
|
||||
version := "0.1.0-SNAPSHOT",
|
||||
|
||||
scalaVersion := scala3Version,
|
||||
|
||||
fork := true,
|
||||
libraryDependencies += "org.scalameta" %% "munit" % "1.0.0" % Test
|
||||
)
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
@main def hello(): Unit =
|
||||
println("Hello world!")
|
||||
println(msg)
|
||||
import days._
|
||||
|
||||
def msg = "I was compiled by Scala 3. :)"
|
||||
@main def main(dayNumber: Int): Unit = {
|
||||
dayNumber match {
|
||||
case 1 => Day1.solve()
|
||||
case 2 => Day2.solve()
|
||||
case 3 => Day3.solve()
|
||||
case _ => println(s"Day $dayNumber is not yet implemented.")
|
||||
}
|
||||
}
|
||||
|
||||
31
src/main/scala/days/Day.scala
Normal file
31
src/main/scala/days/Day.scala
Normal file
@@ -0,0 +1,31 @@
|
||||
package days
|
||||
|
||||
import scala.io.Source
|
||||
|
||||
trait Day {
|
||||
val number: Int
|
||||
|
||||
def getInput(): Option[String] = {
|
||||
val resourcePath = getClass.getResource(s"day${number}.txt")
|
||||
if (resourcePath != null) {
|
||||
Some(Source.fromURL(resourcePath).mkString)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def solve(): Unit = {
|
||||
getInput() match {
|
||||
case Some(input) => {
|
||||
println(s"Day: $number")
|
||||
println(s"Part 1: ${part1(input)}")
|
||||
println(s"Part 2: ${part2(input)}")
|
||||
}
|
||||
case None =>
|
||||
println(s"Missing day $number input")
|
||||
}
|
||||
}
|
||||
|
||||
def part1(input: String): String
|
||||
def part2(input: String): String
|
||||
}
|
||||
35
src/main/scala/days/Day1.scala
Normal file
35
src/main/scala/days/Day1.scala
Normal file
@@ -0,0 +1,35 @@
|
||||
package days
|
||||
|
||||
object Day1 extends Day {
|
||||
val number: Int = 1;
|
||||
|
||||
def inputToLists(input: String): (List[Int], List[Int]) =
|
||||
input.linesIterator
|
||||
.map(l => {
|
||||
val line = l.split(" ")
|
||||
(line(0).toInt, line.last.toInt)
|
||||
})
|
||||
.foldLeft((Nil, Nil): Tuple2[List[Int], List[Int]]) {
|
||||
case ((accL, accR), (l, r)) => (l :: accL, r :: accR)
|
||||
}
|
||||
|
||||
def part1(input: String) = {
|
||||
val (leftList, rightList) = inputToLists(input)
|
||||
leftList
|
||||
.sorted()
|
||||
.zip(rightList.sorted())
|
||||
.map((a, b) => (a - b).abs)
|
||||
.sum
|
||||
.toString()
|
||||
}
|
||||
|
||||
def part2(input: String) = {
|
||||
val (leftList, rightList) = inputToLists(input)
|
||||
val counts =
|
||||
rightList.sorted
|
||||
.groupBy((n: Int) => n)
|
||||
.mapValues(_.length)
|
||||
|
||||
leftList.map(n => counts.getOrElse(n, 0) * n).sum().toString()
|
||||
}
|
||||
}
|
||||
56
src/main/scala/days/Day2.scala
Normal file
56
src/main/scala/days/Day2.scala
Normal file
@@ -0,0 +1,56 @@
|
||||
package days
|
||||
|
||||
object Day2 extends Day {
|
||||
val number: Int = 2;
|
||||
|
||||
def checkFnP1(input: List[Int], order: Option[Boolean]): Boolean =
|
||||
input match {
|
||||
case Nil => true
|
||||
case _ :: Nil => true
|
||||
case a :: b :: t => {
|
||||
val diff = a - b
|
||||
if (diff < -3 || diff > 3 || diff == 0) {
|
||||
return false
|
||||
}
|
||||
val curOrder = Some(diff > 0)
|
||||
val newOrder: Option[Boolean] = (order, curOrder) match {
|
||||
case (None, a) => a
|
||||
case (a, b) if a == b => a
|
||||
case _ => return false
|
||||
}
|
||||
checkFnP1(b :: t, newOrder)
|
||||
}
|
||||
}
|
||||
|
||||
def checkFnP2(
|
||||
input: List[Int]
|
||||
): Boolean = {
|
||||
// Wanted to try a recursive approach like p1 but I gave up.. :(
|
||||
if (checkFnP1(input, None)) {
|
||||
return true
|
||||
}
|
||||
(0 until (input.length)).iterator
|
||||
.map { n =>
|
||||
{
|
||||
val (before, after) = input.splitAt(n)
|
||||
val newInput = before ++ after.tail
|
||||
checkFnP1(newInput, None)
|
||||
}
|
||||
}
|
||||
.dropWhile(_ == false)
|
||||
.nextOption
|
||||
.getOrElse(false)
|
||||
}
|
||||
|
||||
def part1(input: String) =
|
||||
input.linesIterator
|
||||
.map(s => checkFnP1(s.split(" ").map(_.toInt).toList, None))
|
||||
.count(_ == true)
|
||||
.toString()
|
||||
|
||||
def part2(input: String) =
|
||||
input.linesIterator
|
||||
.map(s => checkFnP2(s.split(" ").map(_.toInt).toList))
|
||||
.count(_ == true)
|
||||
.toString()
|
||||
}
|
||||
32
src/main/scala/days/Day3.scala
Normal file
32
src/main/scala/days/Day3.scala
Normal file
@@ -0,0 +1,32 @@
|
||||
package days
|
||||
|
||||
import scala.util.matching.Regex
|
||||
|
||||
object Day3 extends Day {
|
||||
val number: Int = 3;
|
||||
|
||||
def part1(input: String) =
|
||||
"mul\\(([0-9]+),([0-9]+)\\)".r
|
||||
.findAllMatchIn(input)
|
||||
.map(m => m.group(1).toInt * m.group(2).toInt)
|
||||
.sum()
|
||||
.toString()
|
||||
|
||||
def part2(input: String) =
|
||||
"(do)\\(\\)|(don't)\\(\\)|mul\\(([0-9]+),([0-9]+)\\)".r
|
||||
.findAllMatchIn(input)
|
||||
.foldLeft((true, 0)) {
|
||||
// Activate flag if "do()" matched
|
||||
case ((_, acc), m) if m.group(1) != null => (true, acc)
|
||||
// Deactivate flag if "dont() matched"
|
||||
case ((_, acc), m) if m.group(2) != null => (false, acc)
|
||||
// Ignore mul() if deactivated
|
||||
case ((false, acc), _) => (false, acc)
|
||||
// Add mul() result to the accumulator
|
||||
case ((true, acc), m) =>
|
||||
(true, acc + m.group(3).toInt * m.group(4).toInt)
|
||||
}
|
||||
._2
|
||||
.toString()
|
||||
|
||||
}
|
||||
9
src/main/scala/days/Day4.scala
Normal file
9
src/main/scala/days/Day4.scala
Normal file
@@ -0,0 +1,9 @@
|
||||
package days
|
||||
|
||||
object Day4 extends Day {
|
||||
val number: Int = 4;
|
||||
|
||||
def part1(input: String) = "pouet"
|
||||
|
||||
def part2(input: String) = "pouet"
|
||||
}
|
||||
Reference in New Issue
Block a user