diff --git a/Backtracking/Knight's Tour Problem/code.js b/Backtracking/Knight's Tour Problem/code.js
index ceeb7f62..e334bc8f 100644
--- a/Backtracking/Knight's Tour Problem/code.js
+++ b/Backtracking/Knight's Tour Problem/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
/*
For N>3 the time taken by this algorithm is sufficiently high
@@ -26,6 +28,7 @@ const Y = [1, 2, 2, 1, -1, -2, -2, -1];
const pos = new Array(2);
pos[0] = pos[1] = -1;
+// define tracer variables {
const boardTracer = new Array2DTracer('Board');
const posTracer = new Array1DTracer('Knight Position');
const logTracer = new LogTracer('Console');
@@ -33,6 +36,7 @@ boardTracer.set(board);
posTracer.set(pos);
Layout.setRoot(new VerticalLayout([boardTracer, posTracer, logTracer]));
Tracer.delay();
+// }
function knightTour(x, y, moveNum) {
if (moveNum === N * N) {
@@ -43,12 +47,14 @@ function knightTour(x, y, moveNum) {
const nextX = x + X[i];
const nextY = y + Y[i];
+ // visualize {
posTracer.patch(0, nextX);
Tracer.delay();
posTracer.patch(1, nextY);
Tracer.delay();
posTracer.depatch(0);
posTracer.depatch(1);
+ // }
/*
Check if knight is still in the board
Check that knight does not visit an already visited square
@@ -56,24 +62,33 @@ function knightTour(x, y, moveNum) {
if (nextX >= 0 && nextX < N && nextY >= 0 && nextY < N && board[nextX][nextY] === -1) {
board[nextX][nextY] = moveNum;
+ // visualize {
logTracer.println(`Move to ${nextX},${nextY}`);
boardTracer.patch(nextX, nextY, moveNum);
Tracer.delay();
boardTracer.depatch(nextX, nextY);
boardTracer.select(nextX, nextY);
+ // }
const nextMoveNum = moveNum + 1;
if (knightTour(nextX, nextY, nextMoveNum) === true) {
return true;
}
+
+ // logger {
logTracer.println(`No place to move from ${nextX},${nextY}: Backtrack`);
+ // }
board[nextX][nextY] = -1; // backtrack
+ // visualize {
boardTracer.patch(nextX, nextY, -1);
Tracer.delay();
boardTracer.depatch(nextX, nextY);
boardTracer.deselect(nextX, nextY);
+ // }
} else {
+ // logger {
logTracer.println(`${nextX},${nextY} is not a valid move`);
+ // }
}
}
return false;
@@ -83,6 +98,7 @@ board[0][0] = 0; // start from this position
pos[0] = 0;
pos[0] = 0;
+// visualize {
boardTracer.patch(0, 0, 0);
Tracer.delay();
posTracer.patch(0, 0);
@@ -93,9 +109,12 @@ boardTracer.depatch(0, 0);
boardTracer.depatch(0, 0);
posTracer.depatch(0);
posTracer.depatch(1);
+// }
+// logger {
if (knightTour(0, 0, 1) === false) {
logTracer.println('Solution does not exist');
} else {
logTracer.println('Solution found');
}
+// }
diff --git a/Backtracking/N-Queens Problem/code.js b/Backtracking/N-Queens Problem/code.js
index 7812dd40..5f2e5b90 100644
--- a/Backtracking/N-Queens Problem/code.js
+++ b/Backtracking/N-Queens Problem/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const N = 4; // just change the value of N and the visuals will reflect the configuration!
const board = (function createArray(N) {
@@ -16,6 +18,7 @@ const queens = (function qSetup(N) {
return result;
}(N));
+// define tracer variables {
const boardTracer = new Array2DTracer('Board');
const queenTracer = new Array2DTracer('Queen Positions');
const logger = new LogTracer('Progress');
@@ -25,6 +28,7 @@ boardTracer.set(board);
queenTracer.set(queens);
logger.println(`N Queens: ${N}X${N}matrix, ${N} queens`);
Tracer.delay();
+// }
function validState(row, col, currentQueen) {
for (let q = 0; q < currentQueen; q++) {
@@ -37,24 +41,31 @@ function validState(row, col, currentQueen) {
}
function nQ(currentQueen, currentCol) {
+ // logger {
logger.println(`Starting new iteration of nQueens () with currentQueen = ${currentQueen} & currentCol = ${currentCol}`);
logger.println('------------------------------------------------------------------');
+ // }
if (currentQueen >= N) {
+ // logger {
logger.println('The recursion has BOTTOMED OUT. All queens have been placed successfully');
+ // }
return true;
}
let found = false;
let row = 0;
while ((row < N) && (!found)) {
+ // visualize {
boardTracer.select(row, currentCol);
Tracer.delay();
logger.println(`Trying queen ${currentQueen} at row ${row} & col ${currentCol}`);
-
+ // }
+
if (validState(row, currentCol, currentQueen)) {
queens[currentQueen][0] = row;
queens[currentQueen][1] = currentCol;
+ // visualize {
queenTracer.patch(currentQueen, 0, row);
Tracer.delay();
queenTracer.patch(currentQueen, 1, currentCol);
@@ -63,14 +74,17 @@ function nQ(currentQueen, currentCol) {
Tracer.delay();
queenTracer.depatch(currentQueen, 1);
Tracer.delay();
-
+ // }
+
found = nQ(currentQueen + 1, currentCol + 1);
}
if (!found) {
+ // visualize {
boardTracer.deselect(row, currentCol);
Tracer.delay();
logger.println(`row ${row} & col ${currentCol} didn't work out. Going down`);
+ // }
}
row++;
}
@@ -78,6 +92,10 @@ function nQ(currentQueen, currentCol) {
return found;
}
+// logger {
logger.println('Starting execution');
+// }
nQ(0, 0);
+// logger {
logger.println('DONE');
+// }
diff --git a/Branch and Bound/Binary Search Tree/insertion.js b/Branch and Bound/Binary Search Tree/insertion.js
index a2656c45..f327b301 100644
--- a/Branch and Bound/Binary Search Tree/insertion.js
+++ b/Branch and Bound/Binary Search Tree/insertion.js
@@ -1,8 +1,12 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const T = {};
const elements = [5, 8, 10, 3, 1, 6, 9, 7, 2, 0, 4]; // item to be inserted
+
+// define tracer variables {
const graphTracer = new GraphTracer(' BST - Elements marked red indicates the current status of tree ');
const elemTracer = new Array1DTracer(' Elements ');
const logger = new LogTracer(' Log ');
@@ -10,10 +14,13 @@ Layout.setRoot(new VerticalLayout([graphTracer, elemTracer, logger]));
elemTracer.set(elements);
graphTracer.log(logger);
Tracer.delay();
+// }
function bstInsert(root, element, parent) { // root = current node , parent = previous node
+ // visualize {
graphTracer.visit(root, parent);
Tracer.delay();
+ // }
const treeNode = T[root];
let propName = '';
if (element < root) {
@@ -25,30 +32,40 @@ function bstInsert(root, element, parent) { // root = current node , parent = pr
if (!(propName in treeNode)) { // insert as left child of root
treeNode[propName] = element;
T[element] = {};
+ // visualize {
graphTracer.addNode(element);
graphTracer.addEdge(root, element);
graphTracer.select(element, root);
Tracer.delay();
graphTracer.deselect(element, root);
logger.println(`${element} Inserted`);
+ // }
} else {
bstInsert(treeNode[propName], element, root);
}
}
+ // visualize {
graphTracer.leave(root, parent);
Tracer.delay();
+ // }
}
const Root = elements[0]; // take first element as root
T[Root] = {};
+// visualize {
graphTracer.addNode(Root);
graphTracer.layoutTree(Root, true);
logger.println(`${Root} Inserted as root of tree `);
+// }
for (let i = 1; i < elements.length; i++) {
+ // visualize {
elemTracer.select(i);
Tracer.delay();
+ // }
bstInsert(Root, elements[i]); // insert ith element
+ // visualize {
elemTracer.deselect(i);
Tracer.delay();
+ // }
}
diff --git a/Branch and Bound/Binary Search Tree/search.js b/Branch and Bound/Binary Search Tree/search.js
index f45f5f8a..0d9fdf0c 100644
--- a/Branch and Bound/Binary Search Tree/search.js
+++ b/Branch and Bound/Binary Search Tree/search.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th node exists or not
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
@@ -29,6 +31,7 @@ const T = [ // mapping to G as a binary tree , [i][0] indicates left child, [i][
];
const key = Randomize.Integer({ min: 0, max: G.length - 1 }); // item to be searched
+// define tracer variables {
const tracer = new GraphTracer(' Binary Search Tree ');
const logger = new LogTracer(' Log ');
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -36,26 +39,37 @@ tracer.set(G);
tracer.layoutTree(5);
tracer.log(logger);
Tracer.delay();
+// }
function bst(item, node, parent) { // node = current node , parent = previous node
+ // visualize {
tracer.visit(node, parent);
Tracer.delay();
+ // }
if (item === node) { // key found
+ // logger {
logger.println(' Match Found ');
+ // }
} else if (item < node) { // key less than value of current node
if (T[node][0] === -1) {
+ // logger {
logger.println(' Not Found ');
+ // }
} else {
bst(item, T[node][0], node);
}
} else { // key greater than value of current node
if (T[node][1] === -1) {
+ // logger {
logger.println(' Not Found ');
+ // }
} else {
bst(item, T[node][1], node);
}
}
}
+// logger {
logger.println(`Finding number ${key}`);
+// }
bst(key, 5); // node with key 5 is the root
diff --git a/Branch and Bound/Binary Search/iterative.js b/Branch and Bound/Binary Search/iterative.js
index 5bb2d658..3fd3e005 100644
--- a/Branch and Bound/Binary Search/iterative.js
+++ b/Branch and Bound/Binary Search/iterative.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, ChartTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const chart = new ChartTracer();
const tracer = new Array1DTracer();
const logger = new LogTracer();
@@ -8,6 +11,7 @@ const D = Randomize.Array1D({ N: 15, value: () => Randomize.Integer({ min: 0, ma
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
function BinarySearch(array, element) { // array = sorted array, element = element to be found
let minIndex = 0;
@@ -18,6 +22,7 @@ function BinarySearch(array, element) { // array = sorted array, element = eleme
const middleIndex = Math.floor((minIndex + maxIndex) / 2);
testElement = array[middleIndex];
+ // visualize {
tracer.select(minIndex, maxIndex);
Tracer.delay();
tracer.patch(middleIndex);
@@ -25,26 +30,37 @@ function BinarySearch(array, element) { // array = sorted array, element = eleme
Tracer.delay();
tracer.depatch(middleIndex);
tracer.deselect(minIndex, maxIndex);
+ // }
if (testElement < element) {
+ // logger {
logger.println('Going right.');
+ // }
minIndex = middleIndex + 1;
} else if (testElement > element) {
+ // logger {
logger.println('Going left.');
+ // }
maxIndex = middleIndex - 1;
} else {
+ // visualize {
logger.println(`${element} is found at position ${middleIndex}!`);
tracer.select(middleIndex);
+ // }
return middleIndex;
}
}
+ // logger {
logger.println(`${element} is not found!`);
+ // }
return -1;
}
const element = D[Randomize.Integer({ min: 0, max: D.length - 1 })];
+// logger {
logger.println(`Using iterative binary search to find ${element}`);
+// }
BinarySearch(D, element);
diff --git a/Branch and Bound/Binary Search/recursive.js b/Branch and Bound/Binary Search/recursive.js
index 2a20e61d..814e64ac 100644
--- a/Branch and Bound/Binary Search/recursive.js
+++ b/Branch and Bound/Binary Search/recursive.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, ChartTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const chart = new ChartTracer();
const tracer = new Array1DTracer();
const logger = new LogTracer();
@@ -8,16 +11,20 @@ const D = Randomize.Array1D({ N: 15, value: () => Randomize.Integer({ min: 0, ma
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
function BinarySearch(array, element, minIndex, maxIndex) { // array = sorted array, element = element to be found, minIndex = low index, maxIndex = high index
if (minIndex > maxIndex) {
+ // logger {
logger.println(`${element} is not found!`);
+ // }
return -1;
}
const middleIndex = Math.floor((minIndex + maxIndex) / 2);
const testElement = array[middleIndex];
+ // visualize {
tracer.select(minIndex, maxIndex);
Tracer.delay();
tracer.patch(middleIndex);
@@ -25,28 +32,39 @@ function BinarySearch(array, element, minIndex, maxIndex) { // array = sorted ar
Tracer.delay();
tracer.depatch(middleIndex);
tracer.deselect(minIndex, maxIndex);
+ // }
if (testElement < element) {
+ // logger {
logger.println('Going right.');
+ // }
return BinarySearch(array, element, middleIndex + 1, maxIndex);
}
if (testElement > element) {
+ // logger {
logger.println('Going left.');
+ // }
return BinarySearch(array, element, minIndex, middleIndex - 1);
}
if (testElement === element) {
+ // visualize {
logger.println(`${element} is found at position ${middleIndex}!`);
tracer.select(middleIndex);
+ // }
return middleIndex;
}
+ // logger {
logger.println(`${element} is not found!`);
+ // }
return -1;
}
const element = D[Randomize.Integer({ min: 0, max: D.length - 1 })];
+// logger {
logger.println(`Using binary search to find ${element}`);
+// }
BinarySearch(D, element, 0, D.length - 1);
diff --git a/Branch and Bound/Depth-Limited Search/code.js b/Branch and Bound/Depth-Limited Search/code.js
index b4f2530d..21709b93 100644
--- a/Branch and Bound/Depth-Limited Search/code.js
+++ b/Branch and Bound/Depth-Limited Search/code.js
@@ -1,9 +1,7 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new GraphTracer();
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([tracer, logger]));
-tracer.log(logger);
const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th node exists or not
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
@@ -17,15 +15,24 @@ const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
+
+// define tracer variables {
+const tracer = new GraphTracer();
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([tracer, logger]));
+tracer.log(logger);
tracer.set(G);
tracer.layoutTree(0);
Tracer.delay();
+// }
// This is a sample DLS applications where
// we try to find number of descendant of root within some depth
function DLSCount(limit, node, parent) { // node = current node, parent = previous node
+ // visualize {
tracer.visit(node, parent);
Tracer.delay();
+ // }
let child = 0;
if (limit > 0) { // cut off the search
for (let i = 0; i < G[node].length; i++) {
@@ -38,4 +45,6 @@ function DLSCount(limit, node, parent) { // node = current node, parent = previo
return child;
}
+// logger {
logger.println(`Number of descendant is ${DLSCount(2, 0)}`);
+// }
diff --git a/Branch and Bound/Topological Sort/code.js b/Branch and Bound/Topological Sort/code.js
index e55b7124..9f08909b 100644
--- a/Branch and Bound/Topological Sort/code.js
+++ b/Branch and Bound/Topological Sort/code.js
@@ -1,9 +1,7 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new GraphTracer();
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([tracer, logger]));
-tracer.log(logger);
// G[i][j] indicates whether the path from the i-th node to the j-th node exists or not. NOTE: The graph must be Directed-Acyclic
const G = [
[0, 0, 0, 0, 0, 0],
@@ -13,70 +11,108 @@ const G = [
[1, 0, 0, 1, 0, 0],
[1, 1, 0, 0, 0, 0],
];
+
+// define tracer variables {
+const tracer = new GraphTracer();
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([tracer, logger]));
+tracer.log(logger);
tracer.set(G);
Tracer.delay();
+// }
const inDegrees = Array(...Array(G.length)).map(Number.prototype.valueOf, 0); // create an Array of G.length number of 0s
const Q = [];
let iter = 0;
let i;
+// logger {
logger.println('Calculating in-degrees for each Node...');
+// }
+
for (let currNode = 0; currNode < G.length; currNode++) {
for (let currNodeNeighbor = 0; currNodeNeighbor < G.length; currNodeNeighbor++) {
if (G[currNode][currNodeNeighbor]) {
+ // visualize {
logger.println(`${currNodeNeighbor} has an incoming edge from ${currNode}`);
tracer.visit(currNodeNeighbor, currNode);
Tracer.delay();
+ // }
inDegrees[currNodeNeighbor]++;
+ // visualize {
tracer.leave(currNodeNeighbor, currNode);
Tracer.delay();
+ // }
}
}
}
+// logger {
logger.println(`Done. In-Degrees are: [ ${String(inDegrees)} ]`);
logger.println('');
logger.println('Initializing queue with all the sources (nodes with no incoming edges)');
+// }
inDegrees.map((indegrees, node) => {
+ // visualize {
tracer.visit(node);
Tracer.delay();
+ // }
if (!indegrees) {
+ // logger {
logger.println(`${node} is a source`);
+ // }
Q.push(node);
}
+ // visualize {
tracer.leave(node);
Tracer.delay();
+ // }
});
+// logger {
logger.println(`Done. Initial State of Queue: [ ${String(Q)} ]`);
logger.println('');
+// }
// begin topological sort (kahn)
while (Q.length > 0) {
+ // logger {
logger.println(`Iteration #${iter}. Queue state: [ ${String(Q)} ]`);
+ // }
const currNode = Q.shift();
+ // visualize {
tracer.visit(currNode);
Tracer.delay();
+ // }
for (i = 0; i < G.length; i++) {
if (G[currNode][i]) {
+ // visualize {
logger.println(`${i} has an incoming edge from ${currNode}. Decrementing ${i}'s in-degree by 1.`);
tracer.visit(i, currNode);
Tracer.delay();
+ // }
inDegrees[i]--;
+ // visualize {
tracer.leave(i, currNode);
Tracer.delay();
+ // }
if (!inDegrees[i]) {
+ // logger {
logger.println(`${i}'s in-degree is now 0. Enqueuing ${i}`);
+ // }
Q.push(i);
}
}
}
+ // visualize {
tracer.leave(currNode);
Tracer.delay();
+ // }
+ // logger {
logger.println(`In-degrees are: [${String(inDegrees)} ]`);
logger.println('-------------------------------------------------------------------');
-
+ // }
+
iter++;
}
diff --git a/Brute Force/Binary Tree Traversal/inOrder.js b/Brute Force/Binary Tree Traversal/inOrder.js
index 8f8e26b2..1970212f 100644
--- a/Brute Force/Binary Tree Traversal/inOrder.js
+++ b/Brute Force/Binary Tree Traversal/inOrder.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th node exists or not
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
@@ -28,6 +30,7 @@ const T = [ // mapping to G as a binary tree , [i][0] indicates left child, [i][
[9, -1],
];
+// define tracer variables {
const treeTracer = new GraphTracer('Traversal In-order');
const arrayTracer = new Array1DTracer('Print In-order');
const logger = new LogTracer('Log');
@@ -36,24 +39,30 @@ treeTracer.set(G);
treeTracer.layoutTree(5);
arrayTracer.set(new Array(T.length).fill('-'));
Tracer.delay();
+// }
let index = 0;
function inOrder(root, parent) {
if (root === -1) {
+ // logger {
logger.println('No more nodes. Backtracking.');
Tracer.delay();
+ // }
return;
}
+ // visualize {
logger.println(`Reached ${root}`);
treeTracer.visit(root, parent);
Tracer.delay();
logger.println(` Going left from ${root}`);
Tracer.delay();
+ // }
inOrder(T[root][0], root);
+ // visualize {
logger.println(`Printing ${root}`);
treeTracer.leave(root);
arrayTracer.patch(index++, root);
@@ -61,8 +70,11 @@ function inOrder(root, parent) {
logger.println(` Going right from ${root}`);
Tracer.delay();
+ // }
inOrder(T[root][1], root);
}
inOrder(5); // node with key 5 is the root
+// logger {
logger.println('Finished');
+// }
diff --git a/Brute Force/Binary Tree Traversal/postOrder.js b/Brute Force/Binary Tree Traversal/postOrder.js
index e34b9752..c6da428b 100644
--- a/Brute Force/Binary Tree Traversal/postOrder.js
+++ b/Brute Force/Binary Tree Traversal/postOrder.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th node exists or not
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
@@ -28,6 +30,7 @@ const T = [ // mapping to G as a binary tree , [i][0] indicates left child, [i][
[9, -1],
];
+// define tracer variables {
const treeTracer = new GraphTracer('Traversal Post-order');
const arrayTracer = new Array1DTracer('Print Post-order');
const logger = new LogTracer('Log');
@@ -36,33 +39,44 @@ treeTracer.set(G);
treeTracer.layoutTree(5);
arrayTracer.set(new Array(T.length).fill('-'));
Tracer.delay();
+// }
let index = 0;
function postOrder(root, parent) {
if (root === -1) {
+ // logger {
logger.println('No more nodes. Backtracking.');
Tracer.delay();
+ // }
return;
}
+ // visualize {
logger.println(`Reached ${root}`);
treeTracer.visit(root, parent);
Tracer.delay();
logger.println(` Going left from ${root}`);
Tracer.delay();
+ // }
postOrder(T[root][0], root);
+ // logger {
logger.println(` Going right from ${root}`);
Tracer.delay();
+ // }
postOrder(T[root][1], root);
+ // visualize {
logger.println(`Printing ${root}`);
treeTracer.leave(root);
arrayTracer.patch(index++, root);
Tracer.delay();
+ // }
}
postOrder(5); // node with key 5 is the root
+// logger {
logger.println('Finished');
+// visualize {
diff --git a/Brute Force/Binary Tree Traversal/preOrder.js b/Brute Force/Binary Tree Traversal/preOrder.js
index 67c110b2..ccd0f4b5 100644
--- a/Brute Force/Binary Tree Traversal/preOrder.js
+++ b/Brute Force/Binary Tree Traversal/preOrder.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th node exists or not
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
@@ -28,6 +30,7 @@ const T = [ // mapping to G as a binary tree , [i][0] indicates left child, [i][
[9, -1],
];
+// define tracer variables {
const treeTracer = new GraphTracer('Traversal Pre-order');
const arrayTracer = new Array1DTracer('Print Pre-order');
const logger = new LogTracer('Log');
@@ -36,16 +39,20 @@ treeTracer.set(G);
treeTracer.layoutTree(5);
arrayTracer.set(new Array(T.length).fill('-'));
Tracer.delay();
+// }
let index = 0;
function preOrder(root, parent) {
if (root === -1) {
+ // logger {
logger.println('No more nodes. Backtracking.');
Tracer.delay();
+ // }
return;
}
+ // visualize {
logger.println(`Reached ${root}`);
treeTracer.visit(root, parent);
Tracer.delay();
@@ -57,12 +64,17 @@ function preOrder(root, parent) {
logger.println(` Going left from ${root}`);
Tracer.delay();
+ // }
preOrder(T[root][0], root);
+ // logger {
logger.println(` Going right from ${root}`);
Tracer.delay();
+ // }
preOrder(T[root][1], root);
}
preOrder(5); // node with key 5 is the root
+// logger {
logger.println('Finished');
+// }
diff --git a/Brute Force/Bipartiteness Test/code.js b/Brute Force/Bipartiteness Test/code.js
index 3e36f342..62d4e4ec 100644
--- a/Brute Force/Bipartiteness Test/code.js
+++ b/Brute Force/Bipartiteness Test/code.js
@@ -1,8 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
-
-const tracer = new GraphTracer().directed(false);
-const logger = new LogTracer();
-tracer.log(logger);
+// }
const G = [
[0, 1, 0, 1, 1],
@@ -11,11 +9,16 @@ const G = [
[1, 0, 1, 0, 0], // <-- replace latest 0 with 1 to make G not biparted
[1, 0, 0, 0, 0],
];
-tracer.set(G);
+// define tracer variables {
+const tracer = new GraphTracer().directed(false);
+const logger = new LogTracer();
+tracer.log(logger);
+tracer.set(G);
const colorsTracer = new Array1DTracer('Colors');
Layout.setRoot(new VerticalLayout([tracer, logger, colorsTracer]));
Tracer.delay();
+// }
function BFSCheckBipartiteness(s) {
const Q = [];
@@ -23,36 +26,50 @@ function BFSCheckBipartiteness(s) {
// Create a new matrix to set colors (0,1)
const Colors = [];
for (let _i = 0; _i < G.length; _i++) Colors[_i] = -1;
+ // visualize {
colorsTracer.set(Colors);
+ // }
Colors[s] = 1;
+ // visualize {
colorsTracer.patch(s, 1);
+ // }
Q.push(s); // add start node to queue
while (Q.length > 0) {
const node = Q.shift(); // dequeue
+ // visualize {
tracer.visit(node);
Tracer.delay();
+ // }
for (let i = 0; i < G[node].length; i++) {
if (G[node][i]) {
if (Colors[i] === -1) {
Colors[i] = 1 - Colors[node];
+ // visualize {
colorsTracer.patch(i, 1 - Colors[node]);
+ // }
Q.push(i);
+ // visualize {
tracer.visit(i, node);
Tracer.delay();
+ // }
} else if (Colors[i] === Colors[node]) {
+ // logger {
logger.println('Graph is not biparted');
+ // }
return false;
}
}
}
}
+ // logger {
logger.println('Graph is biparted');
+ // }
return true;
}
diff --git a/Brute Force/Breadth-First Search/shortestPath.js b/Brute Force/Breadth-First Search/shortestPath.js
index bee38433..0875ad82 100644
--- a/Brute Force/Breadth-First Search/shortestPath.js
+++ b/Brute Force/Breadth-First Search/shortestPath.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new GraphTracer().directed(false).weighted();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -7,6 +10,7 @@ tracer.log(logger);
const G = Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true });
tracer.set(G);
Tracer.delay();
+// }
function BFS() {
const W = []; // W[i] indicates the length of the shortest path from start node to the i-th node
@@ -14,12 +18,16 @@ function BFS() {
let i;
for (i = 0; i < G.length; i++) {
W.push(MAX_VALUE);
+ // visualize {
tracer.updateNode(i, MAX_VALUE);
+ // }
}
W[s] = 0;
Q.push(s); // add start node to queue
+ // visualize {
tracer.visit(s, undefined, 0);
Tracer.delay();
+ // }
while (Q.length > 0) {
const node = Q.shift(); // dequeue
for (i = 0; i < G[node].length; i++) {
@@ -27,8 +35,10 @@ function BFS() {
if (W[i] > W[node] + G[node][i]) { // if current path is shorter than the previously shortest path
W[i] = W[node] + G[node][i]; // update the length of the shortest path
Q.push(i); // add child node to queue
+ // visualize {
tracer.visit(i, node, W[i]);
Tracer.delay();
+ // }
}
}
}
@@ -42,10 +52,14 @@ do {
e = Randomize.Integer({ min: 0, max: G.length - 1 });
} while (s === e);
let MAX_VALUE = 0x7fffffff;
+// logger {
logger.println(`finding the shortest path from ${s} to ${e}`);
+// }
const minWeight = BFS(s);
+// logger {
if (minWeight === MAX_VALUE) {
logger.println(`there is no path from ${s} to ${e}`);
} else {
logger.println(`the shortest path from ${s} to ${e} is ${minWeight}`);
}
+// }
diff --git a/Brute Force/Breadth-First Search/tree.js b/Brute Force/Breadth-First Search/tree.js
index 598a7dd1..f2c8411b 100644
--- a/Brute Force/Breadth-First Search/tree.js
+++ b/Brute Force/Breadth-First Search/tree.js
@@ -1,9 +1,7 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new GraphTracer();
-const logger = new LogTracer();
-tracer.log(logger);
-Layout.setRoot(new VerticalLayout([tracer, logger]));
const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th node exists or not
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
@@ -17,22 +15,33 @@ const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
+
+// define tracer variables {
+const tracer = new GraphTracer();
+const logger = new LogTracer();
+tracer.log(logger);
+Layout.setRoot(new VerticalLayout([tracer, logger]));
tracer.set(G);
tracer.layoutTree(0);
Tracer.delay();
+// }
function BFS(s) { // s = start node
const Q = [];
Q.push(s); // add start node to queue
+ // visualize {
tracer.visit(s);
Tracer.delay();
+ // }
while (Q.length > 0) {
const node = Q.shift(); // dequeue
for (let i = 0; i < G[node].length; i++) {
if (G[node][i]) { // if current node has the i-th node as a child
Q.push(i); // add child node to queue
+ // visualize {
tracer.visit(i, node);
Tracer.delay();
+ // }
}
}
}
diff --git a/Brute Force/Bridge Finding/efficient.js b/Brute Force/Bridge Finding/efficient.js
index a9c05b83..9864d2b2 100644
--- a/Brute Force/Bridge Finding/efficient.js
+++ b/Brute Force/Bridge Finding/efficient.js
@@ -1,8 +1,7 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const graphTracer = new GraphTracer().directed(false);
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([graphTracer, logger]));
const G = [
[0, 1, 0, 0, 1, 0],
[1, 0, 0, 0, 1, 0],
@@ -12,8 +11,13 @@ const G = [
[0, 0, 0, 1, 0, 0],
];
+// define tracer variables {
+const graphTracer = new GraphTracer().directed(false);
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([graphTracer, logger]));
graphTracer.set(G);
Tracer.delay();
+// }
/*
NOTE: Code assumes NO parallel edges
@@ -29,56 +33,74 @@ const util = (u, disc, low, parent) => {
// disc is the numbering of the vertices in the DFS, starting at 0
// low[v] is the lowest numbered vertex that can be reached from vertex v along the DFS
// parent is the node that u came from
+ // visualize {
logger.println('');
logger.println(`Visiting node ${u}`);
graphTracer.visit(u);
Tracer.delay();
graphTracer.leave(u);
Tracer.delay();
+ // }
// visited [u] = true;
disc[u] = low[u] = timer++;
+ // logger {
logger.println(`Nodes adjacent to ${u} are: [ ${adj[u]} ]`);
+ // }
/* adj [u].forEach (function (v) {
graphTracer.visit (v, u).delay ();
graphTracer.leave (v, u).delay ();
}); */
const trace = (v) => {
+ // visualize {
graphTracer.visit(v, u);
Tracer.delay();
graphTracer.leave(v, u);
Tracer.delay();
+ // }
};
adj[u].forEach((v) => {
if (disc[v] > -1 && v === parent) {
trace(v);
+ // logger {
logger.println(`${u}'s neighbor ${v} is u's parent. Not visiting it.`);
+ // }
} else if (disc[v] > -1 && v !== parent) {
trace(v);
+ // logger {
logger.println(`${u}'s neighbor ${v} is not u's parent. Comparing low[u] with disc[v]`);
+ // }
if (low[u] > disc[v]) {
+ // logger {
logger.println(`low[${u}] is greater than disc[${v}]. Setting low[${u}] to disc[${v}]`);
+ // }
low[u] = disc[v];
}
}
if (disc[v] === -1) {
trace(v);
+ // logger {
logger.println(`${u}'s neighbor ${v} has not been visited yet`);
logger.println(`recursively calling util (${v}, [${disc}], [${low}],${u})`);
+ // }
util(v, disc, low, u);
+ // logger {
logger.println('--------------------------------------------------------------------');
logger.println(`Setting low [${u}] to ${Math.min(low[u], low[v])}`);
+ // }
low[u] = Math.min(low[u], low[v]);
if (low[v] === disc[v]) {
+ // logger {
logger.println(`low [${v}] === disc [${v}], low[${v}]=${low[v]}, disc[${v}]=${disc[v]}`);
logger.println(`${u} -> ${v} is a bridge. Adding ${u}->${v}to the set of bridges found`);
+ // }
bridges.push([u, v]);
}
}
@@ -104,6 +126,7 @@ const util = (u, disc, low, parent) => {
});
}());
+ // logger {
logger.println(`Initializing: disc: ${disc} low: ${low}`);
logger.println('');
logger.println('Beginning efficient Bridge Finding');
@@ -111,17 +134,24 @@ const util = (u, disc, low, parent) => {
logger.println('');
logger.println('Starting the main for loop (for each node)');
+ // }
for (let v = 0; v < graph.length; v++) {
if (disc[v] === -1) {
+ // logger {
logger.println(`${v} has not been visited yet. Calling util (${v}, [${disc}], [${low}],${v}) from the for loop`);
+ // }
util(v, disc, low, v);
+ // logger {
logger.println(`Returned in for loop after util (${v}, [${disc}], [${low}], [${v}])`);
+ // }
}
}
}(G));
+// logger {
logger.println(`There are ${bridges.length} bridges in the Graph`);
for (let i = 0; i < bridges.length; i++) {
logger.println(`${bridges[i][0]}-->${bridges[i][1]}`);
}
logger.println('NOTE: All bridges are both ways (just like in the Naive Algorithm) because the Graph is undirected. So, edge A->B and B->A, both are bridges');
+// }
diff --git a/Brute Force/Bridge Finding/naive.js b/Brute Force/Bridge Finding/naive.js
index c8ab7d14..4dd4233b 100644
--- a/Brute Force/Bridge Finding/naive.js
+++ b/Brute Force/Bridge Finding/naive.js
@@ -1,8 +1,7 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new GraphTracer().directed(false);
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([tracer, logger]));
const G = [
[0, 1, 0, 0, 0, 0],
[1, 0, 0, 1, 1, 0],
@@ -12,8 +11,13 @@ const G = [
[0, 0, 0, 1, 0, 0],
];
+// define tracer variables {
+const tracer = new GraphTracer().directed(false);
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([tracer, logger]));
tracer.set(G);
Tracer.delay();
+// }
// Depth First Search Exploration Algorithm to test connectedness of the Graph (see Graph Algorithms/DFS/exploration), without the tracer & logger commands
function DFSExplore(graph, source) {
@@ -51,11 +55,13 @@ function findBridges(graph) {
for (let i = 0; i < graph.length; i++) {
for (let j = 0; j < graph.length; j++) {
if (graph[i][j]) { // check if an edge exists
+ // visualize {
logger.println(`Deleting edge ${i}->${j} and calling DFSExplore ()`);
tracer.visit(j, i);
Tracer.delay();
tracer.leave(j, i);
Tracer.delay();
+ // }
tempGraph = JSON.parse(JSON.stringify(graph));
tempGraph[i][j] = 0;
@@ -63,9 +69,13 @@ function findBridges(graph) {
visited = DFSExplore(tempGraph, 0);
if (Object.keys(visited).length === graph.length) {
+ // logger {
logger.println('Graph is CONNECTED. Edge is NOT a bridge');
+ // }
} else {
+ // logger {
logger.println('Graph is DISCONNECTED. Edge IS a bridge');
+ // }
bridges.push([i, j]);
}
}
@@ -77,8 +87,10 @@ function findBridges(graph) {
const bridges = findBridges(G);
+// logger {
logger.println('The bridges are: ');
for (const i in bridges) {
logger.println(`${bridges[i][0]} to ${bridges[i][1]}`);
}
logger.println('NOTE: A bridge is both ways, i.e., from A to B and from B to A, because this is an Undirected Graph');
+// }
diff --git a/Brute Force/Bubble Sort/code.js b/Brute Force/Bubble Sort/code.js
index 136f7c97..a69ae686 100644
--- a/Brute Force/Bubble Sort/code.js
+++ b/Brute Force/Bubble Sort/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, ChartTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const chart = new ChartTracer();
const tracer = new Array1DTracer();
const logger = new LogTracer();
@@ -8,32 +11,49 @@ const D = Randomize.Array1D({ N: 15 });
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D.join(', ')}]`);
+// }
let N = D.length;
let swapped;
do {
swapped = false;
+ // visualize {
tracer.select(N - 1);
Tracer.delay();
+ // }
for (let i = 1; i < N; i++) {
+ // visualize {
tracer.select(i);
Tracer.delay();
+ // }
if (D[i - 1] > D[i]) {
+ // logger {
logger.println(`swap ${D[i - 1]} and ${D[i]}`);
+ // }
const temp = D[i - 1];
D[i - 1] = D[i];
D[i] = temp;
swapped = true;
+ // visualize {
tracer.patch(i - 1, D[i - 1]);
tracer.patch(i, D[i]);
Tracer.delay();
tracer.depatch(i - 1);
tracer.depatch(i);
+ // }
}
+ // visualize {
tracer.deselect(i);
+ // }
}
+ // visualize {
tracer.deselect(N - 1);
+ // }
N--;
} while (swapped);
+// logger {
logger.println(`sorted array = [${D.join(', ')}]`);
+// }
diff --git a/Brute Force/Comb Sort/code.js b/Brute Force/Comb Sort/code.js
index fbbdbf89..6d3bc2ae 100644
--- a/Brute Force/Comb Sort/code.js
+++ b/Brute Force/Comb Sort/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, ChartTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const chart = new ChartTracer();
const tracer = new Array1DTracer();
const logger = new LogTracer();
@@ -8,8 +11,11 @@ const D = Randomize.Array1D({ N: 15 });
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D.join(', ')}]`);
+// }
const N = D.length;
let swapped;
let gap = N; // initialize gap size
@@ -26,26 +32,34 @@ do {
swapped = false; // initialize swapped
// a single comb over the input list
for (let i = 0; i + gap < N; i++) {
+ // visualize {
tracer.select(i);
tracer.select(i + gap);
Tracer.delay();
+ // }
if (D[i] > D[i + gap]) {
+ // logger {
logger.println(`swap ${D[i]} and ${D[i + gap]}`); // log swap event
-
+ // }
+
const temp = D[i];
D[i] = D[i + gap];
D[i + gap] = temp;
+ // visualize {
tracer.patch(i, D[i]);
tracer.patch(i + gap, D[i + gap]);
Tracer.delay();
tracer.depatch(i);
tracer.depatch(i + gap);
+ // }
swapped = true; // Flag swapped has happened and list is not guaranteed sorted
}
+ // visualize {
tracer.deselect(i);
tracer.deselect(i + gap);
+ // }
} // End of combing
} while (gap !== 1 || swapped);
diff --git a/Brute Force/Cycle Sort/code.js b/Brute Force/Cycle Sort/code.js
index 8bc185d2..9dac822a 100644
--- a/Brute Force/Cycle Sort/code.js
+++ b/Brute Force/Cycle Sort/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, ChartTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const chart = new ChartTracer();
const tracer = new Array1DTracer();
const logger = new LogTracer();
@@ -8,8 +11,11 @@ const D = Randomize.Array1D({ N: 15 });
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D.join(', ')}]`);
+// }
const N = D.length;
let writes = 0; // number of writing performed
let pos; // the index of item in the sorted array
@@ -20,12 +26,16 @@ for (let cycleStart = 0; cycleStart <= N - 2; cycleStart++) {
// find where to put the item
pos = cycleStart;
+ // visualize {
tracer.select(cycleStart);
+ // }
for (let i = cycleStart + 1; i <= N - 1; i++) {
+ // visualize {
tracer.select(i);
Tracer.delay();
tracer.deselect(i);
+ // }
if (D[i] < item) {
pos++;
}
@@ -33,7 +43,9 @@ for (let cycleStart = 0; cycleStart <= N - 2; cycleStart++) {
// if the item is already there, this is not a circle
if (pos === cycleStart) {
+ // visualize {
tracer.deselect(cycleStart);
+ // }
continue;
}
@@ -49,11 +61,14 @@ for (let cycleStart = 0; cycleStart <= N - 2; cycleStart++) {
writes++;
+ // logger {
if (pos !== cycleStart) {
logger.println(`Rewrite ${D[pos]} to index ${pos}; the next value to rewrite is ${item}`);
} else {
logger.println(`Rewrite ${D[pos]} to index ${pos}`);
}
+ // }
+ // visualize {
tracer.select(pos);
Tracer.delay();
tracer.deselect(pos);
@@ -62,15 +77,18 @@ for (let cycleStart = 0; cycleStart <= N - 2; cycleStart++) {
Tracer.delay();
tracer.depatch(pos);
tracer.depatch(cycleStart);
+ // }
// rotate the rest of the cycle
while (pos !== cycleStart) {
pos = cycleStart;
for (let i = cycleStart + 1; i <= N - 1; i++) {
+ // visualize {
tracer.select(i);
Tracer.delay();
tracer.deselect(i);
+ // }
if (D[i] < item) {
pos++;
}
@@ -84,11 +102,14 @@ for (let cycleStart = 0; cycleStart <= N - 2; cycleStart++) {
D[pos] = item;
item = temp;
+ // logger {
if (pos !== cycleStart) {
logger.println(`Rewrite ${D[pos]} to index ${pos}; the next value to rewrite is ${item}`);
} else {
logger.println(`Rewrite ${D[pos]} to index ${pos}`);
}
+ // }
+ // visualize {
tracer.select(pos);
Tracer.delay();
tracer.deselect(pos);
@@ -97,9 +118,12 @@ for (let cycleStart = 0; cycleStart <= N - 2; cycleStart++) {
Tracer.delay();
tracer.depatch(pos);
tracer.depatch(cycleStart);
+ // }
writes++;
}
}
+// logger {
logger.println(`Number of writes performed is ${writes}`);
+// }
diff --git a/Brute Force/Depth-First Search/graph.js b/Brute Force/Depth-First Search/graph.js
index eb7881de..07660a77 100644
--- a/Brute Force/Depth-First Search/graph.js
+++ b/Brute Force/Depth-First Search/graph.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const graphTracer = new GraphTracer().directed(false);
const visitedTracer = new Array1DTracer('visited');
const logger = new LogTracer();
@@ -8,6 +11,7 @@ graphTracer.log(logger);
const G = Randomize.Graph({ N: 8, ratio: .3, directed: false });
graphTracer.set(G);
Tracer.delay();
+// }
function DFSExplore(graph, source) {
const stack = [[source, null]];
@@ -19,7 +23,9 @@ function DFSExplore(graph, source) {
for (i = 0; i < graph.length; i++) {
visited.push(false);
}
+ // visualize {
visitedTracer.set(visited);
+ // }
while (stack.length > 0) {
temp = stack.pop();
@@ -28,6 +34,7 @@ function DFSExplore(graph, source) {
if (!visited[node]) {
visited[node] = true;
+ // visualize {
visitedTracer.patch(node, visited[node]);
if (prev !== undefined && graph[node][prev]) {
@@ -37,6 +44,7 @@ function DFSExplore(graph, source) {
graphTracer.visit(node);
Tracer.delay();
}
+ // }
for (i = 0; i < graph.length; i++) {
if (graph[node][i]) {
@@ -52,8 +60,10 @@ function DFSExplore(graph, source) {
const visited = DFSExplore(G, 0);
let check = true;
for (let i = 0; i < visited.length; i++) check &= visited[i];
+// logger {
if (check) {
logger.println('The Graph is CONNECTED');
} else {
logger.println('The Graph is NOT CONNECTED');
}
+// }
diff --git a/Brute Force/Depth-First Search/shortestPath.js b/Brute Force/Depth-First Search/shortestPath.js
index 9403fc24..646b865c 100644
--- a/Brute Force/Depth-First Search/shortestPath.js
+++ b/Brute Force/Depth-First Search/shortestPath.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new GraphTracer().directed(false).weighted();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -7,22 +10,29 @@ tracer.log(logger);
const G = Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true });
tracer.set(G);
Tracer.delay();
+// }
function DFS(node, parent, weight) { // node = current node, parent = previous node
if (minWeight < weight) return;
if (node === e) {
+ // visualize {
tracer.visit(node, parent, weight);
Tracer.delay();
+ // }
if (minWeight > weight) {
minWeight = weight;
}
+ // visualize {
tracer.leave(node, parent, minWeight);
Tracer.delay();
+ // }
return;
}
D[node] = true; // label current node as discovered
+ // visualize {
tracer.visit(node, parent, weight);
Tracer.delay();
+ // }
for (let i = 0; i < G[node].length; i++) {
if (G[node][i]) { // if the path from current node to the i-th node exists
if (!D[i]) { // if the i-th node is not labeled as discovered
@@ -31,8 +41,10 @@ function DFS(node, parent, weight) { // node = current node, parent = previous n
}
}
D[node] = false; // label current node as undiscovered
+ // visualize {
tracer.leave(node, parent, 0);
Tracer.delay();
+ // }
}
const s = Randomize.Integer({ min: 0, max: G.length - 1 }); // s = start node
@@ -42,12 +54,16 @@ do {
} while (s === e);
const MAX_VALUE = Infinity;
let minWeight = MAX_VALUE;
+// logger {
logger.println(`finding the shortest path from ${s} to ${e}`);
+// }
let D = []; // D[i] indicates whether the i-th node is discovered or not
for (let i = 0; i < G.length; i++) D.push(false);
DFS(s, undefined, 0);
+// logger {
if (minWeight === MAX_VALUE) {
logger.println(`there is no path from ${s} to ${e}`);
} else {
logger.println(`the shortest path from ${s} to ${e} is ${minWeight}`);
}
+// }
diff --git a/Brute Force/Depth-First Search/tree.js b/Brute Force/Depth-First Search/tree.js
index 4d9a3508..a582c529 100644
--- a/Brute Force/Depth-First Search/tree.js
+++ b/Brute Force/Depth-First Search/tree.js
@@ -1,9 +1,7 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new GraphTracer();
-const logger = new LogTracer();
-tracer.log(logger);
-Layout.setRoot(new VerticalLayout([tracer, logger]));
const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th node exists or not
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
@@ -17,13 +15,22 @@ const G = [ // G[i][j] indicates whether the path from the i-th node to the j-th
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
+
+// define tracer variables {
+const tracer = new GraphTracer();
+const logger = new LogTracer();
+tracer.log(logger);
+Layout.setRoot(new VerticalLayout([tracer, logger]));
tracer.set(G);
tracer.layoutTree(0);
Tracer.delay();
+// }
function DFS(node, parent) { // node = current node, parent = previous node
+ // visualize {/
tracer.visit(node, parent);
Tracer.delay();
+ // }
for (let i = 0; i < G[node].length; i++) {
if (G[node][i]) { // if current node has the i-th node as a child
DFS(i, node); // recursively call DFS
diff --git a/Brute Force/Depth-First Search/weightedGraph.js b/Brute Force/Depth-First Search/weightedGraph.js
index c71549af..b57b1f0b 100644
--- a/Brute Force/Depth-First Search/weightedGraph.js
+++ b/Brute Force/Depth-First Search/weightedGraph.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, GraphTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new GraphTracer().directed(false).weighted();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -7,12 +10,15 @@ tracer.log(logger);
const G = Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true });
tracer.set(G);
Tracer.delay();
+// }
let D; // D[i] indicates whether the i-th node is discovered or not
function DFS(node, parent, weight) { // node = current node, parent = previous node
+ // visualize {
tracer.visit(node, parent, weight);
Tracer.delay();
+ // }
D[node] = true; // label current node as discovered
for (let i = 0; i < G[node].length; i++) {
if (G[node][i]) { // if the edge from current node to the i-th node exists
@@ -22,12 +28,16 @@ function DFS(node, parent, weight) { // node = current node, parent = previous n
}
}
D[node] = false; // label current node as undiscovered
+ // visualize {
tracer.leave(node, parent, 0);
Tracer.delay();
+ // }
}
for (let i = 0; i < G.length; i++) { // start from every node
+ // logger {
logger.println(`start from ${i}`);
+ // }
D = [];
for (let j = 0; j < G.length; j++) D.push(false);
DFS(i, undefined, 0);
diff --git a/Brute Force/Flood Fill/code.js b/Brute Force/Flood Fill/code.js
index f6b17a26..316b5fff 100644
--- a/Brute Force/Flood Fill/code.js
+++ b/Brute Force/Flood Fill/code.js
@@ -1,7 +1,7 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new Array2DTracer();
-Layout.setRoot(new VerticalLayout([tracer]));
const G = [
['#', '#', '#', '#', '#', '#', '#', '#', '#'],
['#', '-', '-', '-', '#', '-', '-', '-', '#'],
@@ -13,8 +13,13 @@ const G = [
['#', '-', '-', '-', '#', '-', '-', '-', '#'],
['#', '#', '#', '#', '#', '#', '#', '#', '#'],
];
+
+// define tracer variables {
+const tracer = new Array2DTracer();
+Layout.setRoot(new VerticalLayout([tracer]));
tracer.set(G);
Tracer.delay();
+// }
function FloodFill(i, j, oldColor, newColor) {
if (i < 0 || i >= G.length || j < 0 || j >= G[i].length) return;
@@ -23,10 +28,12 @@ function FloodFill(i, j, oldColor, newColor) {
// set the color of node to newColor
G[i][j] = newColor;
+ // visualize {
tracer.select(i, j);
Tracer.delay();
tracer.patch(i, j, G[i][j]);
Tracer.delay();
+ // }
// next step four-way
FloodFill(i + 1, j, oldColor, newColor);
diff --git a/Brute Force/Heapsort/code.js b/Brute Force/Heapsort/code.js
index 73832cb8..d0abb120 100644
--- a/Brute Force/Heapsort/code.js
+++ b/Brute Force/Heapsort/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, ChartTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const chart = new ChartTracer();
const tracer = new Array1DTracer();
const logger = new LogTracer();
@@ -8,8 +11,11 @@ const D = Randomize.Array1D({ N: 10 });
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
+// logger {
logger.println(`Original array = [${D.join(', ')}]`);
+// }
function heapSort(array, size) {
let i;
@@ -25,6 +31,7 @@ function heapSort(array, size) {
array[0] = array[j];
array[j] = temp;
+ // visualize {
tracer.patch(0, array[0]);
tracer.patch(j, array[j]);
logger.println(`Swapping elements : ${array[0]} & ${array[j]}`);
@@ -33,10 +40,13 @@ function heapSort(array, size) {
tracer.depatch(j);
tracer.select(j);
Tracer.delay();
+ // }
heapify(array, j, 0);
+ // visualize {
tracer.deselect(j);
+ // }
}
}
@@ -59,12 +69,14 @@ function heapify(array, size, root) {
array[root] = array[largest];
array[largest] = temp;
+ // visualize {
tracer.patch(root, array[root]);
tracer.patch(largest, array[largest]);
logger.println(`Swapping elements : ${array[root]} & ${array[largest]}`);
Tracer.delay();
tracer.depatch(root);
tracer.depatch(largest);
+ // }
heapify(array, size, largest);
}
@@ -72,4 +84,6 @@ function heapify(array, size, root) {
heapSort(D, D.length);
+// logger {
logger.println(`Final array = [${D.join(', ')}]`);
+// }
diff --git a/Dynamic Programming/Knuth-Morris-Pratt's String Search/code.js b/Dynamic Programming/Knuth-Morris-Pratt's String Search/code.js
index ce1788fe..c19230a1 100644
--- a/Dynamic Programming/Knuth-Morris-Pratt's String Search/code.js
+++ b/Dynamic Programming/Knuth-Morris-Pratt's String Search/code.js
@@ -1,155 +1,129 @@
-const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
-
-function randString(length) {
- const result = Math.random().toString(36);
- return result.substring(result.length - length);
-}
-
-const string = randString(15);
-
-const startIndex = Math.floor(Math.random() * 10); // Random start index from 0 to 9
-const substring = string.substr(startIndex, 5); // Substring of `string` of length 5
-
-// let string = 'abcxabcdabxabcdabcdabxabcda', substring = 'xabcda';
-// let string = 'abcxabcdabxabcdabcdabcyiuhsiuhduiahdubhbuuabcdabcysbhbh', substring = 'abcdabcy';
-
-let track = Array(...Array(substring.length)).map(Number.prototype.valueOf, 0);
-
-const trackTracer = new Array1DTracer('Tracker');
-const substrTracer = new Array1DTracer('Substring');
-const stringTracer = new Array1DTracer('Major String');
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([trackTracer, substrTracer, stringTracer, logger]));
-
-trackTracer.set(track);
-substrTracer.set(substring);
-stringTracer.set(string);
-Tracer.delay();
-
-// Fix JS Negative number modulo Bug
-Number.prototype.mod = function (n) {
- return ((this % n) + n) % n;
-};
-
-function tracker(substring) {
- let i = 1;
- let j = 0;
-
- logger.println('Initializing i to 1, j to 0.');
- substrTracer.select(j);
- while (i < track.length) {
- substrTracer.select(i);
- Tracer.delay();
-
- while ((substring[i] !== substring[j]) && (j > 0)) {
- logger.println(`j = ${track[j - 1]}`);
- trackTracer.select(j - 1);
- Tracer.delay();
- trackTracer.deselect(j - 1);
- Tracer.delay();
-
- substrTracer.deselect(j);
- j = track[j - 1];
- logger.println(`j = ${j}`);
- substrTracer.select(j);
- }
-
- if (substring[i] === substring[j]) {
- substrTracer.deselect(j);
- track[i] = ++j;
- trackTracer.patch(i, track[i]);
- Tracer.delay();
- trackTracer.depatch(i);
- Tracer.delay();
- logger.println(`substring [ ${i} ] (${substring[i]}) equals substring [ ${j} ] (${substring[j]}), track [ ${i} ] updated to: ${track[i]}`);
-
- logger.println(`j = ${j}`);
- substrTracer.select(j);
- } else {
- track[i] = 0;
- logger.println(`substring [ ${i} ] (${substring[i]}) is not equal to substring [ ${j} ] (${substring[j]}), setting track [${i}] to 0`);
- trackTracer.select(i);
- Tracer.delay();
- trackTracer.deselect(i);
- Tracer.delay();
+// import visualization libraries {
+const { Tracer, Array1DTracer, Array2DTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+const string = "AAAABAABAAAABAAABAAAA";
+const pattern = "AAAABAAA";
+
+let _next = Array(...Array(pattern.length)).map(Number.prototype.valueOf, 0);
+// define tracer variables {
+const pattern_tracer = new Array2DTracer('Pattern');
+const string_tracer = new Array1DTracer('String');
+Layout.setRoot(new VerticalLayout([pattern_tracer, string_tracer]));
+pattern_tracer.set([_next, pattern, pattern]);
+string_tracer.set(string); Tracer.delay();
+// }
+
+function get_next(pattern)
+{
+ let q = 1; // postfix pointer
+ let k = 0; // prefix pointer
+ // visualize {
+ pattern_tracer.select(2, k);
+ // }
+ for (; q < pattern.length; ++q)
+ {
+ // visualize {
+ pattern_tracer.select(1, q); Tracer.delay();
+ // }
+ while ((k > 0) && (pattern[q] !== pattern[k]))
+ {
+ // visualize {
+ pattern_tracer.select(0, k - 1); Tracer.delay();
+ pattern_tracer.deselect(2, k);
+ pattern_tracer.select(2, _next[k - 1]); Tracer.delay();
+ pattern_tracer.deselect(0, k - 1);
+ // }
+ k = _next[k - 1];
+ }
+ if (pattern[q] === pattern[k])
+ {
+ // visualize {
+ pattern_tracer.deselect(2, k);
+ pattern_tracer.select(2, k + 1); Tracer.delay();
+ // }
+ ++k;
+ }
+ // visualize {
+ pattern_tracer.patch(0, q, k); Tracer.delay();
+ pattern_tracer.depatch(0, q); Tracer.delay();
+ pattern_tracer.deselect(1, q);
+ // }
+ _next[q] = k;
}
-
- substrTracer.deselect(i);
- Tracer.delay();
- i++;
- logger.println(`i = ${i}`);
- }
-
- return track;
+ // visualize {
+ pattern_tracer.deselect(2, k);
+ pattern_tracer.set([_next, pattern]); Tracer.delay();
+ // }
}
-function kmp(string, substr) {
- const positions = [];
- let j = 0;
- let startPos;
-
- logger.println(`Constructing Tracker for substring ${substr}`);
- track = tracker(substr);
- logger.println(`Tracker for substring constructed: [ ${String(track)} ]`);
- logger.println('--------------------------------------------------------------------------');
- logger.println('Running KMP...');
-
- logger.println('Initializing i = 0, j = 0');
- for (let i = 0; i < string.length; i++) {
- logger.println(`comparing string [${i}] (${string[i]}) and substring [${j}] (${substr[j]})...`);
- stringTracer.select(i);
- Tracer.delay();
- stringTracer.select(j);
- Tracer.delay();
-
- if (string[i] === substr[j]) {
- logger.println('they\'re equal!');
-
- if (j === substr.length - 1) {
- logger.println(`j (${j}) equals length of substring - 1 (${substr.length}-1), we've found a new match in the string!`);
- startPos = i - substr.length + 1;
- positions.push(startPos);
-
- logger.println(`Adding start position of the substring (${startPos}) to the results.`);
- stringTracer.select(startPos);
- Tracer.delay();
- } else {
- stringTracer.deselect(j);
- Tracer.delay();
- logger.println(`But j (${j}) does not equal length of substring (${substr.length}) Incrementing j and moving forward.`);
- j++;
- logger.println(`j = ${j}`);
- stringTracer.select(j);
- Tracer.delay();
- }
- } else {
- const tempJ = (j - 1).mod(substr.length);
- logger.println('they\'re NOT equal');
- trackTracer.select(tempJ);
- Tracer.delay();
- stringTracer.deselect(j);
- Tracer.delay();
-
- j = track[tempJ]; // use modulo to wrap around, i.e., if index = -1, access the LAST element of array (PYTHON-LIKE)
-
- logger.println(`Setting j to ${j}`);
- stringTracer.select(j);
- Tracer.delay();
- trackTracer.deselect(tempJ);
- Tracer.delay();
+function KMP(string, pattern)
+{
+ const match_positions = [];
+ let match_start_position;
+
+ let i = 0; // string pointer
+ let k = 0; // pattern pointer
+ get_next(pattern);
+ for (; i < string.length; i++)
+ {
+ // visualize {
+ string_tracer.select(i);
+ pattern_tracer.select(1, k); Tracer.delay();
+ // }
+ while ((k > 0) && (string[i] != pattern[k]))
+ {
+ // visualize {
+ pattern_tracer.select(0, k - 1); Tracer.delay();
+ pattern_tracer.deselect(1, k);
+ pattern_tracer.select(1, _next[k - 1]); Tracer.delay();
+ pattern_tracer.deselect(0, k - 1);
+ // }
+ k = _next[k - 1];
+ }
+ if (string[i] === pattern[k])
+ {
+ ++k;
+ if (k === pattern.length)
+ {
+ match_start_position = i - pattern.length + 1;
+ match_positions.push(match_start_position);
+ // visualize {
+ string_tracer.select(match_start_position, match_start_position + pattern.length - 1); Tracer.delay();
+ string_tracer.deselect(match_start_position, match_start_position + pattern.length - 1); Tracer.delay();
+ pattern_tracer.select(0, k - 1); Tracer.delay();
+ pattern_tracer.deselect(1, k - 1);
+ pattern_tracer.select(1, _next[k - 1]); Tracer.delay();
+ pattern_tracer.deselect(0, k - 1);
+ // }
+ k = _next[k - 1];
+ }
+ else
+ {
+ // visualize {
+ pattern_tracer.deselect(1, k - 1);
+ pattern_tracer.select(1, k); Tracer.delay();
+ // }
+ }
+ }
+ else
+ {
+ // visualize {
+ pattern_tracer.select(0, k); Tracer.delay();
+ // }
+ }
+ // visualize {
+ pattern_tracer.deselect(0, k);
+ pattern_tracer.deselect(1, k);
+ string_tracer.deselect(i);
+ // }
}
-
- stringTracer.deselect(i);
- Tracer.delay();
- }
-
- return positions;
+ // visualize {
+ for (let j = 0; j < match_positions.length; j++)
+ {
+ string_tracer.select(match_positions[j], match_positions[j] + pattern.length - 1); Tracer.delay();
+ string_tracer.deselect(match_positions[j], match_positions[j] + pattern.length - 1);
+ }
+ // }
}
-const positions = kmp(string, substring);
-
-logger.println(`Substring positions are: ${positions.length ? String(positions) : 'NONE'}`);
-for (let i = 0; i < positions.length; i++) {
- stringTracer.select(positions[i], positions[i] + substring.length - 1);
- Tracer.delay();
-}
+KMP(string, pattern);