├── .editorconfig ├── .github └── workflows │ └── static.yml ├── LICENSE ├── README.md └── Source ├── .DS_Store ├── Algorithms ├── BubbleSort.js ├── CocktailSort.js ├── CountingSort.js ├── GnomeSort.js ├── HeapSort.js ├── InsertionSort.js ├── MonkeySort.js ├── QuickSort.js ├── SelectionSort.js └── mod.js ├── App.js ├── Misc ├── Document.js └── Extensions.js ├── Styles ├── Dark.css ├── General.css └── Light.css ├── Visual ├── Colors.js ├── ProgressAnimation.js └── Theme.js └── index.html /.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | root = true 4 | 5 | 6 | [*] 7 | insert_final_newline = true 8 | end_of_line = lf 9 | 10 | 11 | [*.{md,js,css,html}] 12 | indent_style = space 13 | indent_size = 4 14 | charset = utf-8 15 | -------------------------------------------------------------------------------- /.github/workflows/static.yml: -------------------------------------------------------------------------------- 1 | 2 | name : Deploy the visualization page to GitHub Pages 3 | 4 | 5 | # Only rebuild the page if something 6 | # changes in the /Source/ folder. 7 | 8 | on: 9 | workflow_dispatch: # Allow manual starting 10 | push: 11 | branches: 12 | - 'main' 13 | 14 | paths: 15 | - 'Source/**' 16 | 17 | 18 | permissions: 19 | id-token : write 20 | contents : read 21 | pages : write 22 | 23 | 24 | concurrency: 25 | cancel-in-progress : true 26 | group : 'pages' 27 | 28 | 29 | jobs: 30 | deploy: 31 | 32 | environment: 33 | name : github-pages 34 | url : ${{ steps.deployment.outputs.page_url }} 35 | 36 | runs-on : ubuntu-latest 37 | 38 | steps: 39 | 40 | - name : Checkout 41 | uses : actions/checkout@v3 42 | 43 | - name : Setup Pages 44 | uses : actions/configure-pages@v2 45 | 46 | - name : Upload artifact 47 | uses : actions/upload-pages-artifact@v1 48 | with : 49 | path : 'Source/' 50 | 51 | - name : Deploy to GitHub Pages 52 | uses : actions/deploy-pages@v1 53 | id : deployment 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 David Kobalia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 | # Sorting Algorithms 7 | 8 | *Visualization of a variety of sorting algorithms.* 9 | 10 |
11 |
12 | 13 | [![Button Website]][Website] 14 | 15 |
16 |
17 | 18 |
19 | 20 | ## Algorithms 21 | 22 | *List of algorithms used on the page.* 23 | 24 | - **[Insertion Sort]** 25 | 26 | - **[Selection Sort]** 27 | 28 | - **[Counting Sort]** 29 | 30 | - **[Cocktail Sort]** 31 | 32 | - **[Bubble Sort]** 33 | 34 | - **[Gnome Sort]** 35 | 36 | - **[Quick Sort]** 37 | 38 | - **[Heap Sort]** 39 | 40 | - **[Bogo Sort] a.k.a. Monkey Sort** 41 | 42 |
43 | 44 | 45 | 46 | 47 | [Website]: https://blocage.github.io/sorting_algos 48 | 49 | [Insertion Sort]: https://en.wikipedia.org/wiki/Insertion_sort 50 | [Selection Sort]: https://en.wikipedia.org/wiki/Selection_sort 51 | [Counting Sort]: https://en.wikipedia.org/wiki/Counting_sort 52 | [Cocktail Sort]: https://en.wikipedia.org/wiki/Cocktail_shaker_sort 53 | [Bubble Sort]: https://en.wikipedia.org/wiki/Bubble_sort 54 | [Gnome Sort]: https://en.wikipedia.org/wiki/Gnome_sort 55 | [Quick Sort]: https://en.wikipedia.org/wiki/Quicksort 56 | [Heap Sort]: https://en.wikipedia.org/wiki/Heapsort 57 | [Bogo Sort]: https://en.wikipedia.org/wiki/Bogosort 58 | 59 | 60 | 61 | 62 | [Button Website]: https://img.shields.io/badge/Website-7D929E?style=for-the-badge&logoColor=white&logo=ApacheCouchDB 63 | -------------------------------------------------------------------------------- /Source/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blocage/sorting_algos/8e752dc54a2b5ff2edae51f049d538a0aa64210f/Source/.DS_Store -------------------------------------------------------------------------------- /Source/Algorithms/BubbleSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Unsorted, Alpha, Beta } from 'Colors' 3 | 4 | 5 | export default function* (size, items) { 6 | 7 | for (let i = 0; i < size - 1; i++) { 8 | 9 | for (let j = 0; j < size - i - 1; j++) { 10 | 11 | yield [Alpha, j] 12 | yield [Beta, j + 1] 13 | 14 | if (items[j] > items[j + 1]) { 15 | 16 | [items[j], items[j + 1]] = [items[j + 1], items[j]]; 17 | 18 | yield [Beta, j] 19 | yield [Alpha, j + 1] 20 | } 21 | 22 | yield [Unsorted, j] 23 | yield [Unsorted, j + 1] 24 | } 25 | 26 | yield [Sorted, size - 1 - i] 27 | } 28 | 29 | yield [Sorted, 0] 30 | } 31 | -------------------------------------------------------------------------------- /Source/Algorithms/CocktailSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Unsorted, Alpha, Beta } from 'Colors' 3 | 4 | 5 | export default function* (size, items) { 6 | 7 | let 8 | swapped = true, 9 | lsize = size, 10 | index = 0; 11 | 12 | while (swapped) { 13 | 14 | swapped = false; 15 | 16 | for (let i = index; i < lsize - 1; ++i) { 17 | 18 | yield [Alpha, i] 19 | yield [Beta, i + 1] 20 | 21 | if (items[i] > items[i + 1]) { 22 | 23 | [items[i], items[i + 1]] = [items[i + 1], items[i]]; 24 | 25 | yield [Beta, i] 26 | yield [Alpha, i + 1] 27 | 28 | swapped = true; 29 | } 30 | 31 | yield [Unsorted, i] 32 | yield [Unsorted, i + 1] 33 | } 34 | 35 | swapped = false; 36 | lsize--; 37 | 38 | for (let i = lsize - 1; i >= index; i--) { 39 | 40 | yield [Alpha, i] 41 | yield [Beta, i + 1] 42 | 43 | if (items[i] > items[i + 1]) { 44 | 45 | [items[i], items[i + 1]] = [items[i + 1], items[i]]; 46 | 47 | yield [Beta, i] 48 | yield [Alpha, i + 1] 49 | 50 | swapped = true; 51 | } 52 | 53 | yield [Unsorted, i] 54 | yield [Unsorted, i + 1] 55 | } 56 | 57 | yield [Sorted, index] 58 | 59 | index++ 60 | 61 | yield [Sorted, lsize] 62 | } 63 | 64 | for (let i = 0; i < size; i++) 65 | yield [Sorted, i] 66 | } 67 | -------------------------------------------------------------------------------- /Source/Algorithms/CountingSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Unsorted, Alpha, Beta } from 'Colors' 3 | 4 | 5 | export default function* (size, items) { 6 | const counter = {} 7 | let max = -1, 8 | max_index = 0, 9 | min = 10e6, 10 | min_index = 0; 11 | 12 | for (let i = 0; i < size; i++) { 13 | yield [Alpha, i]; 14 | if (items[i] > max) { 15 | max = items[i]; 16 | max_index = i; 17 | } 18 | if (items[i] < min) { 19 | min = items[i]; 20 | min_index = i; 21 | } 22 | if (items[i] in counter) 23 | counter[items[i]].push(i); 24 | else 25 | counter[items[i]] = [i]; 26 | } 27 | 28 | yield [Beta, max_index] 29 | yield [Beta, min_index] 30 | let c = 0, 31 | replaced_index, 32 | old_items = [...items]; 33 | for (let i = min; i <= max; i++) { 34 | if (!(i in counter)) continue; 35 | while (counter[i].length) { 36 | replaced_index = counter[i].pop(); 37 | yield [Alpha, c]; 38 | yield [Beta, replaced_index]; 39 | yield [Unsorted, c]; 40 | yield [Unsorted, replaced_index]; 41 | [items[c], old_items[replaced_index]] = [old_items[replaced_index], items[c]]; 42 | yield [Beta, replaced_index]; 43 | yield [Sorted, c++]; 44 | } 45 | } 46 | 47 | for (let i = 0; i < size; i++) { 48 | yield [Sorted, i]; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Source/Algorithms/GnomeSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Unsorted, Alpha, Beta } from 'Colors' 3 | 4 | 5 | export default function* (size, items) { 6 | 7 | let index = 0; 8 | 9 | while (index < size) { 10 | 11 | if (items[index] >= items[index - 1] || index == 0) { 12 | 13 | yield [Alpha, index] 14 | yield [Sorted, index] 15 | 16 | index++; 17 | 18 | } else { 19 | 20 | [items[index], items[index - 1]] = [items[index - 1], items[index]]; 21 | 22 | yield [Beta, index] 23 | yield [Unsorted, index + 1] 24 | 25 | index--; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Source/Algorithms/HeapSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted , Unsorted , Alpha , Beta } from 'Colors' 3 | 4 | const { floor } = Math; 5 | 6 | 7 | export default function * ( size , items ){ 8 | 9 | for ( let i = 0 ; i < size ; i++ ) 10 | yield * heap_up(items,i); 11 | 12 | for ( let i = 0 ; i < size - 1 ; i++){ 13 | 14 | let last = size - 1 - i; 15 | 16 | [ items[0] , items[last] ] = [ items[last] , items[0] ]; 17 | 18 | yield [ Sorted , 0 ] 19 | yield [ Sorted , last ] 20 | 21 | yield * heap_down(items,last); 22 | } 23 | } 24 | 25 | 26 | function * heap_up ( items , i ){ 27 | 28 | let root = floor((i - 1) / 2); 29 | 30 | while ( i > 0 && items[root] < items[i]){ 31 | 32 | [ items[i] , items[root] ] = [ items[root] , items[i] ]; 33 | 34 | yield [ Alpha , i ] 35 | yield [ Beta , root ] 36 | yield [ Unsorted , i ] 37 | yield [ Unsorted , root ] 38 | 39 | i = root; 40 | 41 | root = floor((i - 1) / 2); 42 | } 43 | 44 | yield [ Unsorted , i ] 45 | } 46 | 47 | function * heap_down ( items , size ){ 48 | 49 | let i = 0; 50 | 51 | while ( 2 * i + 1 < size ){ 52 | 53 | let child = 2 * i + 1; 54 | 55 | if(2 * i + 2 < size && items[2 * i + 2] >= items[child]) 56 | child = 2 * i + 2; 57 | 58 | yield [ Alpha , i ] 59 | yield [ Beta , child ] 60 | yield [ Unsorted , i ] 61 | yield [ Unsorted , child ] 62 | 63 | if(items[i] >= items[child]) 64 | return 65 | 66 | [ items[i] , items[child] ] = [ items[child] , items[i] ]; 67 | 68 | i = child; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Source/Algorithms/InsertionSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Alpha, Beta } from 'Colors' 3 | 4 | 5 | export default function* (size, items) { 6 | 7 | for (let i = 0; i < size; i++) { 8 | 9 | let temp = items[i]; 10 | 11 | yield [Beta, i] 12 | 13 | let j = i - 1; 14 | 15 | for (j = i - 1; j >= 0 && items[j] > temp; j--) { 16 | 17 | items[j + 1] = items[j]; 18 | 19 | yield [Alpha, j] 20 | yield [Beta, j + 1] 21 | yield [Sorted, j + 1] 22 | yield [Sorted, j] 23 | } 24 | 25 | items[j + 1] = temp; 26 | 27 | yield [Beta, i] 28 | yield [Sorted, i] 29 | yield [Beta, j + 1] 30 | yield [Sorted, j + 1] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Source/Algorithms/MonkeySort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Alpha, Beta } from 'Colors' 3 | const { floor, random } = Math 4 | 5 | export default function* (size, items) { 6 | while (!items.slice(1).every((item, i) => items[i] <= item)) { 7 | yield* shuffle(size, items) 8 | } 9 | yield* colorize_bars(size, Alpha) 10 | yield* colorize_bars(size, Beta) 11 | yield* colorize_bars(size, Sorted) 12 | } 13 | 14 | function* shuffle(size, items) { 15 | for (let i = 0; i < size; i++) { 16 | var random_index = floor(random() * size); 17 | [items[i], items[random_index]] = [items[random_index], items[i]]; 18 | yield [Alpha, i] 19 | yield [Beta, random_index] 20 | } 21 | } 22 | 23 | function* colorize_bars(size, color) { 24 | for (let i = 0; i < size; i++) 25 | yield [color, i] 26 | } 27 | -------------------------------------------------------------------------------- /Source/Algorithms/QuickSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Unsorted, Alpha, Beta } from 'Colors' 3 | 4 | 5 | export default function* sort(size, items, start, end) { 6 | 7 | if (start > end) { 8 | yield [Sorted, start] 9 | return 10 | } 11 | 12 | if (start == end) { 13 | yield [Sorted, start] 14 | return 15 | } 16 | 17 | let pivot = items[start], 18 | tail = end + 1, 19 | head = start; 20 | 21 | while (head < tail) { 22 | 23 | do { 24 | 25 | yield [Alpha, head] 26 | yield [Unsorted, head] 27 | 28 | head++; 29 | 30 | } while (items[head] <= pivot); 31 | 32 | do { 33 | 34 | tail--; 35 | 36 | yield [Beta, tail] 37 | yield [Unsorted, tail] 38 | 39 | } while (items[tail] > pivot); 40 | 41 | if (head < tail) 42 | [items[head], items[tail]] = [items[tail], items[head]]; 43 | } 44 | 45 | [items[start], items[tail]] = [items[tail], items[start]]; 46 | 47 | yield [Sorted, tail] 48 | 49 | yield* sort(size, items, start, tail - 1); 50 | yield* sort(size, items, tail + 1, end); 51 | } 52 | -------------------------------------------------------------------------------- /Source/Algorithms/SelectionSort.js: -------------------------------------------------------------------------------- 1 | 2 | import { Sorted, Unsorted, Alpha } from 'Colors' 3 | 4 | 5 | export default function* (size, items) { 6 | 7 | for (let i = 0; i < size - 1; i++) { 8 | 9 | let min = i; 10 | 11 | for (let j = size - 1; j > i; j--) { 12 | 13 | yield [Alpha, j] 14 | 15 | if (items[j] < items[min]) 16 | min = j; 17 | 18 | yield [Unsorted, j] 19 | } 20 | 21 | [items[i], items[min]] = [items[min], items[i]]; 22 | 23 | yield [Sorted, i] 24 | 25 | if (min != i) 26 | yield [Unsorted, min] 27 | } 28 | 29 | yield [Sorted, size - 1] 30 | } 31 | -------------------------------------------------------------------------------- /Source/Algorithms/mod.js: -------------------------------------------------------------------------------- 1 | 2 | export { default as 'Selection Sort' } from './SelectionSort.js' 3 | export { default as 'Insertion Sort' } from './InsertionSort.js' 4 | export { default as 'Cocktail Sort' } from './CocktailSort.js' 5 | export { default as 'Bubble Sort' } from './BubbleSort.js' 6 | export { default as 'Gnome Sort' } from './GnomeSort.js' 7 | export { default as 'Quick Sort' } from './QuickSort.js' 8 | export { default as 'Heap Sort' } from './HeapSort.js' 9 | export { default as 'Counting Sort' } from './CountingSort.js' 10 | export { default as 'Monkey Sort' } from './MonkeySort.js' 11 | -------------------------------------------------------------------------------- /Source/App.js: -------------------------------------------------------------------------------- 1 | 2 | import { queryAll, query, create, byId } from 'Document' 3 | import progressAnimation from 'Progress' 4 | import * as Algorithms from 'Algorithms' 5 | 6 | 7 | const { random, floor } = Math; 8 | 9 | 10 | const randomInt = (minimum, maximum) => 11 | floor(random() * (maximum - minimum + 1) + minimum); 12 | 13 | const sleep = (millis) => 14 | new Promise((resolve) => setTimeout(resolve, millis)); 15 | 16 | 17 | let 18 | sorting_progress = 0, 19 | sortingProcess, 20 | algorithm = 'Bubble Sort', 21 | animation, 22 | cancel = false, 23 | values = [], 24 | bars = [], 25 | size = 35, 26 | time = 0; 27 | 28 | 29 | const delayFrom = (factor) => 30 | 10000 / (floor(size / 10) * factor); 31 | 32 | let delay = delayFrom(500); 33 | 34 | 35 | const algorithmSelection = 36 | queryAll('.dropdown-menu > li'); 37 | 38 | const activeSelection = 39 | byId('nav-menu'); 40 | 41 | const button_randomize = 42 | query('.random-array'); 43 | 44 | const slider_speed = 45 | byId('speed'); 46 | 47 | const slider_size = 48 | byId('size'); 49 | 50 | const button_sort = 51 | byId('SORT'); 52 | 53 | const list_bars = 54 | query('.BARS'); 55 | 56 | 57 | 58 | function onAlgorithmSelect(event) { 59 | 60 | const { target } = event; 61 | 62 | target.swapTextWith(activeSelection); 63 | 64 | algorithm = activeSelection.innerText; 65 | } 66 | 67 | function onSizeChange(event) { 68 | size = event.target.value; 69 | randomizeValues(); 70 | } 71 | 72 | function onSpeedChange(event) { 73 | 74 | const { value } = event.target; 75 | 76 | delay = delayFrom(value); 77 | } 78 | 79 | 80 | 81 | function animateSorting() { 82 | 83 | const steps = progressAnimation(); 84 | 85 | const animate = () => 86 | button_sort.innerText = steps.next().value; 87 | 88 | animation = setInterval(animate, 500); 89 | } 90 | 91 | 92 | async function randomizeValues() { 93 | 94 | cancel = true; 95 | 96 | await sortingProcess; 97 | 98 | clearInterval(animation); 99 | 100 | disableNavigation(false); 101 | 102 | sorting_progress = 0; 103 | time = 0; 104 | 105 | list_bars.innerHTML = ''; 106 | button_sort.innerText = 'Sort'; 107 | 108 | values = []; 109 | bars = []; 110 | 111 | prepareBars(); 112 | } 113 | 114 | 115 | function prepareBars() { 116 | 117 | for (let i = 0; i < size; i++) 118 | generateBar(); 119 | 120 | const stable = create('div'); 121 | stable.classList.add('stable'); 122 | list_bars.appendChild(stable); 123 | } 124 | 125 | 126 | function generateBar() { 127 | 128 | const 129 | value = randomInt(50, 500), 130 | bar = create('div'); 131 | 132 | const { style } = bar; 133 | 134 | style.height = `${value}px`; 135 | style.width = `${60 / size}%`; 136 | 137 | list_bars.appendChild(bar); 138 | values.push(value); 139 | bars.push(bar); 140 | } 141 | 142 | async function visualize(index, color) { 143 | 144 | const [value, bar] = [values[index], bars[index]]; 145 | 146 | if (bar) { 147 | 148 | await sleep(delay); 149 | 150 | const { style } = bar; 151 | 152 | style.backgroundColor = color; 153 | style.height = `${value}px`; 154 | } 155 | } 156 | 157 | 158 | function disableNavigation(state) { 159 | activeSelection.disabled = state; 160 | button_sort.disabled = state; 161 | slider_size.disabled = state; 162 | } 163 | 164 | 165 | function onStartSorting() { 166 | sortingProcess = sort(); 167 | } 168 | 169 | async function sort() { 170 | 171 | sorting_progress = 1; 172 | cancel = false; 173 | 174 | disableNavigation(true); 175 | animateSorting(); 176 | 177 | const parameters = [size, values, 0, size - 1] 178 | 179 | const process = Algorithms[algorithm](...parameters); 180 | 181 | for (const [color, index] of process) { 182 | 183 | await visualize(index, color); 184 | 185 | if (cancel) 186 | break; 187 | } 188 | 189 | disableNavigation(false); 190 | 191 | clearInterval(animation); 192 | 193 | button_sort.innerText = 'Sort'; 194 | 195 | sorting_progress = 0; 196 | time = 0; 197 | } 198 | 199 | 200 | 201 | for (const choice of algorithmSelection) 202 | choice.addEventListener('click', onAlgorithmSelect); 203 | 204 | button_randomize 205 | .addEventListener('click', randomizeValues); 206 | 207 | slider_speed 208 | .addEventListener('input', onSpeedChange); 209 | 210 | button_sort 211 | .addEventListener('click', onStartSorting); 212 | 213 | slider_size 214 | .addEventListener('input', onSizeChange); 215 | 216 | 217 | 218 | randomizeValues(); 219 | -------------------------------------------------------------------------------- /Source/Misc/Document.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export const queryAll = (selector) => 4 | document.querySelectorAll(selector); 5 | 6 | export const query = (selector) => 7 | document.querySelector(selector); 8 | 9 | export const create = (type) => 10 | document.createElement(type); 11 | 12 | export const byId = (id) => 13 | document.getElementById(id); 14 | -------------------------------------------------------------------------------- /Source/Misc/Extensions.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const Element = HTMLElement.prototype; 4 | 5 | 6 | Element.visible = function (state) { 7 | this.classList[state ? 'add' : 'remove']('d-none'); 8 | } 9 | 10 | Element.show = function () { 11 | this.classList.remove('d-none'); 12 | } 13 | 14 | Element.hide = function () { 15 | this.classList.add('d-none'); 16 | } 17 | 18 | 19 | Element.enable = function () { 20 | this.disabled = false; 21 | } 22 | 23 | Element.disable = function () { 24 | this.disabled = true; 25 | } 26 | 27 | 28 | Element.swapTextWith = function (other) { 29 | [this.innerText, other.innerText] = 30 | [other.innerText, this.innerText]; 31 | } 32 | -------------------------------------------------------------------------------- /Source/Styles/Dark.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --sort-btn-background-color: #212529; 3 | --bar-background-color: #f5f5f5; 4 | --source-code-color: #00ffff; 5 | --sort-btn-color: #f5f5f5; 6 | --shadow-color: #888888; 7 | } 8 | 9 | body { 10 | background-color: #212529; 11 | color: white; 12 | } 13 | -------------------------------------------------------------------------------- /Source/Styles/General.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bar-background-color: #f5f5f5; 3 | --sort-btn-color: #f5f5f5; 4 | --sort-btn-background-color: #212529; 5 | --source-code-color: #00ffff; 6 | --shadow-color: #888888; 7 | } 8 | 9 | body { 10 | background-color: #212529; 11 | color: #fff; 12 | text-align: center; 13 | font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; 14 | height: 100vh; 15 | transition: 0.5s; 16 | -webkit-transition: 0.5s; 17 | -moz-transition: 0.5s; 18 | -ms-transition: 0.5s; 19 | -o-transition: 0.5s; 20 | } 21 | 22 | a, 23 | a:hover, 24 | a:focus, 25 | a:active { 26 | text-decoration: none; 27 | color: #ffffff; 28 | } 29 | 30 | .range { 31 | color: #ffffff; 32 | } 33 | 34 | /* Dark and Light mode */ 35 | .toggle { 36 | cursor: pointer; 37 | transition: 0.5s; 38 | -webkit-transition: 0.70s; 39 | -moz-transition: 0.70s; 40 | -ms-transition: 0.70s; 41 | -o-transition: 0.70s; 42 | } 43 | 44 | #light:hover { 45 | color: yellow; 46 | } 47 | 48 | 49 | .about { 50 | font-size: 25px; 51 | font-family: 'Courier New', Courier, monospace; 52 | margin-left: 20px; 53 | } 54 | 55 | .container-fluid { 56 | padding: 1% 2% 0 2%; 57 | text-align: left; 58 | } 59 | 60 | .nav-items { 61 | margin-left: auto; 62 | font-size: 1.5rem; 63 | font-weight: bold; 64 | } 65 | 66 | .random-array { 67 | margin-right: 1rem; 68 | } 69 | 70 | .nav-dropdown { 71 | font-size: 1.5rem; 72 | font-weight: bold; 73 | } 74 | 75 | .BARS { 76 | margin-top: 5%; 77 | height: 500px; 78 | width: 100%; 79 | text-align: center; 80 | } 81 | 82 | .stable { 83 | height: 500px; 84 | width: 0.1%; 85 | display: inline-block; 86 | } 87 | 88 | .BARS>*:not(:last-child) { 89 | background-color: var(--bar-background-color); 90 | margin-right: 0.1%; 91 | margin-left: 0.3%; 92 | border-radius: 50px; 93 | box-shadow: 3px 5px var(--shadow-color); 94 | bottom: 0px; 95 | display: inline-block; 96 | } 97 | 98 | .btn-sort, 99 | .btn-sort:disabled { 100 | background-color: var(--sort-btn-background-color); 101 | color: var(--sort-btn-color); 102 | font-size: 1.75rem; 103 | font-weight: bold; 104 | border-radius: 50px; 105 | box-shadow: 5px 3px var(--shadow-color); 106 | width: 80%; 107 | margin-left: 10%; 108 | margin-right: 10%; 109 | } 110 | 111 | .dropdown-menu>li { 112 | display: block; 113 | width: 100%; 114 | padding: 0.25rem 1rem; 115 | clear: both; 116 | font-weight: 400; 117 | color: #212529; 118 | text-align: inherit; 119 | text-decoration: none; 120 | white-space: nowrap; 121 | background-color: transparent; 122 | border: 0; 123 | cursor: pointer; 124 | } 125 | 126 | .dropdown-menu>li:hover { 127 | color: #1e2125; 128 | background-color: #e9ecef 129 | } 130 | -------------------------------------------------------------------------------- /Source/Styles/Light.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --sort-btn-background-color: #f5f5f5; 3 | --bar-background-color: #212529; 4 | --source-code-color: #000000; 5 | --sort-btn-color: #212529; 6 | --shadow-color: #212529; 7 | } 8 | 9 | body { 10 | background-color: #f5f5f5; 11 | color: black; 12 | } 13 | -------------------------------------------------------------------------------- /Source/Visual/Colors.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export const Sorted 4 | = '#3CB371'; 5 | 6 | export const Unsorted 7 | = '#DC143C'; 8 | 9 | export const Alpha 10 | = '#FFFF00'; 11 | 12 | export const Beta 13 | = '#0096FF'; 14 | -------------------------------------------------------------------------------- /Source/Visual/ProgressAnimation.js: -------------------------------------------------------------------------------- 1 | 2 | const 3 | steps = ['/', '-', '\\', '|'], 4 | text = 'Sorting'; 5 | 6 | 7 | export default function* animation() { 8 | 9 | let progress = 0; 10 | 11 | while (true) { 12 | 13 | const chars = [...text]; 14 | 15 | chars[progress % text.length] = steps[progress % 4]; 16 | 17 | yield chars.join(''); 18 | 19 | progress++; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Source/Visual/Theme.js: -------------------------------------------------------------------------------- 1 | 2 | import { byId } from 'Document' 3 | 4 | 5 | const { values } = Object; 6 | 7 | 8 | const sheets = values(document.styleSheets); 9 | 10 | const findSheet = (name) => 11 | sheets.find((sheet) => sheet.href?.endsWith(`${name}.css`)); 12 | 13 | 14 | const 15 | lightStyle = findSheet('Light'), 16 | darkStyle = findSheet('Dark'); 17 | 18 | const 19 | light = byId('light'), 20 | dark = byId('dark'); 21 | 22 | light.addEventListener('click', () => enableDark(false)); 23 | dark.addEventListener('click', () => enableDark(true)); 24 | 25 | 26 | function enableDark(state) { 27 | 28 | lightStyle.disabled = state; 29 | dark.visible(state); 30 | 31 | darkStyle.disabled = !state; 32 | light.visible(!state); 33 | } 34 | 35 | enableDark(true); 36 | -------------------------------------------------------------------------------- /Source/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 14 | 15 | Sorting Algorithms 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 86 |
87 | 88 |
89 | 90 | 91 | 92 | 93 | 97 | 98 | 99 | --------------------------------------------------------------------------------