-
Notifications
You must be signed in to change notification settings - Fork 0
/
solution.lua
157 lines (130 loc) · 3.03 KB
/
solution.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
145
146
147
148
149
150
151
152
153
154
155
156
157
Stack = {}
function Stack:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
function Stack:push(value)
table.insert(self, value)
end
function Stack:pop()
return table.remove(self)
end
function Stack:top()
return self[#self]
end
function Stack:reverse()
local newStack = Stack:new()
while #self > 0 do
newStack:push(self:pop())
end
return newStack
end
function string:split(delimiter)
delimiter = delimiter or " "
result = {};
for match in (self..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
function deepcopy(orig, copies)
copies = copies or {}
local orig_type = type(orig)
local copy
if orig_type == 'table' then
if copies[orig] then
copy = copies[orig]
else
copy = {}
copies[orig] = copy
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key, copies)] = deepcopy(orig_value, copies)
end
setmetatable(copy, deepcopy(getmetatable(orig), copies))
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
-- Read input data
if arg[1] == nil then
print("Usage: "..arg[0].." <filename>")
os.exit(1)
end
file = io.open(arg[1], "r")
if file == nil then
print("File not found: "..arg[1])
os.exit(1)
end
inputLines = file:read("all")
file:close()
parts = inputLines:split("\n\n")
initialState = parts[1]:split("\n")
moves = parts[2]:split("\n")
-- Initialize stacks
stackCount = (#initialState[1] + 1) // 4
stacks = {}
for i = 1, stackCount do
stacks[i] = Stack:new()
end
-- Fill stacks
for i = 1, #initialState-1 do
for j = 1, stackCount do
letter = string.sub(initialState[i], 4 * j - 2, 4 * j - 2)
if letter ~= " " then
stacks[j]:push(letter)
end
end
end
for i = 1, #stacks do
stacks[i] = stacks[i]:reverse()
end
stacks2 = deepcopy(stacks)
print("Initial state:")
for i = 1, stackCount do
print("Stack "..i..": "..table.concat(stacks[i], " "))
end
print("")
-- Perform moves
-- Part 1
for i = 1, #moves do
move = moves[i]:split()
count = tonumber(move[2])
from = tonumber(move[4])
to = tonumber(move[6])
for j = 1, count do
stacks[to]:push(stacks[from]:pop())
end
end
part1 = ""
for i = 1, stackCount do
part1 = part1..stacks[i]:top()
end
print("Part 1: "..part1)
-- print("Final state:")
-- for i = 1, stackCount do
-- print("Stack "..i..": "..table.concat(stacks[i], " "))
-- end
-- Part 2
for i = 1, #moves do
move = moves[i]:split()
count = tonumber(move[2])
from = tonumber(move[4])
to = tonumber(move[6])
temp = Stack:new()
for j = 1, count do
temp:push(stacks2[from]:pop())
end
-- print("Move "..i..": "..table.concat(temp, " "))
for j = 1, count do
stacks2[to]:push(temp:pop())
end
end
part2 = ""
for i = 1, stackCount do
part2 = part2..stacks2[i]:top()
end
print("Part 2: "..part2)