import copy


def computeClosure(X, func_deps):
    """Compute {X}^+ set (closure set) of list of attributes X
    """
    prev = set()
    closure = set(X)

    # True flag implies a change so we must reiterate through func_deps
    flag = True

    # iterate while no change
    while flag == True:
        cp = copy.deepcopy(func_deps)
        for fd in cp:
            # unpack tuple
            X, Y = fd

            # if X is in the closure set
            if set(X).issubset(closure):
                prev = copy.deepcopy(closure)

                # add Y to the set
                closure = closure.union(set(Y))

                # if we actually updated closure, must re-enter for loop
                if closure != prev:
                    flag = True
                    break
        else:
            # if we don't break, set flag to False
            flag = False
    
    return list(closure)