diff --git a/luau/src.luau b/luau/src.luau index db7ac69..c9d6c43 100644 --- a/luau/src.luau +++ b/luau/src.luau @@ -4,85 +4,172 @@ local Array = {} Array.__index = Array -type constructor = { inner: {T} } -export type Array = typeof(setmetatable({} :: constructor, Array)) +type constructor = { __inner: {T} } +export type Array = setmetatable, typeof(Array)> type FnCall = (T, number, Array) -> R function Array.new(from: {T}?): Array - return setmetatable({ inner = from or {} }, Array) + return setmetatable({ __inner = from or {} }, Array) end -function Array:table(): {T} - return self.inner -end - -function Array:pop(): T? - return table.remove(self.inner, #self.inner) -end - -function Array:concat(sep: string?, i: number?, j: number?): string - return table.concat(self.inner, sep, i, j) -end - -function Array:clone(): Array - return Array.new(table.clone(self.inner)) +function Array:into_table(): {T} + return self.__inner end function Array:len(): number - return #self.inner + return #self.__inner +end + +function Array:pop(): T? + return table.remove(self.__inner, self:len()) +end + +function Array:concat(sep: string?, i: number?, j: number?): string + return table.concat(self.__inner, sep, i, j) +end + +function Array:clone(): Array + return Array.new(table.clone(self.__inner)) +end + +function Array:is_empty(): boolean + return self:len() == 0 +end + +function Array:type_id(): string + return type(self.__inner[1]) end function Array:get(index: I): T? - return self.inner[index] + return self.__inner[index] +end + +function Array:get_base0(index: number): T? + return self:get(index + 1) +end + +function Array:join(sep: T): Array + return self +end + +function Array:append(other: Array): Array + return self:append_table(other:into_table()) +end + +function Array:append_table(t: {T}): Array + table.move(t, 1, #t, self:len() + 1, self.__inner) + return self +end + +function Array:slice(start: number, endj: number?): Array + local slice_t: {T} = {} + table.move(self.__inner, start, endj or self:len(), 1, slice_t) + return Array.new(slice_t) end function Array:push(...: T): () for _, val: T in {...} do - table.insert(self.inner, val) + table.insert(self.__inner, val) end end -function Array:foreach(callbackFn: FnCall): Array - for ind: number, val: T in self.inner do - callbackFn(val, ind, self) +function Array:foreach(f: FnCall): Array + for ind: number, val: T in self.__inner do + f(val, ind, self) end return self end -function Array:map(callbackFn: FnCall): Array - local n: {M} = {} - for ind: number, val: T in self.inner do - table.insert(n, callbackFn(val, ind, self)) +function Array:map(f: FnCall): Array + local t_map: {M} = {} + for ind: number, val: T in self.__inner do + table.insert(t_map, f(val, ind, self)) end - return Array.new(n) + return Array.new(t_map) end -function Array:filter(callbackFn: FnCall): Array - local n: {T} = {} - for ind: number, val: T in self.inner do - if callbackFn(val, ind, self) then - table.insert(n, val) +function Array:filter(f: FnCall): Array + local t_filter: {T} = {} + for ind: number, val: T in self.__inner do + if f(val, ind, self) then + table.insert(t_filter, val) end end - return Array.new(n) + return Array.new(t_filter) end -function Array:binary_search(x: T): T? - local size = #self.inner +function Array:reverse(): Array + local t_rev: {T} = {} + local t_len = self:len() + for i = 1, t_len do + t_rev[i] = self.__inner[t_len - i + 1] + end + self.__inner = t_rev + return self +end + +function Array:sort(): Array + table.sort(self.__inner, function(a: T, z: T) + if type(a) == "number" then + return a < z + end + return tostring(a) < tostring(z) + end) + return self +end + +function Array:reduce(f: (number, number) -> number): number + local init_v = self.__inner[1] + if type(init_v) == "string" then + return tonumber("nan") :: number + end + for _, val: number in self.__inner do + init_v = f(init_v, val) + end + return init_v +end + +local function binary_search_by(self: Array, x: number, eq: (number, number) -> number): number? + local size = self:len() if size == 0 then return nil end local base = 1 - - while base < size do - size -= bit32.rshift(base + size, 1) + while base <= size do + local mid = eq(base, size) + if self.__inner[mid] == x then + return mid + elseif self.__inner[mid] < x then + base = mid + 1 + else + size = mid - 1 + end end - return nil end -function Array:debug_display(): string - return self:map(function(val: T, ind: number) - return ind .. ": " .. tostring(val) .. (ind ~= self:len() and ", " or "") +function Array:binary_search(x: number): number? + if self:type_id() ~= "number" then + return nil + end + return binary_search_by(self, x, function(base, size) + return bit32.rshift(base + size, 1) + end) +end + +function Array:binary_search_64(x: number): number? + if self:type_id() ~= "number" then + return nil + end + return binary_search_by(self, x, function(base, size) + return math.floor((base + size) / 2) + end) +end + +function Array:tostring(): string + return self:map(function(val: T, index: number) + local formatted_val = if type(val) == "string" then `"{val}"` else tostring(val) + local formatted_end = if index ~= self:len() then ", " else "" + return index .. ": " .. formatted_val .. formatted_end end):concat() end