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/Brute Force/Insertion Sort/code.js b/Brute Force/Insertion Sort/code.js
index 462a66cd..7b3db3d0 100644
--- a/Brute Force/Insertion Sort/code.js
+++ b/Brute Force/Insertion 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,24 +11,35 @@ const D = Randomize.Array1D({ N: 15 });
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D.join(', ')}]`);
+// }
for (let i = 1; i < D.length; i++) {
const key = D[i];
+ // visualize {
logger.println(`insert ${key}`);
tracer.select(i);
Tracer.delay();
+ // }
let j;
for (j = i - 1; (j >= 0) && (D[j] > key); j--) {
D[j + 1] = D[j];
+ // visualize {
tracer.patch(j + 1, D[j + 1]);
Tracer.delay();
tracer.depatch(j + 1);
+ // }
}
D[j + 1] = key;
+ // visualize {
tracer.patch(j + 1, D[j + 1]);
Tracer.delay();
tracer.depatch(j + 1);
tracer.deselect(i);
+ // }
}
+// logger {
logger.println(`sorted array = [${D.join(', ')}]`);
+// }
diff --git a/Brute Force/Lowest Common Ancestor/code.js b/Brute Force/Lowest Common Ancestor/code.js
index 309a4881..b3b8df64 100644
--- a/Brute Force/Lowest Common Ancestor/code.js
+++ b/Brute Force/Lowest Common Ancestor/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, 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,23 +30,31 @@ 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 logger = new LogTracer(' Log ');
Layout.setRoot(new VerticalLayout([treeTracer, logger]));
treeTracer.set(G);
treeTracer.layoutTree(5);
Tracer.delay();
+// }
function lcaBT(parent, root, a, b) {
+ // logger {
logger.println(`Beginning new Iteration of lcaBT () with parent: ${parent}, current root: ${root}`);
+ // }
if (root === -1) {
+ // logger {
logger.println('Reached end of path & target node(s) not found');
+ // }
return null;
}
+ // visualize {
if (parent !== null) treeTracer.visit(root, parent);
else treeTracer.visit(root);
Tracer.delay();
+ // visualize {
if (root === a || root === b) return root;
@@ -53,8 +63,10 @@ function lcaBT(parent, root, a, b) {
if (left !== null && right !== null) return root;
if (left === null && right === null) {
+ // visualize {
treeTracer.leave(root, parent);
Tracer.delay();
+ // }
}
return (left !== null ? left : right);
@@ -62,4 +74,6 @@ function lcaBT(parent, root, a, b) {
const a = 7;
const b = 2;
+// logger {
logger.println(`Lowest common ancestor of ${a} & ${b} is: ${lcaBT(null, 5, a, b)}`);
+// }
diff --git a/Brute Force/PageRank/code.js b/Brute Force/PageRank/code.js
index 69e9c82d..8332c37c 100644
--- a/Brute Force/PageRank/code.js
+++ b/Brute Force/PageRank/code.js
@@ -1,9 +1,12 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, GraphTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
function filledArray(length, value) {
return Array(...Array(length)).map(Number.prototype.valueOf, value);
}
+// define tracer variables {
const G = Randomize.Graph({ N: 5, ratio: .4 });
let ranks;
const outgoingEdgeCounts = filledArray(G.length, 0);
@@ -22,6 +25,7 @@ oecTracer.set(outgoingEdgeCounts);
for (incomingNodes = []; incomingNodes.length < G.length; incomingNodes.push(filledArray(G.length, -1))) ;
inTracer.set(incomingNodes);
Tracer.delay();
+// }
/*
PageRank Algorithm Version 2
@@ -41,40 +45,51 @@ function arraySum(array) {
function showOutgoingEdges(i) {
G[i].forEach((edgeExists, j) => {
if (edgeExists) {
+ // visualize {
graphTracer.visit(j, i);
Tracer.delay();
graphTracer.leave(j, i);
Tracer.delay();
+ // }
}
});
}
// PRECOMPUTATIONS
+// logger {
logger.println('Calculate Outgoing Edge Count for each Node');
+// }
(function calculateOEC() {
G.forEach((relations, i) => {
outgoingEdgeCounts[i] = arraySum(relations);
showOutgoingEdges(i);
+ // visualize {
oecTracer.patch(i, outgoingEdgeCounts[i]);
Tracer.delay();
oecTracer.depatch(i);
Tracer.delay();
+ // }
});
}());
+// logger {
logger.println('determine incoming nodes for each node');
+// }
(function determineIN() {
for (let i = 0; i < G.length; i++) {
for (let j = 0; j < G.length; j++) {
if (G[i][j]) {
// there's an edge FROM i TO j
+ // visualize {
graphTracer.visit(j, i);
Tracer.delay();
+ // }
const nextPos = incomingNodes[j].indexOf(-1);
incomingNodes[j][nextPos] = i;
+ // visualize {
inTracer.patch(j, nextPos, i);
Tracer.delay();
inTracer.depatch(j, nextPos);
@@ -82,6 +97,7 @@ logger.println('determine incoming nodes for each node');
graphTracer.leave(j, i);
Tracer.delay();
+ // }
}
}
}
@@ -96,27 +112,37 @@ function updateRank(nodeIndex) {
let inNodeSummation = 0;
let result;
+ // logger {
logger.println(`Updating rank of ${nodeIndex}`);
logger.println(`The incoming Nodes of ${nodeIndex} are being highlighted`);
+ // }
incomingNodes[nodeIndex].forEach((incoming, i) => {
+ // visualize {
inTracer.select(nodeIndex, i);
Tracer.delay();
logger.println(`Outgoing edge count of ${incoming} is ${outgoingEdgeCounts[incoming]}`);
oecTracer.select(incoming);
Tracer.delay();
+ // }
inNodeSummation += (ranks[incoming] / outgoingEdgeCounts[incoming]);
+ // visualize {
oecTracer.deselect(incoming);
Tracer.delay();
inTracer.deselect(nodeIndex, i);
Tracer.delay();
+ // }
});
+ // logger {
logger.println(`In-Node summation of ${nodeIndex} = ${inNodeSummation}`);
-
+ // }
+
result = ((1 - damping) / G.length) + (damping * inNodeSummation); // notice the subtle difference between equations of Basic PR & PR version 2 (divide by N)
+ // logger {
logger.println(`Therefore, using Equation, new rank of ${nodeIndex} = ${result}`);
+ // }
return result;
}
@@ -124,27 +150,37 @@ let damping = 0.85;
let iterations = 7;
const initialRank = 1.0;
+// logger {
logger.println(`Initialized all Page ranks to ${initialRank}`);
+// }
ranks = filledArray(G.length, initialRank);
+// visualize {
rankTracer.set(ranks);
+// }
+// logger {
logger.println('Begin execution of PageRank Version #1');
logger.println('Equation used: PR (X) = (1 - D) + D (In-Node-Summation i->X (PR (I) / Out (i)))');
logger.println('D = Damping Factor, PR (X) = Page rank of Node X, i = the ith In-Node of X, Out (i) = outgoing Edge Count of i');
logger.println('');
+// }
while (iterations--) {
for (let node = 0; node < ranks.length; node++) {
ranks[node] = updateRank(node);
+ // visualize {
rankTracer.patch(node, ranks[node]);
Tracer.delay();
rankTracer.patch(node);
Tracer.delay();
+ // }
}
}
+// logger {
logger.println('Page Ranks have been converged to.');
ranks.forEach((rank, node) => {
logger.println(`Rank of Node #${node} = ${rank}`);
});
logger.println('Done');
+// }
diff --git a/Brute Force/Pancake Sort/code.js b/Brute Force/Pancake Sort/code.js
index f520a64a..4e066872 100644
--- a/Brute Force/Pancake Sort/code.js
+++ b/Brute Force/Pancake 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,43 +11,63 @@ const D = Randomize.Array1D({ N: 10 });
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D.join(', ')}]`);
+// }
const N = D.length;
function flip(start) {
+ // visualize {
tracer.select(start, N - 1);
Tracer.delay();
+ // }
let idx = 0;
for (let i = start; i < (start + N) / 2; i++) {
+ // visualize {
tracer.select(i);
Tracer.delay();
+ // }
const temp = D[i];
D[i] = D[N - idx - 1];
D[N - idx - 1] = temp;
+ // visualize {
tracer.patch(i, D[i]);
tracer.patch(N - idx - 1, D[N - idx - 1]);
Tracer.delay();
tracer.depatch(i);
tracer.depatch(N - idx - 1);
tracer.deselect(i);
+ // }
idx++;
}
+ // visualize {
tracer.deselect(start, N - 1);
+ // }
}
for (let i = 0; i < N - 1; i++) {
+ // logger {
logger.println(`round ${i + 1}`);
+ // }
const currArr = D.slice(i, N);
const currMax = currArr.reduce((prev, curr, idx) => ((curr > prev.val) ? { idx, val: curr } : prev), {
idx: 0,
val: currArr[0],
});
if (currMax.idx !== 0) { // if currMax.idx === 0 that means max element already at the bottom, no flip required
+ // logger {
logger.println(`flip at ${currMax.idx + i} (step 1)`);
+ // }
flip(currMax.idx + i, N);
+ // logger {
logger.println(`flip at ${i} (step 2)`);
+ // }
flip(i, N);
}
}
+
+// logger {
logger.println(`sorted array = [${D.join(', ')}]`);
+// }
diff --git a/Brute Force/Rabin-Karp's String Search/code.js b/Brute Force/Rabin-Karp's String Search/code.js
index 7ede6390..ef9d1e58 100644
--- a/Brute Force/Rabin-Karp's String Search/code.js
+++ b/Brute Force/Rabin-Karp's String Search/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const text = ['h', 'e', 'l', 'l', 'o', ' ', 's', 'i', 'r', ' ', 'h', 'e', 'l', 'l', 'o'];
const pattern = ['h', 'e', 'l', 'l', 'o'];
@@ -6,6 +8,7 @@ const pattern = ['h', 'e', 'l', 'l', 'o'];
const Q = 101; // A prime number
const D = 256; // number of characters in the input alphabet
+// define tracer variables {
const logger = new LogTracer();
const tracer1 = new Array1DTracer('Text');
const tracer2 = new Array1DTracer('Pattern');
@@ -13,6 +16,7 @@ Layout.setRoot(new VerticalLayout([logger, tracer1, tracer2]));
tracer1.set(text);
tracer2.set(pattern);
Tracer.delay();
+// }
const N = text.length;
const M = pattern.length;
@@ -38,27 +42,35 @@ for (let i = 0; i <= N - M; i++) {
*/
if (hashPattern === hashText) {
let f = 0;
+ // visualize {
tracer1.select(i, i + M - 1);
Tracer.delay();
tracer2.select(0, M - 1);
Tracer.delay();
+ // }
for (let j = 0; j < M; j++) {
+ // visualize {
tracer1.patch(i + j);
Tracer.delay();
tracer2.patch(j);
Tracer.delay();
+ // }
if (text[i + j] !== pattern[j]) {
f++;
}
+ // visualize {
tracer1.depatch(i + j);
tracer2.depatch(j);
+ // }
}
+ // visualize {
if (f === 0) {
logger.println(` Pattern found at index ${i}`);
}
tracer1.deselect(i, i + M);
tracer2.deselect(0, M - 1);
+ // }
}
/*
diff --git a/Brute Force/Selection Sort/code.js b/Brute Force/Selection Sort/code.js
index d7316338..41af8a11 100644
--- a/Brute Force/Selection Sort/code.js
+++ b/Brute Force/Selection 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,34 +11,53 @@ const D = Randomize.Array1D({ N: 15 });
tracer.set(D);
tracer.chart(chart);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D.join(', ')}]`);
+// }
for (let i = 0; i < D.length - 1; i++) {
let minJ = i;
+ // visualize {
tracer.select(i);
Tracer.delay();
+ // }
for (let j = i + 1; j < D.length; j++) {
+ // visualize {
tracer.select(j);
Tracer.delay();
+ // }
if (D[j] < D[minJ]) {
minJ = j;
+ // visualize {
tracer.patch(j);
Tracer.delay();
tracer.depatch(j);
+ // }
}
+ // visualize {
tracer.deselect(j);
+ // }
}
if (minJ !== i) {
+ // logger {
logger.println(`swap ${D[i]} and ${D[minJ]}`);
+ // }
const temp = D[i];
D[i] = D[minJ];
D[minJ] = temp;
+ // visualize {
tracer.patch(i, D[i]);
tracer.patch(minJ, D[minJ]);
Tracer.delay();
tracer.depatch(i);
tracer.depatch(minJ);
+ // }
}
+ // visualize {
tracer.deselect(i);
+ // }
}
+// logger {
logger.println(`sorted array = [${D.join(', ')}]`);
+// }
diff --git a/Brute Force/Shellsort/code.js b/Brute Force/Shellsort/code.js
index d13739be..333ad2ce 100644
--- a/Brute Force/Shellsort/code.js
+++ b/Brute Force/Shellsort/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,29 +11,43 @@ 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;
for (let gap = N; gap = parseInt(gap / 2);) {
+ // logger {
logger.println('');
logger.println(`Gap of ${gap}`);
+ // }
for (let i = gap; i < N; i++) {
+ // visualize {
tracer.select(i);
tracer.select(i - gap);
Tracer.delay();
+ // }
const k = D[i];
+ // logger {
logger.println(`Holding: ${k}`);
+ // }
let j;
for (j = i; j >= gap && k < D[j - gap]; j -= gap) {
+ // logger {
logger.println(`${k} < ${D[j - gap]}`);
+ // }
D[j] = D[j - gap];
+ // visualize {
tracer.patch(j, D[j]);
Tracer.delay();
tracer.depatch(j);
+ // }
}
const old = D[j];
D[j] = k;
+ // visualize {
if (old !== k) {
tracer.patch(j, D[j]);
Tracer.delay();
@@ -40,7 +57,10 @@ for (let gap = N; gap = parseInt(gap / 2);) {
tracer.deselect(i);
tracer.deselect(i - gap);
+ // }
}
}
+// logger {
logger.println('');
logger.println(`Sorted array = [${D.join(', ')}]`);
+// }
diff --git a/Brute Force/Tarjan's Strongly Connected Components/code.js b/Brute Force/Tarjan's Strongly Connected Components/code.js
index 0bcc0c63..415c5838 100644
--- a/Brute Force/Tarjan's Strongly Connected Components/code.js
+++ b/Brute Force/Tarjan's Strongly Connected Components/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const G = [
[0, 0, 1, 1, 0, 0],
@@ -9,16 +11,6 @@ const G = [
[0, 0, 0, 0, 1, 0],
];
-const graphTracer = new GraphTracer();
-graphTracer.set(G);
-
-const discTracer = new Array1DTracer('Disc');
-const lowTracer = new Array1DTracer('Low');
-const stackMemberTracer = new Array1DTracer('stackMember');
-const stTracer = new Array1DTracer('st');
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([graphTracer, discTracer, lowTracer, stackMemberTracer, stTracer, logger]));
-
const disc = new Array(G.length);
const low = new Array(G.length);
const stackMember = new Array(G.length);
@@ -31,31 +23,51 @@ for (let i = 0; i < G.length; i++) {
stackMember[i] = false;
}
+// define tracer variables {
+const graphTracer = new GraphTracer();
+graphTracer.set(G);
+const discTracer = new Array1DTracer('Disc');
+const lowTracer = new Array1DTracer('Low');
+const stackMemberTracer = new Array1DTracer('stackMember');
+const stTracer = new Array1DTracer('st');
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([graphTracer, discTracer, lowTracer, stackMemberTracer, stTracer, logger]));
discTracer.set(disc);
lowTracer.set(low);
stackMemberTracer.set(stackMember);
stTracer.set(st);
Tracer.delay();
+// }
function SCCVertex(u, disc, low, st, stackMember, carry) {
+ // visualize {
graphTracer.visit(u);
Tracer.delay();
+ // }
disc[u] = ++carry.time;
+ // visualize {
discTracer.patch(u, carry.time);
Tracer.delay();
+ // }
low[u] = carry.time;
+ // visualize {
lowTracer.patch(u, carry.time);
Tracer.delay();
+ // }
st.push(u);
+ // visualize {
stTracer.set(st);
Tracer.delay();
+ // }
stackMember[u] = true;
+ // visualize {
stackMemberTracer.patch(u, true);
Tracer.delay();
+ // }
// Go through all vertices adjacent to this
for (let v = 0; v < G[u].length; v++) {
@@ -67,15 +79,20 @@ function SCCVertex(u, disc, low, st, stackMember, carry) {
// Check if the subtree rooted with 'v' has a
// connection to one of the ancestors of 'u'
low[u] = Math.min(low[u], low[v]);
+ // visualize {
lowTracer.patch(u, low[u]);
+ Tracer.delay();
+ // }
}
// Update low value of 'u' only of 'v' is still in stack
// (i.e. it's a back edge, not cross edge).
else if (stackMember[v] === true) {
low[u] = Math.min(low[u], disc[v]);
+ // visualize {
lowTracer.patch(u, low[u]);
Tracer.delay();
+ // }
}
}
}
@@ -85,28 +102,36 @@ function SCCVertex(u, disc, low, st, stackMember, carry) {
if (low[u] === disc[u]) {
while (st[st.length - 1] !== u) {
w = st.pop();
+ // visualize {
stTracer.set(st);
Tracer.delay();
logger.println(w);
Tracer.delay();
+ // }
stackMember[w] = false;
+ // visualize {
stackMemberTracer.patch(w, false);
Tracer.delay();
+ // }
}
w = st.pop();
+ // visualize {
stTracer.set(st);
Tracer.delay();
logger.println(w);
Tracer.delay();
logger.println('------');
+ // }
stackMember[w] = false;
+ // visualize {
stackMemberTracer.patch(w, false);
Tracer.delay();
+ // }
}
}
diff --git a/Divide and Conquer/Merge Sort/bottomUp.js b/Divide and Conquer/Merge Sort/bottomUp.js
index 195e8f47..e3200fed 100644
--- a/Divide and Conquer/Merge Sort/bottomUp.js
+++ b/Divide and Conquer/Merge Sort/bottomUp.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new Array2DTracer();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -10,8 +13,11 @@ const D = [
tracer.set(D);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D[0].join(', ')}]`);
+// }
function mergeSort(start, end) {
if (Math.abs(end - start) <= 1) return;
@@ -21,7 +27,7 @@ function mergeSort(start, end) {
let width;
let i;
for (width = 1; width < end; width *= 2) {
- // visualization {
+ // visualize {
logger.println(`merging arrays of width: ${width}`);
// }
for (i = 0; i < end; i += 2 * width) {
@@ -34,7 +40,7 @@ function mergeSort(start, end) {
mergeTo = 1 - mergeFrom;
}
if (mergeFrom !== 0) {
- // visualization {
+ // visualize {
logger.println('final copy to original');
// }
copy(mergeFrom, mergeTo, start, end);
@@ -47,7 +53,7 @@ function merge(mergeFrom, start, middle, end, mergeTo) {
let k;
// in an actual merge implementation, mergeFrom and mergeTo would be arrays
// here for the ability to trace what is going on better, the arrays are D[mergeFrom] and D[mergeTo]
- // visualization {
+ // visualize {
logger.println(`merging segments [${start}..${middle}] and [${middle}..${end}]`);
tracer.selectRow(mergeFrom, start, end - 1);
Tracer.delay();
@@ -55,7 +61,7 @@ function merge(mergeFrom, start, middle, end, mergeTo) {
// }
for (k = start; k < end; k++) {
- // visualization {
+ // visualize {
if (j < end) {
tracer.select(mergeFrom, j);
}
@@ -69,7 +75,7 @@ function merge(mergeFrom, start, middle, end, mergeTo) {
// }
if (i < middle && (j >= end || D[mergeFrom][i] <= D[mergeFrom][j])) {
- // visualization {
+ // visualize {
if (j < end) {
logger.println('writing smaller value to output');
} else {
@@ -84,7 +90,7 @@ function merge(mergeFrom, start, middle, end, mergeTo) {
D[mergeTo][k] = D[mergeFrom][i];
i += 1;
} else {
- // visualization {
+ // visualize {
if (i < middle) {
logger.println('writing smaller value to output');
} else {
@@ -105,7 +111,7 @@ function merge(mergeFrom, start, middle, end, mergeTo) {
function copy(mergeFrom, mergeTo, start, end) {
let i;
for (i = start; i < end; i++) {
- // visualization {
+ // visualize {
tracer.select(mergeFrom, i);
tracer.patch(mergeTo, i, D[mergeFrom][i]);
Tracer.delay();
@@ -113,7 +119,7 @@ function copy(mergeFrom, mergeTo, start, end) {
D[mergeTo][i] = D[mergeFrom][i];
- // visualization {
+ // visualize {
tracer.deselect(mergeFrom, i);
tracer.depatch(mergeTo, i);
// }
@@ -121,4 +127,6 @@ function copy(mergeFrom, mergeTo, start, end) {
}
mergeSort(0, D[0].length);
+// logger {
logger.println(`sorted array = [${D[0].join(', ')}]`);
+// }
diff --git a/Divide and Conquer/Merge Sort/topDown.js b/Divide and Conquer/Merge Sort/topDown.js
index eac4f824..9ad9b208 100644
--- a/Divide and Conquer/Merge Sort/topDown.js
+++ b/Divide and Conquer/Merge Sort/topDown.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(', ')}]`);
+// }
function mergeSort(start, end) {
if (Math.abs(end - start) <= 1) return [];
@@ -18,7 +24,9 @@ function mergeSort(start, end) {
mergeSort(start, middle);
mergeSort(middle, end);
+ // logger {
logger.println(`divide left[${start}, ${middle - 1}], right[${middle}, ${end - 1}]`);
+ // }
return mergeSort.merge(start, middle, end);
}
@@ -34,48 +42,68 @@ mergeSort.merge = (start, middle, end) => {
for (i = 0; i < maxSize; i++) {
if (i < leftSize) {
left.push(D[start + i]);
+ // visualize {
tracer.select(start + i);
logger.println(`insert value into left array[${i}] = ${D[start + i]}`);
Tracer.delay();
+ // }
}
if (i < rightSize) {
right.push(D[middle + i]);
+ // visualize {
tracer.select(middle + i);
logger.println(`insert value into right array[${i}] = ${D[middle + i]}`);
Tracer.delay();
+ // }
}
}
+ // logger {
logger.println(`left array = [${left.join(', ')}], ` + `right array = [${right.join(', ')}]`);
+ // }
i = 0;
while (i < size) {
if (left[0] && right[0]) {
if (left[0] > right[0]) {
D[start + i] = right.shift();
+ // logger {
logger.println(`rewrite from right array[${i}] = ${D[start + i]}`);
+ // }
} else {
D[start + i] = left.shift();
+ // logger {
logger.println(`rewrite from left array[${i}] = ${D[start + i]}`);
+ // }
}
} else if (left[0]) {
D[start + i] = left.shift();
+ // logger {
logger.println(`rewrite from left array[${i}] = ${D[start + i]}`);
+ // }
} else {
D[start + i] = right.shift();
+ // logger {
logger.println(`rewrite from right array[${i}] = ${D[start + i]}`);
+ // }
}
+ // visualize {
tracer.deselect(start + i);
tracer.patch(start + i, D[start + i]);
Tracer.delay();
tracer.depatch(start + i);
+ // }
i++;
}
const tempArray = [];
for (i = start; i < end; i++) tempArray.push(D[i]);
+ // logger {
logger.println(`merged array = [${tempArray.join(', ')}]`);
+ // }
};
mergeSort(0, D.length);
+// logger {
logger.println(`sorted array = [${D.join(', ')}]`);
+// }
diff --git a/Divide and Conquer/Pigeonhole Sort/code.js b/Divide and Conquer/Pigeonhole Sort/code.js
index 27923636..4617cdaf 100644
--- a/Divide and Conquer/Pigeonhole Sort/code.js
+++ b/Divide and Conquer/Pigeonhole Sort/code.js
@@ -1,14 +1,18 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const A = Randomize.Array1D({ N: 7 });
const N = A.length;
+// define tracer variables {
const tracer1 = new Array1DTracer('Array');
const tracer2 = new Array2DTracer('Holes');
const logTracer = new LogTracer('Console');
Layout.setRoot(new VerticalLayout([tracer1, tracer2, logTracer]));
tracer1.set(A);
Tracer.delay();
+// }
let min = A[0];
let max = A[0];
@@ -27,31 +31,47 @@ const holes = new Array(range);
for (let i = 0; i < range; i++) {
holes[i] = [];
}
+// visualize {
tracer2.set(holes);
+// }
+// logger {
logTracer.println('Filling up holes');
+// }
for (let i = 0; i < N; i++) {
+ // visualize {
tracer1.select(i);
Tracer.delay();
+ // }
holes[A[i] - min].push(A[i]);
+ // visualize {
tracer2.set(holes);
tracer1.deselect(i);
+ // }
}
+// logger {
logTracer.println('Building sorted array');
+// }
let k = 0;
for (let i = 0; i < range; i++) {
for (let j = 0; j < holes[i].length; j++) {
+ // visualize {
tracer2.select(i, j);
Tracer.delay();
+ // }
A[k++] = holes[i][j];
+ // visualize {
tracer1.patch(k - 1, A[k - 1]);
Tracer.delay();
tracer2.deselect(i, j);
tracer1.depatch(k - 1);
+ // }
}
}
+// logger {
logTracer.println(`Sorted array is ${A}`);
+// }
diff --git a/Divide and Conquer/Quicksort/code.js b/Divide and Conquer/Quicksort/code.js
index 0cd46345..4eb5373b 100644
--- a/Divide and Conquer/Quicksort/code.js
+++ b/Divide and Conquer/Quicksort/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(', ')}]`);
+// }
function partition(D, low, high) {
let i;
@@ -20,36 +26,48 @@ function partition(D, low, high) {
j = high;
s = D[low];
while (i < j) {
+ // visualize {
tracer.select(high);
tracer.select(low);
Tracer.delay();
+ // }
while (D[j] > s) {
+ // visualize {
tracer.select(j);
Tracer.delay();
tracer.deselect(j);
+ // }
j--;
}
D[i] = D[j];
+ // visualize {
tracer.patch(i, D[j]);
Tracer.delay();
tracer.depatch(i);
+ // }
while (s >= D[i] && i < j) {
+ // visualize {
tracer.select(i);
Tracer.delay();
tracer.deselect(i);
+ // }
i++;
}
D[j] = D[i];
+ // visualize {
tracer.patch(j, D[i]);
Tracer.delay();
tracer.depatch(j);
tracer.deselect(high);
tracer.deselect(low);
+ // }
}
D[i] = s;
+ // visualize {
tracer.patch(i, s);
Tracer.delay();
tracer.depatch(i);
+ // }
partition(D, low, i - 1);
low = i + 1;
}
@@ -60,4 +78,6 @@ function quicksort(D) {
}
quicksort(D);
+// logger {
logger.println(`sorted array = [${D.join(', ')}]`);
+// }
diff --git a/Divide and Conquer/Radix Sort/leastSignificantDigit.js b/Divide and Conquer/Radix Sort/leastSignificantDigit.js
index 7a7c21d1..1d0d3ea6 100644
--- a/Divide and Conquer/Radix Sort/leastSignificantDigit.js
+++ b/Divide and Conquer/Radix Sort/leastSignificantDigit.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new Array2DTracer();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -11,8 +14,11 @@ const D = [
];
tracer.set(D);
Tracer.delay();
+// }
+// logger {
logger.println(`original array = [${D[0].join(', ')}]`);
+// }
function pow(base, expo) {
let ans = 1;
@@ -27,55 +33,79 @@ function digit(i, exp) {
}
for (let exp = 0; exp < 3; exp++) {
+ // logger {
logger.println(`Digit: ${exp}`);
+ // }
let i;
for (i = 0; i < D[0].length; i++) {
const d = digit(i, exp);
+ // visualize {
tracer.select(0, i);
Tracer.delay();
+ // }
D[2][d] += 1;
+ // visualize {
tracer.patch(2, d, D[2][d]);
Tracer.delay();
tracer.depatch(2, d);
tracer.deselect(0, i);
+ // }
}
for (i = 1; i < 10; i++) {
+ // visualize {
tracer.select(2, i - 1);
Tracer.delay();
+ // }
D[2][i] += D[2][i - 1];
+ // visualize {
tracer.patch(2, i, D[2][i]);
Tracer.delay();
tracer.depatch(2, i);
tracer.deselect(2, i - 1);
+ // }
}
for (i = D[0].length - 1; i >= 0; i--) {
const d = digit(i, exp);
+ // visualize {
tracer.select(0, i);
Tracer.delay();
+ // }
D[2][d] -= 1;
+ // visualize {
tracer.patch(2, d, D[2][d]);
Tracer.delay();
tracer.depatch(2, d);
+ // }
D[1][D[2][d]] = D[0][i];
+ // visualize {
tracer.patch(1, D[2][d], D[1][D[2][d]]);
Tracer.delay();
tracer.depatch(1, D[2][d]);
tracer.deselect(0, i);
+ // }
}
for (i = 0; i < D[0].length; i++) {
+ // visualize {
tracer.select(1, i);
Tracer.delay();
+ // }
D[0][i] = D[1][i];
+ // visualize {
tracer.patch(0, i, D[0][i]);
Tracer.delay();
tracer.depatch(0, i);
tracer.deselect(1, i);
+ // }
}
for (i = 0; i < 10; i++) {
D[2][i] = 0;
+ // visualize {
tracer.patch(2, i, D[2][i]);
Tracer.delay();
tracer.depatch(2, i);
+ // }
}
}
+// logger {
logger.println(`sorted array = [${D[0].join(', ')}]`);
+// }
diff --git a/Dynamic Programming/Bellman-Ford's Shortest Path/code.js b/Dynamic Programming/Bellman-Ford's Shortest Path/code.js
index 2bd0925c..69cae5bb 100644
--- a/Dynamic Programming/Bellman-Ford's Shortest Path/code.js
+++ b/Dynamic Programming/Bellman-Ford's Shortest Path/code.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().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: .5, value: () => Randomize.Integer({ min: -2, max: 5 }), weighted: true });
tracer.set(G);
Tracer.delay();
+// }
function BELLMAN_FORD(src, dest) {
const weights = new Array(G.length);
@@ -15,37 +19,51 @@ function BELLMAN_FORD(src, dest) {
for (i = 0; i < G.length; i++) {
weights[i] = MAX_VALUE;
+ // visualize {
tracer.updateNode(i, weights[i]);
+ // }
}
weights[src] = 0;
+ // visualize {
tracer.updateNode(src, 0);
+ // }
+ // logger {
logger.println(`Initializing weights to: [${weights}]`);
logger.println('');
+ // }
// begin BF algorithm execution
let k = G.length;
while (k--) {
+ // logger {
logger.println(`Iteration: ${G.length - k}`);
logger.println('------------------------------------------------------------------');
+ // }
for (i = 0; i < G.length; i++) {
for (j = 0; j < G.length; j++) {
if (G[i][j]) { // proceed to relax Edges only if a particular weight !== 0 (0 represents no edge)
if (weights[j] > (weights[i] + G[i][j])) {
weights[j] = weights[i] + G[i][j];
+ // logger {
logger.println(`weights[${j}] = weights[${i}] + ${G[i][j]}`);
+ // }
}
+ // visualize {
tracer.visit(j, i, weights[j]);
Tracer.delay();
tracer.leave(j, i);
Tracer.delay();
+ // }
}
}
}
+ // logger {
logger.println(`updated weights: [${weights.join(', ')}]`);
logger.println('');
+ // }
}
// check for cycle
@@ -54,14 +72,18 @@ function BELLMAN_FORD(src, dest) {
for (j = 0; j < G.length; j++) {
if (G[i][j]) {
if (weights[j] > (weights[i] + G[i][j])) {
+ // logger {
logger.println(`A cycle was detected: weights[${j}] > weights[${i}] + ${G[i][j]}`);
+ // }
return (MAX_VALUE);
}
}
}
}
+ // logger {
logger.println(`No cycles detected. Final weights for the source ${src} are: [${weights}]`);
+ // }
return weights[dest];
}
@@ -81,12 +103,16 @@ do {
}
while (src === dest);
+// logger {
logger.println(`finding the shortest path from ${src} to ${dest}`);
+// }
minWeight = BELLMAN_FORD(src, dest);
+// logger {
if (minWeight === MAX_VALUE) {
logger.println(`there is no path from ${src} to ${dest}`);
} else {
logger.println(`the shortest path from ${src} to ${dest} is ${minWeight}`);
}
+// }
diff --git a/Dynamic Programming/Catalan Number/code.js b/Dynamic Programming/Catalan Number/code.js
index 74c520cd..f9b4830c 100644
--- a/Dynamic Programming/Catalan Number/code.js
+++ b/Dynamic Programming/Catalan Number/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const N = 10;
const A = new Array(N + 1);
@@ -6,24 +8,31 @@ for (let i = N; i >= 0; i--) {
A[i] = 0;
}
+// define tracer variables {
const tracer = new Array1DTracer(' Catalan Numbers ');
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
tracer.set(A);
Tracer.delay();
+// }
A[0] = 1;
+// visualize {
tracer.patch(0, A[0]);
Tracer.delay();
tracer.depatch(0);
+// }
A[1] = 1;
+// visualize {
tracer.patch(1, A[1]);
Tracer.delay();
tracer.depatch(1);
+// }
for (let i = 2; i <= N; i++) {
for (let j = 0; j < i; j++) {
A[i] += A[j] * A[i - j - 1];
+ // visualize {
tracer.select(j);
Tracer.delay();
tracer.select(i - j - 1);
@@ -33,9 +42,12 @@ for (let i = 2; i <= N; i++) {
tracer.deselect(j);
tracer.deselect(i - j - 1);
tracer.depatch(i);
+ // }
}
}
+// visualize {
logger.println(` The ${N}th Catalan Number is ${A[N]}`);
tracer.select(N);
Tracer.delay();
+// }
diff --git a/Dynamic Programming/Fibonacci Sequence/code.js b/Dynamic Programming/Fibonacci Sequence/code.js
index 66910bf6..3f10a27b 100644
--- a/Dynamic Programming/Fibonacci Sequence/code.js
+++ b/Dynamic Programming/Fibonacci Sequence/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new Array1DTracer('Sequence');
Layout.setRoot(new VerticalLayout([tracer]));
const index = 15;
@@ -9,13 +12,16 @@ for (let i = 2; i < index; i++) {
}
tracer.set(D);
Tracer.delay();
+// }
for (let i = 2; i < index; i++) {
D[i] = D[i - 2] + D[i - 1];
+ // visualize {
tracer.select(i - 2, i - 1);
Tracer.delay();
tracer.patch(i, D[i]);
Tracer.delay();
tracer.depatch(i);
tracer.deselect(i - 2, i - 1);
+ // }
}
diff --git a/Dynamic Programming/Floyd-Warshall's Shortest Path/code.js b/Dynamic Programming/Floyd-Warshall's Shortest Path/code.js
index 5c8dd7e7..e526c293 100644
--- a/Dynamic Programming/Floyd-Warshall's Shortest Path/code.js
+++ b/Dynamic Programming/Floyd-Warshall's Shortest Path/code.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().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, weighted: true });
tracer.set(G);
Tracer.delay();
+// }
function FloydWarshall() {
// Finds the shortest path between all nodes
@@ -27,32 +31,48 @@ function FloydWarshall() {
for (let k = 0; k < G.length; k++) {
for (let i = 0; i < G.length; i++) {
if (k === i) continue;
+ // visualize {
tracer.visit(k, i);
Tracer.delay();
+ // }
for (let j = 0; j < G.length; j++) {
if (i === j || j === k) continue;
+ // visualize {
tracer.visit(j, k);
Tracer.delay();
+ // }
if (S[i][j] > S[i][k] + S[k][j]) {
+ // visualize {
tracer.visit(j, i, S[i][j]);
Tracer.delay();
+ // }
S[i][j] = S[i][k] + S[k][j];
+ // visualize {
tracer.leave(j, i, S[i][j]);
+ // }
}
+ // visualize {
tracer.leave(j, k);
+ // }
}
+ // visualize {
tracer.leave(k, i);
Tracer.delay();
+ // }
}
}
+ // logger {
for (let i = 0; i < G.length; i++) {
for (let j = 0; j < G.length; j++) {
if (S[i][j] === MAX_VALUE) logger.println(`there is no path from ${i} to ${j}`);
else logger.println(`the shortest path from ${i} to ${j} is ${S[i][j]}`);
}
}
+ // }
}
let MAX_VALUE = Infinity;
+// logger {
logger.println('finding the shortest paths from and to all nodes');
+// }
FloydWarshall();
diff --git a/Dynamic Programming/Integer Partition/code.js b/Dynamic Programming/Integer Partition/code.js
index 0a4f969b..3618098c 100644
--- a/Dynamic Programming/Integer Partition/code.js
+++ b/Dynamic Programming/Integer Partition/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new Array2DTracer();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -14,9 +17,12 @@ for (let i = 0; i <= integer; i++) {
}
tracer.set(D);
Tracer.delay();
+// }
function partition(A, n, p) {
+ // logger {
if (n === 0) logger.println(`[${A.join(', ')}]`);
+ // }
else {
let end = n;
if (p !== 0 && A[p - 1] < n) end = A[p - 1];
@@ -33,19 +39,27 @@ function integerPartition(n) {
// We are allowed to use numbers from 2 to i
for (let j = 1; j <= i; j++) {
// Number of partitions without j number + number of partitions with max j
+ // visualize {
tracer.select(i, j);
Tracer.delay();
+ // }
D[i][j] = D[i][j - 1] + D[i - j][Math.max(j, i - j)];
+ // visualize {
tracer.patch(i, j, D[i][j]);
Tracer.delay();
tracer.depatch(i, j);
tracer.deselect(i, j);
+ // }
}
}
return D[n][n];
}
+// logger {
logger.println(`Partitioning: ${integer}`);
+// }
partition(A, integer, 0);
const part = integerPartition(integer);
+// logger {
logger.println(part);
+// }
diff --git a/Dynamic Programming/Knapsack Problem/code.js b/Dynamic Programming/Knapsack Problem/code.js
index 83c5c567..8fc41c73 100644
--- a/Dynamic Programming/Knapsack Problem/code.js
+++ b/Dynamic Programming/Knapsack Problem/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const val = [1, 4, 5, 7]; // The value of all available items
const wt = [1, 3, 4, 5]; // The weights of available items
@@ -13,6 +15,7 @@ for (let i = 0; i < N + 1; i++) {
}
}
+// define tracer variables {
const tracer = new Array2DTracer('Knapsack Table');
const dataViewer1 = new Array1DTracer('Values');
const dataViewer2 = new Array1DTracer('Weights');
@@ -22,6 +25,7 @@ tracer.set(DP);
dataViewer1.set(val);
dataViewer2.set(wt);
Tracer.delay();
+// }
for (let i = 0; i <= N; i++) {
for (let j = 0; j <= W; j++) {
@@ -31,16 +35,20 @@ for (let i = 0; i <= N; i++) {
then the total weight in our collection is 0
*/
DP[i][0] = 0;
+ // visualize {
tracer.patch(i, j, DP[i][j]);
Tracer.delay();
tracer.depatch(i, j);
+ // }
} else if (wt[i - 1] <= j) { // take the current item in our collection
+ // visualize {
dataViewer1.select(i - 1);
Tracer.delay();
dataViewer2.select(i - 1);
Tracer.delay();
tracer.select(i - 1, j);
Tracer.delay();
+ // }
const A = val[i - 1] + DP[i - 1][j - wt[i - 1]];
const B = DP[i - 1][j];
@@ -50,25 +58,35 @@ for (let i = 0; i <= N; i++) {
*/
if (A > B) {
DP[i][j] = A;
+ // visualize {
tracer.patch(i, j, DP[i][j]);
Tracer.delay();
+ // }
} else {
DP[i][j] = B;
+ // visualize {
tracer.patch(i, j, DP[i][j]);
Tracer.delay();
+ // }
}
+ // visualize {
tracer.deselect(i - 1, j);
tracer.depatch(i, j);
dataViewer2.deselect(i - 1);
dataViewer1.deselect(i - 1);
+ // }
} else { // leave the current item from our collection
DP[i][j] = DP[i - 1][j];
+ // visualize {
tracer.patch(i, j, DP[i][j]);
Tracer.delay();
tracer.depatch(i, j);
+ // }
}
}
}
+// logger {
logger.println(` Best value we can achieve is ${DP[N][W]}`);
+// }
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);
diff --git a/Dynamic Programming/Levenshtein's Edit Distance/code.js b/Dynamic Programming/Levenshtein's Edit Distance/code.js
index f4e8d616..788678c2 100644
--- a/Dynamic Programming/Levenshtein's Edit Distance/code.js
+++ b/Dynamic Programming/Levenshtein's Edit Distance/code.js
@@ -1,8 +1,7 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new Array2DTracer('Distance Table');
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([tracer, logger]));
const str1 = 'stack';
const str2 = 'racket';
const table = new Array(str1.length + 1);
@@ -15,50 +14,71 @@ for (let i = 1; i < str2.length + 1; i++) {
table[0][i] = i;
}
+// define tracer variables {
+const tracer = new Array2DTracer('Distance Table');
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([tracer, logger]));
tracer.set(table);
Tracer.delay();
+// }
+// logger {
logger.println('Initialized DP Table');
logger.println(`Y-Axis (Top to Bottom): ${str1}`);
logger.println(`X-Axis (Left to Right): ${str2}`);
+// }
const dist = (function editDistance(str1, str2, table) {
// display grid with words
+ // logger {
logger.println(`*** ${str2.split('').join(' ')}`);
table.forEach((item, index) => {
const character = (index === 0) ? '*' : str1[index - 1];
logger.println(`${character}\t${item}`);
});
+ // }
// begin ED execution
for (let i = 1; i < str1.length + 1; i++) {
for (let j = 1; j < str2.length + 1; j++) {
if (str1[i - 1] === str2[j - 1]) {
+ // visualize {
tracer.select(i - 1, j - 1);
Tracer.delay();
+ // }
table[i][j] = table[i - 1][j - 1];
+ // visualize {
tracer.patch(i, j, table[i][j]);
Tracer.delay();
tracer.depatch(i, j);
tracer.deselect(i - 1, j - 1);
+ // }
} else {
+ // visualize {
tracer.select(i - 1, j);
tracer.select(i, j - 1);
tracer.select(i - 1, j - 1);
Tracer.delay();
+ // }
table[i][j] = Math.min(table[i - 1][j], table[i][j - 1], table[i - 1][j - 1]) + 1;
+ // visualize {
tracer.patch(i, j, table[i][j]);
Tracer.delay();
tracer.depatch(i, j);
tracer.deselect(i - 1, j);
tracer.deselect(i, j - 1);
tracer.deselect(i - 1, j - 1);
+ // }
}
}
}
+ // visualize {
tracer.select(str1.length, str2.length);
+ // }
return table[str1.length][str2.length];
}(str1, str2, table));
+// logger {
logger.println(`Minimum Edit Distance: ${dist}`);
+// }
diff --git a/Dynamic Programming/Longest Common Subsequence/code.js b/Dynamic Programming/Longest Common Subsequence/code.js
index 051a4ce3..eeb3e068 100644
--- a/Dynamic Programming/Longest Common Subsequence/code.js
+++ b/Dynamic Programming/Longest Common Subsequence/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const string1 = 'AGGTAB';
const string2 = 'GXTXAYB';
@@ -9,6 +11,7 @@ for (let i = 0; i < m + 1; i++) {
A[i] = new Array(n + 1);
}
+// define tracer variables {
const tracer1 = new Array1DTracer('String 1');
const tracer2 = new Array1DTracer('String 2');
const tracer3 = new Array2DTracer('Memo Table');
@@ -18,6 +21,7 @@ tracer1.set(string1);
tracer2.set(string2);
tracer3.set(A);
Tracer.delay();
+// }
let i;
let j;
@@ -28,23 +32,29 @@ for (i = 0; i <= m; i++) {
if (i === 0 || j === 0) {
A[i][j] = 0;
} else if (string1[i - 1] === string2[j - 1]) {
+ // visualize {
tracer1.select(i - 1);
Tracer.delay();
tracer2.select(j - 1);
Tracer.delay();
tracer3.select(i - 1, j - 1);
Tracer.delay();
+ // }
A[i][j] = A[i - 1][j - 1] + 1;
+ // visualize {
tracer1.deselect(i - 1);
tracer2.deselect(j - 1);
tracer3.deselect(i - 1, j - 1);
+ // }
} else {
+ // visualize {
tracer3.select(i - 1, j);
Tracer.delay();
tracer3.select(i, j - 1);
Tracer.delay();
+ // }
if (A[i - 1][j] > A[i][j - 1]) {
A[i][j] = A[i - 1][j];
@@ -52,12 +62,16 @@ for (i = 0; i <= m; i++) {
A[i][j] = A[i][j - 1];
}
+ // visualize {
tracer3.deselect(i - 1, j);
tracer3.deselect(i, j - 1);
+ // }
}
+ // visualize {
tracer3.patch(i, j, A[i][j]);
Tracer.delay();
tracer3.depatch(i, j);
+ // }
}
}
@@ -65,13 +79,17 @@ let finalString = '';
i = m;
j = n;
while (i >= 1 && j >= 1) {
+ // visualize {
tracer3.select(i, j);
Tracer.delay();
+ // }
if (string1[i - 1] === string2[j - 1]) {
+ // visualize {
tracer1.select(i - 1);
Tracer.delay();
tracer2.select(j - 1);
Tracer.delay();
+ // }
finalString = string1[i - 1] + finalString;
i--;
@@ -83,5 +101,7 @@ while (i >= 1 && j >= 1) {
}
}
+// logger {
logger.println(`Longest Common Subsequence Length is ${A[m][n]}`);
logger.println(`Longest Common Subsequence is ${finalString}`);
+// }
diff --git a/Dynamic Programming/Longest Increasing Subsequence/code.js b/Dynamic Programming/Longest Increasing Subsequence/code.js
index cfc13fc0..1cc46e40 100644
--- a/Dynamic Programming/Longest Increasing Subsequence/code.js
+++ b/Dynamic Programming/Longest Increasing Subsequence/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new Array1DTracer();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
@@ -7,35 +10,50 @@ const A = Randomize.Array1D({ N: 10, value: () => Randomize.Integer({ min: 0, ma
const LIS = new Array(A.length);
tracer.set(A);
Tracer.delay();
+// }
// Initialize LIS values for all indexes
for (let i = 0; i < A.length; i++) {
LIS[i] = 1;
}
+// logger {
logger.println('Calculating Longest Increasing Subsequence values in bottom up manner ');
+// }
// Compute optimized LIS values in bottom up manner
for (let i = 1; i < A.length; i++) {
+ // visualize {
tracer.select(i);
logger.println(` LIS[${i}] = ${LIS[i]}`);
+ // }
for (let j = 0; j < i; j++) {
+ // visualize {
tracer.patch(j);
Tracer.delay();
tracer.depatch(j);
+ // }
if (A[i] > A[j] && LIS[i] < LIS[j] + 1) {
LIS[i] = LIS[j] + 1;
+ // logger {
logger.println(` LIS[${i}] = ${LIS[i]}`);
+ // }
}
}
+ // visualize {
tracer.deselect(i);
+ // }
}
// Pick maximum of all LIS values
+// logger {
logger.println('Now calculate maximum of all LIS values ');
+// }
let max = LIS[0];
for (let i = 1; i < A.length; i++) {
if (max < LIS[i]) {
max = LIS[i];
}
}
+// logger {
logger.println(`Longest Increasing Subsequence = max of all LIS = ${max}`);
+// }
diff --git a/Dynamic Programming/Longest Palindromic Subsequence/code.js b/Dynamic Programming/Longest Palindromic Subsequence/code.js
index 42b67224..1e7de776 100644
--- a/Dynamic Programming/Longest Palindromic Subsequence/code.js
+++ b/Dynamic Programming/Longest Palindromic Subsequence/code.js
@@ -1,9 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
-
-const tracer = new Array1DTracer('Input Text');
-const matrix = new Array2DTracer('Matrix');
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([tracer, matrix, logger]));
+// }
const seq = 'BBABCBCAB';
let N;
@@ -20,9 +17,15 @@ for (i = 0; i < N; i++) {
L[i][i] = 1;
}
+// define tracer variables {
+const tracer = new Array1DTracer('Input Text');
+const matrix = new Array2DTracer('Matrix');
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([tracer, matrix, logger]));
tracer.set(seq);
matrix.set(L);
Tracer.delay();
+// }
function max(a, b) {
if (a > b) {
@@ -31,56 +34,81 @@ function max(a, b) {
return b;
}
+// logger {
logger.println('LPS for any string with length = 1 is 1');
+// }
for (i = 2; i <= N; i++) {
+ // logger {
logger.println('--------------------------------------------------');
logger.println(`Considering a sub-string of length ${i}`);
logger.println('--------------------------------------------------');
+ // }
for (j = 0; j < N - i + 1; j++) {
const k = j + i - 1;
+ // visualize {
tracer.select(j);
Tracer.delay();
tracer.patch(k);
Tracer.delay();
+ // }
+ // logger {
logger.println(`Comparing ${seq[j]} and ${seq[k]}`);
+ // }
if (seq[j] === seq[k] && i === 2) {
+ // logger {
logger.println(`They are equal and size of the string in the interval${j} to ${k} is 2, so the Longest Palindromic Subsequence in the Given range is 2`);
+ // }
+ // visualize {
matrix.patch(j, k);
Tracer.delay();
+ // }
L[j][k] = 2;
+ // visualize {
matrix.set(L);
matrix.depatch(j, k);
Tracer.delay();
+ // }
} else if (seq[j] === seq[k]) {
+ // logger {
logger.println(`They are equal, so the Longest Palindromic Subsequence in the Given range is 2 + the Longest Increasing Subsequence between the indices ${j + 1} to ${k - 1}`);
+ // }
+ // visualize {
matrix.patch(j, k);
Tracer.delay();
matrix.select(j + 1, k - 1);
Tracer.delay();
+ // }
L[j][k] = L[j + 1][k - 1] + 2;
+ // visualize {
matrix.set(L);
matrix.depatch(j, k);
Tracer.delay();
matrix.deselect(j + 1, k - 1);
Tracer.delay();
+ // }
} else {
+ // logger {
logger.println(`They are NOT equal, so the Longest Palindromic Subsequence in the Given range is the maximum Longest Increasing Subsequence between the indices ${j + 1} to ${k} and ${j} to ${k - 1}`);
+ // }
+ // visualize {
matrix.patch(j, k);
Tracer.delay();
matrix.select(j + 1, k);
Tracer.delay();
matrix.select(j, k - 1);
Tracer.delay();
+ // }
L[j][k] = max(L[j + 1][k], L[j][k - 1]);
+ // visualize {
matrix.set(L);
matrix.depatch(j, k);
@@ -89,12 +117,19 @@ for (i = 2; i <= N; i++) {
Tracer.delay();
matrix.deselect(j, k - 1);
Tracer.delay();
+ // }
}
+ // logger {
logger.println('--------------------------------------------------');
+ // }
+ // visualize {
tracer.deselect(j);
Tracer.delay();
tracer.depatch(k);
Tracer.delay();
+ // }
}
}
+// logger {
logger.println(`Longest Increasing Subsequence of the given string = L[0][${N - 1}]=${L[0][N - 1]}`);
+// }
diff --git a/Dynamic Programming/Maximum Subarray/code.js b/Dynamic Programming/Maximum Subarray/code.js
index 23bf888f..241f206c 100644
--- a/Dynamic Programming/Maximum Subarray/code.js
+++ b/Dynamic Programming/Maximum Subarray/code.js
@@ -1,39 +1,60 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+const D = [-2, -3, 4, -1, -2, 1, 5, -3];
+
+// define tracer variables {
const tracer = new Array1DTracer();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
-const D = [-2, -3, 4, -1, -2, 1, 5, -3];
tracer.set(D);
Tracer.delay();
+// }
const maxSubarraySum = (function maxSubarray(array) {
let maxSoFar = 0;
let maxEndingHere = 0;
+ // logger {
logger.println('Initializing maxSoFar = 0 & maxEndingHere = 0');
+ // }
for (let i = 0; i < array.length; i++) {
+ // visualize {
tracer.select(i);
+ // }
+ // logger {
logger.println(`${maxEndingHere} + ${array[i]}`);
+ // }
maxEndingHere += array[i];
+ // logger {
logger.println(`=> ${maxEndingHere}`);
+ // }
if (maxEndingHere < 0) {
+ // logger {
logger.println('maxEndingHere is negative, set to 0');
+ // }
maxEndingHere = 0;
}
if (maxSoFar < maxEndingHere) {
+ // logger {
logger.println(`maxSoFar < maxEndingHere, setting maxSoFar to maxEndingHere (${maxEndingHere})`);
+ // }
maxSoFar = maxEndingHere;
}
+ // visualize {
Tracer.delay();
tracer.deselect(i);
+ // }
}
return maxSoFar;
}(D));
+// logger {
logger.println(`Maximum Subarray's Sum is: ${maxSubarraySum}`);
+// }
diff --git a/Dynamic Programming/Maximum Sum Path/code.js b/Dynamic Programming/Maximum Sum Path/code.js
index 6a267ae1..b95e518e 100644
--- a/Dynamic Programming/Maximum Sum Path/code.js
+++ b/Dynamic Programming/Maximum Sum Path/code.js
@@ -1,5 +1,8 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const D = Randomize.Array2D({ N: 5, M: 5, value: () => Randomize.Integer({ min: 1, max: 5 }) });
const dataViewer = new Array2DTracer();
const tracer = new Array2DTracer('Results Table');
@@ -15,18 +18,21 @@ for (let i = 0; i < D.length; i++) {
}
tracer.set(DP);
Tracer.delay();
+// }
const N = DP.length;
const M = DP[0].length;
function update(i, j, value) {
DP[i][j] = value;
+ // visualize {
dataViewer.select(i, j);
Tracer.delay();
tracer.patch(i, j, DP[i][j]);
Tracer.delay();
tracer.depatch(i, j);
dataViewer.deselect(i, j);
+ // }
}
for (let i = 0; i < N; i++) {
@@ -34,20 +40,34 @@ for (let i = 0; i < N; i++) {
if (i === 0 && j === 0) {
update(i, j, D[i][j]);
} else if (i === 0) {
+ // visualize {
tracer.select(i, j - 1);
+ // }
update(i, j, DP[i][j - 1] + D[i][j]);
+ // visualize {
tracer.deselect(i, j - 1);
+ // }
} else if (j === 0) {
+ // visualize {
tracer.select(i - 1, j);
+ // }
update(i, j, DP[i - 1][j] + D[i][j]);
+ // visualize {
tracer.deselect(i - 1, j);
+ // }
} else {
+ // visualize {
tracer.select(i, j - 1);
tracer.select(i - 1, j);
+ // }
update(i, j, Math.max(DP[i][j - 1], DP[i - 1][j]) + D[i][j]);
+ // visualize {
tracer.deselect(i, j - 1);
tracer.deselect(i - 1, j);
+ // }
}
}
}
+// logger {
logger.println(`max = ${DP[N - 1][M - 1]}`);
+// }
diff --git a/Dynamic Programming/Pascal's Triangle/code.js b/Dynamic Programming/Pascal's Triangle/code.js
index b2e89291..eea8fd7c 100644
--- a/Dynamic Programming/Pascal's Triangle/code.js
+++ b/Dynamic Programming/Pascal's Triangle/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const N = 9;
const A = new Array(N);
@@ -6,32 +8,40 @@ for (let i = N - 1; i >= 0; i--) {
A[i] = new Array(N);
}
+// define tracer variables {
const tracer = new Array2DTracer('Pascal\'s Triangle');
Layout.setRoot(new VerticalLayout([tracer]));
tracer.set(A);
Tracer.delay();
+// }
for (let i = 0; i < N; i++) {
for (let j = 0; j <= i; j++) {
if (j === i || j === 0) { // First and last values in every row are 1
A[i][j] = 1;
+ // visualize {
tracer.patch(i, j, A[i][j]);
Tracer.delay();
tracer.depatch(i, j);
+ // }
} else { // Other values are sum of values just above and left of above
+ // visualize {
tracer.select(i - 1, j - 1);
Tracer.delay();
tracer.select(i - 1, j);
Tracer.delay();
+ // }
A[i][j] = A[i - 1][j - 1] + A[i - 1][j];
+ // visualize {
tracer.patch(i, j, A[i][j]);
Tracer.delay();
tracer.depatch(i, j);
tracer.deselect(i - 1, j - 1);
tracer.deselect(i - 1, j);
+ // }
}
}
}
diff --git a/Dynamic Programming/Shortest Common Supersequence/code.js b/Dynamic Programming/Shortest Common Supersequence/code.js
index d60387c9..7c726fc3 100644
--- a/Dynamic Programming/Shortest Common Supersequence/code.js
+++ b/Dynamic Programming/Shortest Common Supersequence/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const string1 = 'AGGTAB';
const string2 = 'GXTXAYB';
@@ -9,6 +11,7 @@ for (let i = 0; i < m + 1; i++) {
A[i] = new Array(n + 1);
}
+// define tracer variables {
const tracer1 = new Array1DTracer('String 1');
const tracer2 = new Array1DTracer('String 2');
const tracer3 = new Array2DTracer('Memo Table');
@@ -18,6 +21,7 @@ tracer1.set(string1);
tracer2.set(string2);
tracer3.set(A);
Tracer.delay();
+// }
let i;
let j;
@@ -30,23 +34,29 @@ for (i = 0; i <= m; i++) {
} else if (j === 0) {
A[i][j] = i;
} else if (string1[i - 1] === string2[j - 1]) {
+ // visualize {
tracer1.select(i - 1);
Tracer.delay();
tracer2.select(j - 1);
Tracer.delay();
tracer3.select(i - 1, j - 1);
Tracer.delay();
+ // }
A[i][j] = A[i - 1][j - 1] + 1;
+ // visualize {
tracer1.deselect(i - 1);
tracer2.deselect(j - 1);
tracer3.deselect(i - 1, j - 1);
+ // }
} else {
+ // visualize {
tracer3.select(i - 1, j);
Tracer.delay();
tracer3.select(i, j - 1);
Tracer.delay();
+ // }
if (A[i - 1][j] < A[i][j - 1]) {
A[i][j] = 1 + A[i - 1][j];
@@ -54,13 +64,19 @@ for (i = 0; i <= m; i++) {
A[i][j] = 1 + A[i][j - 1];
}
+ // visualize {
tracer3.deselect(i - 1, j);
tracer3.deselect(i, j - 1);
+ // }
}
+ // visualize {
tracer3.patch(i, j, A[i][j]);
Tracer.delay();
tracer3.depatch(i, j);
+ // }
}
}
+// logger {
logger.println(`Shortest Common Supersequence is ${A[m][n]}`);
+// }
diff --git a/Dynamic Programming/Sieve of Eratosthenes/code.js b/Dynamic Programming/Sieve of Eratosthenes/code.js
index 986a1192..fdac4920 100644
--- a/Dynamic Programming/Sieve of Eratosthenes/code.js
+++ b/Dynamic Programming/Sieve of Eratosthenes/code.js
@@ -1,6 +1,7 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new Array1DTracer('Sieve');
const N = 30;
const a = [];
const b = [];
@@ -8,27 +9,41 @@ for (let i = 1; i <= N; i++) {
a.push(i);
b.push(0);
}
+
+// define tracer variables {
+const tracer = new Array1DTracer('Sieve');
tracer.set(a);
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
Tracer.delay();
+// }
+// visualize {
logger.println('1 is not prime');
tracer.select(0);
Tracer.delay();
+// }
for (let i = 2; i <= N; i++) {
if (b[i] === 0) {
+ // visualize {
logger.println(`${i} is not marked, so it is prime`);
// a[i-1] is prime mark by red indicators
tracer.patch(i - 1);
Tracer.delay();
+ // }
for (let j = i + i; j <= N; j += i) {
b[j] = 1; // a[j-1] is not prime, mark by blue indicators
+ // visualize {
logger.println(`${j} is a multiple of ${i} so it is marked as composite`);
tracer.select(j - 1);
Tracer.delay();
+ // }
}
+ // visualize {
tracer.depatch(i - 1);
+ // }
}
}
+// logger {
logger.println(`The unmarked numbers are the prime numbers from 1 to ${N}`);
+// }
diff --git a/Dynamic Programming/Sliding Window/code.js b/Dynamic Programming/Sliding Window/code.js
index 60d7212c..7cf9b4ad 100644
--- a/Dynamic Programming/Sliding Window/code.js
+++ b/Dynamic Programming/Sliding Window/code.js
@@ -1,24 +1,34 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const tracer = new Array1DTracer();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
const D = Randomize.Array1D({ N: 20, value: () => Randomize.Integer({ min: -5, max: 5 }) });
tracer.set(D);
Tracer.delay();
+// }
let sum = D[0] + D[1] + D[2];
let max = sum;
+// visualize {
tracer.select(0, 2);
logger.println(`sum = ${sum}`);
Tracer.delay();
+// }
for (let i = 3; i < D.length; i++) {
sum += D[i] - D[i - 3];
if (max < sum) max = sum;
+ // visualize {
tracer.deselect(i - 3);
tracer.select(i);
logger.println(`sum = ${sum}`);
Tracer.delay();
+ // }
}
+// visualize {
tracer.deselect(D.length - 3, D.length - 1);
logger.println(`max = ${max}`);
+// }
diff --git a/Dynamic Programming/Ugly Numbers/code.js b/Dynamic Programming/Ugly Numbers/code.js
index 1f3006b5..356ab7de 100644
--- a/Dynamic Programming/Ugly Numbers/code.js
+++ b/Dynamic Programming/Ugly Numbers/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const N = 15;
const A = new Array(N);
@@ -10,6 +12,7 @@ A[0] = 1; // By convention 1 is an ugly number
const M = [2, 3, 5]; // multiples of 2, 3, 5 respectively
const I = [0, 0, 0]; // iterators of 2, 3, 5 respectively
+// define tracer variables {
const tracer = new Array1DTracer('Ugly Numbers');
const tracer2 = new Array1DTracer('Multiples of 2, 3, 5');
const tracer3 = new Array1DTracer(' Iterators I0, I1, I2 ');
@@ -19,45 +22,56 @@ tracer.set(A);
tracer2.set(M);
tracer3.set(I);
Tracer.delay();
+// }
for (let i = 1; i < N; i++) {
// next is minimum of m2, m3 and m5
const next = (M[0] <= M[1]) ? (M[0] <= M[2]) ? M[0] : M[2] : (M[1] <= M[2]) ? M[1] : M[2];
+ // logger {
logger.println(` Minimum of ${M[0]}, ${M[1]}, ${M[2]} : ${next}`);
+ // }
A[i] = next;
+ // visualize {
tracer.patch(i, A[i]);
Tracer.delay();
tracer.depatch(i);
+ // }
if (next === M[0]) {
I[0]++;
M[0] = A[I[0]] * 2;
+ // visualize {
tracer2.patch(0, M[0]);
Tracer.delay();
tracer3.patch(0, I[0]);
Tracer.delay();
tracer2.depatch(0);
tracer3.depatch(0);
+ // }
}
if (next === M[1]) {
I[1]++;
M[1] = A[I[1]] * 3;
+ // visualize {
tracer2.patch(1, M[1]);
Tracer.delay();
tracer3.patch(1, I[1]);
Tracer.delay();
tracer2.depatch(1);
tracer3.depatch(1);
+ // }
}
if (next === M[2]) {
I[2]++;
M[2] = A[I[2]] * 5;
+ // visualize {
tracer2.patch(2, M[2]);
Tracer.delay();
tracer3.patch(2, I[2]);
Tracer.delay();
tracer2.depatch(2);
tracer3.depatch(2);
+ // }
}
}
diff --git a/Dynamic Programming/Z String Search/code.js b/Dynamic Programming/Z String Search/code.js
index b76cf622..cf831db3 100644
--- a/Dynamic Programming/Z String Search/code.js
+++ b/Dynamic Programming/Z String Search/code.js
@@ -1,9 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
-
-const textTracer = new Array1DTracer('text');
-const pattTracer = new Array1DTracer('pattern');
-const concatTracer = new Array1DTracer('concatenated string');
-const tracer = new Array1DTracer('zArray');
+// }
// let pattern = "aab";
// let text = "aabxaabxcaabxaabxay";
@@ -15,13 +12,18 @@ const len = pattern.length + text.length + 1;
const z = new Array(len);
z[0] = 0;
+// define tracer variables {
+const textTracer = new Array1DTracer('text');
+const pattTracer = new Array1DTracer('pattern');
+const concatTracer = new Array1DTracer('concatenated string');
+const tracer = new Array1DTracer('zArray');
pattTracer.set(pattern);
textTracer.set(text);
tracer.set(z);
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([textTracer, pattTracer, concatTracer, tracer, logger]));
Tracer.delay();
-
+// }
function createZarr(concat) {
let left;
@@ -31,19 +33,24 @@ function createZarr(concat) {
left = 0;
right = 0;
for (let i = 1; i < N; i++) {
+ // visualize {
tracer.select(i);
Tracer.delay();
+ // }
if (i > right) {
left = right = i;
while (right < N && concat[right] === concat[right - left]) {
+ // visualize {
concatTracer.patch(right);
concatTracer.select(right - left);
logger.println(`${concat[right]} (at index ${right}) is equal to ${concat[right - left]} (at index ${right - left})`);
Tracer.delay();
concatTracer.depatch(right);
concatTracer.deselect(right - left);
+ // }
right++;
}
+ // visualize {
if (right < N) {
concatTracer.patch(right);
concatTracer.select(right - left);
@@ -52,31 +59,43 @@ function createZarr(concat) {
concatTracer.depatch(right);
concatTracer.deselect(right - left);
}
+ // }
z[i] = (right - left);
+ // logger {
logger.println('--------------------------------');
logger.println(`Value of z[${i}] = the length of the substring starting from ${i} which is also the prefix of the concatinated string(=${right - left})`);
logger.println('--------------------------------');
+ // }
right--;
} else if (z[i - left] < (right - i + 1)) {
+ // visualize {
logger.println(`The substring from index ${i - left} will not cross the right end.`);
concatTracer.patch(right - i + 1);
concatTracer.select(i - left);
Tracer.delay();
+ // }
z[i] = z[i - left];
+ // visualize {
concatTracer.depatch(right - i + 1);
concatTracer.deselect(i - left);
+ // }
} else {
+ // logger {
logger.println(`The substring from index ${i - left} will cross the right end.`);
+ // }
left = i;
while (right < N && concat[right] === concat[right - left]) {
+ // visualize {
concatTracer.patch(right);
concatTracer.select(right - left);
logger.println(`${concat[right]} (at index ${right}) is equal to ${concat[right - left]} (at index ${right - left})`);
Tracer.delay();
concatTracer.depatch(right);
concatTracer.deselect(right - left);
+ // }
right++;
}
+ // visualize {
if (right < N) {
concatTracer.patch(right);
concatTracer.select(right - left);
@@ -85,22 +104,32 @@ function createZarr(concat) {
concatTracer.depatch(right);
concatTracer.deselect(right - left);
}
+ // }
z[i] = (right - left);
right--;
+ // logger {
logger.println('--------------------------------');
logger.println(`Value of z[${i}] = the length of the substring starting from ${i} which is also the prefix of the concatinated string(=${right - left})`);
logger.println('--------------------------------');
+ // }
}
+ // visualize {
tracer.deselect(i);
tracer.set(z);
+ // }
}
}
const concat = `${pattern}$${text}`;
+// visualize {
concatTracer.set(concat);
+// }
const patLen = pattern.length;
createZarr(concat);
+// visualize {
tracer.set(z);
+// }
+// logger {
logger.println('The Values in Z array equal to the length of the pattern indicates the index at which the pattern is present');
logger.println('===================================');
for (let i = 0; i < len; i++) {
@@ -110,3 +139,4 @@ for (let i = 0; i < len; i++) {
}
}
logger.println('===================================');
+// }
diff --git "a/Greedy/Boyer\342\200\223Moore's Majority Vote/code.js" "b/Greedy/Boyer\342\200\223Moore's Majority Vote/code.js"
index bcd48952..be6b45af 100644
--- "a/Greedy/Boyer\342\200\223Moore's Majority Vote/code.js"
+++ "b/Greedy/Boyer\342\200\223Moore's Majority Vote/code.js"
@@ -1,79 +1,119 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const A = [1, 3, 3, 2, 1, 1, 1];
const N = A.length;
+// define tracer variables {
const tracer = new Array1DTracer('List of element');
const logger = new LogTracer('Console');
Layout.setRoot(new VerticalLayout([tracer, logger]));
tracer.set(A);
Tracer.delay();
+// }
function isMajorityElement(element) {
let count = 0;
+ // logger {
logger.println(`Verify majority element ${element}`);
+ // }
for (let i = N - 1; i >= 0; i--) {
+ // visualize {
tracer.patch(i, A[i]);
Tracer.delay();
+ // }
if (A[i] === element) {
count++;
} else {
+ // visualize {
tracer.depatch(i);
+ // }
}
}
+ // logger {
logger.println(`Count of our assumed majority element ${count}`);
+ // }
if (count > Math.floor(N / 2)) {
+ // logger {
logger.println('Our assumption was correct!');
+ // }
return true;
}
+ // logger {
logger.println('Our assumption was incorrect!');
+ // }
return false;
}
function findProbableElement() {
let index = 0;
let count = 1;
+ // visualize {
tracer.select(index);
Tracer.delay();
+ // }
+ // logger {
logger.println(`Beginning with assumed majority element : ${A[index]} count : ${count}`);
logger.println('--------------------------------------------------------');
+ // }
for (let i = 1; i < N; i++) {
+ // visualize {
tracer.patch(i, A[i]);
Tracer.delay();
+ // }
if (A[index] === A[i]) {
count++;
+ // logger {
logger.println(`Same as assumed majority element! Count : ${count}`);
+ // }
} else {
count--;
+ // logger {
logger.println(`Not same as assumed majority element! Count : ${count}`);
+ // }
}
if (count === 0) {
+ // logger {
logger.println('Wrong assumption in majority element');
+ // }
+ // visualize {
tracer.deselect(index);
tracer.depatch(i);
+ // }
index = i;
count = 1;
+ // visualize {
tracer.select(i);
Tracer.delay();
+ // }
+ // logger {
logger.println(`New assumed majority element!${A[i]} Count : ${count}`);
logger.println('--------------------------------------------------------');
+ // }
} else {
+ // visualize {
tracer.depatch(i);
+ // }
}
}
+ // logger {
logger.println(`Finally assumed majority element ${A[index]}`);
logger.println('--------------------------------------------------------');
+ // }
return A[index];
}
function findMajorityElement() {
const element = findProbableElement();
+ // logger {
if (isMajorityElement(element) === true) {
logger.println(`Majority element is ${element}`);
} else {
logger.println('No majority element');
}
+ // }
}
findMajorityElement();
diff --git a/Greedy/Dijkstra's Shortest Path/code.js b/Greedy/Dijkstra's Shortest Path/code.js
index d0a57ad9..3cafa918 100644
--- a/Greedy/Dijkstra's Shortest Path/code.js
+++ b/Greedy/Dijkstra's Shortest Path/code.js
@@ -1,17 +1,22 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, GraphTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+const G = Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true });
+const MAX_VALUE = Infinity;
+const S = []; // S[end] returns the distance from start node to end node
+for (let i = 0; i < G.length; i++) S[i] = MAX_VALUE;
+
+// define tracer variables {
const tracer = new GraphTracer().directed(false).weighted();
const tracerS = new Array1DTracer();
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, tracerS, logger]));
tracer.log(logger);
-const G = Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true });
tracer.set(G);
-const MAX_VALUE = Infinity;
-const S = []; // S[end] returns the distance from start node to end node
-for (let i = 0; i < G.length; i++) S[i] = MAX_VALUE;
tracerS.set(S);
Tracer.delay();
+// }
function Dijkstra(start, end) {
let minIndex;
@@ -19,10 +24,12 @@ function Dijkstra(start, end) {
const D = []; // D[i] indicates whether the i-th node is discovered or not
for (let i = 0; i < G.length; i++) D.push(false);
S[start] = 0; // Starting node is at distance 0 from itself
+ // visualize {
tracerS.patch(start, S[start]);
Tracer.delay();
tracerS.depatch(start);
tracerS.select(start);
+ // }
let k = G.length;
while (k--) {
// Finding a node with the shortest distance from S[minIndex]
@@ -35,30 +42,38 @@ function Dijkstra(start, end) {
}
if (minDistance === MAX_VALUE) break; // If there is no edge from current node, jump out of loop
D[minIndex] = true;
+ // visualize {
tracerS.select(minIndex);
tracer.visit(minIndex);
Tracer.delay();
+ // }
// For every unvisited neighbour of current node, we check
// whether the path to it is shorter if going over the current node
for (let i = 0; i < G.length; i++) {
if (G[minIndex][i] && S[i] > S[minIndex] + G[minIndex][i]) {
S[i] = S[minIndex] + G[minIndex][i];
+ // visualize {
tracerS.patch(i, S[i]);
tracer.visit(i, minIndex, S[i]);
Tracer.delay();
tracerS.depatch(i);
tracer.leave(i, minIndex);
Tracer.delay();
+ // }
}
}
+ // visualize {
tracer.leave(minIndex);
Tracer.delay();
+ // }
}
+ // logger {
if (S[end] === MAX_VALUE) {
logger.println(`there is no path from ${start} to ${end}`);
} else {
logger.println(`the shortest path from ${start} to ${end} is ${S[end]}`);
}
+ // }
}
const s = Randomize.Integer({ min: 0, max: G.length - 1 }); // s = start node
@@ -66,6 +81,8 @@ let e; // e = end node
do {
e = Randomize.Integer({ min: 0, max: G.length - 1 });
} while (s === e);
+// logger {
logger.println(`finding the shortest path from ${s} to ${e}`);
Tracer.delay();
+// }
Dijkstra(s, e);
diff --git a/Greedy/Job Scheduling Problem/code.js b/Greedy/Job Scheduling Problem/code.js
index d8888165..4192792d 100644
--- a/Greedy/Job Scheduling Problem/code.js
+++ b/Greedy/Job Scheduling Problem/code.js
@@ -1,16 +1,11 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const jobId = ['a', 'b', 'c', 'd', 'e'];
const deadline = [2, 1, 2, 1, 3];
const profit = [100, 19, 27, 25, 15];
const N = deadline.length;
-
-const tracer3 = new Array1DTracer('Schedule');
-const tracer = new Array1DTracer('Job Ids');
-const tracer1 = new Array1DTracer('Deadlines');
-const tracer2 = new Array1DTracer('Profit');
-Layout.setRoot(new VerticalLayout([tracer3, tracer, tracer1, tracer2]));
-
// sort according to decreasing order of profit
// Bubble sort implemented ... Implement a better algorithm for better performance
for (let i = 0; i < N - 1; i++) {
@@ -34,11 +29,19 @@ const result = new Array(N);
for (let i = N - 1; i >= 0; i--) {
result[i] = '-';
}
+
+// define tracer variables {
+const tracer3 = new Array1DTracer('Schedule');
+const tracer = new Array1DTracer('Job Ids');
+const tracer1 = new Array1DTracer('Deadlines');
+const tracer2 = new Array1DTracer('Profit');
+Layout.setRoot(new VerticalLayout([tracer3, tracer, tracer1, tracer2]));
tracer.set(jobId);
tracer1.set(deadline);
tracer2.set(profit);
tracer3.set(result);
Tracer.delay();
+// }
// Initialise all slots to free
for (let i = 0; i < N; i++) {
@@ -51,21 +54,29 @@ for (let i = 0; i < N; i++) {
Start from the last possible slot.
Find a slot for the job
*/
+ // visualize {
tracer.select(i);
Tracer.delay();
tracer1.select(i);
Tracer.delay();
+ // }
for (let j = Math.min(N, deadline[i]) - 1; j >= 0; j--) {
if (slot[j] === 0) {
+ // visualize {
tracer3.patch(j, jobId[i]);
Tracer.delay();
+ // }
result[j] = jobId[i];
slot[j] = 1;
+ // visualize {
tracer3.depatch(j);
+ // }
break;
}
}
+ // visualize {
tracer.deselect(i);
tracer1.deselect(i);
+ // }
}
diff --git a/Greedy/Kruskal's Minimum Spanning Tree/code.js b/Greedy/Kruskal's Minimum Spanning Tree/code.js
index 77b9ff6a..8cc2535e 100644
--- a/Greedy/Kruskal's Minimum Spanning Tree/code.js
+++ b/Greedy/Kruskal's Minimum Spanning Tree/code.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]));
@@ -13,6 +16,7 @@ Layout.setRoot(new VerticalLayout([tracer, logger]));
const G = Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true });
tracer.set(G);
Tracer.delay();
+// }
function kruskal() {
const vcount = G.length;
@@ -40,12 +44,16 @@ function kruskal() {
let wsum = 0;
for (let n = 0; n < vcount - 1 && edges.length > 0;) {
const e = edges.shift(); // Get the edge of min weight
+ // visualize {
tracer.visit(e[0], e[1]);
Tracer.delay();
+ // }
if (t[e[0]] === t[e[1]]) {
// e[0] & e[1] already in the same tree, ignore
+ // visualize {
tracer.leave(e[0], e[1]);
Tracer.delay();
+ // }
continue;
}
@@ -61,7 +69,9 @@ function kruskal() {
n += 1;
}
+ // logger {
logger.println(`The sum of all edges is: ${wsum}`);
+ // }
}
kruskal();
diff --git a/Greedy/Prim's Minimum Spanning Tree/code.js b/Greedy/Prim's Minimum Spanning Tree/code.js
index e44458fc..107f0144 100644
--- a/Greedy/Prim's Minimum Spanning Tree/code.js
+++ b/Greedy/Prim's Minimum Spanning Tree/code.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]));
@@ -14,6 +17,7 @@ tracer.log(logger);
const G = Randomize.Graph({ N: 10, ratio: .4, directed: false, weighted: true });
tracer.set(G);
Tracer.delay();
+// }
function prim() {
// Finds a tree so that there exists a path between
@@ -33,8 +37,10 @@ function prim() {
{
for (let j = 0; j < G.length; j++) {
if (!D[j] && G[i][j]) {
+ // visualize {
tracer.visit(i, j);
Tracer.delay();
+ // }
// Second node must not be visited and must be connected to first node
if (G[i][j] < minD) {
// Searching for cheapest edge which satisfies requirements
@@ -42,19 +48,27 @@ function prim() {
minI = i;
minJ = j;
}
+ // visualize {
tracer.leave(i, j);
Tracer.delay();
+ // }
}
}
}
}
+ // visualize {
tracer.visit(minI, minJ);
Tracer.delay();
+ // }
D[minJ] = 1; // Visit second node and insert it into or tree
sum += G[minI][minJ];
}
+ // logger {
logger.println(`The sum of all edges is: ${sum}`);
+ // }
}
+// logger {
logger.println('nodes that belong to minimum spanning tree are: ');
+// }
prim();
diff --git a/Greedy/Stable Matching/code.js b/Greedy/Stable Matching/code.js
index 1c15579e..40369cf2 100644
--- a/Greedy/Stable Matching/code.js
+++ b/Greedy/Stable Matching/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const ARank = {
Flavio: ['Valentine', 'July', 'Summer', 'Violet'],
@@ -14,6 +16,7 @@ const BRank = {
Summer: ['Stephen', 'Flavio', 'Albert', 'Jack'],
};
+// define tracer variables {
const tracerA = new Array1DTracer('A');
const tracerB = new Array1DTracer('B');
@@ -25,6 +28,7 @@ tracerB.set(_bKeys);
const logTracer = new LogTracer('Console');
Layout.setRoot(new VerticalLayout([tracerA, tracerB, logTracer]));
Tracer.delay();
+// }
function init(rank) {
const o = {};
@@ -51,44 +55,58 @@ const B = init(BRank);
let a;
while ((a = extractUnstable(A))) {
+ // logger {
logTracer.println(`Selecting ${a.key}`);
Tracer.delay();
+ // }
const bKey = a.rankKeys.shift();
const b = B[bKey];
+ // logger {
logTracer.println(`--> Choicing ${b.key}`);
Tracer.delay();
+ // }
if (b.stable === false) {
+ // logger {
logTracer.println(`--> ${b.key} is not stable, stabilizing with ${a.key}`);
Tracer.delay();
+ // }
a.stable = b;
b.stable = a;
+ // visualize {
tracerA.select(_aKeys.indexOf(a.key));
Tracer.delay();
tracerB.select(_bKeys.indexOf(b.key));
Tracer.delay();
+ // }
} else {
const rankAinB = b.rankKeys.indexOf(a.key);
const rankPrevAinB = b.rankKeys.indexOf(b.stable.key);
if (rankAinB < rankPrevAinB) {
+ // logger {
logTracer.println(`--> ${bKey} is more stable with ${a.key} rather than ${b.stable.key} - stabilizing again`);
Tracer.delay();
+ // }
A[b.stable.key].stable = false;
+ // visualize {
tracerA.deselect(_aKeys.indexOf(b.stable.key));
Tracer.delay();
+ // }
a.stable = b;
b.stable = a;
+ // visualize {
tracerA.select(_aKeys.indexOf(a.key));
Tracer.delay();
tracerB.select(_bKeys.indexOf(b.key));
Tracer.delay();
+ // }
}
}
}
diff --git a/Simple Recursive/Cellular Automata/code.js b/Simple Recursive/Cellular Automata/code.js
index c65f1954..58246d56 100644
--- a/Simple Recursive/Cellular Automata/code.js
+++ b/Simple Recursive/Cellular Automata/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const gridSize = 10;
const generations = 4;
@@ -18,11 +20,15 @@ for (let i = 0; i < gridSize; i++) {
nextG[i][j] = '#';
}
}
+
+// define tracer variables {
const tracer = new Array2DTracer();
Layout.setRoot(new VerticalLayout([tracer]));
tracer.set(G);
Tracer.delay();
+// }
+// visualize {
for (let gi = 0; gi < G.length; gi++) {
for (let gj = 0; gj < G[gi].length; gj++) {
if (G[gi][gj] === '#') {
@@ -30,6 +36,7 @@ for (let gi = 0; gi < G.length; gi++) {
}
}
}
+// }
function CellularAutomata(fillShape, emptyShape) {
const nextGrid = [];
@@ -70,10 +77,13 @@ function CellularAutomata(fillShape, emptyShape) {
for (let i = 0; i < nextGrid.length; i++) {
for (let j = 0; j < nextGrid[i].length; j++) {
+ // visualize {
tracer.depatch(i, j, G[i][j]);
tracer.select(i, j);
Tracer.delay();
+ // }
G[i][j] = nextGrid[i][j];
+ // visualize {
if (G[i][j] === fillShape) {
tracer.patch(i, j, G[i][j]);
} else {
@@ -81,6 +91,7 @@ function CellularAutomata(fillShape, emptyShape) {
tracer.depatch(i, j, G[i][j]);
tracer.deselect(i, j);
}
+ // }
}
}
}
diff --git a/Simple Recursive/Euclidean Greatest Common Divisor/code.js b/Simple Recursive/Euclidean Greatest Common Divisor/code.js
index 7f7dc53c..3419978f 100644
--- a/Simple Recursive/Euclidean Greatest Common Divisor/code.js
+++ b/Simple Recursive/Euclidean Greatest Common Divisor/code.js
@@ -1,42 +1,63 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new Array1DTracer('Euclidean Algorithm');
const a = [];
a.push(465);
a.push(255);
+
+// define tracer variables {
+const tracer = new Array1DTracer('Euclidean Algorithm');
tracer.set(a);
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([tracer, logger]));
Tracer.delay();
+// }
+// logger {
logger.println(`Finding the greatest common divisor of ${a[0]} and ${a[1]}`);
logger.println('Checking if first number is at most the second number');
+// }
if (a[0] > a[1]) {
const tmp = a[0];
a[0] = a[1];
a[1] = tmp;
+ // logger {
logger.println('The first number is bigger than the second number. Switching the numbers.');
+ // }
+ // visualize {
tracer.set(a);
Tracer.delay();
+ // }
}
while (a[0] > 0) {
+ // logger {
logger.println(`${a[1]} % ${a[0]} = ${a[1] % a[0]}`);
logger.println('Switching a[1] with a[1]%a[0]');
+ // }
a[1] %= a[0];
+ // visualize {
tracer.patch(1, a[1]);
Tracer.delay();
+ // }
+ // logger {
logger.println('Now switching the two values to keep a[0] < a[1]');
+ // }
const tmp = a[0];
a[0] = a[1];
a[1] = tmp;
+ // visualize {
tracer.patch(0, a[0]);
tracer.patch(1, a[1]);
Tracer.delay();
tracer.depatch(0);
tracer.depatch(1);
+ // }
}
+// logger {
logger.println(`The greatest common divisor is ${a[1]}`);
+// }
diff --git a/Simple Recursive/Suffix Array/code.js b/Simple Recursive/Suffix Array/code.js
index 6ddf49b4..dc0c0261 100644
--- a/Simple Recursive/Suffix Array/code.js
+++ b/Simple Recursive/Suffix Array/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
let word = 'virgo';
const suffixArray = (function skeleton(word) {
@@ -11,6 +13,7 @@ const suffixArray = (function skeleton(word) {
return arr;
}(word));
+// define tracer variables {
const saTracer = new Array2DTracer('Suffix Array');
const wordTracer = new Array1DTracer('Given Word');
const logger = new LogTracer('Progress');
@@ -19,24 +22,35 @@ Layout.setRoot(new VerticalLayout([saTracer, wordTracer, logger]));
saTracer.set(suffixArray);
wordTracer.set(word);
Tracer.delay();
+// }
word += '$'; // special character
+// logger {
logger.println('Appended \'$\' at the end of word as terminating (special) character. Beginning filling of suffixes');
+// }
function selectSuffix(word, i) {
let c = i;
while (i < word.length - 1) {
+ // visualize {
wordTracer.select(i);
+ // }
i++;
}
+ // visualize {
Tracer.delay();
+ // }
while (c < word.length - 1) {
+ // visualize {
wordTracer.deselect(c);
+ // }
c++;
}
+ // visualize {
Tracer.delay();
+ // }
}
(function createSA(sa, word) {
@@ -44,19 +58,26 @@ function selectSuffix(word, i) {
sa[i][1] = word.slice(i);
selectSuffix(word, i);
+ // visualize {
saTracer.patch(i, 1, sa[i][1]);
Tracer.delay();
saTracer.depatch(i, 1);
Tracer.delay();
+ // }
}
}(suffixArray, word));
+// logger {
logger.println('Re-organizing Suffix Array in sorted order of suffixes using efficient sorting algorithm (O(N.log(N)))');
+// }
suffixArray.sort((a, b) => {
+ // logger {
logger.println(`The condition a [1] (${a[1]}) > b [1] (${b[1]}) is ${a[1] > b[1]}`);
+ // }
return a[1] > b[1];
});
+// visualize {
for (let i = 0; i < word.length; i++) {
saTracer.patch(i, 0, suffixArray[i][0]);
saTracer.patch(i, 1, suffixArray[i][1]);
@@ -65,3 +86,4 @@ for (let i = 0; i < word.length; i++) {
saTracer.depatch(i, 0);
saTracer.depatch(i, 1);
}
+// }
diff --git a/Uncategorized/Affine Cipher/code.js b/Uncategorized/Affine Cipher/code.js
index 934b6f6e..55bc0349 100644
--- a/Uncategorized/Affine Cipher/code.js
+++ b/Uncategorized/Affine Cipher/code.js
@@ -1,6 +1,10 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const plainText = 'secret';
+
+// define tracer variables {
const ptTracer = new Array1DTracer('Encryption');
const ctTracer = new Array1DTracer('Decryption');
const logger = new LogTracer();
@@ -8,6 +12,7 @@ Layout.setRoot(new VerticalLayout([ptTracer, ctTracer, logger]));
ptTracer.set(plainText);
Tracer.delay();
+// }
/*
code assumes that plainText contains ONLY LOWER CASE ALPHABETS
@@ -27,26 +32,34 @@ function encrypt(plainText) {
const index = alpha.charCodeAt(0) - 'a'.charCodeAt(0);
let result = ((keys.a * index) + keys.b).mod(N);
+ // logger {
logger.println(`Index of ${alpha} = ${index}`);
+ // }
result += 'a'.charCodeAt(0);
return String.fromCharCode(result);
}
+ // logger {
logger.println('Beginning Affine Encryption');
logger.println('Encryption formula: ((keys.a * indexOfAlphabet) + keys.b) % N');
logger.println(`keys.a=${keys.a}, keys.b=${keys.b}, N=${N}`);
+ // }
for (const i in plainText) {
+ // visualize {
ptTracer.select(i);
Tracer.delay();
ptTracer.deselect(i);
+ // }
cypherText += cryptAlpha(plainText[i]);
+ // visualize {
ptTracer.patch(i, cypherText.slice(-1));
Tracer.delay();
ptTracer.depatch(i);
+ // }
}
return cypherText;
@@ -62,34 +75,44 @@ function decrypt(cypherText) {
}
})());
+ // logger {
logger.println(`a-1 = ${aInverse}`);
+ // }
function decryptAlpha(alpha) {
const index = alpha.charCodeAt(0) - 'a'.charCodeAt(0);
let result = (aInverse * (index - keys.b)).mod(N);
+ // logger {
logger.println(`Index of ${alpha} = ${index}`);
+ // }
result += 'a'.charCodeAt(0);
return String.fromCharCode(result);
}
+ // logger {
logger.println('Beginning Affine Decryption');
logger.println('Decryption formula: (a-1 * (index - keys.b)) % N');
logger.println(`keys.b=${keys.b}, N=${N}`);
+ // }
for (const i in cypherText) {
+ // visualize {
ctTracer.select(i);
Tracer.delay();
ctTracer.deselect(i);
Tracer.delay();
+ // }
plainText += decryptAlpha(cypherText[i]);
+ // visualize {
ctTracer.patch(i, plainText.slice(-1));
Tracer.delay();
ctTracer.depatch(i);
Tracer.delay();
+ // }
}
return plainText;
diff --git a/Uncategorized/Caesar Cipher/code.js b/Uncategorized/Caesar Cipher/code.js
index 4edf6f16..b2c60e09 100644
--- a/Uncategorized/Caesar Cipher/code.js
+++ b/Uncategorized/Caesar Cipher/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const string = 'hello! how are you doing?';
const rotation = 5;
@@ -11,6 +13,7 @@ const alphabetMap = alphabet.split('').reduce((map, curr, idx) => {
return map;
}, {});
+// define tracer variables {
const encryptTracer = new Array1DTracer('Encryption');
const decryptTracer = new Array1DTracer('Decryption');
const logger = new LogTracer();
@@ -18,6 +21,7 @@ Layout.setRoot(new VerticalLayout([encryptTracer, decryptTracer, logger]));
encryptTracer.set(string);
Tracer.delay();
+// }
function getPosUp(pos) {
return (pos === alphabet.length - 1) ? 0 : pos + 1;
@@ -32,7 +36,9 @@ function getNextChar(currChar, direction) {
const nextPos = direction === 'up' ? getPosUp(pos) : getPosDown(pos);
const nextChar = alphabet.charAt(nextPos);
+ // logger {
logger.println(`${currChar} -> ${nextChar}`);
+ // }
return nextChar;
}
@@ -40,45 +46,65 @@ function cipher(str, rotation, direction, cipherTracer) {
if (!str) return '';
for (let i = 0; i < str.length; i++) {
+ // visualize {
Tracer.delay();
+ // }
let currChar = str.charAt(i);
if (typeof alphabetMap[currChar] === 'number') { // don't encrpt/decrypt characters not in alphabetMap
let r = rotation;
+ // logger {
logger.println(`Rotating ${currChar} ${direction} ${rotation} times`);
+ // }
+ // visualize {
cipherTracer.select(i);
Tracer.delay();
+ // }
// perform given amount of rotations in the given direction
while (r-- > 0) {
currChar = getNextChar(currChar, direction);
+ // visualize {
cipherTracer.patch(i, currChar);
Tracer.delay();
+ // }
}
} else {
+ // logger {
logger.println('Ignore this character');
+ // }
}
str = str.substring(0, i) + currChar + str.substring(i + 1);
+ // logger {
logger.println(`Current result: ${str}`);
+ // }
}
return str;
}
function encrypt(str, rotation) {
+ // logger {
logger.println(`Encrypting: ${str}`);
+ // }
return cipher(str, rotation, 'up', encryptTracer);
}
function decrypt(str, rotation) {
+ // logger {
logger.println(`Decrypting: ${str}`);
+ // }
return cipher(str, rotation, 'down', decryptTracer);
}
const encrypted = encrypt(string, rotation);
+// logger {
logger.println(`Encrypted result: ${encrypted}`);
+// }
decryptTracer.set(encrypted);
const decrypted = decrypt(encrypted, rotation);
+// logger {
logger.println(`Decrypted result: ${decrypted}`);
+// }
diff --git a/Uncategorized/Freivalds' Matrix-Multiplication Verification/code.js b/Uncategorized/Freivalds' Matrix-Multiplication Verification/code.js
index b2afff6c..86fce896 100644
--- a/Uncategorized/Freivalds' Matrix-Multiplication Verification/code.js
+++ b/Uncategorized/Freivalds' Matrix-Multiplication Verification/code.js
@@ -1,9 +1,12 @@
+// import visualization libraries {
const { Tracer, Array1DTracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const A = [[2, 3], [3, 4]];
const B = [[1, 0], [1, 2]];
const C = [[6, 5], [8, 7]];
+// define tracer variables {
const matrixATracer = new Array2DTracer('Matrix A');
const matrixBTracer = new Array2DTracer('Matrix B');
const matrixCTracer = new Array2DTracer('Matrix C');
@@ -15,6 +18,7 @@ matrixATracer.set(A);
matrixBTracer.set(B);
matrixCTracer.set(C);
Tracer.delay();
+// }
function FreivaldsAlgorithm() {
let k = 5;
@@ -26,7 +30,9 @@ function FreivaldsAlgorithm() {
const n = A.length;
while (k--) {
+ // logger {
logger.println(`Iterations remained: #${k}`);
+ // }
// Generate random vector
const r = [];
@@ -36,8 +42,10 @@ function FreivaldsAlgorithm() {
P.push(-1);
r.push((Math.random() < 0.5) << 0);
}
+ // visualize {
randomVectorTracer.set(r);
Tracer.delay();
+ // }
// Compute Br, Cr
const Br = [];
@@ -63,17 +71,23 @@ function FreivaldsAlgorithm() {
}
P.push(tmp);
}
+ // visualize {
resultVectorTracer.set(P);
Tracer.delay();
+ // }
for (i = 0; i < n; i++) {
if (P[i] !== 0) {
+ // logger {
logger.println(`P[${i}] !== 0 (${P[i]}), exit`);
+ // }
return false;
}
}
+ // logger {
logger.println('Result vector is identity, continue...');
+ // }
}
return true;
diff --git a/Uncategorized/Magic Square/code.js b/Uncategorized/Magic Square/code.js
index 88f62f5c..912f52d9 100644
--- a/Uncategorized/Magic Square/code.js
+++ b/Uncategorized/Magic Square/code.js
@@ -1,4 +1,6 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
const n = 7;
const A = new Array(n);
@@ -12,51 +14,67 @@ for (let i = n - 1; i >= 0; i--) {
}
}
+// define tracer variables {
const tracer = new Array2DTracer('Magic Square');
const logTracer = new LogTracer('Console');
Layout.setRoot(new VerticalLayout([tracer, logTracer]));
tracer.set(A);
Tracer.delay();
+// }
let i = Math.floor(n / 2);
let j = n - 1;
for (let num = 1; num <= n * n;) {
+ // logger {
logTracer.println(`i = ${i}`);
logTracer.println(`j = ${j}`);
+ // }
if (i === -1 && j === n) {
j = n - 2;
i = 0;
+ // logger {
logTracer.println('Changing : ');
logTracer.println(`i = ${i}`);
logTracer.println(`j = ${j}`);
+ // }
} else {
if (j === n) {
j = 0;
+ // logger {
logTracer.println(`Changing : j = ${j}`);
+ // }
}
if (i < 0) {
i = n - 1;
+ // logger {
logTracer.println(`Changing : i = ${i}`);
+ // }
}
}
if (A[i][j] > 0) {
+ // logger {
logTracer.println(`Cell already filled : Changing i = ${i} j = ${j}`);
+ // }
j -= 2;
i++;
} else {
A[i][j] = num++;
+ // visualize {
tracer.patch(i, j, A[i][j]);
Tracer.delay();
tracer.depatch(i, j);
tracer.select(i, j);
Tracer.delay();
+ // }
j++;
i--;
}
}
+// logger {
logTracer.println(`Magic Constant is ${n * (n * n + 1) / 2}`);
+// }
diff --git a/Uncategorized/Maze Generation/code.js b/Uncategorized/Maze Generation/code.js
index 835c62b1..223753ef 100644
--- a/Uncategorized/Maze Generation/code.js
+++ b/Uncategorized/Maze Generation/code.js
@@ -1,8 +1,7 @@
+// import visualization libraries {
const { Tracer, Array2DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
-const tracer = new Array2DTracer();
-const logger = new LogTracer();
-Layout.setRoot(new VerticalLayout([tracer, logger]));
const n = 6; // rows (change these!)
const m = 6; // columns (change these!)
@@ -56,8 +55,13 @@ for (let i = 0; i < vEnd; i++) { // by row
}
}
+// define tracer variables {
+const tracer = new Array2DTracer();
+const logger = new LogTracer();
+Layout.setRoot(new VerticalLayout([tracer, logger]));
tracer.set(G);
Tracer.delay();
+// }
function buildMaze() {
const mySet = new disjointSet();
@@ -73,7 +77,9 @@ function buildMaze() {
mySet.addElements(width * height);
+ // logger {
logger.println('initializing grid (all walls are up)');
+ // }
// init 'graph'
// each room has two walls, a down and right wall.
for (let i = 0; i < width; i++) {
@@ -91,7 +97,9 @@ function buildMaze() {
G[j * 2 + 1][i * 3 + 1] = locationString[0];
G[j * 2 + 1][i * 3 + 2] = locationString[1];
+ // visualize {
tracer.set(G);
+ // }
}
rightWalls.push({ x: i, y: j });
@@ -100,7 +108,9 @@ function buildMaze() {
}
}
+ // logger {
logger.println('shuffled the walls for random selection');
+ // }
// Randomly shuffle the walls
shuffle(rightWalls);
shuffle(downWalls);
@@ -117,26 +127,34 @@ function buildMaze() {
if (iYdown < height) {
const u = graph[iX][iY];
const v = graph[iX][iYdown];
+ // visualize {
tracer.patch(iY * 2 + 1, iX * 3 + 1);
tracer.patch(iY * 2 + 1, iX * 3 + 2);
tracer.patch(iYdown * 2 + 1, iX * 3 + 1);
tracer.patch(iYdown * 2 + 1, iX * 3 + 2);
+ // }
if (mySet.find(u) !== mySet.find(v)) {
+ // logger {
logger.println(`Rooms: ${u} & ${v} now belong to the same set, delete wall between them`);
Tracer.delay();
+ // }
mySet.setUnion(u, v);
setSize++;
// delete wall
walls[u].down = false;
} else {
+ // logger {
logger.println(`Rooms: ${u} & ${v} would create a cycle! This is not good!`);
Tracer.delay();
+ // }
}
+ // visualize {
tracer.depatch(iY * 2 + 1, iX * 3 + 1);
tracer.depatch(iY * 2 + 1, iX * 3 + 2);
tracer.depatch(iYdown * 2 + 1, iX * 3 + 1);
tracer.depatch(iYdown * 2 + 1, iX * 3 + 2);
+ // }
}
} else if (randomWall === 2 && rightWalls.length > 0) {
// Right Wall
@@ -147,31 +165,41 @@ function buildMaze() {
if (iXright < width) {
const u = graph[iX][iY];
const v = graph[iXright][iY];
+ // visualize {
tracer.patch(iY * 2 + 1, iX * 3 + 1);
tracer.patch(iY * 2 + 1, iX * 3 + 2);
tracer.patch(iY * 2 + 1, iXright * 3 + 1);
tracer.patch(iY * 2 + 1, iXright * 3 + 2);
+ // }
if (mySet.find(u) !== mySet.find(v)) {
+ // logger {
logger.println(`Rooms: ${u} & ${v} now belong to the same set, delete wall between them`);
Tracer.delay();
+ // }
mySet.setUnion(u, v);
setSize++;
// delete wall
walls[u].right = false;
} else {
+ // logger {
logger.println(`Rooms: ${u} & ${v} would create a cycle! This is not good!`);
Tracer.delay();
+ // }
}
+ // visualize {
tracer.depatch(iY * 2 + 1, iX * 3 + 1);
tracer.depatch(iY * 2 + 1, iX * 3 + 2);
tracer.depatch(iY * 2 + 1, iXright * 3 + 1);
tracer.depatch(iY * 2 + 1, iXright * 3 + 2);
+ // }
}
}
}
+ // logger {
logger.println('deleting the walls');
+ // }
// update deleted walls
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
@@ -180,28 +208,38 @@ function buildMaze() {
if (currentWall.down === false) {
G[j * 2 + 2][i * 3 + 1] = ' ';
G[j * 2 + 2][i * 3 + 2] = ' ';
+ // visualize {
tracer.select(j * 2 + 2, i * 3 + 1);
Tracer.delay();
tracer.select(j * 2 + 2, i * 3 + 2);
Tracer.delay();
+ // }
}
if (currentWall.right === false) {
G[j * 2 + 1][i * 3 + 3] = ' ';
+ // visualize {
tracer.select(j * 2 + 1, i * 3 + 3);
Tracer.delay();
+ // }
}
+ // visualize {
tracer.set(G);
+ // }
}
}
+ // logger {
logger.println('cleaning up the grid!');
+ // }
cleanUpGrid(width, height);
// Clear out walls for the start and end locations.
const randomStart = Math.floor(Math.random() * width);
const randomEnd = Math.floor(Math.random() * width);
+ // logger {
logger.println('setting the Start (S) & End (E) locations');
+ // }
// Start Location
G[0][randomStart * 3 + 1] = ' ';
@@ -216,10 +254,14 @@ function buildMaze() {
cleanUpStartLocation(randomStart);
cleanUpEndLocation(randomEnd);
+ // logger {
logger.println('maze is completed!');
+ // }
// set the data
+ // visualize {
tracer.set(G);
+ // }
}
function cleanUpStartLocation(start) {
diff --git a/Uncategorized/Miller-Rabin's Primality Test/code.js b/Uncategorized/Miller-Rabin's Primality Test/code.js
index 91eec368..50a374e9 100644
--- a/Uncategorized/Miller-Rabin's Primality Test/code.js
+++ b/Uncategorized/Miller-Rabin's Primality Test/code.js
@@ -1,18 +1,26 @@
+// import visualization libraries {
const { Tracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
+// }
+// define tracer variables {
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([logger]));
Tracer.delay();
+// }
for (let i = 0; i < 3; i++) {
let a = Math.floor(Math.random() * 300);
if (a % 2 === 0) a += 1;
testProbablyPrime(a);
+ // visualize {
logger.println('----------');
+ // }
}
testProbablyPrime(151);
+// visualize {
logger.println('----------');
+// }
testProbablyPrime(199, 10);
@@ -39,14 +47,20 @@ function power(x, y, p) {
* @return {Boolean}
*/
function testProbablyPrime(n, k = 5) {
+ // visualize {
logger.println(`==> Testing number ${n}`);
+ // }
if (n === 1 || n === 3) {
+ // visualize {
logger.println('==> Simple case, N is 1 or 3');
+ // }
return true;
}
if (n % 2 === 0) {
+ // visualize {
logger.println(`==> Simple case, ${n} mod 2 = 0`);
+ // }
return false;
}
@@ -55,25 +69,35 @@ function testProbablyPrime(n, k = 5) {
while (d % 2 === 0) {
d /= 2;
}
+ // visualize {
logger.println(`d = ${d}`);
+ // }
const P = 100 * (1 - (1 / Math.pow(4, k)));
WitnessLoop: do {
+ // visualize {
logger.println(`Remaining iterations: #${k}`);
+ // }
const a = 2 + Math.floor(Math.random() * (n - 4));
+ // visualize {
logger.println(`--> first test with random = ${a}`);
+ // }
// Compute a^d % n
let x = power(a, d, n);
if (x === 1 || x === n - 1) {
+ // visualize {
logger.println('--> continue WitnessLoop, x = 1 or x = n-1');
+ // }
continue;
}
+ // visualize {
logger.println('--> second test');
+ // }
// Keep squaring x while one of the following doesn't
// happen
@@ -86,20 +110,28 @@ function testProbablyPrime(n, k = 5) {
i *= 2;
if (x === 1) {
+ // visualize {
logger.println(`--> exiting, ${n} is composite`);
+ // }
return false;
}
if (x === n - 1) {
+ // visualize {
logger.println('--> continue WitnessLoop');
+ // }
continue WitnessLoop;
}
}
+ // visualize {
logger.println(`--> exiting, ${n} is composite 'cause (n-1) is reached`);
+ // }
return false;
} while (--k);
+ // visualize {
logger.println(`End of tests, ${n} is probably prime with probabilty of ${P}%`);
+ // }
return true;
}