-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday16_part02.fs
98 lines (85 loc) · 3.33 KB
/
day16_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
module day16_part02
open System.Text.RegularExpressions
open AdventOfCode_2020.Modules
type Range = {
Start: int64
End: int64
IsDeparture: bool
}
type Notes = {
Ranges: Range list array
MyTickets: int64 array
OtherTickets: int64 array array
}
let parseContent(input: string) =
let parts = input.Split($"{System.Environment.NewLine}{System.Environment.NewLine}")
let rangepattern = @"(\d+)-(\d+) or (\d+)-(\d+)"
let numberspattern = @"(\d+)"
let ranges =
[
for p in parts[0].Split(System.Environment.NewLine) do
let m' = Regex.Match(p, rangepattern)
let departure = p.StartsWith("departure")
let (f1, t1, f2, t2) =
((int64)(m'.Groups[1].Value), (int64)(m'.Groups[2].Value), (int64)(m'.Groups[3].Value), (int64)(m'.Groups[4].Value))
yield [{ Start = f1; End = t1; IsDeparture = departure }; { Start = f2; End = t2; IsDeparture = departure }]
]
let myticket = (parts[1].Split(System.Environment.NewLine)[1]).Split(",") |> Array.map int64
let otickets = parts[2].Split(System.Environment.NewLine) |> Array.skip(1)
let nearby =
[
for n in otickets do
yield n.Split(",") |> Array.map int64
]
{ Ranges = ranges |> Array.ofList; MyTickets = myticket; OtherTickets = nearby |> Array.ofList }
let errorRate(notes: Notes) =
let otherfiltered =
notes.OtherTickets
|> Array.filter(fun ta ->
ta
|> Array.forall(fun t ->
(notes.Ranges |> List.concat) |> List.exists(fun r -> r.Start <= t && t <= r.End)
)
)
{ notes with OtherTickets = otherfiltered }
let calculatedeparture(notes: Notes) =
let maxnumber = 19
let cleanednotes = errorRate notes
let alltickets = Array.append [| cleanednotes.MyTickets |] cleanednotes.OtherTickets
let validindexes =
[|0..maxnumber|]
|> Array.map(fun idx ->
notes.Ranges
|> Array.indexed
|> Array.filter(fun (_, ranges) ->
alltickets
|> Array.forall(fun t ->
ranges |> List.exists(fun r -> r.Start <= t[idx] && t[idx] <= r.End)
)
)
|> Array.map fst
|> Set.ofArray
)
let solution = Array.create (maxnumber+1) -1
let rec cleanIndexes (indexes: Set<int> array) (current: Set<int>) (index: int) =
if current.Count > maxnumber then
[0..5]
|> List.map(fun idx ->
notes.MyTickets[solution[idx]]
)
|> List.reduce (*)
else
let idx = validindexes |> Array.findIndex(fun v -> v.Count = index + 1)
let tobecleaned = indexes[idx]
let sindex = (Set.difference tobecleaned current).MinimumElement
solution[sindex] <- idx
cleanIndexes indexes (Set.add sindex current) (index + 1)
let index = validindexes |> Array.findIndex(fun v -> v.Count = 1)
let sindex = validindexes[index].MinimumElement
solution[sindex] <- index
cleanIndexes validindexes (Set.ofList([solution[index]])) 1
let execute =
let path = "day16/day16_input.txt"
let content = LocalHelper.GetContentFromFile path
let notes = parseContent content
calculatedeparture notes