Day 7 #6

Merged
patrick merged 8 commits from day7 into main 2023-12-07 09:32:22 +00:00
Showing only changes of commit 61c3f1c79a - Show all commits

View File

@@ -3,15 +3,6 @@ namespace AdventOfCode2023
open System open System
open System.Collections.Generic open System.Collections.Generic
//type Hand =
// | Five of byte
// | Four of high: byte * low: byte
// | FullHouse of three: byte * two: byte
// | Three of three: byte * highOther: byte * lowOther: byte
// | TwoPairs of highPair: byte * lowPair: byte * other: byte
// | Pair of pair: byte * highOther: byte * midOther: byte * lowOther: byte
// | High of high: byte * mid: byte * low: byte * lowest: byte * lowestest: byte
type Hand = type Hand =
| Five = 10 | Five = 10
| Four = 9 | Four = 9
@@ -42,7 +33,7 @@ module Day7 =
elif c = 'A' then 14uy elif c = 'A' then 14uy
else failwithf "could not parse: %c" c else failwithf "could not parse: %c" c
let inline private updateState (tallies : ResizeArray<_>) (newNum) = let inline private updateState (tallies : ResizeArray<_>) newNum =
let mutable isAdded = false let mutable isAdded = false
for i = 0 to tallies.Count - 1 do for i = 0 to tallies.Count - 1 do
@@ -53,7 +44,12 @@ module Day7 =
if not isAdded then if not isAdded then
tallies.Add (newNum, 1) tallies.Add (newNum, 1)
let inline parseHand (adjustJoker : bool) (s : ReadOnlySpan<char>) : Hand * HandContents = let inline parseHand
(tallyBuffer : ResizeArray<_>)
(adjustJoker : bool)
(s : ReadOnlySpan<char>)
: Hand * HandContents
=
let contents = let contents =
{ {
First = toByte adjustJoker s.[0] First = toByte adjustJoker s.[0]
@@ -63,29 +59,32 @@ module Day7 =
Fifth = toByte adjustJoker s.[4] Fifth = toByte adjustJoker s.[4]
} }
let tallies = ResizeArray 5 tallyBuffer.Clear ()
tallies.Add (contents.First, 1) tallyBuffer.Add (contents.First, 1)
updateState tallies contents.Second updateState tallyBuffer contents.Second
updateState tallies contents.Third updateState tallyBuffer contents.Third
updateState tallies contents.Fourth updateState tallyBuffer contents.Fourth
updateState tallies contents.Fifth updateState tallyBuffer contents.Fifth
let jokerCount, jokerPos = let jokerCount, jokerPos =
let mutable count = 0 if not adjustJoker then
let mutable jokerPos = -1 0, -1
else
let mutable count = 0
let mutable jokerPos = -1
for i = 0 to tallies.Count - 1 do for i = 0 to tallyBuffer.Count - 1 do
let card, tally = tallies.[i] let card, tally = tallyBuffer.[i]
if card = 1uy then if card = 1uy then
count <- tally count <- tally
jokerPos <- i jokerPos <- i
count, jokerPos count, jokerPos
let hand = let hand =
if jokerCount > 0 then if jokerCount > 0 then
match tallies.Count with match tallyBuffer.Count with
| 1 -> | 1 ->
// Five jokers // Five jokers
Hand.Five Hand.Five
@@ -97,39 +96,42 @@ module Day7 =
if jokerCount >= 2 then if jokerCount >= 2 then
// JJABB or JJJAB // JJABB or JJJAB
Hand.Four Hand.Four
else else if
// JAABB or JAAAB // JAABB or JAAAB
let tallies = tallies |> Seq.map snd |> Seq.toArray jokerPos <> 0
then
if Array.contains 3 tallies then if snd tallyBuffer.[0] = 2 then
Hand.Four
else
Hand.FullHouse Hand.FullHouse
else
Hand.Four
else if snd tallyBuffer.[1] = 2 then
Hand.FullHouse
else
Hand.Four
| 4 -> | 4 ->
// Jokers plus three other card types, exactly one of which therefore is a two-of. // Jokers plus three other card types, exactly one of which therefore is a two-of.
Hand.Three Hand.Three
| 5 -> | 5 ->
// Five different cards, one of which is a joker. // Five different cards, one of which is a joker.
Hand.Pair Hand.Pair
| _ -> failwithf "bad tallies: %+A" tallies | _ -> failwith "bad tallyBuffer"
else elif tallyBuffer.Count = 1 then
let tallies = tallies |> Seq.map snd |> Seq.toArray
if tallies |> Array.contains 5 then
Hand.Five Hand.Five
elif Array.contains 4 tallies then elif tallyBuffer.Count = 2 then
Hand.Four // AAAAB or AAABB
elif Array.contains 3 tallies then if snd tallyBuffer.[0] = 3 || snd tallyBuffer.[0] = 2 then
if Array.contains 2 tallies then
Hand.FullHouse Hand.FullHouse
else else
Hand.Three Hand.Four
elif Array.contains 2 tallies then elif tallyBuffer.Count = 3 then
if tallies |> Array.filter (fun x -> x = 2) |> Array.length = 2 then // AAABC or AABBC
Hand.TwoPairs if snd tallyBuffer.[0] = 3 then Hand.Three
else elif snd tallyBuffer.[0] = 2 then Hand.TwoPairs
Hand.Pair elif snd tallyBuffer.[1] = 3 then Hand.Three
elif snd tallyBuffer.[1] = 2 then Hand.TwoPairs
else Hand.Three
elif tallyBuffer.Count = 4 then
Hand.Pair
else else
Hand.High Hand.High
@@ -138,12 +140,13 @@ module Day7 =
let parse (adjustJoker : bool) (s : string) : ResizeArray<Hand * HandContents * int> = let parse (adjustJoker : bool) (s : string) : ResizeArray<Hand * HandContents * int> =
use mutable lines = StringSplitEnumerator.make '\n' s use mutable lines = StringSplitEnumerator.make '\n' s
let result = ResizeArray () let result = ResizeArray ()
let tallies = ResizeArray 5
while lines.MoveNext () do while lines.MoveNext () do
if not lines.Current.IsEmpty then if not lines.Current.IsEmpty then
use mutable line = StringSplitEnumerator.make' ' ' lines.Current use mutable line = StringSplitEnumerator.make' ' ' lines.Current
line.MoveNext () |> ignore line.MoveNext () |> ignore
let hand, contents = parseHand adjustJoker line.Current let hand, contents = parseHand tallies adjustJoker line.Current
line.MoveNext () |> ignore line.MoveNext () |> ignore
let bid = Int32.Parse line.Current let bid = Int32.Parse line.Current