-
-
Save waynejo/ae3cc1423d8d6014516e004d2c98ca6b to your computer and use it in GitHub Desktop.
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
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