Problem description
The puzzle input is a list of problems. For each problem, there is a list of numbers, and an the operation that must be applied to numbers : either an addition (+) or a multiplication (*).
For example, the test case I used is :
123 328 51 64
45 64 387 23
6 98 215 314
* + * +
Part 1
In this part, the numbers are arranged vertically, one number per line. The four problems are :
First, I defined an immutable Problem class, with an array of numbers, and the operation to apply. For this class, I defined a result method
case class Problem(op: Char, numbers: Array[Long]):
def result: Long =
op match
case '+' => numbers.sum
case '*' => numbers.reduce((x, y) => x * y)
Input data parsing is straightforward.
private def parseProblems1(input: List[String]): Array[Problem] =
val matrix = input.init.map(line => line.split(" ").filter(s => !s.equals("")).map(s => s.toLong))
val ops = input.last.split(" ").filter(s => !s.equals("")).map(s => s.head)
(0 until ops.length)
.map(i => Problem(ops(i), (0 until matrix.length).map(j => matrix(j)(i)).toArray))
.toArray
The final result is given by summing the results obtained for each problem.
def solvePart1(input: List[String]): Long =
val problems = parseProblems1(input)
problems.map(x => x.result).sum
Part 2
Now, things become a bit more complicated. The numbers are now written in columns, one in each column, the most significant digit at the top. The four problems in our test case become :
The first thing I did was to find the empty columns, delimiting the problems, and to build a “datamap”, with start and end columns for each problem.
var problems: ArrayBuffer[Problem] = ArrayBuffer()
val opLine = input.last
val numbersLines = input.init
var opIndexes: ArrayBuffer[Int] = ArrayBuffer()
for i <- 0 until opLine.length do
if opLine.charAt(i) != ' ' then opIndexes += i
opIndexes += opLine.length + 1
val columns = (0 until opIndexes.length - 1).map(i => (opIndexes(i), opIndexes(i+1) - 2)).toArray
Then, I explored each non-empty column, to build their corresponding numbers :
for (start, end) <- columns do
var numbers: ArrayBuffer[Long] = ArrayBuffer()
var i = end
while i >= start do
var n = 0
for line <- numbersLines do
val c = line.charAt(i)
if c >= '0' && c <= '9' then n = 10 * n + (c - 48)
i -= 1
numbers += n
problems += Problem(input.last.charAt(start), numbers.toArray)
The final result is obtained by the same method as in Part 1.