aoc2023/Day4.scala

58 lines
1.3 KiB
Scala
Raw Normal View History

2023-12-04 13:25:10 +00:00
package aoc.day4
import aoc._
import scala.collection.mutable.Map
case class Card(id: Int, winning: List[Int], got: List[Int]):
lazy val won =
val winSet = winning.toSet
got.filter(winSet contains _)
def pointValue =
if won.isEmpty then 0 else 1L << (won.length - 1)
object Parser extends CommonParser:
val nums = rep1(num)
val card = "Card " ~ num ~ ":" ~ nums ~ "|" ~ nums ^^ {
case (_ ~ id ~ _ ~ winning ~ _ ~ got) => Card(id, winning, got)
}
end Parser
val cards = lines.map(l => Parser.parse(Parser.card, l).get).toSeq
// Part 1
def part1 =
val res = cards.map(_.pointValue).sum
println(res)
// Part 2
class Tails():
private val map = Map[Int, Long]()
var sum = 0L
def add(tail: Int, copies: Long): Unit =
sum += copies
map.updateWith(tail)(v => Some(v.fold(copies)(_ + copies)))
def filter(id: Int): Unit =
map.remove(id).foreach { sum -= _ }
end Tails
@scala.annotation.tailrec
def traverse(ids: Iterator[Card], tails: Tails, accum: Long = 0): Long =
if !ids.hasNext then return accum
val card = ids.next()
val copies = 1 + tails.sum
tails.add(card.id + card.won.length, copies)
tails.filter(card.id)
traverse(ids, tails, accum + copies)
def part2 =
val res = traverse(cards.toIterator, new Tails())
println(res)
@main def Day4(part: Int) = part match
case 1 => part1
case 2 => part2