Build a Sorting Visualizer - Build a Sorting Visualizer

Tell us what’s happening:

Hello! Tests 18 and 19 doesn’t seem to pass. I have tried stopping the div container creation just after the array is sorted and one more pass after the array is sorted. I don’t understand what the 18th test is asking . It seems kind of random in the example project too.
Any help would be much appreciated .
Thank You!

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Sorting Visualizer</title>
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <main>
        <div id="array-container">
            <div id="starting-array"></div>
        </div>
        <div id="btn-container">
            <button id="generate-btn" type="button">Generate Array</button>
            <button id="sort-btn" type="button">Sort Array</button>
        </div>
    </main>
    <script src="script.js"></script>
</body>

</html>
/* file: styles.css */
* {
    box-sizing: border-box;
}

main {
    height: 100vh;
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
}

#array-container {
    max-height: 95vh;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    gap: 2px;

}

#array-container>div {
    min-width: 8rem;
    height: 2rem;
    box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
    border-radius: 10px;
    margin-bottom: 0.2rem;
    border: 2px solid darkgray;
    display: flex;
    justify-content: space-evenly;
    align-items: center;
}

#starting-array {
    border: 4px solid darkblue !important;
}

#btn-container {
    display: flex;
    justify-content: space-around;
}

button {
    padding: 2px;
    margin: 5px;
}

span {
    border-radius: 2px;
    padding: 0.5px;
    margin: 0
}

@media (min-width: 430px) {
  #array-container>div {
    min-width: 12rem;    
  }
  span {
    padding: 1px;
    margin: 1px;
  }
}
/* file: script.js */
const generateBtn = document.getElementById("generate-btn");
const sortBtn = document.getElementById("sort-btn");
const startingArray = document.getElementById("starting-array");
const arrayContainer = document.getElementById("array-container");
let sortedStatus = false;
sortBtn.style.display = "none";

const generateElement = () => {
  return Math.ceil((Math.random() * 100)); 
}

const generateArray = () => {
  const generatedArray = [];
  for (let i = 0 ; i < 5 ; i++ ) {
    generatedArray.push(generateElement());
  }
  return generatedArray;
}

const generateContainer = () => {
  const divElement = document.createElement("div");
  return divElement;
} 

const fillArrContainer = (htmlElem, arr) => {
  htmlElem.innerHTML = '';
  arr.forEach((elem) => {
    const spanElem = document.createElement("span");
    spanElem.textContent = elem;
    htmlElem.appendChild(spanElem);
  });
}

const isOrdered = (num1, num2) => {
  return num1 <= num2 ? true : false;
}

const swapElements = (array, index) => {
 if (array[index] > array[index + 1]) {
        [array[index], array[index + 1]] = [array[index + 1], array[index]];
        return true;
    }
    return false;
}

const highlightCurrentEls = (htmlElem, index) => {
  const childElements = htmlElem.children;
  if (index < childElements.length - 1) {
    childElements[index].style.border = '3px dashed red';
    childElements[index + 1].style.border = '3px dashed red';
  }
}

// const isSorted = (arr) => {
//   for (let i = 0; i < arr.length - 1; i++) {
//     if (arr[i] > arr[i + 1]) {
//       return false;
//     }
//   }
//   return true;
// }

const bubbleSortAlgo = () => {
  sortBtn.style.display = "none";
  const spanElems = startingArray.querySelectorAll("span");
  highlightCurrentEls(startingArray, 0);
  const generatedArray = []; 
  spanElems.forEach((spanElem) => {
    generatedArray.push(Number(spanElem.innerText));
  })

  for (let i = 0; i < 4; i++) { 
    for (let j = 0; j < 4 ; j++){
      
      if (i !== 0 || j!== 0) {
      let newDivElem = generateContainer();
      fillArrContainer(newDivElem, generatedArray);
      arrayContainer.appendChild(newDivElem);
      highlightCurrentEls(newDivElem, j);
      } 

      if (!isOrdered(generatedArray[j], generatedArray[j + 1])) { 
        swapElements(generatedArray, j); 
      }
    }
    // if (isSorted(generatedArray)) break;
  }
  sortedStatus = true;
  let sortedArray = generateContainer();
  fillArrContainer(sortedArray, generatedArray);
  sortedArray.style.border = '4px solid green';
  arrayContainer.appendChild(sortedArray);
}

generateBtn.addEventListener("click", () => {
  const startingArrayChildren = startingArray.querySelectorAll("span");
  if (startingArrayChildren.length > 0 && sortedStatus) {
    arrayContainer.innerHTML = '';
    arrayContainer.appendChild(startingArray);
    fillArrContainer(startingArray, generateArray())
    sortedStatus = false;
  }
  sortBtn.style.display = "block";
  fillArrContainer(startingArray, generateArray());
})
 
sortBtn.addEventListener("click", bubbleSortAlgo);

Your browser information:

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

Challenge Information:

Build a Sorting Visualizer - Build a Sorting Visualizer

any input on this would be really helpful. I’ve been stuck on this for quite some while now. So please share your thoughts.

Test 18 checks if sorting follows bubble sort as described in instructions:

The Bubble Sort algorithm sorts a sequence of integers by comparing couples of adjacent elements starting from the beginning of the sequence. If the first element is greater than the second one, it swaps them. Then, it proceeds with the following couple. When the last element of the sequence is reached, it starts a new cycle from the beginning of the sequence, and repeats the process until the elements are sorted. The algorithm stops after one cycle completes with no swaps.

Could you also explain how the callback in the event listener on generateBtn is supposed to work?

You aren’t following this instruction:

The algorithm stops after one cycle completes with no swaps.

Run the example project and then pass the same array hardcoded into your project. Your project should behave in the exact same way.

@sanity @pkdvalis I took both of your feedback . It’s mb that I missed the info given in the question. Thank you for that. Now my 18th step is passing but 19th is not. I hardcoded a result from the example project and I’m getting the same results - the same no: of div containers and the same output. I also inspected my result in the browser to check if all the span elements mentioned were also there. I can’t seem to find any error regarding the proper creation of the span elements within each div container.
Here’s my updated JS code:

const generateBtn = document.getElementById("generate-btn");
const sortBtn = document.getElementById("sort-btn");
const startingArray = document.getElementById("starting-array");
const arrayContainer = document.getElementById("array-container");
let sortedStatus = false;
sortBtn.style.display = "none";

const generateElement = () => {
  return Math.ceil((Math.random() * 100)); 
}

const generateArray = () => {
  const generatedArray = [];
  for (let i = 0 ; i < 5 ; i++ ) {
    generatedArray.push(generateElement());
  }
  return generatedArray;
}

const generateContainer = () => {
  const divElement = document.createElement("div");
  return divElement;
} 

const fillArrContainer = (htmlElem, arr) => {
  htmlElem.innerHTML = '';
  arr.forEach((elem) => {
    const spanElem = document.createElement("span");
    spanElem.textContent = elem;
    htmlElem.appendChild(spanElem);
  });
}

const isOrdered = (num1, num2) => {
  return num1 <= num2 ? true : false;
}

const swapElements = (array, index) => {
 if (array[index] > array[index + 1]) {
        [array[index], array[index + 1]] = [array[index + 1], array[index]];
        return true;
    }
    return false;
}

const highlightCurrentEls = (htmlElem, index) => {
  const childElements = htmlElem.children;
  if (index < childElements.length - 1) {
    childElements[index].style.border = '3px dashed red';
    childElements[index + 1].style.border = '3px dashed red';
  }
}

const isSorted = (arr) => {
  for (let i = 0; i < arr.length - 1; i++) {
    if (arr[i] > arr[i + 1]) {
      return false;
    }
  }
  return true;
}

const bubbleSortAlgo = () => {
  sortBtn.style.display = "none";
  const spanElems = startingArray.querySelectorAll("span");
  highlightCurrentEls(startingArray, 0);
  const generatedArray = []; 
  spanElems.forEach((spanElem) => {
    generatedArray.push(Number(spanElem.innerText));
  })
  let stopLoop = false;
  for (let i = 0; i < 5; i++) { 
    for (let j = 0; j < 4 ; j++){
      
      if (i !== 0 || j!== 0) {
      let newDivElem = generateContainer();
      fillArrContainer(newDivElem, generatedArray);
      arrayContainer.appendChild(newDivElem);
      highlightCurrentEls(newDivElem, j);
      } 

      if (!isOrdered(generatedArray[j], generatedArray[j + 1])) { 
        swapElements(generatedArray, j); 
      }
    }
    if (stopLoop) {break;};
    stopLoop = isSorted(generatedArray);
  }
  sortedStatus = true;
  let sortedArray = generateContainer();
  fillArrContainer(sortedArray, generatedArray);
  sortedArray.style.border = '4px solid green';
  arrayContainer.appendChild(sortedArray);
}

generateBtn.addEventListener("click", () => {
  const startingArrayChildren = startingArray.querySelectorAll("span");
  if (startingArrayChildren.length > 0 && sortedStatus) {
    arrayContainer.innerHTML = '';
    fillArrContainer(startingArray, generateArray())
    arrayContainer.appendChild(startingArray);
    sortedStatus = false;
  }
  sortBtn.style.display = "block";
  fillArrContainer(startingArray, generateArray());
})
 
sortBtn.addEventListener("click", bubbleSortAlgo);

Once again, could you explain what’s happening in the callback of the generateBtn’s event listener?

Oh Sorry. That part is to check whether there is any span elements in the starting array. If there is and the sorting is done, when we click generateBtn it should clear everything inside arrayContainer and a new generated array should be in the startingArray.
The sortedStatus variable is there to check if the entire sorting process is done or not.

I think it’s a roundabout way of doing this. But it seems to work and if the issue I’m facing is concerning this part of the code , please let me know.
Thank You!

Hmm, okay… why though it sometimes generates two arrays?

What does this code return if Math.random() returns 0?

Does that align with this instruction?

  1. You should have a function named generateElement that returns a random integer between 1 and 100, inclusive.

UPDATE: But that’s not what’s breaking the tests. @sanity is correct that your generateBtn event listener is borked. Why do you think you need sortedStatus in your code? In fact, why do you need the if statement at all?

1 Like

Thank You so much @sanity, @fcc4b6d10c4-b540-4e2

The problem was with the logic in the generateBtn callback. I tried to rewrite my entire logic for the bubble sort and was unsuccessful. I just rewrote the callback logic and it worked. I was so sure the bubble sort logic was the wrong part. Anyways tysm for your input and I learned to not have tunnel vision when debugging.