-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday16_part01.fs
81 lines (73 loc) · 3.12 KB
/
day16_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
module day16_part01
open System
open System.IO
open System.Globalization
let rev str =
StringInfo.ParseCombiningCharacters(str)
|> Array.rev
|> Seq.map (fun i -> StringInfo.GetNextTextElement(str, i))
|> String.concat ""
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 rec parseMessage(mymessage: string, versions: int64 list) =
let version = binToDec(mymessage.Substring(0, 3))
let typeid = binToDec(mymessage.Substring(3, 3))
match (int)typeid with
| 4 ->
let number = mymessage.Substring(6)
let leadingzeros = if (4 - (number.Length % 4)) = 4 then 0 else (4 - (number.Length % 4))
let parts = number.ToCharArray() |> Array.chunkBySize(5) |> Array.map(fun chunk -> String.Join("", chunk))
let splitIdx = parts |> Array.findIndex(fun p -> p.Substring(0, 1) = "0")
let usedParts = parts |> Array.take(splitIdx + 1)
let usedPartsLength = usedParts |> Array.sumBy(fun l -> l.Length)
let remainingPart = mymessage.Substring(6 + usedPartsLength)//String.Join("", (parts |> Array.skip(splitIdx + 1)))
let finalnumber = String.Join("", usedParts |> Array.map(fun p -> p.Substring(1, 4)))
printf "literal value of %i", binToDec(finalnumber)
versions @ [version] @ if (remainingPart.Contains("1") && remainingPart.Length >= 7) then parseMessage(remainingPart, []) else []
| _ ->
let lenghtypeid = mymessage.Substring(6, 1)
match lenghtypeid with
| "0" ->
let adjustedMymessage =
if(22 - mymessage.Length > 0) then
mymessage + (new String('0', 22 - mymessage.Length))
else
mymessage
let totallength = binToDec(adjustedMymessage.Substring(7, 15))
let subpacket = adjustedMymessage.Substring(22)
[version] @ if (subpacket.Contains("1") && subpacket.Length >= 7) then parseMessage(subpacket, []) else []
| "1" ->
let adjustedMymessage =
if (18 - mymessage.Length > 0) then
mymessage + (new String('0', 18 - mymessage.Length))
else
mymessage
let numberofpackets = binToDec(adjustedMymessage.Substring(7, 11))
let subpackets = adjustedMymessage.Substring(18)
[version] @ if (subpackets.Contains("1") && subpackets.Length >= 7) then parseMessage(subpackets, []) else []
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))))
let tmpmessage = message |> Seq.exactlyOne
parseMessage(tmpmessage, []) |> List.sum