-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday13.lua
144 lines (128 loc) · 3.81 KB
/
day13.lua
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
util = require('util')
day13 = {}
function day13.lineToArray(line)
local stack = { }
local currentNum = nil
for i=1,#line do
local ch = string.sub(line, i, i)
if ch == "[" then
table.insert(stack, {})
elseif ch == "]" then
if currentNum ~= nil then
table.insert(stack[#stack], currentNum)
currentNum = nil
end
local last = stack[#stack]
table.remove(stack, #stack)
if #stack == 0 then
table.insert(stack, last)
else
table.insert(stack[#stack], last)
end
elseif ch == "," then
if currentNum ~= nil then
table.insert(stack[#stack], currentNum)
currentNum = nil
end
else
if currentNum == nil then
currentNum = 0
end
currentNum = currentNum*10 + math.tointeger(ch)
end
end
return stack[1]
end
function day13.pprint(stack)
if type(stack) == "number" then
return string.format("%d", stack)
end
contents = ""
for i=1,#stack do
if i > 1 then
contents = contents .. ","
end
contents = contents .. day13.pprint(stack[i])
end
return "[" .. contents .. "]"
end
-- 1 means right order
-- 0 mean unknown
-- -1 means wrong order
function day13.compare(l, r)
if (type(l) == "table") and (type(r) == "table") then
local comparisonResult = 0
for i=1,#l do
if i > #r then
return -1
end
comparisonResult = day13.compare(l[i], r[i])
if comparisonResult ~= 0 then
return comparisonResult
end
end
if comparisonResult == 0 then
if #l < #r then
return 1
end
end
return 0
end
if (type(l) == "number") and (type(r) == "table") then
return day13.compare({ l }, r)
end
if (type(l) == "table") and (type(r) == "number") then
return day13.compare(l, { r })
end
if (type(l) == "number") and (type(r) == "number") then
if l < r then
return 1
elseif l > r then
return -1
elseif l == r then
return 0
end
end
end
function day13.parseCount(filename, addDividers)
local packets = {}
local sumIndices = 0
local i, first, second, index = 0, {}, {}, 1
for line in io.lines(filename) do
if i % 3 == 0 then
first = line
elseif i % 3 == 1 then
second = line
local s1, s2 = day13.lineToArray(first), day13.lineToArray(second)
local isValid = day13.compare(s1, s2)
if (isValid > 0) then
sumIndices = sumIndices + index
end
table.insert(packets, s1)
table.insert(packets, s2)
index = index + 1
end
i = i + 1
end
local d1, d2 = day13.lineToArray("[[2]]"), day13.lineToArray("[[6]]")
if addDividers then
table.insert(packets, d1)
table.insert(packets, d2)
end
table.sort(packets, function(s1,s2) return day13.compare(s1, s2) > 0 end)
local decoderKey = 1
for pi=1,#packets do
if (day13.pprint(packets[pi]) == "[[2]]") or (day13.pprint(packets[pi]) == "[[6]]") then
day13.pprint(packets[pi])
decoderKey = decoderKey * pi
end
end
return sumIndices, decoderKey
end
if util.is_main(arg, ...) then
local sumIndices, _ = day13.parseCount("input/day13_input.txt", false)
local _, decoderKey = day13.parseCount("input/day13_input.txt", true)
print("[day 13] count in-order transmissions:", sumIndices)
print("[day 13] decoder key:", decoderKey)
end
return day13