From 85268dfc89207422ad60add8403df92fd5424659 Mon Sep 17 00:00:00 2001 From: Hoang Tran <99.hoangtran@gmail.com> Date: Mon, 9 May 2022 21:28:12 +0700 Subject: [PATCH] [New] sort simulator 2 --- .vscode/settings.json | 3 + 2022/sort-simulator-2/index.html | 30 ++++++ .../js/binaryInsertionSort.js | 38 ++++++++ 2022/sort-simulator-2/js/bubbleSort.js | 20 ++++ 2022/sort-simulator-2/js/insertionSort.js | 22 +++++ 2022/sort-simulator-2/js/mergeSort.js | 57 +++++++++++ 2022/sort-simulator-2/js/quickSort.js | 58 +++++++++++ 2022/sort-simulator-2/js/radixSort.js | 96 +++++++++++++++++++ 2022/sort-simulator-2/js/selectionSort.js | 27 ++++++ 2022/sort-simulator-2/js/shakerSort.js | 27 ++++++ 2022/sort-simulator-2/js/shellSort.js | 30 ++++++ 2022/sort-simulator-2/js/utils.js | 34 +++++++ 2022/sort-simulator-2/sketch.js | 70 ++++++++++++++ 2022/sort-simulator-2/style.css | 29 ++++++ 14 files changed, 541 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 2022/sort-simulator-2/index.html create mode 100644 2022/sort-simulator-2/js/binaryInsertionSort.js create mode 100644 2022/sort-simulator-2/js/bubbleSort.js create mode 100644 2022/sort-simulator-2/js/insertionSort.js create mode 100644 2022/sort-simulator-2/js/mergeSort.js create mode 100644 2022/sort-simulator-2/js/quickSort.js create mode 100644 2022/sort-simulator-2/js/radixSort.js create mode 100644 2022/sort-simulator-2/js/selectionSort.js create mode 100644 2022/sort-simulator-2/js/shakerSort.js create mode 100644 2022/sort-simulator-2/js/shellSort.js create mode 100644 2022/sort-simulator-2/js/utils.js create mode 100644 2022/sort-simulator-2/sketch.js create mode 100644 2022/sort-simulator-2/style.css diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6f3a291 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/2022/sort-simulator-2/index.html b/2022/sort-simulator-2/index.html new file mode 100644 index 0000000..b373247 --- /dev/null +++ b/2022/sort-simulator-2/index.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/2022/sort-simulator-2/js/binaryInsertionSort.js b/2022/sort-simulator-2/js/binaryInsertionSort.js new file mode 100644 index 0000000..c991a09 --- /dev/null +++ b/2022/sort-simulator-2/js/binaryInsertionSort.js @@ -0,0 +1,38 @@ +// https://www.geeksforgeeks.org/binary-insertion-sort/ +function binarySearch(a, item, low, high) { + if (high <= low) return item > a[low] ? low + 1 : low; + mid = Math.floor((low + high) / 2); + if (item == a[mid]) return mid + 1; + if (item > a[mid]) return binarySearch(a, item, mid + 1, high); + + return binarySearch(a, item, low, mid - 1); +} + +async function binaryInsertionSort(array) { + for (let i = 1; i < array.length; i++) { + highlightIndexes[0] = i; + let j = i - 1; + let x = array[i]; + + // Find location to insert + // using binary search + let loc = Math.abs(binarySearch(array, x, 0, j)); + + // Shifting array to one + // location right + + while (j >= loc) { + array[j + 1] = array[j]; + j--; + + highlightIndexes[1] = loc; + highlightIndexes[2] = j; + await sleep(sleepTime); + } + + // Placing element at its + // correct location + array[j + 1] = x; + } + highlightIndexes = []; +} diff --git a/2022/sort-simulator-2/js/bubbleSort.js b/2022/sort-simulator-2/js/bubbleSort.js new file mode 100644 index 0000000..9c5ff7e --- /dev/null +++ b/2022/sort-simulator-2/js/bubbleSort.js @@ -0,0 +1,20 @@ +// https://viblo.asia/p/javascript-algorithms-bubble-sort-djeZ1RRolWz +async function bubbleSort(array) { + let isOrdered; + for (let i = 0; i < array.length; i++) { + isOrdered = true; + for (let x = 0; x < array.length - 1 - i; x++) { + if (array[x] > array[x + 1]) { + swap(array, x, x + 1); + isOrdered = false; + + highlightIndexes[1] = x + 1; + await sleep(sleepTime); + } + } + if (isOrdered) break; + } + + highlightIndexes = []; + return array; +} diff --git a/2022/sort-simulator-2/js/insertionSort.js b/2022/sort-simulator-2/js/insertionSort.js new file mode 100644 index 0000000..51527a3 --- /dev/null +++ b/2022/sort-simulator-2/js/insertionSort.js @@ -0,0 +1,22 @@ +// https://stackabuse.com/insertion-sort-in-javascript/ +async function insertionSort(array) { + let n = array.length; + for (let i = 1; i < n; i++) { + highlightIndexes[0] = i; + + // Choosing the first element in our unsorted subarray + let current = array[i]; + // The last element of our sorted subarray + let j = i - 1; + while (j > -1 && current < array[j]) { + array[j + 1] = array[j]; + j--; + + highlightIndexes[1] = j; + await sleep(sleepTime); + } + array[j + 1] = current; + } + highlightIndexes = []; + return array; +} diff --git a/2022/sort-simulator-2/js/mergeSort.js b/2022/sort-simulator-2/js/mergeSort.js new file mode 100644 index 0000000..8f28674 --- /dev/null +++ b/2022/sort-simulator-2/js/mergeSort.js @@ -0,0 +1,57 @@ +// https://www.geeksforgeeks.org/iterative-merge-sort/ +async function mergeSort(array) { + if (array == null) { + return; + } + + if (array.length > 1) { + var mid = parseInt(array.length / 2); + + // Split left part + var left = Array(mid).fill(0); + for (i = 0; i < mid; i++) { + left[i] = array[i]; + } + + // Split right part + var right = Array(array.length - mid).fill(0); + for (i = mid; i < array.length; i++) { + right[i - mid] = array[i]; + } + mergeSort(left); + mergeSort(right); + + var i = 0; + var j = 0; + var k = 0; + + // Merge left and right arrays + while (i < left.length && j < right.length) { + if (left[i] < right[j]) { + array[k] = left[i]; + i++; + } else { + array[k] = right[j]; + j++; + } + k++; + + highlightIndexes[0] = k; + await sleep(sleepTime); + } + + // Collect remaining elements + while (i < left.length) { + array[k] = left[i]; + i++; + k++; + } + while (j < right.length) { + array[k] = right[j]; + j++; + k++; + } + } + + highlightIndexes = []; +} diff --git a/2022/sort-simulator-2/js/quickSort.js b/2022/sort-simulator-2/js/quickSort.js new file mode 100644 index 0000000..92c5f60 --- /dev/null +++ b/2022/sort-simulator-2/js/quickSort.js @@ -0,0 +1,58 @@ +// https://learnersbucket.com/examples/algorithms/quick-sort-iterative/ +async function partitionHigh(array, low, high) { + //Pick the first element as pivot + let pivot = array[high]; + let i = low; + + //Partition the array into two parts using the pivot + for (let j = low; j < high; j++) { + highlightIndexes[2] = j; + await sleep(sleepTime); + if (array[j] <= pivot) { + swap(array, i, j); + i++; + highlightIndexes[3] = i; + } + } + + swap(array, i, high); + + //Return the pivot index + return i; +} + +async function quickSort(array) { + //Stack for storing start and end index + let stack = []; + + //Get the start and end index + let start = 0; + let end = array.length - 1; + + //Push start and end index in the stack + stack.push({ x: start, y: end }); + + //Iterate the stack + while (stack.length) { + //Get the start and end from the stack + const { x, y } = stack.shift(); + + highlightIndexes[0] = x; + highlightIndexes[1] = y; + + //Partition the array along the pivot + const i = await partitionHigh(array, x, y); + + //Push sub array with less elements than pivot into the stack + if (i - 1 > x) { + stack.push({ x: x, y: i - 1 }); + } + + //Push sub array with greater elements than pivot into the stack + if (i + 1 < y) { + stack.push({ x: i + 1, y: y }); + } + } + + highlightIndexes = []; +} diff --git a/2022/sort-simulator-2/js/radixSort.js b/2022/sort-simulator-2/js/radixSort.js new file mode 100644 index 0000000..eea646d --- /dev/null +++ b/2022/sort-simulator-2/js/radixSort.js @@ -0,0 +1,96 @@ +// https://stackoverflow.com/a/38979903 +// ONLY int value +async function radixSort(array) { + var idx1, idx2, idx3, len1, len2, radix, radixKey; + var radices = {}, + buckets = {}, + curr; + var currLen, currBucket; + + len1 = array.length; + len2 = 10; // radix sort uses ten buckets + + // find the relevant radices to process for efficiency + for (idx1 = 0; idx1 < len1; idx1++) { + radices[array[idx1].toString().length] = 0; + } + + // loop for each radix. For each radix we put all the items + // in buckets, and then pull them out of the buckets. + for (radix in radices) { + // put each array item in a bucket based on its radix value + len1 = array.length; + for (idx1 = 0; idx1 < len1; idx1++) { + await sleep(sleepTime); + highlightIndexes[0] = idx1; + + curr = array[idx1]; + // item length is used to find its current radix value + currLen = curr.toString().length; + // only put the item in a radix bucket if the item + // key is as long as the radix + if (currLen >= radix) { + // radix starts from beginning of key, so need to + // adjust to get redix values from start of stringified key + radixKey = curr.toString()[currLen - radix]; + // create the bucket if it does not already exist + if (!buckets.hasOwnProperty(radixKey)) { + buckets[radixKey] = []; + } + // put the array value in the bucket + buckets[radixKey].push(curr); + } else { + if (!buckets.hasOwnProperty("0")) { + buckets["0"] = []; + } + buckets["0"].push(curr); + } + } + // for current radix, items are in buckets, now put them + // back in the array based on their buckets + // this index moves us through the array as we insert items + idx1 = 0; + // go through all the buckets + for (idx2 = 0; idx2 < len2; idx2++) { + // only process buckets with items + if (buckets[idx2] != null) { + currBucket = buckets[idx2]; + // insert all bucket items into array + len1 = currBucket.length; + for (idx3 = 0; idx3 < len1; idx3++) { + array[idx1++] = currBucket[idx3]; + + await sleep(sleepTime); + highlightIndexes[0] = idx1; + highlightIndexes[1] = idx3; + } + } + } + buckets = {}; + } + + highlightIndexes = []; +} + +// https://stackoverflow.com/a/3817440 +async function radixSort2(array) { + for (var div = 1, radix = 16; div < 65536 * 65536; div *= radix) { + var piles = []; + + for (var i = 0; i < array.length; ++i) { + var p = Math.floor(array[i] / div) % radix; + (piles[p] || (piles[p] = [])).push(array[i]); + } + + for (var i = 0, ai = 0; i < piles.length; ++i) { + if (!piles[i]) continue; + for (var pi = 0; pi < piles[i].length; ++pi) { + array[ai++] = piles[i][pi]; + + highlightIndexes[0] = ai; + await sleep(sleepTime); + } + } + } + highlightIndexes = []; +} diff --git a/2022/sort-simulator-2/js/selectionSort.js b/2022/sort-simulator-2/js/selectionSort.js new file mode 100644 index 0000000..bbc2941 --- /dev/null +++ b/2022/sort-simulator-2/js/selectionSort.js @@ -0,0 +1,27 @@ +// https://stackabuse.com/selection-sort-in-javascript/ +async function selectionSort(array) { + let n = array.length; + + for (let i = 0; i < n; i++) { + highlightIndexes[0] = i; + // Finding the smallest number in the subarray + let min = i; + for (let j = i + 1; j < n; j++) { + await sleep(sleepTime); + highlightIndexes[1] = j; + if (array[j] < array[min]) { + highlightIndexes[2] = j; + min = j; + } + } + if (min != i) { + // Swapping the elements + let tmp = array[i]; + array[i] = array[min]; + array[min] = tmp; + } + } + + highlightIndexes = []; + return array; +} diff --git a/2022/sort-simulator-2/js/shakerSort.js b/2022/sort-simulator-2/js/shakerSort.js new file mode 100644 index 0000000..c48a3ab --- /dev/null +++ b/2022/sort-simulator-2/js/shakerSort.js @@ -0,0 +1,27 @@ +// https://www.stdio.vn/giai-thuat-lap-trinh/bubble-sort-va-shaker-sort-01Si3U +async function shakerSort(array) { + let left = 0; + let right = array.length - 1; + let k = 0; + while (left < right) { + for (let i = left; i < right; i++) { + if (array[i] > array[i + 1]) { + swap(array, i, i + 1); + k = i; + } + highlightIndexes[1] = i + 1; + await sleep(sleepTime); + } + right = k; + for (i = right; i > left; i--) { + if (array[i] < array[i - 1]) { + swap(array, i, i - 1); + k = i; + } + highlightIndexes[1] = i - 1; + await sleep(sleepTime); + } + left = k; + } + highlightIndexes = []; +} diff --git a/2022/sort-simulator-2/js/shellSort.js b/2022/sort-simulator-2/js/shellSort.js new file mode 100644 index 0000000..4fa9d47 --- /dev/null +++ b/2022/sort-simulator-2/js/shellSort.js @@ -0,0 +1,30 @@ +// https://www.w3resource.com/javascript-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-6.php +async function shellSort(array) { + var increment = array.length / 2; + while (increment > 0) { + for (i = increment; i < array.length; i++) { + highlightIndexes[0] = i; + var j = i; + var temp = array[i]; + + while (j >= increment && array[j - increment] > temp) { + array[j] = array[j - increment]; + j = j - increment; + + highlightIndexes[1] = j; + await sleep(sleepTime); + } + + array[j] = temp; + await sleep(sleepTime); + } + + if (increment == 2) { + increment = 1; + } else { + increment = parseInt((increment * 5) / 11); + } + } + highlightIndexes = []; + return array; +} diff --git a/2022/sort-simulator-2/js/utils.js b/2022/sort-simulator-2/js/utils.js new file mode 100644 index 0000000..806de16 --- /dev/null +++ b/2022/sort-simulator-2/js/utils.js @@ -0,0 +1,34 @@ +function swap(arr, i, j) { + [arr[i], arr[j]] = [arr[j], arr[i]]; +} + +function sleep(ms) { + if (ms === 0) return; + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +// https://bost.ocks.org/mike/shuffle/ +async function shuffleArray(array) { + var m = array.length, + t, + i; + + // While there remain elements to shuffle… + while (m) { + // Pick a remaining element… + i = Math.floor(Math.random() * m--); + + // And swap it with the current element. + t = array[m]; + array[m] = array[i]; + array[i] = t; + + highlightIndexes[0] = m; + highlightIndexes[1] = i; + await sleep(sleepTime); + } + + highlightIndexes = []; + + return array; +} diff --git a/2022/sort-simulator-2/sketch.js b/2022/sort-simulator-2/sketch.js new file mode 100644 index 0000000..b26f062 --- /dev/null +++ b/2022/sort-simulator-2/sketch.js @@ -0,0 +1,70 @@ +let arr = []; +let highlightIndexes = []; +let sleepTime = 10; + +let delaySlider; + +function setup() { + createCanvas(min(windowWidth, 800), 500); + colorMode(HSB, 100); + + for (let i = 0; i < 50; i++) arr.push(~~random(100)); + + delaySlider = createSlider(0, 250, 10, 5); + + createButton("Shuffle").mouseClicked(() => { + shuffleArray(arr); + }); + createButton("Bubble Sort").mouseClicked(() => { + bubbleSort(arr); + }); + createButton("Selection Sort").mouseClicked(() => { + selectionSort(arr); + }); + createButton("Merge Sort").mouseClicked(() => { + // alert("Not implemented yet"); + mergeSort(arr); + }); + createButton("Insertion Sort").mouseClicked(() => { + insertionSort(arr); + }); + createButton("Binary Insertion Sort").mouseClicked(() => { + binaryInsertionSort(arr); + }); + createButton("Shaker Sort").mouseClicked(() => { + shakerSort(arr); + }); + createButton("Shell Sort").mouseClicked(() => { + shellSort(arr); + }); + createButton("Quick Sort").mouseClicked(() => { + quickSort(arr); + }); + createButton("Radix Sort").mouseClicked(() => { + radixSort(arr); + }); +} + +function draw() { + background(20); + + sleepTime = delaySlider.value(); + let w = width / arr.length; + + noStroke(); + for (let i = 0; i < arr.length; i++) { + let value = arr[i]; + let h = map(value, 0, 100, 0, height); + let top = height - h; + let left = i * w; + + fill(value, 255, 255); + rect(left, top, w, h); + + let hi = highlightIndexes.indexOf(i); + if (hi >= 0) { + fill(255); + rect(left, 0, w, height - h); + } + } +} diff --git a/2022/sort-simulator-2/style.css b/2022/sort-simulator-2/style.css new file mode 100644 index 0000000..5183ad5 --- /dev/null +++ b/2022/sort-simulator-2/style.css @@ -0,0 +1,29 @@ +html, +body { + margin: 0; + padding: 0; +} + +body { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + display: block; +} + +button { + display: inline-block; + padding: 10px 15px; + margin: 5px; + border-radius: 5px; + background-color: #333; + cursor: pointer; + + font-family: 'Courier New', Courier, monospace; + font-size: 1.2em; +} + +button:hover { + background-color: #444; +} \ No newline at end of file