cyclic-graph.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Testing setup.
  2. mocha.setup('bdd');
  3. var expect = chai.expect;
  4. // The implementation.
  5. function Obj() {
  6. this.links = [];
  7. this.isLinkedToSelf = false;
  8. this.visited_nodes = [];
  9. };
  10. Obj.prototype.linkTo = function(to) {
  11. if (this.links.indexOf(to) === -1) {
  12. if (this === to) {
  13. this.isLinkedToSelf = true;
  14. } else this.links.push(to);
  15. }
  16. };
  17. Obj.prototype.resetMem = function() {
  18. // clear visited nodes memory
  19. this.visited_nodes = []
  20. this.links.forEach((link) => link.visited_nodes = [])
  21. }
  22. Obj.prototype.isLinkedTo = function(to) {
  23. // is linked to self
  24. if (this === to && this.isLinkedToSelf) return true;
  25. // is linked to neighbours
  26. for (var i = 0; i < this.links.length; i++) {
  27. var link = this.links[i];
  28. // if a cycle is reached while searching, return false
  29. if (this.visited_nodes.includes(link)) {
  30. // reset memory
  31. break;
  32. }
  33. // still searching, then add current node to memory
  34. this.visited_nodes.push(link)
  35. // find the node, return true
  36. if (link === to || link.isLinkedTo(to)) {
  37. // reset memory
  38. this.resetMem();
  39. return true;
  40. }
  41. }
  42. this.resetMem();
  43. return false;
  44. };
  45. // The tests.
  46. describe("Obj", function() {
  47. it("can link to itself", function() {
  48. var foo = new Obj;
  49. foo.linkTo(foo);
  50. expect(foo.isLinkedTo(foo)).to.equal(true);
  51. });
  52. it("does not link to itself", function() {
  53. var foo = new Obj;
  54. expect(foo.isLinkedTo(foo)).to.equal(false);
  55. });
  56. it("has unidirectional link to neighbour", function() {
  57. var foo = new Obj;
  58. var bar = new Obj;
  59. bar.linkTo(foo);
  60. expect(bar.isLinkedTo(foo)).to.equal(true);
  61. expect(foo.isLinkedTo(bar)).to.equal(false);
  62. });
  63. it("has neighbours with connections to themselves", function() {
  64. var foo = new Obj;
  65. var bar = new Obj;
  66. var baz = new Obj;
  67. // Connect the Objs to themselves.
  68. foo.linkTo(foo);
  69. bar.linkTo(bar);
  70. baz.linkTo(baz);
  71. // Connect baz => bar => foo.
  72. baz.linkTo(bar);
  73. bar.linkTo(foo);
  74. expect(baz.isLinkedTo(foo)).to.equal(true);
  75. expect(baz.isLinkedTo(bar)).to.equal(true);
  76. expect(bar.isLinkedTo(foo)).to.equal(true);
  77. });
  78. it("can be a cyclic graph", function() {
  79. var foo = new Obj;
  80. var bar = new Obj;
  81. var baz = new Obj;
  82. // Connect the nodes baz => bar => foo => baz.
  83. baz.linkTo(bar);
  84. bar.linkTo(foo);
  85. foo.linkTo(baz);
  86. expect(baz.isLinkedTo(foo)).to.equal(true);
  87. expect(baz.isLinkedTo(bar)).to.equal(true);
  88. expect(baz.isLinkedTo(baz)).to.equal(true);
  89. });
  90. it("can have neighbours in cyclic graph", function() {
  91. var foo = new Obj;
  92. var bar = new Obj;
  93. var baz = new Obj;
  94. // Connect the nodes baz => bar <=> foo.
  95. baz.linkTo(bar);
  96. bar.linkTo(foo);
  97. foo.linkTo(bar);
  98. expect(baz.isLinkedTo(foo)).to.equal(true);
  99. expect(baz.isLinkedTo(bar)).to.equal(true);
  100. expect(baz.isLinkedTo(baz)).to.equal(false);
  101. });
  102. it("can have a cycle of more than 2 Objs", function() {
  103. var foo = new Obj;
  104. var bar = new Obj;
  105. var baz = new Obj;
  106. var qux = new Obj;
  107. // Connect the nodes baz => bar => foo => qux => bar.
  108. baz.linkTo(bar);
  109. bar.linkTo(foo);
  110. foo.linkTo(qux);
  111. qux.linkTo(bar);
  112. expect(qux.isLinkedTo(baz)).to.equal(false);
  113. expect(baz.isLinkedTo(foo)).to.equal(true);
  114. expect(baz.isLinkedTo(bar)).to.equal(true);
  115. expect(baz.isLinkedTo(qux)).to.equal(true);
  116. expect(baz.isLinkedTo(baz)).to.equal(false);
  117. });
  118. });
  119. // Run the suite.
  120. mocha.run();