Last active
December 8, 2023 04:49
-
-
Save thanhbv/38bd6676d3348334db58e4926add0a11 to your computer and use it in GitHub Desktop.
Advent of Code 2023 day 7 scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Dev using scala-cli and vscode https://scala-cli.virtuslab.org/docs/cookbooks/ide/vscode | |
//> using scala 3.3.1 | |
import Hand.*, Kind.* | |
import scala.math.Ordering | |
enum Kind: | |
case HighCard, OnePair, TwoPair, ThreeOfAKind, FullHouse, FourOfAKind, FiveOfAKind | |
object Hand: | |
val Joker = 'J' | |
val Order1 = "23456789TJQKA" | |
val Order2 = "J23456789TQKA" | |
def ord(kind: Hand => Kind, cardOrder: String): Ordering[Hand] = (x: Hand, y: Hand) => | |
val (k, k2) = (kind(x), kind(y)) | |
if k != k2 then | |
k.ordinal - k2.ordinal | |
else | |
x.cards.zip(y.cards).collectFirst{ | |
case (c, c2) if c != c2 => cardOrder.indexOf(c) - cardOrder.indexOf(c2) | |
}.getOrElse(0) | |
case class Hand(cards: String): | |
def kind: Kind = | |
val m = cards.map { c => c -> cards.count(_ == c) }.toMap | |
m.size match | |
case 5 => HighCard | |
case 4 => OnePair | |
case 3 => if m.values.max == 3 then ThreeOfAKind else TwoPair | |
case 2 => if m.values.max == 4 then FourOfAKind else FullHouse | |
case _ => FiveOfAKind | |
def kind2: Kind = | |
val cs = cards.replace(Joker.toString, "") | |
if cs.isEmpty() then FiveOfAKind | |
else | |
val m = cs.map { c => c -> cs.count(_ == c) }.toMap | |
val c = m.maxBy(_._2)._1 | |
Hand(cards.replace(Joker, c)).kind | |
case class Game(hand: Hand, bid: Long) | |
val input = """32T3K 765 | |
T55J5 684 | |
KK677 28 | |
KTJJT 220 | |
QQQJA 483""" | |
val games = input. | |
linesIterator. | |
map { line => | |
val Array(cs, b) = line.split(' ') | |
Game(Hand(cs), b.toLong) | |
}. | |
toList | |
def win(using ord: Ordering[Hand]): Long = games.sortBy(_.hand).zipWithIndex.map { (g, i) => g.bid * (i + 1) }.sum | |
@main def part1() = | |
println(win(using Hand.ord(_.kind, Order1))) | |
@main def part2() = | |
println(win(using Hand.ord(_.kind2, Order2))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment