Skip to content

Instantly share code, notes, and snippets.

@waynejo
Last active January 5, 2024 13:23
Show Gist options
  • Save waynejo/ae3cc1423d8d6014516e004d2c98ca6b to your computer and use it in GitHub Desktop.
Save waynejo/ae3cc1423d8d6014516e004d2c98ca6b to your computer and use it in GitHub Desktop.
import java.io.FileInputStream
import scala.annotation.tailrec
import scala.io.StdIn
case class Number(number: Int, rect: Rect)
case class Map(values: Vector[String])
case class Rect(x: Int, y: Int, width: Int, height: Int):
def expanded(): Rect = Rect(x - 1, y - 1, width + 2, height + 2)
def intersected(other: Rect): Boolean =
x < other.x + other.width && x + width > other.x && y < other.y + other.height && y + height > other.y
object Rect:
def apply(x: Int, y: Int): Rect =
new Rect(x, y, 1, 1)
@tailrec
def findNumbers(map: Map, x: Int, y: Int, last: Option[Number], acc: Vector[Number]): Vector[Number] =
if y >= map.values.length then acc
else if x >= map.values(y).length then findNumbers(map, 0, y + 1, None, last.map(acc :+ _).getOrElse(acc))
else
val c = map.values(y)(x)
if c.isDigit then
last match
case Some(number) =>
val rect = number.rect
val newRect = Rect(rect.x, rect.y, rect.width + 1, rect.height)
findNumbers(map, x + 1, y, Some(Number(number.number * 10 + c.asDigit, newRect)), acc)
case None =>
val number = Number(c.asDigit, Rect(x, y))
findNumbers(map, x + 1, y, Some(number), acc)
else
val rect = last.map(_.rect).getOrElse(Rect(x, y))
findNumbers(map, x + 1, y, None, last.map(acc :+ _).getOrElse(acc))
def solve3_1(map: Map, numbers: Vector[Number]): Int =
val symbolIndices = map.values.zipWithIndex.flatMap { case (line, y) =>
line.zipWithIndex.collect { case (c, x) if c != '.' && !c.isDigit => (x, y) }
}
numbers.filter(
number => symbolIndices.exists(symbol => number.rect.intersected(Rect(symbol._1, symbol._2).expanded()))
).map(_.number).sum
def solve3_2(map: Map, numbers: Vector[Number]): Int =
val starIndices = map.values.zipWithIndex.flatMap { case (line, y) =>
line.zipWithIndex.collect { case ('*', x) => (x, y) }
}
val adjustedNumbers = starIndices.map(star => numbers.filter(_.rect.intersected(Rect(star._1, star._2).expanded())))
adjustedNumbers.filter(_.length == 2).map(_.map(_.number).product).sum
@main def solve3(): Unit =
val in = new FileInputStream("example3-2.in")
System.setIn(in)
val inputs = Iterator.continually(StdIn.readLine())
.takeWhile(line => null != line)
.toVector
val map = Map(inputs)
val numbers = findNumbers(map, 0, 0, None, Vector.empty)
println(solve3_1(Map(inputs), numbers))
println(solve3_2(Map(inputs), numbers))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment