58 lines
1.3 KiB
Scala
58 lines
1.3 KiB
Scala
|
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
|