-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day04.fs
70 lines (54 loc) · 2.06 KB
/
Day04.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
module aoc23.Day04
open FSharp.Text.RegexProvider
open FSharp.Text.RegexExtensions
open Xunit
open Swensen.Unquote
type Card =
{ Id: int
CardNumbers: int list
WinningNumbers: int list }
module Card =
type CardRegex = Regex< @"Card +(?<id>\d+): (?<winning>[\d ]*)\|(?<cardNumbers>[\d ]*)" >
type NumberRegex = Regex< @"(?<num>\d+)" >
let getAllNumbers str =
NumberRegex().TypedMatches(str) |> Seq.map _.num.AsInt
let fromString line =
let match' = CardRegex().TypedMatch(line)
{ Id = match'.id.AsInt
CardNumbers = match'.cardNumbers.Value |> getAllNumbers |> Seq.toList
WinningNumbers = match'.winning.Value |> getAllNumbers |> Seq.toList }
let matchingNumbers
{ CardNumbers = cn
WinningNumbers = wn }
=
Set.intersect (Set cn) (Set wn)
let part1 lines =
lines
|> Seq.map (Card.fromString >> Card.matchingNumbers)
|> Seq.map (Set.count >> (fun count -> pown 2 (count - 1)))
|> Seq.sum
let part2 lines =
let scores =
lines |> Array.map (Card.fromString >> Card.matchingNumbers >> Set.count)
let folder (sum, remainingCounts) score =
match remainingCounts with
| x :: xs ->
let xs1, xs2 = xs |> List.splitAt score
let newXs1 = xs1 |> List.map ((+) x)
(sum + x, newXs1 @ xs2)
| _ -> failwith "initial state too short"
let initialState = (0, List.init scores.Length (fun _ -> 1))
Seq.fold folder initialState scores |> fst
let run = runReadAllLines part1 part2
module Tests =
let example =
[| "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53"
"Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19"
"Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1"
"Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83"
"Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36"
"Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11" |]
[<Fact>]
let ``part 1`` () = part1 example =! 13
[<Fact>]
let ``part 2`` () = part2 example =! 30