Last active
December 7, 2023 16:59
-
-
Save Szer/3bdf613c93a3e9b50db5f207d1a278a8 to your computer and use it in GitHub Desktop.
Advent of Code 2023 7
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
let input2 = """32T3K 765 | |
T55J5 684 | |
KK677 28 | |
KTJJT 220 | |
QQQJA 483""" |> fun x -> x.Split('\n') // 6440 | |
let cardPower isPart1 = function | |
| 'A' -> 0xE | |
| 'K' -> 0xD | |
| 'Q' -> 0xC | |
| 'J' -> if isPart1 then 0xB else 0x1 | |
| 'T' -> 0xA | |
| x -> int x - 48 | |
type Hand = { handPower: int; bet: int } | |
let parseHand isPart1 (rawHand: string) = | |
let [|rawCards; rawBet|] = rawHand.Split(' ') | |
let handPower = | |
(0, rawCards) | |
||> Seq.fold (fun result card -> | |
cardPower isPart1 card + (result <<< 4) | |
) | |
let counts = | |
rawCards | |
|> Seq.filter (fun x -> isPart1 || x <> 'J') | |
|> Seq.countBy id | |
|> Seq.toArray | |
let jokerCounts = rawCards |> Seq.filter (fun x -> x = 'J') |> Seq.length | |
let inline (<?>) x y = | |
if isPart1 then x = y | |
else x + jokerCounts = y | |
let isFiveOfAKind = counts |> Seq.exists (fun (_, count) -> count <?> 5) || jokerCounts = 5 | |
let isFourOfAKind = counts |> Seq.exists (fun (_, count) -> count <?> 4) | |
let isThreeOfAKind = counts |> Seq.exists (fun (_, count) -> count <?> 3) | |
let pairs = counts |> Array.filter (fun (_, count) -> count >= 2) |> Array.sortBy snd | |
let isTwoPair = (pairs.Length + if isPart1 then 0 else jokerCounts) = 2 | |
let isOnePair = (pairs.Length + if isPart1 then 0 else jokerCounts) = 1 | |
let isFullHouse = | |
if isPart1 || jokerCounts = 0 then | |
if pairs.Length = 2 then | |
let [|(_, twoCounts); (_, threeCounts)|] = pairs | |
twoCounts = 2 && threeCounts = 3 | |
else false | |
else | |
// we don't care about 2+ Jokers as FH with 2 Js is possible only with another pair | |
// which makes it a 4+ of a kind | |
// and 2 Js with rainbow is a 3 of a kind | |
if jokerCounts = 1 && pairs.Length = 2 then | |
let [|(_, twoCounts1); (_, twoCounts2)|] = pairs | |
twoCounts1 = 2 && twoCounts2 = 2 | |
else false | |
let comboPower = | |
if isFiveOfAKind then 0xF | |
elif isFourOfAKind then 0xE | |
elif isFullHouse then 0xD | |
elif isThreeOfAKind then 0xC | |
elif isTwoPair then 0xB | |
elif isOnePair then 0xA | |
else (* high card *) 0x9 | |
let finalHandPower = (comboPower <<< 20) + handPower | |
{ handPower = finalHandPower | |
bet = int rawBet } | |
let game isPart1 = | |
input | |
|> Array.map (parseHand isPart1) | |
|> Array.sortWith (fun h1 h2 -> h1.handPower.CompareTo h2.handPower) | |
|> Seq.mapi (fun i hand -> hand.bet * (i + 1)) | |
|> Seq.sum | |
let part1 = game true // 6440 | |
let part2 = game false // 5905 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment