Build a Sorting Visualizer - Step 18

Tell us what’s happening:

This test keeps failing:

After you click #sort-btn, #array-container should contain as many div elements as the steps required by the Bubble Sort algorithm to sort the starting array, including the div representing the starting array and a div representing the sorted array.

please help.

Your code so far

<!-- file: index.html -->

function generateElement() {
  return Math.floor(Math.random() * 100) + 1;
}

function generateArray() {
  return Array.from({ length: 5 }, generateElement);
}

// Updates the container with the given array
function fillArrContainer(container, arr) {
  container.innerHTML = "";
  arr.forEach(num => {
    const span = document.createElement("span");
    span.textContent = num;
    span.style.margin = "5px";
    container.appendChild(span);
  });
}

// Checks if two elements are in order
function isOrdered(a, b) {
  return a <= b; 
}

// Swaps adjacent elements if needed
function swapElements(arr, i) {
  if (arr[i] > arr[i + 1]) {
    [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]];
  }
}

// Highlights current elements being compared
function highlightCurrentEls(container, index, borderWidth = "2px") {
  for (let k = 0; k < container.children.length; k++) {
    container.children[k].style.border = "none";
  }
  if (index < container.children.length - 1) {
    container.children[index].style.border = `${borderWidth} dashed red`;
    container.children[index + 1].style.border = `${borderWidth} dashed red`;
  }
}

// Generates a div container for sorting steps
function generateContainer() {
  const div = document.createElement("div");
  div.style.margin = "5px";
  return div;
}

const generateBtn = document.getElementById("generate-btn");
const sortBtn = document.getElementById("sort-btn");
const arrayContainer = document.getElementById("array-container");
const startingArray = document.getElementById("starting-array");

generateBtn.addEventListener("click", () => {
  // Reset array container, keeping only the starting array
  [...arrayContainer.children].forEach(child => {
    if (child !== startingArray) {
      arrayContainer.removeChild(child);
    }
  });

  // Generate and display a new array
  const newNumbers = generateArray();
  fillArrContainer(startingArray, newNumbers);
});

sortBtn.addEventListener("click", () => {
  const spans = [...startingArray.children];
  if (!spans.length) return;
  
  // Copy numbers from the displayed array
  let workingArray = spans.map(span => parseInt(span.textContent));

  // Reset previous sorting steps
  [...arrayContainer.children].forEach(child => {
    if (child !== startingArray) {
      arrayContainer.removeChild(child);
    }
  });

  // Perform bubble sort with step visualization
  for (let i = 0; i < workingArray.length - 1; i++) {
    for (let j = 0; j < workingArray.length - 1 - i; j++) {
      if (!isOrdered(workingArray[j], workingArray[j + 1])) {
        swapElements(workingArray, j);
      }

      // Display the current step
      const stepDiv = generateContainer();
      fillArrContainer(stepDiv, workingArray);
      highlightCurrentEls(stepDiv, j);
      arrayContainer.appendChild(stepDiv);
    }
  }
});


/* file: styles.css */

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36

Challenge Information:

Build a Sorting Visualizer - Build a Sorting Visualizer

Where did you get stuck debugging this code?

are you sure you have all the required steps? notice how the example app doesn’t skip comparisons

I’m modified it so all elements are compared in each iteration. But I still have the same problem.

Please post your updated code

function generateElement() {
  return Math.floor(Math.random() * 100) + 1;
}

function generateArray() {
  return Array.from({ length: 5 }, generateElement);
}


function fillArrContainer(container, arr) {
  container.innerHTML = "";
  arr.forEach(num => {
    const span = document.createElement("span");
    span.textContent = num;
    span.style.margin = "5px";
    container.appendChild(span);
  });
}

function isOrdered(a, b) {
  return a <= b;
}


function swapElements(arr, i) {
  if (arr[i] > arr[i + 1]) {
    [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]];
  }
}


function highlightCurrentEls(container, index, borderWidth = "2px") {
  if (!container.children.length) return;
  for (let k = 0; k < container.children.length; k++) {
    container.children[k].style.border = "none";
  }
  if (index < container.children.length - 1) {
    container.children[index].style.border = `${borderWidth} dashed red`;
    container.children[index + 1].style.border = `${borderWidth} dashed red`;
  }
}


function generateContainer() {
  const div = document.createElement("div");
  div.style.margin = "5px";
  return div;
}

const generateBtn = document.getElementById("generate-btn");
const sortBtn = document.getElementById("sort-btn");
const arrayContainer = document.getElementById("array-container");
const startingArray = document.getElementById("starting-array");


generateBtn.addEventListener("click", () => {
  while (arrayContainer.children.length > 1) {
    arrayContainer.removeChild(arrayContainer.lastChild);
  }
  const newNumbers = generateArray();
  fillArrContainer(startingArray, newNumbers);
});


sortBtn.addEventListener("click", () => {
  const spans = Array.from(startingArray.children);
  if (spans.length < 5) return; 
  

  highlightCurrentEls(startingArray, 0);
  

  while (arrayContainer.children.length > 1) {
    arrayContainer.removeChild(arrayContainer.lastChild);
  }
  

  let workingArray = spans.map(span => parseInt(span.textContent));
  
  
  for (let i = 0; i < workingArray.length - 1; i++) {
    for (let j = 0; j < workingArray.length - 1; j++) {
      if (!isOrdered(workingArray[j], workingArray[j + 1])) {
        swapElements(workingArray, j);
      }
     
      const stepDiv = generateContainer();
      fillArrContainer(stepDiv, workingArray);
      highlightCurrentEls(stepDiv, j);
      arrayContainer.appendChild(stepDiv);
    }
  }
  
  
  const finalStep = generateContainer();
  fillArrContainer(finalStep, workingArray);

  arrayContainer.appendChild(finalStep);
});

You need to first highlight two numbers, then swap them if needed in the next line, but see here:
image
You should highlight 73 and 19 on the top row and have them swapped in the bottom row

I think the issue is from the start:
image

you should have the highlight in the second row to be the second and third item

I fixed that issue but still not passing tests 18, 19 and 21. Here’s my code:

function generateElement() {
  return Math.floor(Math.random() * 100) + 1;
}

function generateArray() {
  return Array.from({ length: 5 }, generateElement);
}

function fillArrContainer(container, arr) {
  container.innerHTML = "";
  arr.forEach(num => {
    const span = document.createElement("span");
    span.textContent = num;
    span.style.margin = "5px";
    container.appendChild(span);
  });
}

function isOrdered(a, b) {
  return a <= b;
}

function swapElements(arr, i) {
  if (!isOrdered(arr[i], arr[i + 1])) {
    [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]];
    return true;
  }
  return false;
}

function highlightCurrentEls(container, index) {
  for (let k = 0; k < container.children.length; k++) {
    container.children[k].style.border = "none";
  }
  if (index < container.children.length - 1) {
    container.children[index].style.border = "2px dashed red";
    container.children[index + 1].style.border = "2px dashed red";
  }
}

function generateContainer() {
  const div = document.createElement("div");
  div.style.margin = "5px";
  return div;
}

const generateBtn = document.getElementById("generate-btn");
const sortBtn = document.getElementById("sort-btn");
const arrayContainer = document.getElementById("array-container");
const startingArray = document.getElementById("starting-array");

generateBtn.addEventListener("click", () => {
  while (arrayContainer.children.length > 1) {
    arrayContainer.removeChild(arrayContainer.lastChild);
  }
  startingArray.style.display = "block";
  const newNumbers = generateArray();
  fillArrContainer(startingArray, newNumbers);
});

sortBtn.addEventListener("click", () => {
  const spans = Array.from(startingArray.children);
  if (spans.length < 5) return;

  while (arrayContainer.children.length > 1) {
    arrayContainer.removeChild(arrayContainer.lastChild);
  }

  let workingArray = spans.map(span => parseInt(span.textContent));
  const n = workingArray.length;
  startingArray.style.display = "none";

  let sorted = false;
  for (let i = 0; i < n - 1 && !sorted; i++) {
    let swapped = false;
    for (let j = 0; j < n - 1; j++) {
      const stepDiv = generateContainer();
      fillArrContainer(stepDiv, [...workingArray]);
      highlightCurrentEls(stepDiv, j);
      arrayContainer.appendChild(stepDiv);
      if (swapElements(workingArray, j)) {
        swapped = true;
      }
    }
    if (!swapped) {
      sorted = true;
      break;
    }
  }

  const finalDiv = generateContainer();
  fillArrContainer(finalDiv, workingArray);
  arrayContainer.appendChild(finalDiv);
});

What are those tests and what is the behaviour of your output?

Is there something you’ve done to investigate or correct that didn’t work?

Can you provide some more information please?

Here are the tests that my latest code in the comment above fails:

    1. After you click #sort-btn, #array-container should contain as many div elements as the steps required by the Bubble Sort algorithm to sort the starting array, including the div representing the starting array and a div representing the sorted array.
    1. After you click #sort-btn, each div within #array-container should contain five span, each with a number as its text, and arranged to represent the steps required by Bubble Sort algorithm to sort the starting array.
  1. After you click #sort-btn , #starting-array should represent the starting step with the initial array and the first two integers highlighted using highlightCurrentEls .

AFAIK, my code is generating the exact same o/p as the example but still fails. I’m at my wits end. Cannot figure out what am I doing wrong.

Just copy-pasting the error messages doesn’t tell us what debugging you tried and where you got stuck figuring out what was wrong.

I tried these console.log statements to debug in earlier iteration but I couldn’t figure it out.:

console.log(“Starting-array innerHTML:”, startingArray.innerHTML);
console.log(“Starting-array children count:”, startingArray.children.length);
console.log(“Working array at start:”, workingArray);

But mostly, I was just looking at the example project and tried to replicate that o/p.

after you click the Sort button, where does your #starting-array go?

What was the output of these console.logs and what did you expect them to be?

Can’t believe I missed that. Fixed. Now, test 21 is passing but not tests 18 and 19.

function generateElement() {
  return Math.floor(Math.random() * 100) + 1;
}

function generateArray() {
  return Array.from({ length: 5 }, generateElement);
}

function fillArrContainer(container, arr) {
  container.innerHTML = "";
  arr.forEach(num => {
    const span = document.createElement("span");
    span.textContent = num;
    span.style.margin = "5px";
    container.appendChild(span);
  });
}

function isOrdered(a, b) {
  return a <= b;
}

function swapElements(arr, i) {
  if (!isOrdered(arr[i], arr[i + 1])) {
    [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]];
    return true;
  }
  return false;
}

function highlightCurrentEls(container, index) {
  for (let k = 0; k < container.children.length; k++) {
    container.children[k].style.border = "none";
  }
  if (index < container.children.length - 1) {
    container.children[index].style.border = "2px dashed red";
    container.children[index + 1].style.border = "2px dashed red";
  }
}

function generateContainer() {
  const div = document.createElement("div");
  div.style.margin = "5px";
  return div;
}

const generateBtn = document.getElementById("generate-btn");
const sortBtn = document.getElementById("sort-btn");
const arrayContainer = document.getElementById("array-container");
const startingArray = document.getElementById("starting-array");

generateBtn.addEventListener("click", () => {
  while (arrayContainer.children.length > 1) {
    arrayContainer.removeChild(arrayContainer.lastChild);
  }
  startingArray.style.display = "block";
  const newNumbers = generateArray();
  fillArrContainer(startingArray, newNumbers);
});

sortBtn.addEventListener("click", () => {
  const spans = Array.from(startingArray.children);
  if (spans.length < 5) return;

  while (arrayContainer.children.length > 1) {
    arrayContainer.removeChild(arrayContainer.lastChild);
  }

  let workingArray = spans.map(span => parseInt(span.textContent));
  const n = workingArray.length;

  highlightCurrentEls(startingArray, 0);

  let sorted = false;
  for (let i = 0; i < n - 1 && !sorted; i++) {
    let swapped = false;
    for (let j = 0; j < n - 1; j++) {
      if (swapElements(workingArray, j)) {
        swapped = true;
      }
      const stepDiv = generateContainer();
      fillArrContainer(stepDiv, [...workingArray]);
      if (j < n - 2) {
        highlightCurrentEls(stepDiv, j + 1);
      } else if (i < n - 2) {
        highlightCurrentEls(stepDiv, 0);
      }
      arrayContainer.appendChild(stepDiv);
    }
    if (!swapped) {
      sorted = true;
      break;
    }
  }

  const finalDiv = generateContainer();
  fillArrContainer(finalDiv, workingArray);
  arrayContainer.appendChild(finalDiv);

  startingArray.style.border = "2px solid navy";
  arrayContainer.children[arrayContainer.children.length - 1].style.border = "2px solid green";
});

use your app and find what’s wrong

I added those statements to check if the red dash margins are present, if there are 5 span elements in the divs generated. I removed them once those tests passes.

I’ve been trying for 2 days now.

this code is new, right? didn’t you try it?
don’t you notice anything wrong when you generate an array and sort it?

what do you see when you do that?

I’m worried you are relying on others to look for you

hint: look near your final array

1 Like

Can you explain anything about what your code is doing and why it’s failing or passing the tests?

Fix one problem at a time.

Just focus on 18. What is the test and what clue does it give you?