├── README.md ├── bfs.js ├── bubblSort.js ├── dijkstra.js ├── dna.js ├── krish.jpeg ├── krishna.jpg ├── pixelDrawing.js ├── rainDrops.js ├── ramayana.png ├── snowfallCanvas.js └── snowfallRamayana.js /README.md: -------------------------------------------------------------------------------- 1 | ## Visuals based on various algorithms 2 | 3 | To run the code, open any file you like, copy and paste the code here and hit the play button at the top right corner 4 | -------------------------------------------------------------------------------- /bfs.js: -------------------------------------------------------------------------------- 1 | let grid; 2 | let cols = 20; 3 | let rows = 20; 4 | let cellSize; 5 | let start, end; 6 | let openSet = []; 7 | let closedSet = []; 8 | let path = []; 9 | let current; 10 | let finished = false; 11 | let stepCounter = 0; 12 | let speed = 5; // Number of frames to wait before each step 13 | let lerpAmount = 5; // Amount for interpolation 14 | 15 | // New soothing color scheme 16 | let bgColor; 17 | let wallColor; 18 | let cellColor; 19 | let openSetColor; 20 | let closedSetColor; 21 | let pathColor; 22 | let connectionColor; 23 | let startColor; 24 | let endColor; 25 | 26 | function setup() { 27 | createCanvas(600, 600); 28 | cellSize = width / cols; 29 | 30 | // Initialize new color scheme 31 | bgColor = color(230, 230, 250); // Lavender mist 32 | wallColor = color(62.5); // Light steel blue 33 | cellColor = color(255, 255, 255, 150); // Semi-transparent white 34 | openSetColor = color(152, 251, 152, 200); // Pale green 35 | closedSetColor = color(255, 182, 193, 150); // Light pink 36 | pathColor = color(70, 130, 180); // Steel blue 37 | connectionColor = color(221, 160, 221, 150); // Plum 38 | startColor = color(50, 205, 50); // Lime green 39 | endColor = color(255, 99, 71); // Tomato 40 | 41 | // Create and initialize grid 42 | grid = Array.from({ length: cols }, (_, i) => 43 | Array.from({ length: rows }, (_, j) => new Cell(i, j)) 44 | ); 45 | 46 | // Set neighbors 47 | for (let i = 0; i < cols; i++) { 48 | for (let j = 0; j < rows; j++) { 49 | grid[i][j].addNeighbors(grid); 50 | } 51 | } 52 | 53 | // Set start and end 54 | start = grid[0][0]; 55 | end = grid[cols-1][rows-1]; 56 | 57 | // Add walls randomly 58 | for (let i = 0; i < cols; i++) { 59 | for (let j = 0; j < rows; j++) { 60 | if (random(1) < 0.3) { 61 | grid[i][j].wall = true; 62 | } 63 | } 64 | } 65 | start.wall = false; 66 | end.wall = false; 67 | 68 | openSet.push(start); 69 | } 70 | 71 | function draw() { 72 | background(bgColor); 73 | 74 | if (!finished) { 75 | if (stepCounter % speed === 0) { 76 | // BFS algorithm step 77 | if (openSet.length > 0) { 78 | current = openSet.shift(); 79 | 80 | if (current === end) { 81 | console.log("DONE!"); 82 | finished = true; 83 | } 84 | 85 | closedSet.push(current); 86 | 87 | let neighbors = current.neighbors; 88 | for (let i = 0; i < neighbors.length; i++) { 89 | let neighbor = neighbors[i]; 90 | 91 | if (!closedSet.includes(neighbor) && !neighbor.wall) { 92 | if (!openSet.includes(neighbor)) { 93 | openSet.push(neighbor); 94 | neighbor.previous = current; 95 | } 96 | } 97 | } 98 | } else { 99 | console.log("No solution"); 100 | noLoop(); 101 | return; 102 | } 103 | 104 | // Find path 105 | path = []; 106 | let temp = current; 107 | path.push(temp); 108 | while (temp.previous) { 109 | path.push(temp.previous); 110 | temp = temp.previous; 111 | } 112 | lerpAmount = 0; // Reset interpolation amount 113 | } 114 | stepCounter++; 115 | } 116 | 117 | // Interpolation update 118 | lerpAmount += 0.1; // Adjust speed of interpolation 119 | if (lerpAmount > 1) lerpAmount = 1; 120 | 121 | // Draw grid 122 | for (let i = 0; i < cols; i++) { 123 | for (let j = 0; j < rows; j++) { 124 | grid[i][j].show(); 125 | } 126 | } 127 | 128 | // Draw path 129 | noFill(); 130 | stroke(pathColor); 131 | strokeWeight(3); 132 | beginShape(); 133 | for (let i = 0; i < path.length - 1; i++) { 134 | let x1 = path[i].i * cellSize + cellSize / 2; 135 | let y1 = path[i].j * cellSize + cellSize / 2; 136 | let x2 = path[i + 1].i * cellSize + cellSize / 2; 137 | let y2 = path[i + 1].j * cellSize + cellSize / 2; 138 | let lx = lerp(x1, x2, lerpAmount); 139 | let ly = lerp(y1, y2, lerpAmount); 140 | vertex(lx, ly); 141 | } 142 | endShape(); 143 | } 144 | 145 | class Cell { 146 | constructor(i, j) { 147 | this.i = i; 148 | this.j = j; 149 | this.neighbors = []; 150 | this.previous = undefined; 151 | this.wall = false; 152 | } 153 | 154 | addNeighbors(grid) { 155 | let i = this.i; 156 | let j = this.j; 157 | if (i < cols - 1) this.neighbors.push(grid[i+1][j]); 158 | if (i > 0) this.neighbors.push(grid[i-1][j]); 159 | if (j < rows - 1) this.neighbors.push(grid[i][j+1]); 160 | if (j > 0) this.neighbors.push(grid[i][j-1]); 161 | } 162 | 163 | show() { 164 | stroke(100); 165 | strokeWeight(1); 166 | if (this.wall) { 167 | fill(wallColor); 168 | } else if (this === start) { 169 | fill(startColor); 170 | } else if (this === end) { 171 | fill(endColor); 172 | } else if (closedSet.includes(this)) { 173 | fill(closedSetColor); 174 | } else if (openSet.includes(this)) { 175 | fill(openSetColor); 176 | } else { 177 | fill(cellColor); 178 | } 179 | ellipse(this.i * cellSize + cellSize / 2, this.j * cellSize + cellSize / 2, cellSize * 0.7, cellSize * 0.7); 180 | 181 | // Connect to previous cell 182 | if (this.previous) { 183 | stroke(connectionColor); 184 | line(this.i * cellSize + cellSize / 2, this.j * cellSize + cellSize / 2, 185 | this.previous.i * cellSize + cellSize / 2, this.previous.j * cellSize + cellSize / 2); 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /bubblSort.js: -------------------------------------------------------------------------------- 1 | 2 | let values = []; 3 | let i = 0; 4 | let j = 0; 5 | let sorted = false; 6 | 7 | function setup() { 8 | createCanvas(windowWidth, windowHeight); 9 | values = new Array(floor(width / 10)).fill().map(() => random(height)); 10 | frameRate(30); 11 | } 12 | 13 | function draw() { 14 | background(30); 15 | 16 | if (!sorted) { 17 | if (i < values.length) { 18 | for (let k = 0; k < values.length - i - 1; k++) { 19 | let a = values[k]; 20 | let b = values[k + 1]; 21 | 22 | if (a > b) { 23 | values[k] = b; 24 | values[k + 1] = a; 25 | } 26 | } 27 | i++; 28 | } else { 29 | sorted = true; 30 | } 31 | } 32 | 33 | for (let i = 0; i < values.length; i++) { 34 | stroke(255); 35 | let col = map(values[i], 0, height, 0, 255); 36 | fill(col, 100, 255 - col, 150); 37 | rect(i * 10, height - values[i], 10, values[i], 5); 38 | } 39 | 40 | drawFrame(); 41 | } 42 | 43 | function drawFrame() { 44 | strokeWeight(4); 45 | noFill(); 46 | stroke(255); 47 | rect(0, 0, width, height); 48 | } 49 | -------------------------------------------------------------------------------- /dijkstra.js: -------------------------------------------------------------------------------- 1 | let grid; 2 | let cols = 30; 3 | let rows = 30; 4 | let cellSize; 5 | let start, end; 6 | let openSet = []; 7 | let closedSet = []; 8 | let path = []; 9 | let current; 10 | let finished = false; 11 | let animationProgress = 0; 12 | 13 | // Apple-inspired color scheme 14 | let bgColor, cellColor, wallColor, openSetColor, closedSetColor, pathColor, startColor, endColor, gridColor; 15 | 16 | function setup() { 17 | createCanvas(600, 600); 18 | cellSize = min(width * 0.9 / cols, height * 0.9 / rows); 19 | 20 | // Initialize Apple-inspired color scheme 21 | bgColor = color(245, 245, 247); 22 | cellColor = color(255, 255, 255); 23 | wallColor = color(220, 220, 225); 24 | openSetColor = color(0, 122, 255, 150); 25 | closedSetColor = color(88, 86, 214, 100); 26 | pathColor = color(255, 149, 0); 27 | startColor = color(52, 199, 89); 28 | endColor = color(255, 59, 48); 29 | gridColor = color(230, 230, 230); 30 | 31 | initializeGrid(); 32 | } 33 | 34 | function initializeGrid() { 35 | grid = Array.from({ length: cols }, (_, i) => 36 | Array.from({ length: rows }, (_, j) => new Cell(i, j)) 37 | ); 38 | 39 | for (let i = 0; i < cols; i++) { 40 | for (let j = 0; j < rows; j++) { 41 | grid[i][j].addNeighbors(grid); 42 | } 43 | } 44 | 45 | start = grid[0][0]; 46 | end = grid[cols-1][rows-1]; 47 | 48 | for (let i = 0; i < cols; i++) { 49 | for (let j = 0; j < rows; j++) { 50 | if (random(1) < 0.3) { 51 | grid[i][j].wall = true; 52 | } 53 | } 54 | } 55 | start.wall = false; 56 | end.wall = false; 57 | 58 | start.distance = 0; 59 | openSet.push(start); 60 | } 61 | 62 | function draw() { 63 | background(bgColor); 64 | drawGrid(); 65 | updateAlgorithm(); 66 | drawPath(); 67 | } 68 | 69 | function drawGrid() { 70 | let offsetX = (width - cols * cellSize) / 2; 71 | let offsetY = (height - rows * cellSize) / 2; 72 | 73 | for (let i = 0; i < cols; i++) { 74 | for (let j = 0; j < rows; j++) { 75 | grid[i][j].show(offsetX, offsetY); 76 | } 77 | } 78 | } 79 | 80 | function updateAlgorithm() { 81 | if (!finished && frameCount % 3 === 0) { 82 | if (openSet.length > 0) { 83 | current = openSet.reduce((a, b) => a.distance < b.distance ? a : b); 84 | 85 | if (current === end) { 86 | console.log("Path found!"); 87 | finished = true; 88 | return; 89 | } 90 | 91 | openSet = openSet.filter(cell => cell !== current); 92 | closedSet.push(current); 93 | 94 | for (let neighbor of current.neighbors) { 95 | if (!closedSet.includes(neighbor) && !neighbor.wall) { 96 | let tentativeDistance = current.distance + 1; 97 | 98 | if (tentativeDistance < neighbor.distance) { 99 | neighbor.distance = tentativeDistance; 100 | neighbor.previous = current; 101 | if (!openSet.includes(neighbor)) { 102 | openSet.push(neighbor); 103 | } 104 | } 105 | } 106 | } 107 | } else { 108 | console.log("No path found"); 109 | finished = true; 110 | return; 111 | } 112 | 113 | path = []; 114 | let temp = current; 115 | path.push(temp); 116 | while (temp.previous) { 117 | path.push(temp.previous); 118 | temp = temp.previous; 119 | } 120 | } 121 | 122 | animationProgress = lerp(animationProgress, 1, 0.1); 123 | } 124 | 125 | function drawPath() { 126 | if (path.length > 0) { 127 | let offsetX = (width - cols * cellSize) / 2; 128 | let offsetY = (height - rows * cellSize) / 2; 129 | 130 | noFill(); 131 | stroke(pathColor); 132 | strokeWeight(cellSize / 3); 133 | beginShape(); 134 | for (let i = 0; i < path.length * animationProgress; i++) { 135 | let cell = path[i]; 136 | let x = offsetX + cell.i * cellSize + cellSize / 2; 137 | let y = offsetY + cell.j * cellSize + cellSize / 2; 138 | curveVertex(x, y); 139 | } 140 | endShape(); 141 | } 142 | } 143 | 144 | class Cell { 145 | constructor(i, j) { 146 | this.i = i; 147 | this.j = j; 148 | this.neighbors = []; 149 | this.previous = undefined; 150 | this.wall = false; 151 | this.distance = Infinity; 152 | this.animationProgress = 0; 153 | } 154 | 155 | addNeighbors(grid) { 156 | let i = this.i; 157 | let j = this.j; 158 | if (i < cols - 1) this.neighbors.push(grid[i+1][j]); 159 | if (i > 0) this.neighbors.push(grid[i-1][j]); 160 | if (j < rows - 1) this.neighbors.push(grid[i][j+1]); 161 | if (j > 0) this.neighbors.push(grid[i][j-1]); 162 | } 163 | 164 | show(offsetX, offsetY) { 165 | let x = offsetX + this.i * cellSize; 166 | let y = offsetY + this.j * cellSize; 167 | 168 | if (this.wall) { 169 | fill(wallColor); 170 | } else if (this === start) { 171 | fill(startColor); 172 | } else if (this === end) { 173 | fill(endColor); 174 | } else if (closedSet.includes(this)) { 175 | fill(lerpColor(cellColor, closedSetColor, this.animationProgress)); 176 | } else if (openSet.includes(this)) { 177 | fill(lerpColor(cellColor, openSetColor, this.animationProgress)); 178 | } else { 179 | fill(cellColor); 180 | } 181 | 182 | noStroke(); 183 | rect(x, y, cellSize, cellSize, cellSize / 4); 184 | 185 | if (closedSet.includes(this) || openSet.includes(this)) { 186 | this.animationProgress = lerp(this.animationProgress, 1, 0.1); 187 | } 188 | } 189 | } 190 | 191 | function heuristic(a, b) { 192 | return dist(a.i, a.j, b.i, b.j); 193 | } 194 | -------------------------------------------------------------------------------- /dna.js: -------------------------------------------------------------------------------- 1 | function setup(){ 2 | createCanvas(windowWidth,windowHeight); 3 | } 4 | let t = 0; 5 | function draw(){ 6 | background('#0a6078'); 7 | translate(width/2,-5*height); 8 | for(let i = 0;i<500;i++){ 9 | strokeWeight(2); 10 | fill('#dadada'); 11 | stroke('#dadada'); 12 | line(xa1(t+i),ya1(t+i),xa2(t+i)+20,ya2(t+i)+20); 13 | circle(xa1(t+i),ya1(t+i),5); 14 | circle(xa2(t+i)+20,ya2(t+i)+20,5); 15 | strokeWeight(2); 16 | fill('#dadada'); 17 | stroke('#dadada'); 18 | line(x1(t+i),y1(t+i),x2(t+i)+20,y2(t+i)+20); 19 | circle(x1(t+i),y1(t+i),3); 20 | circle(x2(t+i)+20,y2(t+i)+20,3); 21 | } 22 | t+=0.075; 23 | } 24 | 25 | function x1(t){ 26 | return sin(t/10)*100; 27 | } 28 | 29 | function y1(t){ 30 | return (t/10)*100; 31 | } 32 | 33 | function x2(t){ 34 | return -sin(t/10)*100; 35 | } 36 | 37 | function y2(t){ 38 | return (t/10)*100; 39 | } 40 | 41 | function xa1(t){ 42 | return -cos(t/10)*100; 43 | } 44 | 45 | function ya1(t){ 46 | return (t/10)*100; 47 | } 48 | 49 | function xa2(t){ 50 | return cos(t/10)*100; 51 | } 52 | 53 | function ya2(t){ 54 | return (t/10)*100; 55 | } 56 | 57 | function xb1(t){ 58 | return -((cos(t/10)+sin(t/10)))*100; 59 | } 60 | 61 | function yb1(t){ 62 | return (t/10)*100; 63 | } 64 | 65 | function xb2(t){ 66 | return ((cos(t/10)+sin(t/10)))*100; 67 | } 68 | 69 | function yb2(t){ 70 | return (t/10)*100; 71 | } 72 | -------------------------------------------------------------------------------- /krish.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoyron/algoVisuals/f8c42ad8444f0b48733f264963df3cbea57b078b/krish.jpeg -------------------------------------------------------------------------------- /krishna.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoyron/algoVisuals/f8c42ad8444f0b48733f264963df3cbea57b078b/krishna.jpg -------------------------------------------------------------------------------- /pixelDrawing.js: -------------------------------------------------------------------------------- 1 | let img; 2 | let testImg; 3 | let points = []; 4 | const numPoints = 15000; 5 | 6 | function preload() { 7 | img = loadImage("./krishna.jpg"); 8 | } 9 | 10 | function setup() { 11 | testImg = createImage(img.width, img.height); 12 | createCanvas(img.width, img.height); 13 | background(0); 14 | img.loadPixels(); 15 | testImg.loadPixels(); 16 | for (let i = 0; i < img.width; i++) { 17 | for (let j = 0; j < img.height; j++) { 18 | testImg.set(i, j, color(img.get(i, j))); 19 | } 20 | } 21 | testImg.updatePixels(); 22 | 23 | for (let i = 0; i < numPoints; i++) { 24 | points.push(createVector(random(width), random(height))); 25 | } 26 | } 27 | 28 | function draw() { 29 | background(0, 10); 30 | 31 | for (let i = 0; i < points.length; i++) { 32 | let p = points[i]; 33 | 34 | let angle = noise(p.x * 0.005, p.y * 0.005, frameCount * 0.01) * TWO_PI * 2; 35 | let speed = noise(p.x * 0.005, p.y * 0.005, frameCount * 0.01 + 1000) * 2; 36 | 37 | let newX = p.x + cos(angle) * speed; 38 | let newY = p.y + sin(angle) * speed; 39 | 40 | let c = testImg.get(int(p.x), int(p.y)); 41 | stroke(c); 42 | strokeWeight(0.5); 43 | line(p.x, p.y, newX, newY); 44 | 45 | points[i].set(newX, newY); 46 | 47 | if (newX < 0 || newX > width || newY < 0 || newY > height) { 48 | points[i].set(random(width), random(height)); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /rainDrops.js: -------------------------------------------------------------------------------- 1 | class Rain{ 2 | constructor(){ 3 | this.x = random(-width,width); 4 | this.y = random(-height,height); 5 | this.z = random(width); 6 | } 7 | 8 | show(){ 9 | fill(200, 200, 200); 10 | noStroke(); 11 | this.sx = map(this.x/this.z,0,1,0,width); 12 | this.sy = map(this.y/this.z,0,1,0,height); 13 | this.r = map(this.z,0,width,8,0); 14 | circle(this.sx,this.sy,this.r); 15 | } 16 | update(){ 17 | this.z = this.z-6; 18 | if(this.z<1){ 19 | this.x = random(-width,width); 20 | this.y = random(-height,height); 21 | this.z = width; 22 | } 23 | } 24 | } 25 | 26 | let drops = []; 27 | 28 | function setup(){ 29 | createCanvas(windowWidth,windowHeight); 30 | for(let i = 0;i<2500;i++){ 31 | let tempo = new Rain(); 32 | drops.push(tempo); 33 | } 34 | } 35 | 36 | function draw(){ 37 | translate(width/2,height/2); 38 | background(0); 39 | for(let i = 0;i height) { 53 | let index = snowflakes.indexOf(this); 54 | snowflakes.splice(index, 1); 55 | } 56 | }; 57 | 58 | this.display = function() { 59 | fill(color(img.get(this.posX, this.posY))); 60 | ellipse(this.posX, this.posY, this.size); 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /snowfallRamayana.js: -------------------------------------------------------------------------------- 1 | // snowflakes is an array of snowflake objects 2 | let snowflakes = []; 3 | let img; 4 | let xoff = 0; 5 | let scaleFactor = 7/10; // Scale factor for the canvas size 6 | 7 | // preload() is a special function in P5.js that runs once before setup() 8 | function preload() { 9 | // load the image (Ramayana.png) into the img variable 10 | img = loadImage('./ramayana.png'); 11 | } 12 | 13 | // setup() is a special function in P5.js that runs once after preload() 14 | function setup() { 15 | // create a canvas with the same size as the image, but scaled down by scaleFactor 16 | createCanvas(img.width * scaleFactor, img.height * scaleFactor); 17 | // disable drawing outlines around shapes 18 | noStroke(); 19 | // set the background color to black 20 | background("#000000"); 21 | // set the frame rate to 45 frames per second 22 | frameRate(45); 23 | } 24 | 25 | // draw() is a special function in P5.js that runs continuously after setup() 26 | function draw() { 27 | // calculate the time since the last frame was drawn 28 | let t = frameCount / 90; 29 | 30 | // create a random number of snowflakes each frame 31 | for (let i = 0; i < random(50); i++) { 32 | // create a new snowflake object and add it to the snowflakes array 33 | snowflakes.push(new snowflake()); 34 | } 35 | 36 | // loop through snowflakes with a for..of loop 37 | for (let flake of snowflakes) { 38 | // update the position of the snowflake 39 | flake.update(t); 40 | // draw the snowflake 41 | flake.display(); 42 | } 43 | 44 | // increment xoff by 1.0 each frame 45 | xoff += 1.0; 46 | } 47 | 48 | // snowflake is a constructor function that creates a new snowflake object 49 | function snowflake() { 50 | // set the initial position of the snowflake 51 | this.posX = random(width); 52 | this.posY = random(-50, 0); 53 | // set the initial angle of the snowflake 54 | this.initialangle = random(0, 2 * PI); 55 | // set the size of the snowflake 56 | this.size = random(1, 3) * scaleFactor; 57 | // set the radius of the snowflake 58 | this.radius = sqrt(random(pow(width / 2, 2))); 59 | 60 | // update() is a method that updates the position of the snowflake 61 | this.update = function(time) { 62 | // angular speed 63 | let w = 1.6; 64 | // calculate the angle of the snowflake 65 | let angle = w * time + this.initialangle; 66 | // update the position of the snowflake 67 | this.posX = width / 2 + this.radius * sin(angle); 68 | this.posY += pow(this.size / scaleFactor, 0.5) * 2 * scaleFactor; 69 | 70 | // if the snowflake has gone off the bottom of the screen, remove it from the array 71 | if (this.posY > height) { 72 | let index = snowflakes.indexOf(this); 73 | snowflakes.splice(index, 1); 74 | } 75 | }; 76 | 77 | // display() is a method that draws the snowflake 78 | this.display = function() { 79 | // calculate the x and y coordinates of the snowflake on the original image 80 | let imgX = this.posX / scaleFactor; 81 | let imgY = this.posY / scaleFactor; 82 | // get the color of the pixel at the calculated coordinates 83 | fill(color(img.get(imgX, imgY))); 84 | // draw an ellipse at the position of the snowflake 85 | ellipse(this.posX, this.posY, this.size); 86 | }; 87 | 88 | } 89 | --------------------------------------------------------------------------------