Skip to content

Commit 0b0ec40

Browse files
authored
add in alternate color mode; add adtl sorting algorithms (#29)
* feat: add an alternate color mode when light theme * feat: add a number of additional sorting algorithms
1 parent 80194b3 commit 0b0ec40

File tree

11 files changed

+301
-27
lines changed

11 files changed

+301
-27
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ Without the work of these excellent folks, the algorithms you see visualized wou
2222
- [Learn JS With Me](http://learnjswith.me/quick-sort-in-javascript/)
2323
- [NCZOnline](https://www.nczonline.net/blog/2009/09/08/computer-science-in-javascript-selection-sort/)
2424

25+
Additionally, I'd like to credit the work of [reddit user morolin](https://www.reddit.com/r/woahdude/comments/78fzi7/sorting_algorithms_visualized_gifv/?st=jaj5goe1&sh=e80fb95c) for the initial inspiration
26+
2527
[algorithm-playground]: https://algorithm-playground.com

src/algorithms/__tests__/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'fs';
22
import path from 'path';
33
import camelCase from 'lodash.camelcase';
44

5-
const EXCLUDE = [/^__/, /^\./, /index\.js/];
5+
const EXCLUDE = [/^__/, /^\./, /index\.js/, /bogo/];
66

77
const base = path.join(__dirname, '..');
88
const files = fs

src/algorithms/bitonic-merge-sort.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* CODE: https://en.wikipedia.org/wiki/Bitonic_sorter
3+
*
4+
* Bitonic mergesort is a parallel algorithm for sorting. It is also used as a
5+
construction method for building a sorting network. The algorithm was devised
6+
by Ken Batcher.
7+
*
8+
* MORE INFO: https://en.wikipedia.org/wiki/Bitonic_sorter
9+
*/
10+
function kernel(arr, p, q) {
11+
let d = 1 << (p - q);
12+
13+
for (let i = 0; i < arr.length; i++) {
14+
let up = ((i >> p) & 2) === 0;
15+
16+
if ((i & d) === 0 && arr[i] > arr[i | d] === up) {
17+
let temp = arr[i];
18+
arr[i] = arr[i | d];
19+
arr[i | d] = temp;
20+
}
21+
}
22+
}
23+
24+
function bitonicSort(n, arr) {
25+
for (let i = 0; i < n; i++) {
26+
for (let j = 0; j <= i; j++) {
27+
kernel(arr, i, j);
28+
}
29+
}
30+
return arr;
31+
}
32+
33+
export function bitonicMergeSort(arr, n = 25) {
34+
return bitonicSort(n, arr);
35+
}

src/algorithms/bogo-sort.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* CODE: https://www.w3resource.com/javascript-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-14.php
3+
*
4+
* Bogo sort is a highly ineffective sorting function based on the generate
5+
and test paradigm. The function successively generates permutations of its
6+
input until it finds one that is sorted. It is not useful for sorting, but
7+
may be used for educational purposes, to contrast it with more efficient
8+
algorithms.
9+
*
10+
* MORE INFO: https://en.wikipedia.org/wiki/Bogosort
11+
*/
12+
function isSorted(arr) {
13+
return arr.every((num, index) => index === 0 || arr[index - 1] <= num);
14+
}
15+
16+
function shuffle(arr) {
17+
let count = arr.length;
18+
let temp;
19+
let index;
20+
21+
while (count > 0) {
22+
index = Math.floor(Math.random() * count);
23+
count--;
24+
25+
temp = arr[count];
26+
arr[count] = arr[index];
27+
arr[index] = temp;
28+
}
29+
30+
return arr;
31+
}
32+
33+
export function bogoSort(arr, attempts = 10) {
34+
let sorted = false;
35+
for (let i = 0; i < attempts; i++) {
36+
arr = shuffle(arr);
37+
sorted = isSorted(arr);
38+
if (sorted) {
39+
break;
40+
}
41+
}
42+
return arr;
43+
}

src/algorithms/bucket-sort.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
*
3+
*/
4+
function insertionSort(arr) {
5+
for (let i = 1; i < arr.length; i++) {
6+
let value = arr[i];
7+
let j = i - 1;
8+
while (j >= 0 && arr[j] > value) {
9+
arr[j + 1] = arr[j];
10+
j -= 1;
11+
}
12+
arr[j + 1] = value;
13+
}
14+
return arr;
15+
}
16+
17+
export function bucketSort(list, bucketCount = 200) {
18+
// only for numbers
19+
var min = Math.min.apply(Math, list), // get the min
20+
buckets = [];
21+
22+
// build the bucket and distribute the elements in the list
23+
for (var i = 0; i < list.length; i++) {
24+
// this is a simple hash function that will make sure the basic rule of bucket sort
25+
var newIndex = Math.floor((list[i] - min) / bucketCount);
26+
27+
buckets[newIndex] = buckets[newIndex] || [];
28+
buckets[newIndex].push(list[i]);
29+
}
30+
// refill the elements into the list
31+
var idx = 0;
32+
for (i = 0; i < buckets.length; i++) {
33+
if (typeof buckets[i] !== 'undefined') {
34+
// select those non-empty buckets
35+
insertionSort(buckets[i]); // use any sorting algorithm would be fine
36+
// sort the elements in the bucket
37+
for (var j = 0; j < buckets[i].length; j++) {
38+
list[idx++] = buckets[i][j];
39+
}
40+
}
41+
}
42+
return list;
43+
}

src/algorithms/comb-sort.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* CODE: https://www.w3resource.com/javascript-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-9.php
3+
*
4+
* Comb sort is a relatively simple sorting algorithm originally designed by
5+
Włodzimierz Dobosiewicz in 1980. Later it was rediscovered by Stephen Lacey
6+
and Richard Box in 1991. Comb sort improves on bubble sort.
7+
*
8+
* MORE INFO: https://en.wikipedia.org/wiki/Comb_sort
9+
*/
10+
function isSorted(arr) {
11+
return arr.every((num, index) => index === 0 || arr[index - 1] <= num);
12+
}
13+
14+
export function combSort(arr) {
15+
let iteration_count = 0;
16+
let gap = arr.length - 2;
17+
let decrease_factor = 1.25;
18+
19+
while (!isSorted(arr)) {
20+
if (iteration_count > 0) {
21+
gap = gap === 1 ? gap : Math.floor(gap / decrease_factor);
22+
}
23+
24+
let front = 0;
25+
let back = gap;
26+
while (back <= arr.length - 1) {
27+
if (arr[front] > arr[back]) {
28+
let temp = arr[front];
29+
arr[front] = arr[back];
30+
arr[back] = temp;
31+
}
32+
33+
front += 1;
34+
back += 1;
35+
}
36+
iteration_count += 1;
37+
}
38+
return arr;
39+
}

src/algorithms/merge-sort.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* CODE: http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
3+
*
4+
*
5+
* MORE INFO:
6+
*/
7+
8+
function merge(arr, left, right) {
9+
let result = [];
10+
while (left.length && right.length) {
11+
if (left[0] <= right[0]) {
12+
result.push(left.shift());
13+
} else {
14+
result.push(right.shift());
15+
}
16+
}
17+
18+
while (left.length) {
19+
result.push(left.shift());
20+
}
21+
22+
while (right.length) {
23+
result.push(right.shift());
24+
}
25+
26+
return result;
27+
}
28+
29+
/*
30+
* Note: augment would normally not be needed
31+
* but is needed for the visualization to appear correctly
32+
*/
33+
function augment(arr, result) {
34+
for (let i = 0; i < result.length; i++) {
35+
arr[i] = result[i];
36+
}
37+
}
38+
39+
export function mergeSort(arr) {
40+
if (arr.length < 2) {
41+
return arr;
42+
}
43+
44+
const len = arr.length;
45+
46+
let middle = parseInt(len / 2);
47+
let left = arr.slice(0, middle);
48+
let right = arr.slice(middle, len);
49+
50+
return merge(arr, mergeSort(left), mergeSort(right));
51+
}

src/algorithms/radix-sort.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* CODE: http://taoalpha.github.io/blog/2016/01/19/tech-javascript-sorting-algorithm-radix-sort/
3+
*
4+
*
5+
* MORE INFO:
6+
*/
7+
function getDigit(num, nth) {
8+
// get last nth digit of a number
9+
let ret = 0;
10+
while (nth--) {
11+
ret = num % 10;
12+
num = Math.floor((num - ret) / 10);
13+
}
14+
return ret;
15+
}
16+
17+
export function radixSort(arr) {
18+
let max = Math.floor(Math.log10(Math.max.apply(Math, arr))),
19+
digitBuckets = [],
20+
idx = 0;
21+
22+
for (let i = 0; i < max + 1; i++) {
23+
digitBuckets = [];
24+
let j = 0;
25+
for (; j < arr.length; j++) {
26+
let digit = getDigit(arr[j], i + 1);
27+
28+
digitBuckets[digit] = digitBuckets[digit] || [];
29+
digitBuckets[digit].push(arr[j]);
30+
}
31+
32+
idx = 0;
33+
for (let t = 0; t < digitBuckets.length; t++) {
34+
if (digitBuckets[t] && digitBuckets[t].length > 0) {
35+
for (j = 0; j < digitBuckets[t].length; j++) {
36+
arr[idx++] = digitBuckets[t][j];
37+
}
38+
}
39+
}
40+
}
41+
return arr;
42+
}

src/components/AlgorithmPreview/components/Canvas/index.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,15 @@ class CanvasComponent extends Component {
8787
window.removeEventListener('resize', this.handleResize);
8888
}
8989

90-
componentWillReceiveProps({ localChanges, sortFunction }) {
90+
componentWillReceiveProps({ localChanges, sortFunction, theme }) {
9191
if (this.props.localChanges !== localChanges) {
9292
this.handleResize();
9393
} else if (
9494
!this.props.sortFunction ||
95-
(this.props.sortFunction !== sortFunction && this.state.sortComplete)
95+
(this.props.sortFunction !== sortFunction && this.state.sortComplete) ||
96+
this.props.theme !== theme
9697
) {
97-
this.resetGrid({ inProgress: false });
98+
this.resetGrid({ inProgress: false }, theme);
9899
}
99100
}
100101

@@ -171,12 +172,13 @@ class CanvasComponent extends Component {
171172
});
172173
}
173174

174-
resetGrid(additionalUpdate) {
175+
resetGrid(additionalUpdate, theme = this.props.theme) {
175176
this.setState({
176177
inProgress: false,
177178
grid: createGrid(this.state.context)({
178179
height: this.state.height,
179-
width: this.state.width
180+
width: this.state.width,
181+
...this.getMaxAndStart(theme)
180182
}),
181183
sortComplete: false,
182184
sorted: false,
@@ -194,12 +196,23 @@ class CanvasComponent extends Component {
194196
...(reset && {
195197
grid: createGrid(this.state.context)({
196198
height: this.state.height,
197-
width: this.state.width
199+
width: this.state.width,
200+
...this.getMaxAndStart(this.props.theme)
198201
})
199202
}: {})
200203
});
201204
}
202205

206+
getMaxAndStart(theme) {
207+
if (theme === 'dark') {
208+
return {};
209+
}
210+
return {
211+
max: 250,
212+
min: 50
213+
};
214+
}
215+
203216
render() {
204217
const {
205218
height,

0 commit comments

Comments
 (0)