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