63 lines
1.5 KiB
Scala
63 lines
1.5 KiB
Scala
package aoc.day15
|
|
|
|
import aoc._
|
|
import scala.collection.mutable
|
|
|
|
val instructionStrings = lines.next().split(',').toSeq
|
|
|
|
// part 1
|
|
|
|
extension (s: String)
|
|
def day15Hash =
|
|
s.foldLeft(0)((a, b) => ((a + b) * 17) & 255)
|
|
|
|
def part1 =
|
|
println(instructionStrings.map(_.day15Hash).sum)
|
|
|
|
// part 2
|
|
|
|
enum Ins:
|
|
case Del(label: String)
|
|
case Add(label: String, length: Int)
|
|
|
|
def hash = this match
|
|
case Del(label) => label.day15Hash
|
|
case Add(label, length) => label.day15Hash
|
|
import Ins._
|
|
|
|
object Parser extends CommonParser:
|
|
val insKind =
|
|
"""[a-z]+""".r.flatMap { label =>
|
|
("-" ^^^ Del(label)) |
|
|
("=" ~ num ^^ { case _ ~ num => Add(label, num) })
|
|
}
|
|
def apply(s: String) = parse(insKind, s).get
|
|
|
|
val instructions = instructionStrings.map(Parser(_))
|
|
|
|
class Sim(ss: Seq[Ins]):
|
|
private val boxes = (0 to 255).map(_ => mutable.ArrayBuffer.empty[Add]).toArray
|
|
|
|
def handle(ins: Ins): Unit = ins match
|
|
case a @ Add(label, length) =>
|
|
boxes(ins.hash).indexWhere(_.label == label) match
|
|
case -1 => boxes(ins.hash).append(a)
|
|
case pos => boxes(ins.hash)(pos) = a
|
|
case Del(label) => boxes(ins.hash).filterInPlace(_.label != label)
|
|
|
|
ss.foreach(handle)
|
|
|
|
def remain =
|
|
boxes.toIterator.zipWithIndex.flatMap { (box, idx) =>
|
|
box.toIterator.zipWithIndex.map { (add, pos) =>
|
|
(idx + 1, pos + 1, add.length)
|
|
}
|
|
}
|
|
|
|
def part2 =
|
|
println(Sim(instructions).remain.map(_ * _ * _).sum)
|
|
|
|
@main def Day15(part: Int) = part match
|
|
case 1 => part1
|
|
case 2 => part2
|