Node.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. package com.pact;
  2. import java.util.ArrayList;
  3. import java.util.HashSet;
  4. import java.util.Iterator;
  5. import java.util.List;
  6. public class Node {
  7. Node parent;
  8. private String venn;
  9. private List<Node> children;
  10. HashSet<Node> linkNodes;
  11. private Node linkNode;
  12. private int hash;
  13. public Node(Node p, String s) {
  14. this.linkNode = null;
  15. this.linkNodes = new HashSet<>();
  16. this.venn = s;
  17. this.parent = p;
  18. this.hash = 0;
  19. this.children = new ArrayList<>();
  20. if (s.length() > 1)
  21. setChildren(s);
  22. if (children.isEmpty()) {
  23. hash = (venn.hashCode()*1073676287) ^ (venn.hashCode()*97);
  24. } else {
  25. for (Node child : children) {
  26. hash = hash ^ child.hash;
  27. }
  28. hash *= 33;
  29. }
  30. }
  31. public Node(Node p, char s) {
  32. this(p, ""+s);
  33. }
  34. private void setChildren(String s) {
  35. try {
  36. String vennChildren = s.substring(1, s.length() - 1);
  37. int count = 0;
  38. while (count < vennChildren.length())
  39. if (vennChildren.charAt(count) == '(') {
  40. int start = count;
  41. count++;
  42. int end;
  43. int brackets = 1;
  44. while (true)
  45. {
  46. if (vennChildren.charAt(count) == '(') {
  47. brackets++;
  48. }
  49. if (vennChildren.charAt(count) == ')') {
  50. brackets--;
  51. if (brackets == 0) {
  52. count++;
  53. break;
  54. }
  55. }
  56. count++;
  57. }
  58. end = count;
  59. Node child = new Node(this, vennChildren.substring(start, end));
  60. this.children.add(child);
  61. } else {
  62. Node child = new Node(this, vennChildren.charAt(count));
  63. this.children.add(child);
  64. count++;
  65. }
  66. }
  67. catch (StringIndexOutOfBoundsException se) {
  68. throw new BracketException();
  69. }
  70. }
  71. public String getVenn()
  72. {
  73. return this.venn;
  74. }
  75. public String toString()
  76. {
  77. return this.venn;
  78. }
  79. public HashSet<Node> getSiblings() {
  80. if (this.parent != null) {
  81. HashSet<Node> sibs = new HashSet<>(parent.children);
  82. sibs.remove(this);
  83. return sibs;
  84. }
  85. return new HashSet<>();
  86. }
  87. public boolean equals(Object obj) {
  88. if (this == obj) return true; // Literally the same object
  89. if (!(obj instanceof Node)) return false; // Wrong type
  90. Node node = (Node) obj;
  91. if (hash != node.hash) return false; // equal object have equal hash codes
  92. // If above checks fall through, we need to actually look at the structure
  93. // Of the Node.
  94. String nodeVenn = node.getVenn();
  95. // Case for leaf nodes
  96. if ((nodeVenn.length() == 1) && (this.venn.length() == 1)) {
  97. return nodeVenn.equals(this.venn);
  98. }
  99. if (children.size() != node.children.size()){
  100. return false;
  101. }
  102. // Check to make sure all of my children exist in node's children
  103. for (Node theirChild : node.children) {
  104. boolean foundMatch = false;
  105. for (Node myChild : this.children) {
  106. if (myChild.equals(theirChild)) {
  107. foundMatch = true;
  108. break;
  109. }
  110. }
  111. if(!foundMatch) return false;
  112. }
  113. return true;
  114. }
  115. // @Override
  116. // public int hashCode() {
  117. // if (children.isEmpty()) {
  118. // return venn.hashCode();
  119. // } else {
  120. // int h = 0;
  121. // for (Node child : children) {
  122. // h += child.hashCode();
  123. // }
  124. // return Integer.hashCode(h);
  125. // }
  126. //
  127. // }
  128. public void _deepSearch(Node node, List<NodePair> h) {
  129. // res1: Occurrences of node in this tree
  130. List<NodePair> res1 = this.search(node);
  131. // res2: Occurrences of this tree in node
  132. List<NodePair> res2 = node.search(this);
  133. assert(res1.size() == 0 || res2.size() == 0 || res1.equals(res2));
  134. if(!res1.isEmpty()){
  135. h.addAll(res1);
  136. } else if(!res2.isEmpty()){
  137. h.addAll(res2);
  138. }
  139. for(Node child : node.children) {
  140. _deepSearch(child, h);
  141. }
  142. }
  143. public List<NodePair> deepSearch(Node node) {
  144. List<NodePair> result = new ArrayList<>();
  145. _deepSearch(node, result);
  146. return result;
  147. }
  148. public Node root() {
  149. if (getSiblings().isEmpty()) {
  150. return this;
  151. }
  152. return this.parent.root();
  153. }
  154. private int getNumAreas() {
  155. int count = 0;
  156. for (int i = 0; i < this.venn.length(); i++) {
  157. if ((this.venn.charAt(i) != ')') && (this.venn.charAt(i) != '(')) {
  158. count++;
  159. }
  160. }
  161. return count;
  162. }
  163. /**
  164. * Search this tree for the subtree with given root
  165. * @param node the root of the subtree to search for
  166. * @param l
  167. */
  168. private void _search(Node node, List<NodePair> l) {
  169. if (equals(node)) {
  170. this.linkNodes.add(node);
  171. node.linkNodes.add(this);
  172. l.add(new NodePair(this, node));
  173. } else {
  174. for(Node child : children) {
  175. child._search(node, l);
  176. }
  177. }
  178. }
  179. private List<NodePair> search(Node node) {
  180. List<NodePair> result = new ArrayList<>();
  181. _search(node, result);
  182. return result;
  183. }
  184. private boolean isIn(Node node) {
  185. if (this == node) {
  186. return true;
  187. }
  188. for (Node child : this.children) {
  189. if (child.isIn(node)) {
  190. return true;
  191. }
  192. }
  193. return false;
  194. }
  195. private Node hasLink() {
  196. HashSet<Node> sibs = getSiblings();
  197. for (Node curr : sibs) {
  198. if (!curr.linkNodes.isEmpty()) {
  199. return curr;
  200. }
  201. }
  202. return null;
  203. }
  204. private boolean unshared() {
  205. if (this.linkNodes.isEmpty()) {
  206. if(this.children.isEmpty()) {
  207. return true;
  208. } else {
  209. for (Node node : this.children) {
  210. if (!node.unshared()) {
  211. return false;
  212. }
  213. }
  214. }
  215. return true;
  216. } else {
  217. return false;
  218. }
  219. }
  220. private void resetSearch() {
  221. this.linkNodes = new HashSet<>();
  222. this.linkNode = null;
  223. for (Node child : this.children) {
  224. child.resetSearch();
  225. }
  226. }
  227. private HashSet<Node> getDuplicates(List<NodePair> h) {
  228. HashSet<Node> result = new HashSet<>();
  229. for (NodePair curr : h) {
  230. if (curr.node1 == this)
  231. result.add(curr.node2);
  232. else if (curr.node2 == this) {
  233. result.add(curr.node1);
  234. }
  235. }
  236. return result;
  237. }
  238. private Node reduce() {
  239. List<Node> uniqueC = new ArrayList<>();
  240. List<Node> dupC = new ArrayList<>();
  241. for (Node child : this.children) {
  242. if (child.inSet(uniqueC))
  243. dupC.add(child);
  244. else {
  245. uniqueC.add(child);
  246. }
  247. }
  248. if ((dupC.isEmpty()) || (this.venn.length() == 1)) {
  249. return this;
  250. }
  251. Iterator uIt = uniqueC.iterator();
  252. String result = "";
  253. if (uIt.hasNext()) {
  254. result = result + ((Node)uIt.next()).getVenn();
  255. }
  256. if (uIt.hasNext()) {
  257. result = result + "(" + result;
  258. while (uIt.hasNext()) {
  259. result = result + ((Node)uIt.next()).getVenn();
  260. }
  261. result = result + ")";
  262. }
  263. return new Node(null, result);
  264. }
  265. private boolean inSet(List<Node> h) {
  266. for (Node curr : h) {
  267. if (curr.equals(this)) {
  268. return true;
  269. }
  270. }
  271. return false;
  272. }
  273. private boolean inSet(HashSet<Node> h) {
  274. for (Node curr : h) {
  275. if (curr.equals(this)) {
  276. return true;
  277. }
  278. }
  279. return false;
  280. }
  281. private void collectUnshared(HashSet<Node> h) {
  282. if (unshared()) {
  283. h.add(this);
  284. }
  285. for (Node child : children) {
  286. child.collectUnshared(h);
  287. }
  288. }
  289. public static HashSet<Node> combine(Node node1, Node node2) {
  290. node1 = node1.reduce();
  291. node2 = node2.reduce();
  292. node2.resetSearch();
  293. node1.resetSearch();
  294. HashSet result = new HashSet();
  295. if (node1.equals(node2)) {
  296. result.add(node2);
  297. return result;
  298. }
  299. List<NodePair> sResult = node2.deepSearch(node1);
  300. if (sResult.isEmpty()) {
  301. result.add(combineAtRoot(node2, node1));
  302. return result;
  303. }
  304. HashSet<Node> unsharedNodePair = new HashSet<>();
  305. node2.collectUnshared(unsharedNodePair);
  306. node1.collectUnshared(unsharedNodePair);
  307. if ((unsharedNodePair.isEmpty()) && (node1.getNumAreas() == node2.getNumAreas())) {
  308. if (node1.children.size() < node2.children.size()) {
  309. Node toAdd = new Node(null, node1.getVenn());
  310. result.add(toAdd);
  311. return result;
  312. } if (node2.children.size() < node1.children.size()) {
  313. Node toAdd = new Node(null, node2.getVenn());
  314. result.add(toAdd);
  315. return result;
  316. }
  317. }
  318. List<NodePair> largest = getLargestNodePairs(sResult);
  319. if (!largest.isEmpty()) {
  320. Iterator itLargest = largest.iterator();
  321. NodePair flargest = (NodePair)itLargest.next();
  322. HashSet<Node> lg1sibs = flargest.node1.getSiblings();
  323. HashSet<Node> lg2sibs = flargest.node2.getSiblings();
  324. HashSet<Node> newSibs = new HashSet<>();
  325. HashSet<Node> otherSibs1 = new HashSet<>();
  326. HashSet<Node> otherSibs2 = new HashSet<>();
  327. Iterator lg1It = lg1sibs.iterator();
  328. Iterator lg2It = lg2sibs.iterator();
  329. sortLargestSibs(lg1It, flargest.node2, newSibs, otherSibs1);
  330. sortLargestSibs(lg2It, flargest.node1, newSibs, otherSibs2);
  331. if ((otherSibs1.isEmpty()) && (otherSibs2.isEmpty())) {
  332. for (Node newSib : newSibs) {
  333. unsharedNodePair.add(newSib);
  334. }
  335. }
  336. }
  337. HashSet<NodePair> newLinkedNodePair = getLinkedNodePair(unsharedNodePair);
  338. HashSet<HashSet<NodePair>> polys = reviewPolys(newLinkedNodePair);
  339. if (!polys.isEmpty()) {
  340. Iterator polyIt = polys.iterator();
  341. if (polyIt.hasNext()) {
  342. HashSet polyresult = addPolys((HashSet)polyIt.next());
  343. Iterator prIt = polyresult.iterator();
  344. if (prIt.hasNext()) {
  345. NodePair curr = (NodePair)prIt.next();
  346. if ((curr.node1.parent != null) && (curr.node1.linkNode.parent != null)) {
  347. String polyString1 = buildUp(curr.node1.parent, curr.node2.getVenn());
  348. String polyString2 = buildUp(curr.node1.linkNode.parent, curr.node2.getVenn());
  349. Node polyOne = new Node(null, polyString1);
  350. Node polyTwo = new Node(null, polyString2);
  351. HashSet<Node> polyresults = combine(polyOne, polyTwo);
  352. for (Node polyResult : polyresults)
  353. result.add(polyResult);
  354. } else if (curr.node1.parent != null) {
  355. String polyString1 = buildUp(curr.node1.parent, curr.node2.getVenn());
  356. Node polyOne = new Node(null, polyString1);
  357. result.add(polyOne);
  358. } else if (curr.node1.linkNode.parent != null) {
  359. String polyString2 = buildUp(curr.node1.linkNode.parent, curr.node2.getVenn());
  360. Node polyTwo = new Node(null, polyString2);
  361. result.add(polyTwo);
  362. } else {
  363. System.out.println("What's up Houston?");
  364. }
  365. }
  366. }
  367. return result;
  368. }
  369. Iterator nLNit = newLinkedNodePair.iterator();
  370. if (nLNit.hasNext()) {
  371. HashSet combined = ((NodePair)nLNit.next()).combineNew();
  372. Iterator cIt = combined.iterator();
  373. while (cIt.hasNext()) {
  374. NodePair curr = (NodePair)cIt.next();
  375. HashSet newResults = combine(curr.node1, curr.node2);
  376. Iterator nRit = newResults.iterator();
  377. while (nRit.hasNext()) {
  378. result.add(nRit.next());
  379. }
  380. }
  381. return result;
  382. }
  383. if (largest.get(0).nodesSize() == 1) { // Shares only leaves
  384. HashSet unique = getUniqueNodePair(sResult);
  385. Iterator uIt = unique.iterator();
  386. while (uIt.hasNext()) {
  387. Node curr = (Node)uIt.next();
  388. HashSet dupres = curr.getDuplicates(sResult);
  389. if (dupres.size() > 1) {
  390. HashSet newDupNodePair = getLinkedNodePair(dupres);
  391. Iterator ndIt = newDupNodePair.iterator();
  392. while (ndIt.hasNext()) {
  393. HashSet combined = ((NodePair)ndIt.next()).combineNew();
  394. Iterator cIt = combined.iterator();
  395. while (cIt.hasNext()) {
  396. NodePair curr2 = (NodePair)cIt.next();
  397. HashSet newResults = combine(curr2.node1, curr2.node2);
  398. Iterator nRit = newResults.iterator();
  399. while (nRit.hasNext()) {
  400. result.add(nRit.next());
  401. }
  402. }
  403. }
  404. }
  405. else {
  406. result.add(combineAtRoot(node2, node1));
  407. }
  408. }
  409. return result;
  410. }
  411. else { // shares sub-trees
  412. for (Object aLargest : largest) {
  413. NodePair currL = (NodePair) aLargest;
  414. HashSet largeResult = subTrees(currL);
  415. Iterator lrIt = largeResult.iterator();
  416. while (lrIt.hasNext()) {
  417. result.add(lrIt.next());
  418. }
  419. }
  420. return result;
  421. }
  422. }
  423. public static List<Node> reducedCombine(Node node1, Node node2) {
  424. List<Node> result = new ArrayList<>();
  425. if (oneAreaShared(node1, node2)) {
  426. result.add(combineAtRoot(node1, node2));
  427. return result;
  428. }
  429. HashSet<Node> compCombine = combine(node1, node2);
  430. int smallest = Integer.MAX_VALUE;
  431. for (Node curr : compCombine) {
  432. int currAreas = curr.getNumAreas();
  433. if (currAreas < smallest) {
  434. smallest = currAreas;
  435. result.clear();
  436. result.add(curr);
  437. } else if (currAreas == smallest) {
  438. result.add(curr);
  439. }
  440. }
  441. return removeDuplicates(result);
  442. }
  443. private static List<Node> removeDuplicates(List<Node> h) {
  444. HashSet<Node> result = new HashSet<>();
  445. for (Node curr : h) {
  446. if (!curr.inSet(result)) {
  447. result.add(curr);
  448. }
  449. }
  450. return new ArrayList(result);
  451. }
  452. private static boolean oneAreaShared(Node node1, Node node2) {
  453. List<NodePair> result = node2.deepSearch(node1);
  454. if (result.isEmpty()) {
  455. return false;
  456. }
  457. List<NodePair> largest = getLargestNodePairs(result);
  458. return largest.size() == 1 && largest.get(0).nodesSize() == 1;
  459. // return (NodePair.getNodesSize(largest) == 1) && (largest.size() == 1);
  460. }
  461. private static void sortLargestSibs(Iterator<Node> lgsibs, Node lg, HashSet<Node> ns, HashSet<Node> os) {
  462. while (lgsibs.hasNext()) {
  463. Node curr = lgsibs.next();
  464. Iterator linkIt = curr.linkNodes.iterator();
  465. boolean linkFlargest = false;
  466. if (linkIt.hasNext()) {
  467. linkFlargest = true;
  468. }
  469. while (linkIt.hasNext()) {
  470. Node currLink = (Node)linkIt.next();
  471. if (!lg.isIn(currLink)) {
  472. linkFlargest = false;
  473. }
  474. }
  475. if (linkFlargest) {
  476. ns.add(curr);
  477. }
  478. else if (!curr.linkNodes.isEmpty())
  479. os.add(curr);
  480. }
  481. }
  482. private static HashSet<Node> subTrees(NodePair largest) {
  483. HashSet<Node> result = new HashSet();
  484. HashSet<Node> n = largest.combineSubTrees();
  485. for (Node aN : n) {
  486. String curr = aN.getVenn();
  487. if ((curr.length() > 1) && (
  488. (largest.node1.getSiblings().size() != 1) ||
  489. (largest.node2.getSiblings().size() != 1))) {
  490. curr = curr.substring(1, curr.length() - 1);
  491. }
  492. String curr1 = "(" + largest.node1.getVenn() + curr + ")";
  493. String curr2 = "(" + largest.node2.getVenn() + curr + ")";
  494. if ((largest.node1.parent != null) &&
  495. (largest.node2.parent != null)) {
  496. String one = buildUp(largest.node1.parent, curr1);
  497. String two = buildUp(largest.node2.parent, curr2);
  498. Node newOne = new Node(null, one);
  499. Node newTwo = new Node(null, two);
  500. HashSet<Node> newResult = combine(newOne, newTwo);
  501. result.addAll(newResult);
  502. return result;
  503. }
  504. if (largest.node1.parent != null) {
  505. String one = buildUp(largest.node1.parent, curr1);
  506. Node newOne = new Node(null, one);
  507. result.add(newOne);
  508. return result;
  509. }
  510. if (largest.node2.parent != null) {
  511. String two = buildUp(largest.node2.parent, curr2);
  512. Node newTwo = new Node(null, two);
  513. result.add(newTwo);
  514. return result;
  515. }
  516. System.out.println("Houston we have a problem.");
  517. }
  518. return result;
  519. }
  520. /**
  521. *
  522. * @param h HashSet
  523. * @return The largest NodePair in h, based on the length of n1's Venn diagram
  524. */
  525. private static List<NodePair> getLargestNodePairs(List<NodePair> h) {
  526. List<NodePair> result = new ArrayList<>();
  527. int size = -1;
  528. for(NodePair curr : h){
  529. if (curr.nodesSize() > size) {
  530. size = curr.nodesSize();
  531. result.clear();
  532. result.add(curr);
  533. } else if (curr.nodesSize() == size) {
  534. result.add(curr);
  535. }
  536. }
  537. return result;
  538. }
  539. private static Node combineAtRoot(Node node1, Node node2) {
  540. HashSet<Node> uniqueNodes = new HashSet<>();
  541. for(Node curr : node1.children) {
  542. if (!curr.inSet(uniqueNodes))
  543. uniqueNodes.add(curr);
  544. }
  545. for(Node curr : node2.children) {
  546. if (!curr.inSet(uniqueNodes))
  547. uniqueNodes.add(curr);
  548. }
  549. if (uniqueNodes.size() < (node1.children.size() + node2.children.size())) {
  550. String result_venn = "(";
  551. for (Node unique : uniqueNodes) {
  552. result_venn = result_venn + unique;
  553. }
  554. result_venn = result_venn + ")";
  555. return new Node(null, result_venn);
  556. } else {
  557. return new Node(null, "(" + node1.venn + node2.getVenn() + ")");
  558. }
  559. }
  560. private static HashSet<NodePair> getLinkedNodePair(HashSet<Node> h) {
  561. HashSet<NodePair> result = new HashSet<>();
  562. for (Node curr : h) {
  563. if (curr.hasLink() != null)
  564. result.add(new NodePair(curr, curr.hasLink()));
  565. }
  566. return result;
  567. }
  568. private static String buildUp(Node n, String s) {
  569. if (n.parent == null) {
  570. return s;
  571. }
  572. String result = "(" + s;
  573. if (n.parent != null) {
  574. HashSet<Node> sibs = n.getSiblings();
  575. for (Node sib : sibs) {
  576. result = result + sib.getVenn();
  577. }
  578. }
  579. result = result + ")";
  580. return buildUp(n.parent, result);
  581. }
  582. private static HashSet<HashSet<NodePair>> reviewPolys(HashSet<NodePair> h) {
  583. HashSet<HashSet<NodePair>> result = new HashSet<>();
  584. for (NodePair curr : h) {
  585. HashSet<NodePair> curresult = new HashSet<>();
  586. for (NodePair inCurr : h) {
  587. if (inCurr == curr) {
  588. continue;
  589. }
  590. HashSet<Node> linkedNodePair = inCurr.node2.linkNodes;
  591. boolean found = false;
  592. for (Node currln : linkedNodePair) {
  593. if (currln == curr.node2) {
  594. found = true;
  595. inCurr.node2.linkNode = currln;
  596. break;
  597. }
  598. }
  599. if (found) {
  600. curresult.add(inCurr);
  601. }
  602. }
  603. if (!curresult.isEmpty()) {
  604. curresult.add(curr);
  605. result.add(curresult);
  606. }
  607. }
  608. return result;
  609. }
  610. private static HashSet<NodePair> addPolys(HashSet<NodePair> h) {
  611. HashSet<NodePair> setResult = new HashSet<>();
  612. NodePair first = null;
  613. String result = "";
  614. for (NodePair nodes : h) {
  615. if (first == null) {
  616. first = nodes;
  617. result = first.node2.getVenn();
  618. }
  619. result += nodes.node1.getVenn();
  620. }
  621. for (NodePair nodes : h) {
  622. NodePair toAdd = new NodePair((nodes).node2, new Node(null, "(" + result + ")"));
  623. setResult.add(toAdd);
  624. }
  625. return setResult;
  626. }
  627. private static HashSet<Node> getUniqueNodePair(List<NodePair> h) {
  628. HashSet<Node> result = new HashSet<>();
  629. for (NodePair curr : h) {
  630. if (!result.contains(curr.node1)) {
  631. result.add(curr.node1);
  632. }
  633. if (!result.contains(curr.node2)) {
  634. result.add(curr.node2);
  635. }
  636. }
  637. return result;
  638. }
  639. }