-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay05.fs
111 lines (84 loc) · 2.71 KB
/
Day05.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
module aoc24.Day05
module Pages =
let middle (p: int list) = p[p.Length / 2]
let parse input =
let parseRules =
Seq.map (StringEx.splitC '|' >> (fun p -> (int p.[0], int p.[1]))) >> Seq.toList
let parsePages =
Seq.map (StringEx.splitC ',' >> Seq.map int >> Seq.toList) >> Seq.toList
let splitAt = input |> Array.findIndex ((=) "")
(parseRules input.[0 .. splitAt - 1], parsePages input.[splitAt + 1 ..])
let part1 input =
let rules, pages = parse input
let ruleMap = rules |> List.groupBy snd |> Map
let findBrokenRules pages =
let rec loop pNums brokenRules =
match pNums with
| cur :: tail ->
let matchingRules = ruleMap |> Map.tryFind cur |> Option.defaultValue []
let brokenMatchingRules =
matchingRules |> List.filter (fun rule -> tail |> List.contains (rule |> fst))
loop tail (brokenMatchingRules @ brokenRules)
| [] -> brokenRules
loop pages []
pages
|> List.filter (fun p -> (findBrokenRules p |> List.length) = 0)
|> List.sumBy Pages.middle
let part2 input =
let rules, pagesList = parse input
let rulesSet = rules |> Set
let comparer a b =
if rulesSet |> Set.contains (a, b) then -1
elif rulesSet |> Set.contains (b, a) then 1
else 0
let sortedPagesList = pagesList |> List.map (List.sortWith comparer)
let correctedPagesList =
List.zip pagesList sortedPagesList
|> List.choose (function
| original, sorted when original <> sorted -> Some sorted
| _ -> None)
correctedPagesList |> List.sumBy Pages.middle
let run = runReadAllLines part1 part2
module tests =
open Swensen.Unquote
open Xunit
let example =
[| "47|53"
"97|13"
"97|61"
"97|47"
"75|29"
"61|13"
"75|53"
"29|13"
"97|29"
"53|29"
"61|53"
"97|53"
"61|29"
"47|13"
"75|47"
"97|75"
"47|61"
"75|61"
"47|29"
"75|13"
"53|13"
""
"75,47,61,53,29"
"97,61,53,29,13"
"75,29,13"
"75,97,47,61,53"
"61,13,29"
"97,13,75,29,47" |]
[<Fact>]
let ``Parse example`` () =
let rules, pages = parse example
Seq.head rules =! (47, 53)
Seq.last rules =! (53, 13)
Seq.head pages =! [ 75; 47; 61; 53; 29 ]
Seq.last pages =! [ 97; 13; 75; 29; 47 ]
[<Fact>]
let ``Part 1 example`` () = part1 example =! 143
[<Fact>]
let ``Part 2 example`` () = part2 example =! 123