aboutsummaryrefslogtreecommitdiffstats
path: root/day13/solution.nim
diff options
context:
space:
mode:
Diffstat (limited to 'day13/solution.nim')
-rw-r--r--day13/solution.nim121
1 files changed, 121 insertions, 0 deletions
diff --git a/day13/solution.nim b/day13/solution.nim
new file mode 100644
index 0000000..901e646
--- /dev/null
+++ b/day13/solution.nim
@@ -0,0 +1,121 @@
1import strutils
2import strformat
3import algorithm
4
5type
6 Data = ref object
7 val: int
8 list: seq[Data]
9
10 Packet = tuple
11 first: Data
12 second: Data
13
14 Input = seq[Packet]
15
16proc `$`(data: Data): string =
17 if data.val != -1:
18 return fmt"{data.val}"
19
20 result = "[" & data.list.join(",") & "]"
21
22proc parseData(strData: string, i: var int): Data =
23 result = Data(val: -1, list: newSeq[Data]())
24 let dataLen = strData.len()
25 while i < dataLen:
26 case strData[i]:
27 of '[':
28 i += 1
29 result.list.add(parseData(strData, i))
30 of ']':
31 i += 1
32 return result
33 of ',':
34 i += 1
35 else:
36 var j = i
37 while j < dataLen and strData[j].isDigit():
38 j += 1;
39 let toPush = Data(val: strData[i..<j].parseInt())
40 result.list.add(toPush)
41 i = j
42
43proc parsePacket(strPacket: string): Packet =
44 let strDatas = strPacket.splitLines()
45 assert(strDatas.len() == 2)
46 var
47 i0 = 0
48 i1 = 0
49 result = (parseData(strDatas[0][1..^2], i0), parseData(strDatas[1][1..^2], i1))
50
51proc parseFile(content: string): Input =
52 let strPackets = content.strip().split("\n\n")
53
54 for strPacket in strPackets:
55 result.add(parsePacket(strPacket))
56
57proc compare(A, B: int): int =
58 if A < B: return -1
59 elif A > B: return 1
60 else: return 0
61
62proc dataListForm(data: Data): Data =
63 # Check if its already in list form
64 if data.val == -1:
65 return data
66 result = Data(val: -1, list: @[data])
67
68proc compare(A, B: Data): int =
69 # Both numbers:
70 if A.val != -1 and B.val != -1:
71 return compare(A.val, B.val)
72
73 # Transform both data to list form
74 let
75 A = dataListForm(A)
76 B = dataListForm(B)
77
78 assert(A.val == -1 and B.val == -1)
79 # Both are lists now
80 let
81 li = A.list.len()
82 lj = B.list.len()
83 N = min(li, lj)
84
85 var i = 0
86 while i < N:
87 let res = compare(A.list[i], B.list[i])
88 if res != 0:
89 return res
90 i += 1
91
92 return compare(li, lj)
93
94proc part1(Packets: Input): int =
95 for i, packet in Packets:
96 # echo fmt"Checking packet {packet}"
97 let comparison = compare(packet.first, packet.second)
98 # echo fmt"result = {comparison}"
99 if comparison < 0:
100 result += i+1
101
102proc part2(Packets: Input): int =
103 let driverPackets = parseFile("[[6]]\n[[2]]\n")
104 let first = driverPackets[0].first
105 let second = driverPackets[0].second
106 var datas = @[first, second]
107
108 for packet in Packets:
109 datas.add(packet.first)
110 datas.add(packet.second)
111
112 datas.sort(compare)
113 let firstIndex = datas.binarySearch(first, compare) + 1
114 let secondIndex = datas.binarySearch(second, compare) + 1
115 return firstIndex * secondIndex
116
117let content = readFile("./input.txt")
118let input = parseFile(content)
119
120echo part1(input)
121echo part2(input)