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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy