local function assert_argument_valid(a, arg_type) arg_type = arg_type or "table" if type(a) ~= arg_type then error("bad argument #1 to '" .. debug.getinfo(2, "n").name .. "' (table expected, got ".. type(a) .. ")", 3) end end table.remove_element = function(t, element) assert_argument_valid(t) for k,v in pairs(t) do if v == element then table.remove(t, k) break end end end table.add_all = function (t1, t2) assert_argument_valid(t1) assert_argument_valid(t2) for k,v in pairs(t2) do if tonumber(k) then table.insert(t1, v) else t1[k] = v end end end table.size = function(t) assert_argument_valid(t) local size = 0 for _,_ in pairs(t) do size = size + 1 end return size end table.index_of = function(t, e) assert_argument_valid(t) local i = 1 for _,v in pairs(t) do if v == e then return i end i = i + 1 end return -1 end table.contains = function(t, e) assert_argument_valid(t) return table.index_of(t, e) > -1 end table.set = function (t, index, element) assert_argument_valid(t) assert_argument_valid(index, "number") local i = 1 for k,v in pairs(t) do if i == index then t[k] = element return nil end i = i + 1 end error("Index out of bounds", 2) end table.get = function (t, index) assert_argument_valid(t) assert_argument_valid(index, "number") local i = 1 for k,v in pairs(t) do if i == index then return t[k] end i = i + 1 end error("Index out of bounds", 2) end --[[ Returns the index where t[index] == target. If there is no such index, returns a negative vaule such that bit32.bnot(value) is the index that the vaule should be inserted to keep the list ordered. t must be a list in ascending order for the return value to be valid. Usage example: local t = {1,3,5,7,9} local x = 5 local index = table.binary_search(t, x) if index < 0 then game.print("value not found, smallest index where t[index] > x is: " .. bit32.bnot(index)) else game.print("value found at index: " .. index) end ]] table.binary_search = function(t, target) --For some reason bit32.bnot doesn't return negative numbers so I'm using ~x = -1 - x instead. assert_argument_valid(t) assert_argument_valid(target, "number") local lower = 1 local upper = #t if upper == 0 then return -2 -- ~1 end repeat local mid = math.floor( (lower + upper) / 2 ) local value = t[mid] if value == target then return mid elseif value < target then lower = mid + 1 else upper = mid - 1 end until lower > upper return -1 - lower -- ~lower end