-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday18_part01.fs
113 lines (99 loc) · 3.49 KB
/
day18_part01.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
module day18_part01
open AdventOfCode_2021.Modules
type SnailfishNumber =
| Simple of int * depth:int
| Complex of SnailfishNumber * SnailfishNumber * depth:int
let rec snailfishNumberFromLine depth (line:string) =
match line.[0] with
| '[' ->
let (nr1, offset1) = snailfishNumberFromLine (depth+1) line.[1..]
let (nr2, offset2) = snailfishNumberFromLine (depth+1) line.[1+offset1..]
(Complex(nr1, nr2, depth), 1 + offset1 + offset2)
| ']'| ',' ->
let (nr, offset) = snailfishNumberFromLine depth line.[1..]
(nr, offset + 1)
| x ->
(Simple(int x - int '0', depth), 1)
let rec tryAddFromLeft nr sfn =
match sfn with
| Complex(sfn1, sfn2, d) ->
Complex(sfn1
|> tryAddFromLeft nr, sfn2, d)
| Simple(x, d) ->
Simple(x+nr, d)
let rec tryAddFromRight nr sfn =
match sfn with
| Complex(sfn1, sfn2, d) ->
Complex(sfn1, sfn2 |> tryAddFromRight nr, d)
| Simple(x, d) ->
Simple(x+nr, d)
let rec explodeIfRequired sfn =
match sfn with
| Complex(Simple(x1, _), Simple(x2, _), 4) ->
(true, Simple(0, 4), x1, x2)
| Simple(_, _) ->
(false, sfn, 0, 0)
| Complex(x1, x2, d) ->
let (exploded, explodedLeft, l, r) = explodeIfRequired x1
if exploded then
(true, Complex(explodedLeft, x2 |> tryAddFromLeft r, d), l, 0)
else
let (exploded, explodedRight, l_, r_) = explodeIfRequired x2
if exploded then
(true, Complex(x1 |> tryAddFromRight l_, explodedRight, d), 0, r_)
else
(false, sfn, 0, 0)
let rec splitIfRequired sfn =
match sfn with
| Simple(x, d) when x >= 10 ->
(true, Complex(Simple(x/2, d+1), Simple((if x%2 = 0 then x/2 else x/2+1), d+1), d))
| Simple(_, _) ->
(false, sfn)
| Complex(x1, x2, d) ->
let (splitted, splittedSfn) = splitIfRequired x1
if splitted then
(true, Complex(splittedSfn, x2, d))
else
let (splitted, splittedSfn) = splitIfRequired x2
if splitted then
(true, Complex(x1, splittedSfn, d))
else
(false, sfn)
let rec reduceSnailFishNumber sfn =
let (exploded, explodedSfn, _, _) = explodeIfRequired sfn
if not exploded then
let (splitted, splittedSfn) = splitIfRequired sfn
if not splitted then
sfn
else reduceSnailFishNumber splittedSfn
else reduceSnailFishNumber explodedSfn
let rec withIncreasedDepth sfn =
match sfn with
| Simple(x, d) ->
Simple(x, d+1)
| Complex(x1, x2, d) ->
Complex(x1 |> withIncreasedDepth, x2 |> withIncreasedDepth, d+1)
let rec magnitude sfn =
match sfn with
| Complex(sfn1, sfn2, _) ->
3* magnitude sfn1 + 2* magnitude sfn2
| Simple(x, d) ->
x
let parseContent(lines: string list) =
lines
|> List.map (fun line ->
line
|> (snailfishNumberFromLine 0)
|> fst
)
let execute =
let path = "day18/day18_input.txt"
let content = LocalHelper.GetLinesFromFile path |> List.ofArray
let snailfishnumbers = parseContent content
let addedNumber =
snailfishnumbers[1..]
|> List.fold (fun sfn1 sfn2 ->
Complex(sfn1 |> withIncreasedDepth, sfn2 |> withIncreasedDepth, 0)
|> reduceSnailFishNumber
) snailfishnumbers[0]
magnitude addedNumber