-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday07_part02.fs
144 lines (130 loc) · 4.48 KB
/
day07_part02.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
module day07_part02
open System
open AdventOfCode_2023.Modules.LocalHelper
let bigint = System.Numerics.BigInteger.Parse
type HandType = FiveOfKind | FourOfKind | FullHouse | ThreeOfKind | TwoPairs | OnePair | HighCard
let strengthHandTypes = dict[
FiveOfKind, 6
FourOfKind, 5
FullHouse, 4
ThreeOfKind, 3
TwoPairs, 2
OnePair, 1
HighCard, 0
]
let strengthCards = dict[
"2", 2
"3", 3
"4", 4
"5", 5
"6", 6
"7", 7
"8", 8
"9", 9
"T", 10
"J", 1
"Q", 12
"K", 13
"A", 14
]
type Hand = {
HandType: HandType
Cards: string list
Bid: bigint
}
let rec sortByCard (card1: string list) (card2: string list) =
match card1, card2 with
| [], [] -> 0
| head1::_ , head2::_ when strengthCards.[head1] > strengthCards.[head2] -> 1
| head1::_ , head2::_ when strengthCards.[head1] < strengthCards.[head2] -> -1
| head1::tail1 , head2::tail2 when strengthCards.[head1] = strengthCards.[head2] -> sortByCard tail1 tail2
| _ -> failwith "Unexpected"
let sortByHandType (hand1: Hand) (hand2: Hand) =
if strengthHandTypes.[hand1.HandType] > strengthHandTypes.[hand2.HandType] then 1
elif strengthHandTypes.[hand1.HandType] < strengthHandTypes.[hand2.HandType] then -1
else
sortByCard hand1.Cards hand2.Cards
let getRemainingHandType (cards: char array) =
let handType =
let groups = cards |> Array.groupBy id
match cards.Length with
| 5 ->
match groups.Length with
| 5 -> HighCard
| 4 -> OnePair
| 3 ->
match groups |> Array.map (fun (key, value) -> value.Length) |> Array.sort with
| [| 1; 1; 3 |] -> ThreeOfKind
| [| 1; 2; 2 |] -> TwoPairs
| _ -> failwith "Unexpected"
| 2 ->
match groups |> Array.map (fun (key, value) -> value.Length) |> Array.sort with
| [| 1; 4 |] -> FourOfKind
| [| 2; 3 |] -> FullHouse
| _ -> failwith "Unexpected"
| 1 -> FiveOfKind
| _ -> failwith "Unexpected"
| 4 ->
match groups.Length with
| 4 -> HighCard
| 3 -> OnePair
| 2 ->
match groups |> Array.map (fun (key, value) -> value.Length) |> Array.sort with
| [| 1; 3 |] -> ThreeOfKind
| [| 2; 2 |] -> TwoPairs
| _ -> failwith "Unexpected"
| 1 -> FourOfKind
| _ -> failwith "Unexpected"
| 3 ->
match groups.Length with
| 3 -> HighCard
| 2 -> OnePair
| 1 -> ThreeOfKind
| _ -> failwith "Unexpected"
| 2 ->
match groups.Length with
| 1 -> OnePair
| _ -> HighCard
| 1 -> HighCard
| _ -> HighCard
handType
let calculateHandType (cards: char array) =
let numberOfJokers = cards |> Array.filter(fun c -> c = 'J') |> Array.length
let remainingHandType = getRemainingHandType (cards |> Array.filter (fun c -> c <> 'J'))
let newHandType =
match numberOfJokers with
| 1 ->
match remainingHandType with
| HighCard -> OnePair
| OnePair -> ThreeOfKind
| TwoPairs -> FullHouse
| ThreeOfKind -> FourOfKind
| FourOfKind -> FiveOfKind
| _ -> remainingHandType
| 2 ->
match remainingHandType with
| HighCard -> ThreeOfKind
| OnePair -> FourOfKind
| ThreeOfKind -> FiveOfKind
| _ -> remainingHandType
| 3 ->
match remainingHandType with
| HighCard -> FourOfKind
| OnePair -> FiveOfKind
| _ -> remainingHandType
| 4 -> FiveOfKind
| 5 -> FiveOfKind
| _ -> remainingHandType
newHandType
let parseHand (hand: string) =
let cards = hand.Split(' ')
let bid = cards.[1] |> bigint
let cards = cards.[0].ToCharArray()
{ HandType = calculateHandType cards; Cards = cards |> Array.map (string) |>List.ofArray; Bid = bid }
let execute =
let path = "day07/day07_input.txt"
let lines = GetLinesFromFile path
let hands = lines |> Array.map parseHand
let sortedHands = hands |> Array.sortWith sortByHandType
let rankedHands = sortedHands |> Array.mapi (fun index hand -> hand.Bid * (bigint(index.ToString()) + 1I))
rankedHands |> Array.sum