mirror of
https://github.com/mx42/aoc2024.scala.git
synced 2026-01-14 05:49:51 +01:00
feat: add day 4
This commit is contained in:
@@ -5,6 +5,7 @@ import days._
|
|||||||
case 1 => Day1.solve()
|
case 1 => Day1.solve()
|
||||||
case 2 => Day2.solve()
|
case 2 => Day2.solve()
|
||||||
case 3 => Day3.solve()
|
case 3 => Day3.solve()
|
||||||
|
case 4 => Day4.solve()
|
||||||
case _ => println(s"Day $dayNumber is not yet implemented.")
|
case _ => println(s"Day $dayNumber is not yet implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,116 @@
|
|||||||
package days
|
package days
|
||||||
|
|
||||||
|
case class Pos(x: Int, y: Int) {
|
||||||
|
def upLeft: Pos = Pos(x - 1, y - 1)
|
||||||
|
def up: Pos = Pos(x, y - 1)
|
||||||
|
def upRight: Pos = Pos(x + 1, y - 1)
|
||||||
|
def left: Pos = Pos(x - 1, y)
|
||||||
|
def right: Pos = Pos(x + 1, y)
|
||||||
|
def downLeft: Pos = Pos(x - 1, y + 1)
|
||||||
|
def down: Pos = Pos(x, y + 1)
|
||||||
|
def downRight: Pos = Pos(x + 1, y + 1)
|
||||||
|
|
||||||
|
def cross: List[Pos] = List(
|
||||||
|
this.upLeft,
|
||||||
|
this.downRight,
|
||||||
|
this.upRight,
|
||||||
|
this.downLeft
|
||||||
|
)
|
||||||
|
|
||||||
|
def inThreshold(geo: Pos): Boolean =
|
||||||
|
x >= 0 && x < geo.x && y >= 0 && y < geo.y
|
||||||
|
}
|
||||||
|
|
||||||
|
object Pos {
|
||||||
|
def getNeighbors(): List[Pos => Pos] = List(
|
||||||
|
_.upLeft,
|
||||||
|
_.up,
|
||||||
|
_.upRight,
|
||||||
|
_.left,
|
||||||
|
_.right,
|
||||||
|
_.downLeft,
|
||||||
|
_.down,
|
||||||
|
_.downRight
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
object Day4 extends Day {
|
object Day4 extends Day {
|
||||||
val number: Int = 4;
|
val number: Int = 4;
|
||||||
|
|
||||||
def part1(input: String) = "pouet"
|
def getPositions(p: Pos, geo: Pos, size: Int): List[List[Pos]] =
|
||||||
|
// Get neighbors positions around a position (if matching the geometry)
|
||||||
|
Pos
|
||||||
|
// For each neighbor direction (up-left, up, up-right, etc)
|
||||||
|
.getNeighbors()
|
||||||
|
.map(f =>
|
||||||
|
Iterator
|
||||||
|
// Build an iterator going from [P] to the direction's neighbor [P]
|
||||||
|
.iterate(p)(f)
|
||||||
|
// Do it [size] time
|
||||||
|
.take(size)
|
||||||
|
// Drop positions getting outside the designed dimensions
|
||||||
|
.filter(_.inThreshold(geo))
|
||||||
|
.toList
|
||||||
|
)
|
||||||
|
// Only take the list of positions exactly matching the expected length
|
||||||
|
.filter(_.length == size)
|
||||||
|
|
||||||
def part2(input: String) = "pouet"
|
def getCross(p: Pos, geo: Pos): Option[List[Pos]] =
|
||||||
|
// Get surrounding cross around a position (if matching the geometry)
|
||||||
|
p.cross.filter(_.inThreshold(geo)) match {
|
||||||
|
case l if l.length == 4 => Some(l)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
|
||||||
|
def getString(lines: List[String])(ps: List[Pos]): String =
|
||||||
|
// Convert list of positions to matching letters
|
||||||
|
ps.map {
|
||||||
|
case Pos(x, y) => {
|
||||||
|
lines(y)(x)
|
||||||
|
}
|
||||||
|
}.mkString
|
||||||
|
|
||||||
|
def isCrossedMAS(s: String): Boolean =
|
||||||
|
// Verify if a string is a crossed MAS
|
||||||
|
s.length == 4
|
||||||
|
&& s.forall("MS".contains)
|
||||||
|
&& s(0) != s(1)
|
||||||
|
&& s(2) != s(3)
|
||||||
|
|
||||||
|
// Verify if a string is a XMAS
|
||||||
|
def isXMAS: String => Boolean = _ == "XMAS"
|
||||||
|
|
||||||
|
def part1(input: String) = {
|
||||||
|
val lines: List[String] = input.linesIterator.toList
|
||||||
|
val geom: Pos = Pos(lines(0).length, lines.length)
|
||||||
|
lines.zipWithIndex
|
||||||
|
.flatMap { case (s, y) =>
|
||||||
|
s.iterator.zipWithIndex.toList
|
||||||
|
.filter(_._1 == 'X')
|
||||||
|
.flatMap { case (_, x) =>
|
||||||
|
getPositions(Pos(x, y), geom, 4)
|
||||||
|
.map(getString(lines))
|
||||||
|
.filter(isXMAS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.length
|
||||||
|
.toString
|
||||||
|
}
|
||||||
|
|
||||||
|
def part2(input: String) = {
|
||||||
|
val lines: List[String] = input.linesIterator.toList
|
||||||
|
val geom: Pos = Pos(lines(0).length, lines.length)
|
||||||
|
lines.zipWithIndex
|
||||||
|
.flatMap { case (s, y) =>
|
||||||
|
s.iterator.zipWithIndex.toList
|
||||||
|
.filter(_._1 == 'A')
|
||||||
|
.flatMap { case (_, x) =>
|
||||||
|
getCross(Pos(x, y), geom)
|
||||||
|
.map(getString(lines))
|
||||||
|
.filter(isCrossedMAS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.length
|
||||||
|
.toString
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user