Task: Set consolidation


C++: #include <algorithm>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;


void SimpleConsolidate(vector<unordered_set<char>>& sets)
{
    
    for(auto last = sets.rbegin(); last != sets.rend(); ++last)
        for(auto other = last + 1; other != sets.rend(); ++other)
        {
            bool hasIntersection = any_of(last->begin(), last->end(), 
                                          [&](auto val)
                                          { return other->contains(val); });
            if(hasIntersection)
            {
                other->merge(*last);
                sets.pop_back();
                break;
            }
        }
}



struct Node
{
    char Value;
    Node* Parent = nullptr;
};    

Node* FindTop(Node& node)
{
    auto top = &node;
    while (top != top->Parent) top = top->Parent;
    for(auto element = &node; element->Parent != top; )
    {
        
        auto parent = element->Parent;
        element->Parent = top;
        element = parent;
    }
    return top;
}

vector<unordered_set<char>> FastConsolidate(const vector<unordered_set<char>>& sets)
{
    unordered_map<char, Node> elements;
    for(auto& set : sets)
    {
        Node* top = nullptr;
        for(auto val : set)
        {
            auto itr = elements.find(val);
            if(itr == elements.end())
            {
                
                auto& ref = elements[val] = Node{val, nullptr};
                if(!top) top = &ref;
                ref.Parent = top;
            }
            else
            {
                auto newTop = FindTop(itr->second);
                if(top)
                {
                    top->Parent = newTop;
                    itr->second.Parent = newTop;
                }
                else
                {
                    top = newTop;
                }
            }
        }
    } 

    unordered_map<char, unordered_set<char>> groupedByTop;
    for(auto& e : elements)
    {
        auto& element = e.second;
        groupedByTop[FindTop(element)->Value].insert(element.Value);
    }

    vector<unordered_set<char>> ret;
    for(auto& itr : groupedByTop)
    {
        ret.push_back(move(itr.second));
    }

    return ret;
}

void PrintSets(const vector<unordered_set<char>>& sets)
{
    for(const auto& set : sets)
    {
        cout << "{ ";
        for(auto value : set){cout << value << " ";}
        cout << "} "; 
    }
    cout << "\n";
}

int main()
{
    const unordered_set<char> AB{'A', 'B'}, CD{'C', 'D'}, DB{'D', 'B'}, 
                              HIJ{'H', 'I', 'K'}, FGH{'F', 'G', 'H'};
                              
    vector <unordered_set<char>> AB_CD {AB, CD};
    vector <unordered_set<char>> AB_DB {AB, DB};
    vector <unordered_set<char>> AB_CD_DB {AB, CD, DB};
    vector <unordered_set<char>> HIJ_AB_CD_DB_FGH {HIJ, AB, CD, DB, FGH};

    PrintSets(FastConsolidate(AB_CD));
    PrintSets(FastConsolidate(AB_DB));
    PrintSets(FastConsolidate(AB_CD_DB));
    PrintSets(FastConsolidate(HIJ_AB_CD_DB_FGH));

    SimpleConsolidate(AB_CD);
    SimpleConsolidate(AB_DB);
    SimpleConsolidate(AB_CD_DB);
    SimpleConsolidate(HIJ_AB_CD_DB_FGH);

    PrintSets(AB_CD);
    PrintSets(AB_DB);
    PrintSets(AB_CD_DB);
    PrintSets(HIJ_AB_CD_DB_FGH);
}




Java: import java.util.*;

public class SetConsolidation {

    public static void main(String[] args) {
        List<Set<Character>> h1 = hashSetList("AB", "CD");
        System.out.println(consolidate(h1));

        List<Set<Character>> h2 = hashSetList("AB", "BD");
        System.out.println(consolidateR(h2));

        List<Set<Character>> h3 = hashSetList("AB", "CD", "DB");
        System.out.println(consolidate(h3));

        List<Set<Character>> h4 = hashSetList("HIK", "AB", "CD", "DB", "FGH");
        System.out.println(consolidateR(h4));
    }

    
    private static <E> List<Set<E>>
                consolidate(Collection<? extends Set<E>> sets) {
	List<Set<E>> r = new ArrayList<>();
	for (Set<E> s : sets) {
	    List<Set<E>> new_r = new ArrayList<>();
	    new_r.add(s);
	    for (Set<E> x : r) {
		if (!Collections.disjoint(s, x)) {
		    s.addAll(x);
		} else {
		    new_r.add(x);
		}
	    }
	    r = new_r;
	}
	return r;
    }

    
    private static <E> List<Set<E>> consolidateR(List<Set<E>> sets) {
        if (sets.size() < 2)
            return sets;
        List<Set<E>> r = new ArrayList<>();
        r.add(sets.get(0));
        for (Set<E> x : consolidateR(sets.subList(1, sets.size()))) {
            if (!Collections.disjoint(r.get(0), x)) {
                r.get(0).addAll(x);
            } else {
                r.add(x);
            }
        }
        return r;
    }

    private static List<Set<Character>> hashSetList(String... set) {
        List<Set<Character>> r = new ArrayList<>();
        for (int i = 0; i < set.length; i++) {
            r.add(new HashSet<Character>());
            for (int j = 0; j < set[i].length(); j++)
                r.get(i).add(set[i].charAt(j));
        }
        return r;
    }
}