-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathqueue.lua
147 lines (128 loc) · 3.97 KB
/
queue.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
local Queue = {}
--- Create a new queue.
--- @return table Queue with first and last indices.
function Queue.new ()
return {first = 0, last = -1}
end
--- Push an element to the left of the queue.
--- @param queue table The queue to push to.
--- @param value any The value to push.
function Queue.pushleft (queue, value)
local first = queue.first - 1
queue.first = first
queue[first] = value
end
--- Push an element to the right of the queue.
--- @param queue table The queue to push to.
--- @param value any The value to push.
function Queue.pushright (queue, value)
local last = queue.last + 1
queue.last = last
queue[last] = value
end
--- Pop an element from the left of the queue.
--- @param queue table The queue to pop from.
--- @return any Value
function Queue.popleft (queue)
local first = queue.first
-- queue is empty
if first > queue.last then return nil end
local value = queue[first]
queue[first] = nil -- to allow garbage collection
queue.first = first + 1
return value
end
--- Pop an element from the right of the queue.
--- @param queue table The queue to pop from.
--- @return any Value
function Queue.popright (queue)
local last = queue.last
-- queue is empty
if queue.first > last then return nil end
local value = queue[last]
queue[last] = nil -- to allow garbage collection
queue.last = last - 1
return value
end
--- Insert an element at a specific position in the queue.
--- @param queue table The queue to insert into.
--- @param value any The value to insert.
--- @param position number The position where the value should be inserted.
function Queue.insert(queue, value, position)
local last = queue.last
local first = queue.first
if position < first then
Queue.pushleft(queue, value)
return
elseif position > last + 1 then
Queue.pushright(queue, value)
return
else
-- Shift elements to the right to make space for the new value
for i = last, position, -1 do
if queue[i + 1] == nil then
-- If the next element was nil, we can stop shifting values to the right here
-- We're shifting a value into a free cell
queue[i + 1] = queue[i]
break
else
queue[i + 1] = queue[i]
end
end
-- Insert the value at the specified position
queue[position] = value
queue.last = last + 1
end
end
--- Create an iterator to iterate over all values in the queue.
--- Use it like this
--- local iterator = Queue.iterate(myQueue)
--- for value in iterator do
--- @param queue table The queue to iterate over.
--- @return function Iterator
function Queue.iterate(queue)
local index = queue.first - 1
local last = queue.last
return function()
index = index + 1
if index <= last then
return queue[index]
end
end
end
--- Get the number of non-empty elements in the queue.
--- @param queue table The queue to count non-empty elements in.
--- @param fast boolean | nil
--- @return number The number of non-empty elements in the queue.
function Queue.count(queue, fast)
if queue == nil then
return 0
end
local count = 0
if fast then
return queue.last - queue.first + 1
end
for i = queue.first, queue.last do
if queue[i] ~= nil then
count = count + 1
end
end
return count
end
--- Remove duplicate values from the queue.
--- @param queue table The queue to remove duplicates from.
function Queue.removeDuplicates(queue, toKey)
local uniqueValues = {}
local newQueue = Queue.new()
for i = queue.first, queue.last, 1 do
if queue[i] ~= nil then
local value = toKey(queue[i])
if not uniqueValues[value] then
Queue.pushright(newQueue, queue[i])
uniqueValues[value] = true
end
end
end
return newQueue
end
return Queue