diff --git a/comparator.html b/comparator.html
new file mode 100755
index 0000000..f02759a
--- /dev/null
+++ b/comparator.html
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/comparator.js b/comparator.js
new file mode 100644
index 0000000..661ce1a
--- /dev/null
+++ b/comparator.js
@@ -0,0 +1,39 @@
+function nodesEquals(left, right, same) {
+ same = same ?? true;
+
+ if (!left || !right) {
+ return left === right;
+ }
+
+ return (
+ left.value === right.value &&
+ (!same || left.rank === right.rank) &&
+ nodesEquals(left.left, right.left, same) &&
+ nodesEquals(left.right, right.right, same)
+ );
+}
+
+class Comparator {
+ constructor(left, right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ insert(value) {
+ this.left.insert(value);
+ this.right.insert(value);
+ }
+
+ delete(value) {
+ this.left.delete(value);
+ this.right.delete(value);
+ }
+
+ equals() {
+ return nodesEquals(this.left.root, this.right.root);
+ }
+
+ similar() {
+ return nodesEquals(this.left.root, this.right.root, false);
+ }
+}
diff --git a/comparator_visualization.js b/comparator_visualization.js
new file mode 100644
index 0000000..e3fbd5d
--- /dev/null
+++ b/comparator_visualization.js
@@ -0,0 +1,55 @@
+let lRecorder = new Recorder(
+ d3.select("#left").graphviz(),
+ "left"
+).renderAtOnce();
+let rRecorder = new Recorder(
+ d3.select("#right").graphviz(),
+ "right"
+).renderAtOnce();
+
+let left = new AVLTree();
+let right = new WAVLTree();
+
+left.recorder = lRecorder;
+right.recorder = rRecorder;
+
+function insertCallback() {
+ let number = document.getElementById("insertInput").value;
+ if (number === "") {
+ return false;
+ }
+
+ let value = parseInt(number);
+
+ left.insert(value);
+ right.insert(value);
+
+ document.getElementById("insertInput").value = "";
+ return false;
+}
+
+function deleteCallback() {
+ let number = document.getElementById("deleteInput").value;
+ if (number === "") {
+ return false;
+ }
+
+ let value = parseInt(number);
+
+ left.delete(value);
+ right.delete(value);
+
+ document.getElementById("deleteInput").value = "";
+ return false;
+}
+
+async function render() {
+ await Promise.all([
+ new Promise(() => lRecorder.render()),
+ new Promise(() => rRecorder.render()),
+ ]);
+ // lRecorder.render();
+ // rRecorder.render();
+ setTimeout(render);
+}
+render();