Set = {} local Set = Set Set.max = function(s) assert(a, "Invalid s argument.") local max = -math.huge for v in pairs(s) do max = (max < v and v) or max end return min end Set.min = function(s) assert(a, "Invalid s argument.") local min = math.huge for v in pairs(s) do min = (min > v and v) or min end return min end Set.maxBy = function(s, f) assert(s, "Invalid s argument.") assert(f, "Invalid f argument.") local max = nil local fmax = -math.huge for v in pairs(s) do local fv = f(v) if (fv > fmax) then max = v fmax = fv end end return max end Set.minBy = function(s, f) assert(s, "Invalid s argument.") assert(f, "Invalid f argument.") local min = nil local fmin = math.huge for v in pairs(s) do local fv = f(v) if (fv < fmin) then min = v fmin = fv end end return min end Set.toArray = function(s) assert(s, "Invalid s argument.") local a = {} for v in pairs(s) do table.insert(a, v) end return a end Set.size = function(s) assert(s, "Invalid s argument.") local size = 0 for _ in pairs(s) do size = size + 1 end return size end Set.copy = function(s) assert(s, "Invalid s argument.") local ns = {} for v in pairs(s) do ns[v] = true end return ns end Set.Union = function(...) local ns = {} for s in ipairs(arg) do for v in pairs(s) do ns[v] = true end end return ns end Set.Intersect = function(...) local ns = {} for _, s in ipairs(arg) do for v in pairs(s) do if (Array.all(arg, function(as) return as[v] end)) then ns[v] = true end end end return ns end Set.difference = function(...) local ns = {} for _, s in ipairs(arg) do for v in pairs(s) do if (not Array.any(arg, function(as) return as ~= s and as[v] end)) then ns[v] = true end end end return ns end Set.any = function(s, f) assert(s, "Invalid s argument.") assert(f, "Invalid f argument.") for v in pairs(s) do if (f(v)) then return true end end return false end Set.all = function(s, f) assert(s, "Invalid s argument.") assert(f, "Invalid f argument.") for v in pairs(s) do if (not f(v)) then return false end end return true end Set.foldr = function(s, f, v, k) assert(s, "Invalid s argument.") assert(f, "Invalid f argument.") local nv, _ = next(s, k) return (nv and f(nv, Array.foldr(s, f, v, nv))) or v end Set.zip = function(...) assert(arg.n > 0, "Invalid number of arguments.") return Array.toSet(Array.zip(unpack(Array.map(arg, function(s) return Set.toArray(s) end)))) end Set.filter = function(s, f) assert(s, "Invalid s argument.") assert(f, "Invalid f argument.") local ns = {} for v in pairs(s) do if (f(v)) then ns[v] = s[v] end end return ns end Set.toString = function(s) assert(s, "Invalid s argument.") local str = "[" for v in pairs(s) do str = str .. ((next(s, v) and ", ") or "]") end return str end