Browse Source

Continuing work on the HashMap-ectomy (almost finished!)

Caleb Fangmeier 6 years ago
parent
commit
048883fe47
3 changed files with 165 additions and 152 deletions
  1. 147 142
      src/com/pact/Node.java
  2. 6 10
      src/com/pact/NodePair.java
  3. 12 0
      src/com/pact/test/NodeTest.java

+ 147 - 142
src/com/pact/Node.java

@@ -3,17 +3,21 @@ package com.pact;
 import java.util.*;
 
 public class Node {
+    static int ID = 0;
+
     Node parent;
     private String venn;
     private List<Node> children;
-    HashSet<Node> linkNodes;
+    List<Node> linkNodes;
     private Node linkNode;
 
+    private final int id = ++ID;  // Unique Identifier for all created nodes
+
     private int hash;
 
     public Node(Node p, String s) {
         this.linkNode = null;
-        this.linkNodes = new HashSet<>();
+        this.linkNodes = new ArrayList<>();
         this.venn = s;
         this.parent = p;
         this.hash = 0;
@@ -35,6 +39,20 @@ public class Node {
         this(p, ""+s);
     }
 
+
+    public boolean isRoot() {
+        return parent == null;
+    }
+
+    public boolean isLeaf() {
+        return children.isEmpty();
+    }
+
+    public int nSiblings() {
+        if (isRoot()) return 0;
+        else return parent.children.size() - 1;
+    }
+
     private void setChildren(String s) {
         try {
             String vennChildren = s.substring(1, s.length() - 1);
@@ -85,16 +103,7 @@ public class Node {
         return this.venn;
     }
 
-    HashSet<Node> getSiblings() {
-        if (this.parent != null) {
-            HashSet<Node> sibs = new HashSet<>(parent.children);
-            sibs.remove(this);
-            return sibs;
-        }
-        return new HashSet<>();
-    }
-
-    List<Node> getSiblingsL() {
+    List<Node> getSiblings() {
         if (this.parent != null) {
             List<Node> sibs = new ArrayList<>(parent.children);
             sibs.remove(this);
@@ -170,10 +179,8 @@ public class Node {
     }
 
     Node root() {
-        if (getSiblings().isEmpty()) {
-            return this;
-        }
-        return this.parent.root();
+        if (isRoot()) return this;
+        else return this.parent.root();
     }
 
     private int getNumAreas() {
@@ -225,9 +232,13 @@ public class Node {
         return false;
     }
 
+    /**
+     * Looks through this Node's siblings and returns the first one that has linkNodes. If no sibling
+     * has linkNodes, returns null.
+     * @return
+     */
     private Node hasLink() {
-        HashSet<Node> sibs = getSiblings();
-        for (Node curr : sibs) {
+        for (Node curr : getSiblings()) {
             if (!curr.linkNodes.isEmpty()) {
                 return curr;
             }
@@ -253,7 +264,7 @@ public class Node {
     }
 
     private void resetSearch() {
-        this.linkNodes = new HashSet<>();
+        this.linkNodes.clear();
         this.linkNode = null;
 
         for (Node child : this.children) {
@@ -261,8 +272,13 @@ public class Node {
         }
     }
 
-    private HashSet<Node> getDuplicates(List<NodePair> h) {
-        HashSet<Node> result = new HashSet<>();
+    /**
+     * Searches in h for all NodePairs that contain this object as either node1 or node2
+     * @param h
+     * @return
+     */
+    private List<Node> getDuplicates(List<NodePair> h) {
+        List<Node> result = new ArrayList<>();
         for (NodePair curr : h) {
             if (curr.node1 == this)
                 result.add(curr.node2);
@@ -302,40 +318,41 @@ public class Node {
     }
 
     private boolean inSet(List<Node> h) {
-        for (Node curr : h) {
-            if (curr.equals(this)) {
-                return true;
-            }
-        }
-        return false;
+        return h.contains(this);
     }
 
-    private boolean inSet(HashSet<Node> h) {
-        for (Node curr : h) {
-            if (curr.equals(this)) {
-                return true;
+    /**
+     * Traverses tree and collects all unshared nodes.
+     * @return
+     */
+    private List<Node> collectUnshared() {
+        Stack<Node> stack = new Stack<>();
+        List<Node> unshared = new ArrayList();
+        stack.push(this);
+        while (!stack.isEmpty()){
+            Node n = stack.pop();
+            if (n.unshared()) {
+                unshared.add(n);
             }
+            stack.addAll(n.children);
         }
-        return false;
+        return unshared;
     }
 
-    private void collectUnshared(HashSet<Node> h) {
-        if (unshared()) {
-            h.add(this);
-        }
-        for (Node child : children) {
-            child.collectUnshared(h);
-        }
+    static List<Node> combine(Node node1, Node node2) {
+        System.out.println("Combining: " + node1 + ", " + node2);
+        List<Node> result = _combine(node1, node2);
+        System.out.println("Combining Result: " + result);
+        return result;
     }
 
-    static HashSet<Node> combine(Node node1, Node node2) {
-        System.out.println("Combining: " + node1 + ", " + node2);
+    static List<Node> _combine(Node node1, Node node2) {
         node1 = reduce(node1);
         node2 = reduce(node2);
 
         node2.resetSearch();
         node1.resetSearch();
-        HashSet result = new HashSet();
+        List<Node> result = new ArrayList<>();
 
         if (node1.equals(node2)) {
             result.add(node2);
@@ -350,11 +367,11 @@ public class Node {
         }
 
 
-        HashSet<Node> unsharedNodePair = new HashSet<>();
-        node2.collectUnshared(unsharedNodePair);
-        node1.collectUnshared(unsharedNodePair);
+        List<Node> unsharedNodes = new ArrayList<>();
+        unsharedNodes.addAll(node2.collectUnshared());
+        unsharedNodes.addAll(node1.collectUnshared());
 
-        if ((unsharedNodePair.isEmpty()) && (node1.getNumAreas() == node2.getNumAreas())) {
+        if ((unsharedNodes.isEmpty()) && (node1.getNumAreas() == node2.getNumAreas())) {
             if (node1.children.size() < node2.children.size()) {
                 Node toAdd = new Node(null, node1.getVenn());
                 result.add(toAdd);
@@ -373,36 +390,30 @@ public class Node {
 
             NodePair flargest = (NodePair)itLargest.next();
 
-            HashSet<Node> lg1sibs = flargest.node1.getSiblings();
-            HashSet<Node> lg2sibs = flargest.node2.getSiblings();
+            List<Node> lg1sibs = flargest.node1.getSiblings();
+            List<Node> lg2sibs = flargest.node2.getSiblings();
 
-            HashSet<Node> newSibs = new HashSet<>();
-            HashSet<Node> otherSibs1 = new HashSet<>();
-            HashSet<Node> otherSibs2 = new HashSet<>();
+            List<Node> newSibs = new ArrayList<>();
+            List<Node> otherSibs1 = new ArrayList<>();
+            List<Node> otherSibs2 = new ArrayList<>();
 
-            Iterator lg1It = lg1sibs.iterator();
-            Iterator lg2It = lg2sibs.iterator();
-
-            sortLargestSibs(lg1It, flargest.node2, newSibs, otherSibs1);
-            sortLargestSibs(lg2It, flargest.node1, newSibs, otherSibs2);
+            sortLargestSibs(lg1sibs, flargest.node2, newSibs, otherSibs1);
+            sortLargestSibs(lg2sibs, flargest.node1, newSibs, otherSibs2);
 
 
             if ((otherSibs1.isEmpty()) && (otherSibs2.isEmpty())) {
-                for (Node newSib : newSibs) {
-                    unsharedNodePair.add(newSib);
-                }
-
+                unsharedNodes.addAll(newSibs);
             }
 
         }
 
-        HashSet<NodePair> newLinkedNodePair = getLinkedNodePair(unsharedNodePair);
+        List<NodePair> newLinkedNodePair = getLinkedNodePair(unsharedNodes);
 
-        HashSet<HashSet<NodePair>> polys = reviewPolys(newLinkedNodePair);
+        List<List<NodePair>> polys = reviewPolys(newLinkedNodePair);
         if (!polys.isEmpty()) {
-            Iterator polyIt = polys.iterator();
+            Iterator<List<NodePair>> polyIt = polys.iterator();
             if (polyIt.hasNext()) {
-                HashSet polyresult = addPolys((HashSet)polyIt.next());
+                List<NodePair> polyresult = addPolys(polyIt.next());
                 Iterator prIt = polyresult.iterator();
                 if (prIt.hasNext()) {
                     NodePair curr = (NodePair)prIt.next();
@@ -411,14 +422,14 @@ public class Node {
                         String polyString2 = buildUp(curr.node1.linkNode.parent, curr.node2.getVenn());
                         Node polyOne = new Node(null, polyString1);
                         Node polyTwo = new Node(null, polyString2);
-                        HashSet<Node> polyresults = combine(polyOne, polyTwo);
+                        List<Node> polyresults = combine(polyOne, polyTwo);
                         for (Node polyResult : polyresults)
                             result.add(polyResult);
-                    } else if (curr.node1.parent != null) {
+                    } else if (!curr.node1.isRoot()) {
                         String polyString1 = buildUp(curr.node1.parent, curr.node2.getVenn());
                         Node polyOne = new Node(null, polyString1);
                         result.add(polyOne);
-                    } else if (curr.node1.linkNode.parent != null) {
+                    } else if (!curr.node1.linkNode.isRoot()) {
                         String polyString2 = buildUp(curr.node1.linkNode.parent, curr.node2.getVenn());
                         Node polyTwo = new Node(null, polyString2);
                         result.add(polyTwo);
@@ -430,40 +441,29 @@ public class Node {
             return result;
         }
 
-        Iterator nLNit = newLinkedNodePair.iterator();
-        if (nLNit.hasNext()) {
-            HashSet combined = ((NodePair)nLNit.next()).combineNew();
-            Iterator cIt = combined.iterator();
-            while (cIt.hasNext()) {
-                NodePair curr = (NodePair)cIt.next();
-                HashSet newResults = combine(curr.node1, curr.node2);
-                Iterator nRit = newResults.iterator();
-                while (nRit.hasNext()) {
-                    result.add(nRit.next());
-                }
+        if (!newLinkedNodePair.isEmpty()) {
+            List<NodePair> combined = newLinkedNodePair.get(0).combineNew();
+            for (NodePair curr : combined) {
+                result.addAll(combine(curr.node1, curr.node2));
             }
             return result;
         }
 
         if (largest.get(0).nodesSize() == 1) { // Shares only leaves
             List<Node> unique = getUniqueNodes(sResult);
-//            HashSet<Node> unique = getUniqueNodes(sResult);
 
             for (Node curr : unique) {
-                HashSet<Node> dupres = curr.getDuplicates(sResult);
+                List<Node> dupres = curr.getDuplicates(sResult);
                 if (dupres.size() > 1) {
-                    HashSet newDupNodePair = getLinkedNodePair(dupres);
-                    Iterator ndIt = newDupNodePair.iterator();
+                    List<NodePair> newDupNodePair = getLinkedNodePair(dupres);
+                    Iterator<NodePair> ndIt = newDupNodePair.iterator();
                     while (ndIt.hasNext()) {
-                        HashSet combined = ((NodePair)ndIt.next()).combineNew();
+                        List<NodePair> combined = ndIt.next().combineNew();
                         Iterator cIt = combined.iterator();
                         while (cIt.hasNext()) {
                             NodePair curr2 = (NodePair)cIt.next();
-                            HashSet newResults = combine(curr2.node1, curr2.node2);
-                            Iterator nRit = newResults.iterator();
-                            while (nRit.hasNext()) {
-                                result.add(nRit.next());
-                            }
+                            List<Node> newResults = combine(curr2.node1, curr2.node2);
+                            result.addAll(newResults);
                         }
                     }
                 }
@@ -474,13 +474,8 @@ public class Node {
             return result;
         }
         else {  // shares sub-trees
-            for (Object aLargest : largest) {
-                NodePair currL = (NodePair) aLargest;
-                HashSet largeResult = subTrees(currL);
-                Iterator lrIt = largeResult.iterator();
-                while (lrIt.hasNext()) {
-                    result.add(lrIt.next());
-                }
+            for (NodePair largest_ : largest) {
+                result.addAll(subTrees(largest_));
             }
             return result;
         }
@@ -489,11 +484,11 @@ public class Node {
     public static List<Node> reducedCombine(Node node1, Node node2) {
         List<Node> result = new ArrayList<>();
 
-        if (oneAreaShared(node1, node2)) {
+        if (oneLeafShared(node1, node2)) {
             result.add(combineAtRoot(node1, node2));
             return result;
         }
-        HashSet<Node> compCombine = combine(node1, node2);
+        List<Node> compCombine = combine(node1, node2);
 
         int smallest = Integer.MAX_VALUE;
         for (Node curr : compCombine) {
@@ -509,29 +504,47 @@ public class Node {
         return removeDuplicates(result);
     }
 
-    private static List<Node> removeDuplicates(List<Node> h) {
-        HashSet<Node> result = new HashSet<>();
-        for (Node curr : h) {
-            if (!curr.inSet(result)) {
+    /**
+     * Removes any duplicate nodes. Guarantees that
+     * forall A, B in result, A.equals(B) == false
+     * @param all
+     * @return
+     */
+    private static List<Node> removeDuplicates(List<Node> all) {
+        // TODO: Speed up w/ sets as soon as hash problems are sorted
+        List<Node> result = new ArrayList<>();
+        for (Node curr : all) {
+            boolean foundDup = false;
+            for (Node resNode : result) {
+                if (resNode.equals(curr)) {
+                    foundDup = true;
+                    break;
+                }
+            }
+            if (!foundDup) {
                 result.add(curr);
             }
         }
-        return new ArrayList<>(result);
+        return result;
     }
 
-    private static boolean oneAreaShared(Node node1, Node node2) {
+    /**
+     * Returns true if the trees with roots node1 and node1 share exactly one leaf node
+     * @param node1
+     * @param node2
+     * @return
+     */
+    private static boolean oneLeafShared(Node node1, Node node2) {
         List<NodePair> result = deepSearch(node2, node1);
         if (result.isEmpty()) {
             return false;
         }
         List<NodePair> largest = getLargestNodePairs(result);
         return largest.size() == 1 && largest.get(0).nodesSize() == 1;
-//        return (NodePair.getNodesSize(largest) == 1) && (largest.size() == 1);
     }
 
-    private static void sortLargestSibs(Iterator<Node> lgsibs, Node lg, HashSet<Node> ns, HashSet<Node> os) {
-        while (lgsibs.hasNext()) {
-            Node curr = lgsibs.next();
+    private static void sortLargestSibs(List<Node> lgsibs, Node lg, List<Node> newSibs, List<Node> os) {
+        for (Node curr : lgsibs) {
             Iterator linkIt = curr.linkNodes.iterator();
             boolean linkFlargest = false;
             if (linkIt.hasNext()) {
@@ -545,51 +558,43 @@ public class Node {
                 }
             }
             if (linkFlargest) {
-                ns.add(curr);
+                newSibs.add(curr);
             }
             else if (!curr.linkNodes.isEmpty())
                 os.add(curr);
         }
     }
 
-    private static HashSet<Node> subTrees(NodePair largest) {
-        HashSet<Node> result = new HashSet();
-        HashSet<Node> n = largest.combineSubTrees();
+    private static List<Node> subTrees(NodePair largest) {
+        if (largest.node1.isRoot() && largest.node2.isRoot())
+            throw new IllegalArgumentException("Cannot calculate subtrees with two roots.");
+
+        List<Node> result = new ArrayList();
+        List<Node> combined = largest.combineSubTrees();
 
-        for (Node aN : n) {
-            String curr = aN.getVenn();
+        for (Node node : combined) {
+            String curr = node.getVenn();
 
-            if ((curr.length() > 1) && (
-                    (largest.node1.getSiblings().size() != 1) ||
-                            (largest.node2.getSiblings().size() != 1))) {
+            if ((!node.isLeaf()) && ((largest.node1.nSiblings() != 1) || (largest.node2.nSiblings() != 1))) {
                 curr = curr.substring(1, curr.length() - 1);
             }
 
             String curr1 = "(" + largest.node1.getVenn() + curr + ")";
             String curr2 = "(" + largest.node2.getVenn() + curr + ")";
-            if ((largest.node1.parent != null) &&
-                    (largest.node2.parent != null)) {
-                String one = buildUp(largest.node1.parent, curr1);
-                String two = buildUp(largest.node2.parent, curr2);
-                Node newOne = new Node(null, one);
-                Node newTwo = new Node(null, two);
-                HashSet<Node> newResult = combine(newOne, newTwo);
+            Node newOne = new Node(null, buildUp(largest.node1.parent, curr1));
+            Node newTwo = new Node(null, buildUp(largest.node2.parent, curr2));
+
+            if ((!largest.node1.isRoot()) && (!largest.node2.isRoot())) {
+                List<Node> newResult = combine(newOne, newTwo);
                 result.addAll(newResult);
-                return result;
             }
-            if (largest.node1.parent != null) {
-                String one = buildUp(largest.node1.parent, curr1);
-                Node newOne = new Node(null, one);
+            else if (!largest.node1.isRoot()) {
                 result.add(newOne);
-                return result;
             }
-            if (largest.node2.parent != null) {
-                String two = buildUp(largest.node2.parent, curr2);
-                Node newTwo = new Node(null, two);
+            else if (!largest.node2.isRoot()) {
                 result.add(newTwo);
-                return result;
             }
-            System.out.println("Houston we have a problem.");
+            return result;
         }
         return result;
     }
@@ -637,8 +642,8 @@ public class Node {
         }
     }
 
-    private static HashSet<NodePair> getLinkedNodePair(HashSet<Node> h) {
-        HashSet<NodePair> result = new HashSet<>();
+    private static List<NodePair> getLinkedNodePair(List<Node> h) {
+        List<NodePair> result = new ArrayList<>();
         for (Node curr : h) {
             if (curr.hasLink() != null)
                 result.add(new NodePair(curr, curr.hasLink()));
@@ -652,7 +657,7 @@ public class Node {
             return s;
         }
         String result = "(" + s;
-        List<Node> sibs = n.getSiblingsL();
+        List<Node> sibs = n.getSiblings();
         for (Node sib : sibs) {
             result += sib.getVenn();
         }
@@ -660,15 +665,15 @@ public class Node {
         return buildUp(n.parent, result);
     }
 
-    private static HashSet<HashSet<NodePair>> reviewPolys(HashSet<NodePair> h) {
-        HashSet<HashSet<NodePair>> result = new HashSet<>();
+    private static List<List<NodePair>> reviewPolys(List<NodePair> h) {
+        List<List<NodePair>> result = new ArrayList<>();
         for (NodePair curr : h) {
-            HashSet<NodePair> curresult = new HashSet<>();
+            List<NodePair> curresult = new ArrayList<>();
             for (NodePair inCurr : h) {
                 if (inCurr == curr) {
                     continue;
                 }
-                HashSet<Node> linkedNodePair = inCurr.node2.linkNodes;
+                List<Node> linkedNodePair = inCurr.node2.linkNodes;
                 boolean found = false;
                 for (Node currln : linkedNodePair) {
                     if (currln == curr.node2) {
@@ -689,8 +694,8 @@ public class Node {
         return result;
     }
 
-    private static HashSet<NodePair> addPolys(HashSet<NodePair> h) {
-        HashSet<NodePair> setResult = new HashSet<>();
+    private static List<NodePair> addPolys(List<NodePair> h) {
+        List<NodePair> setResult = new ArrayList<>();
         NodePair first = null;
         String result = "";
         for (NodePair nodes : h) {

+ 6 - 10
src/com/pact/NodePair.java

@@ -27,13 +27,7 @@ public class NodePair {
         return "<" + this.node1 + ", " + this.node2 + ">";
     }
 
-    HashSet<Node> combineSubTrees() {
-        List<Node> res = _combineSubTrees();
-        return new HashSet<>(res);
-
-    }
-
-    private List<Node> _combineSubTrees() {
+    List<Node> combineSubTrees() {
         System.out.println("combineSubTrees==========================");
         System.out.println("node1: " + node1.getVenn());
         System.out.println("node2: " + node2.getVenn());
@@ -95,10 +89,12 @@ public class NodePair {
         }
 
         Node nodeSibs2 = new Node(null, siblings2.toString());
-        return new ArrayList<>(Node.combine(nodesibs1, nodeSibs2));
+        List<Node> result = Node.combine(nodesibs1, nodeSibs2);
+        System.out.println("Result: " + result);
+        return result;
     }
 
-    HashSet<NodePair> combineNew() {
+    List<NodePair> combineNew() {
         List<NodePair> setResult = new ArrayList<>();
         Node resultNode1 = new Node(null, this.node2.root().getVenn());
         String added = "(" + this.node2.getVenn() + this.node1.getVenn() + ")";
@@ -108,7 +104,7 @@ public class NodePair {
             Node resultNode2 = new Node(null, result);
             setResult.add(new NodePair(resultNode1, resultNode2));
         }
-        return new HashSet<>(setResult);
+        return setResult;
     }
 
     private String buildUp(Node n, String s) {

+ 12 - 0
src/com/pact/test/NodeTest.java

@@ -182,5 +182,17 @@ class NodeTest {
         reducedCombineTest("((AB)(AB)(AC))", "((AB)(AB)(AB))",
                            "((AB)(AC))");
     }
+//    @Test
+//    void hash() {
+//        String var0 = "Hello World";
+//        int var1;
+//        System.out.println((var1 = var0.hashCode()) ^ (var1 >>> 16));
+//        System.out.println(var1);
+//        System.out.println(var1 >>> 16);
+//        var1 = 0;
+//        System.out.println((var0.hashCode()) ^ (var1 >>> 16));
+////        int x =  var0 == null ? 0 : (var1 = var0.hashCode()) ^ var1 >>> 16;
+////        System.out.println(x);
+//    }
 
 }