Day 7
This commit is contained in:
parent
d1937c0846
commit
44eaf3037e
92
Day7.scala
Normal file
92
Day7.scala
Normal file
|
@ -0,0 +1,92 @@
|
|||
package aoc.day7
|
||||
|
||||
import aoc._
|
||||
|
||||
val possibleCards = "AKQJT98765432".reverse
|
||||
|
||||
enum DeckKind:
|
||||
case High
|
||||
case Pair
|
||||
case Pairs
|
||||
case Three
|
||||
case House
|
||||
case Four
|
||||
case Five
|
||||
|
||||
object DeckKind:
|
||||
def apply(deck: String) =
|
||||
val ranks = deck.sorted.toArray
|
||||
if ranks(0) == ranks(4) then Five
|
||||
else if ranks(0) == ranks(3) || ranks(1) == ranks(4) then Four
|
||||
else if ranks(0) == ranks(2) && ranks(3) == ranks(4) || ranks(0) == ranks(
|
||||
1
|
||||
) && ranks(2) == ranks(4)
|
||||
then House
|
||||
else if ranks(0) == ranks(1) && ranks(2) == ranks(3) || ranks(0) == ranks(
|
||||
1
|
||||
) && ranks(3) == ranks(4) || ranks(1) == ranks(2) && ranks(3) == ranks(4)
|
||||
then Pairs
|
||||
else
|
||||
lazy val three = (0 until ranks.length - 2)
|
||||
.find(i => ranks(i) == ranks(i + 2))
|
||||
.map(i => Three)
|
||||
lazy val pair = (0 until ranks.length - 1)
|
||||
.find(i => ranks(i) == ranks(i + 1))
|
||||
.map(i => Pair)
|
||||
three.orElse(pair).getOrElse(High)
|
||||
|
||||
import DeckKind._
|
||||
|
||||
case class Hand(deck: String, bet: Int):
|
||||
def deckRank(using cardToRank: Map[Char, Int]) = deck.map(cardToRank(_))
|
||||
val kind = DeckKind(deck)
|
||||
|
||||
lazy val bestKind =
|
||||
deck.iterator
|
||||
.foldLeft(Iterator("")) { (it, chr) =>
|
||||
if chr == 'J' then it.flatMap(s => possibleCards.map(s + _))
|
||||
else it.map(_ + chr)
|
||||
}
|
||||
.map(DeckKind(_))
|
||||
.maxBy(_.ordinal)
|
||||
|
||||
inline def nonZero(ins: Int*) = ins.find(_ != 0).getOrElse(0)
|
||||
|
||||
object Parser extends CommonParser:
|
||||
val deck = (s"[${possibleCards}]{5}").r
|
||||
val hand = deck ~ num ^^ { case (deck ~ num) => Hand(deck, num) }
|
||||
def apply(s: String) =
|
||||
parse(hand, s).get
|
||||
|
||||
// part 1
|
||||
|
||||
def handOrdering(toKind: Hand => DeckKind)(using cardOrdering: Map[Char, Int]) =
|
||||
new Ordering[Hand]:
|
||||
override def compare(dx: Hand, dy: Hand): Int =
|
||||
val (x, y) = (toKind(dx), toKind(dy))
|
||||
if x.ordinal != y.ordinal then x.ordinal.compareTo(y.ordinal)
|
||||
else nonZero(dx.deckRank.zip(dy.deckRank).map(_ compareTo _)*)
|
||||
|
||||
def print(using Ordering[Hand]) =
|
||||
val hands = lines.map(Parser(_)).toSeq
|
||||
val res =
|
||||
hands.sorted.zipWithIndex
|
||||
.map((h, idx) => h.bet * (idx + 1L))
|
||||
.sum
|
||||
println(res)
|
||||
|
||||
def part1 =
|
||||
val ordering = possibleCards.zipWithIndex.toMap
|
||||
val handOrd = handOrdering(_.kind)(using ordering)
|
||||
print(using handOrd)
|
||||
|
||||
// part 2
|
||||
|
||||
def part2 =
|
||||
val ordering = "J23456789TQKA".zipWithIndex.toMap
|
||||
val handOrd = handOrdering(_.bestKind)(using ordering)
|
||||
print(using handOrd)
|
||||
|
||||
@main def Day7(part: Int) = part match
|
||||
case 1 => part1
|
||||
case 2 => part2
|
1000
inputs/day7.input
Normal file
1000
inputs/day7.input
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue