├── .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 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
97 |
98 |
99 |
--------------------------------------------------------------------------------