Browse Source

Inheritance based code creation

Marcelo Fornet 5 years ago
commit
0ce2a60c4a
3 changed files with 135 additions and 0 deletions
  1. 2 0
      .gitignore
  2. 107 0
      disjoint_set.hpp
  3. 26 0
      main.cpp

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+.vscode/
+main

+ 107 - 0
disjoint_set.hpp

@@ -0,0 +1,107 @@
+#include <vector>
+
+// Disjoint set trait
+class DisjointSet
+{
+public:
+    std::vector<int> ds;
+
+    DisjointSet(int n)
+    {
+        ds = std::vector<int>(n, -1);
+    }
+
+    virtual int root(int a)
+    {
+        return ds[a] < 0 ? a : ds[a] = root(ds[a]);
+    }
+
+    virtual bool merge(int u, int v)
+    {
+        u = root(u), v = root(v);
+
+        if (u == v)
+            return false;
+
+        if (ds[u] < ds[v])
+            std::swap(u, v);
+
+        ds[v] += ds[u];
+        ds[u] = v;
+
+        return true;
+    }
+
+    virtual int size(int a)
+    {
+        return -ds[root(a)];
+    }
+
+    virtual void undo()
+    {
+        throw "Abstract method";
+    }
+};
+
+class DisjointSetWithUndo : public DisjointSet
+{
+    std::vector<std::pair<int, int>> history;
+
+public:
+    DisjointSetWithUndo(int n) : DisjointSet(n)
+    {
+        history = std::vector<std::pair<int, int>>();
+    }
+
+    bool merge(int u, int v) override
+    {
+        history.push_back({u, ds[u]});
+        history.push_back({v, ds[v]});
+        return DisjointSet::merge(u, v);
+    }
+
+    void undo() override
+    {
+        int u, val;
+        for (int i = 0; i < 2; ++i)
+        {
+            std::tie(u, val) = history.back();
+            history.pop_back();
+            ds[u] = val;
+        }
+    }
+};
+
+/// Disjoint set builder
+class DisjointSetBuilder
+{
+    bool has_undo;
+
+public:
+    DisjointSetBuilder() : has_undo(false)
+    {
+    }
+
+    DisjointSetBuilder *with_undo()
+    {
+        has_undo = true;
+        return this;
+    }
+
+    DisjointSet *init(int size)
+    {
+        if (has_undo)
+        {
+            return new DisjointSetWithUndo(size);
+        }
+        else
+        {
+            return new DisjointSet(size);
+        }
+    }
+};
+
+DisjointSetBuilder *disjoint_set()
+{
+    return new DisjointSetBuilder();
+}

+ 26 - 0
main.cpp

@@ -0,0 +1,26 @@
+#include <iostream>
+#include "disjoint_set.hpp"
+
+#define endl '\n'
+
+using namespace std;
+
+int main()
+{
+    ios_base::sync_with_stdio(0);
+    cin.tie(0);
+
+    auto ds = disjoint_set()->with_undo()->init(2);
+
+    cout << ds->root(0) << " " << ds->size(0) << " " << ds->root(1) << " " << ds->size(1) << endl;
+
+    ds->merge(0, 1);
+
+    cout << ds->root(0) << " " << ds->size(0) << " " << ds->root(1) << " " << ds->size(1) << endl;
+
+    ds->undo();
+
+    cout << ds->root(0) << " " << ds->size(0) << " " << ds->root(1) << " " << ds->size(1) << endl;
+
+    return 0;
+}