Homokozó/Tgr/Set[mi ez?] • [dokumentáció: mutat, szerkeszt] • [tesztek: sikeres: 9, sikertelen: 0, kihagyva: 0 (részletek)]

------------------------------------------------------------------
-- Set functions
------------------------------------------------------------------

local Set = {}

function Set.new(t)
    local base = t or {}
    local set = {}
    for _, v in pairs(base) do
        set[v] = v
    end
    Set.elevate(set)
    return set
end

function Set.has(set, element)
    return set[element] ~= nil
end

function Set.insert(set, element)
    set[element] = element
end

function Set.remove(set, element)
    set[element] = nil
end

function Set.union(set1, set2)
    local set = {}
    for k, v in pairs(set1) do
        set[k] = v
    end    
    for k, v in pairs(set2) do
        set[k] = v
    end
    Set.elevate(set)
    return set
end

-- returns set1 \ set2
function Set.difference(set1, set2)
    local set = {}
    for k, v in pairs(set1) do
        if set2[k] == nil then
            set[k] = v
        end
    end    
    Set.elevate(set)
    return set
end

function Set.intersect(set1, set2)
    local set = {}
    for k, v in pairs(set1) do
        if set2[k] ~= nil then
            set[k] = v
        end
    end    
    Set.elevate(set)
    return set
end

-- true if set1 is a subset of set2
function Set.subset(set1, set2)
    local result = true;
    for k, _ in pairs(set1) do
        if set2[k] == nil then
            result = false
            break
        end
    end
    return result
end

function Set.properSubset(set1, set2)
    return Set.subset(set1, set2) and (set1 ~= set2)
end

-- true if set1 is a subset of set2
function Set.equals(set1, set2)
    return Set.subset(set1, set2) and Set.subset(set2, set1)
end

function Set.join(set, separator)
    local sorted = {}
    for _, v in pairs(set) do
        table.insert(sorted, v)
    end
    table.sort(sorted)
    return table.concat(sorted, separator)
end

function Set.tostring(set)
    return "{" .. Set.join(set, ", ") .. "}"
end

--------------------------------------------------------------------------
-- Set object
--------------------------------------------------------------------------

local SetMeta = {
    __index = {
        has = Set.has,
        insert = Set.insert,
        remove = Set.remove,
    },
    __add = Set.union,
    __sub = Set.difference,
    __concat = Set.union,
    __eq = Set.equals,
    __lt = Set.properSubset,
    __le = Set.subset,
    __tostring = Set.tostring,
}

-- turns a table into a set
-- all values of the table must be equal to their keys for the set to be valid; this is not checked by elevate()
-- @return nil
function Set.elevate(t)
    setmetatable(t, SetMeta)
end

setmetatable(Set, {
    __call = function(_, base) return Set.new(base) end
})

return Set