-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday16_part02.fs
120 lines (112 loc) · 4.57 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
module day16_part02
open System
open System.IO
let hexToBin(hex: string) =
match hex with
| "0" -> "0000"
| "1" -> "0001"
| "2" -> "0010"
| "3" -> "0011"
| "4" -> "0100"
| "5" -> "0101"
| "6" -> "0110"
| "7" -> "0111"
| "8" -> "1000"
| "9" -> "1001"
| "A" -> "1010"
| "B" -> "1011"
| "C" -> "1100"
| "D" -> "1101"
| "E" -> "1110"
| "F" -> "1111"
| _ -> "0000"
let binToDec(bin: string) =
Convert.ToInt64(bin, 2)
let typeToOp(typeid: int64) =
match int32(typeid) with
| 4 -> "lit"
| 0 -> "sum"
| 1 -> "prod"
| 2 -> "min"
| 3 -> "max"
| 5 -> "greater"
| 6 -> "lesser"
| 7 -> "equal"
| _ -> ""
let performOp(myOp: string, values: int64 list) =
match myOp with
| "sum" -> values |> List.sum
| "prod" -> values |> List.fold (*) 1
| "min" -> values |> List.min
| "max" -> values |> List.max
| "lesser" ->
if values.Item(0) < values.Item(1) then 1 else 0
| "greater" ->
if values.Item(0) > values.Item(1) then 1 else 0
| "equal" -> if (values.Item(1) = values.Item(0)) then 1 else 0
| _ -> int64(0)
let rec parseMessage(mymessage: string, length: int64): (int64[] * string) =
let rec parseType0(myremaining: string, mysublength: int64, mytotal: int64, myvalues: int64 list) =
match mytotal = mysublength with
| false ->
let (values, newremaining) = parseMessage(myremaining, mysublength)
parseType0(newremaining, values.[1], mytotal, myvalues @ [values.[0]])
| true ->
(mysublength, myremaining, myvalues)
let rec parseType1(myremaining: string, counter: int64, subpacketlength:int64, mytotal: int64, myvalues: int64 list) =
match mytotal = counter with
| false ->
let (values, newremaining) = parseMessage(myremaining, subpacketlength)
parseType1(newremaining, counter + int64(1), values.[1], mytotal, myvalues @ [values.[0]])
| true ->
(subpacketlength, myremaining, myvalues)
let rec parseType4(myremaining: string, mypacketvalue:string, mylength: int64)=
match myremaining.Substring(0, 1) with
| "0" ->
let newpacketValue = mypacketvalue + myremaining.Substring(1, 4)
let newremaining = myremaining.Substring(5)
let newlength = mylength + int64(5)
([|binToDec(newpacketValue); newlength|], newremaining)
| _ ->
let newpacketValue = mypacketvalue + myremaining.Substring(1, 4)
let newremaining = myremaining.Substring(5)
let newlength = mylength + int64(5)
parseType4(newremaining, newpacketValue, newlength)
let version = binToDec(mymessage.Substring(0, 3))
let packettype = binToDec(mymessage.Substring(3, 3))
let newlength = length + int64(6)
let (values, newremaining) =
match int32(packettype) with
| 4 ->
let remaining = mymessage.Substring(6)
parseType4(remaining, "", newlength)
|_ ->
let typeid = mymessage.Substring(6, 1)
let remaining = mymessage.Substring(7)
let newlength2 = newlength + int64(1)
let (subvalues, newsublength, newremaining) =
match typeid with
| "0" ->
let totallength = binToDec(remaining.Substring(0, 15))
let newremaining = remaining.Substring(15)
let tmplength = newlength2 + int64(15)
let subpacketlength = int64(0)
let (sl, my, mv) = parseType0(newremaining, subpacketlength, totallength, [])
(mv, tmplength + sl, my)
| _ ->
let totalcount = binToDec(remaining.Substring(0, 11))
let newremaining = remaining.Substring(11)
let tmplength = newlength2 + int64(11)
let subpacketlength = int64(0)
let counter = int64(0)
let (sl, my, mv) = parseType1(newremaining, counter, subpacketlength, totalcount, [])
(mv, tmplength + sl, my)
let newpacketvalue = performOp(typeToOp(packettype), subvalues)
([|newpacketvalue; newsublength|], newremaining)
(values, newremaining)
let execute =
let path = "day16_input.txt"
let message =
File.ReadLines(__SOURCE_DIRECTORY__ + @"../../" + path) |>
Seq.map(fun l -> String.Join("", l.ToCharArray() |> Array.map(fun c -> hexToBin((string)c)))) |> Seq.exactlyOne
fst(parseMessage(message, 0)).[0]