├── .gitattributes ├── public ├── favicon.ico ├── robots.txt ├── manifest.json └── index.html ├── screenshots ├── Screenshot-1.png └── Screenshot-2.png ├── src ├── redux │ ├── Store │ │ └── index.js │ ├── action-types │ │ └── index.js │ ├── Actions │ │ └── index.js │ └── Reducers │ │ └── index.js ├── components │ ├── Descreptions │ │ ├── CodeComponent.jsx │ │ ├── DescList │ │ │ └── DescList.styles.js │ │ ├── DescComponents │ │ │ ├── FaithSort.jsx │ │ │ ├── BubbleBogoSort.jsx │ │ │ ├── OddEvenSort.jsx │ │ │ ├── QuantumBogoSort.jsx │ │ │ ├── BubbleSortOptimized.jsx │ │ │ ├── QuickSortStable.jsx │ │ │ ├── GnomeSort.jsx │ │ │ ├── GnomeSortOptimized.jsx │ │ │ ├── InsertionSortBinary.jsx │ │ │ ├── DoubleSelectionSort.jsx │ │ │ ├── IntelligentDesignSort.jsx │ │ │ ├── OddEvenMergeSort.jsx │ │ │ ├── BogoSort.jsx │ │ │ ├── MergeSortBottomUp.jsx │ │ │ ├── PancakeSort.jsx │ │ │ ├── BozoSort.jsx │ │ │ ├── PairwiseSortingNetwork.jsx │ │ │ ├── CycleSort.jsx │ │ │ ├── InsertionSort.jsx │ │ │ ├── HeapSort.jsx │ │ │ ├── ShellSort.jsx │ │ │ ├── CircleSort.jsx │ │ │ ├── TimSort.jsx │ │ │ ├── CombSort.jsx │ │ │ ├── GravitySort.jsx │ │ │ ├── RadixSort.jsx │ │ │ └── SelectionSort.jsx │ │ └── Container │ │ │ ├── HiddenDescList.styles.js │ │ │ ├── HiddenDescList.jsx │ │ │ ├── Description.styles.js │ │ │ ├── Container.styles.js │ │ │ └── index.jsx │ ├── AlgorithmsContainer │ │ ├── index.jsx │ │ ├── AlgorithmsContainer.styles.js │ │ └── Algorithm │ │ │ ├── Algorithm.styles.js │ │ │ └── index.jsx │ ├── SortSettings │ │ ├── index.jsx │ │ └── SettingsHidden.jsx │ ├── Footer │ │ ├── index.jsx │ │ └── Footer.styles.js │ ├── Main │ │ ├── Main.styles.js │ │ └── index.jsx │ ├── Sidebar │ │ ├── HiddenSidebar.jsx │ │ ├── HiddenSidebar.styles.js │ │ ├── index.jsx │ │ ├── Sidebar.styles.js │ │ └── AddAlogoModal.styles.js │ └── Header │ │ ├── index.jsx │ │ ├── InfoModal.styles.js │ │ ├── Header.styles.js │ │ └── InfoModal.jsx ├── setupTests.js ├── App.test.js ├── index.js ├── reportWebVitals.js ├── utils │ ├── newElements.jsx │ ├── SortGenerators │ │ ├── bozoSort.js │ │ ├── gnomeSort.js │ │ ├── bogoSort.js │ │ ├── bubbleBogoSort.js │ │ ├── gnomeSortOptimized.js │ │ ├── insertionSort.js │ │ ├── combSort.js │ │ ├── bubbleSort.js │ │ ├── countingSort.js │ │ ├── selectionSort.js │ │ ├── oddEvenSort.js │ │ ├── radixSortBase10.js │ │ ├── bubbleSortOtimized.js │ │ ├── radixSortBase2.js │ │ ├── radixSortBase5.js │ │ ├── shellSort.js │ │ ├── insertionSortBinary.js │ │ ├── pancakeSort.js │ │ ├── quickSortRightPivot.js │ │ ├── gravitySort.js │ │ ├── quickSortMiddlePivot.js │ │ ├── doubleSelectionSort.js │ │ ├── oddEvenMergeSort.js │ │ ├── pairwiseSortingNetwork.js │ │ ├── circleSort.js │ │ ├── hepSortMax.js │ │ ├── mergeSortBottomUp.js │ │ ├── quickSortLeftPivot.js │ │ ├── bitonicSort.js │ │ ├── cocktailShakerSort.js │ │ ├── heapSortMin.js │ │ ├── mergeSort.js │ │ ├── flashSort.js │ │ ├── quickSortStable.js │ │ ├── bucketSort.js │ │ ├── cycleSort.js │ │ └── timSort.js │ ├── index.js │ └── getSortingMethod.js ├── hooks │ ├── useIntersection.js │ └── useSortingAlgo.jsx ├── Theme.jsx └── App.js ├── .gitignore └── package.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/copperhuh/SortDemon/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /screenshots/Screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/copperhuh/SortDemon/HEAD/screenshots/Screenshot-1.png -------------------------------------------------------------------------------- /screenshots/Screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/copperhuh/SortDemon/HEAD/screenshots/Screenshot-2.png -------------------------------------------------------------------------------- /src/redux/Store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore } from "redux"; 2 | import { reducer } from "../Reducers"; 3 | 4 | export const store = createStore(reducer); 5 | -------------------------------------------------------------------------------- /src/components/Descreptions/CodeComponent.jsx: -------------------------------------------------------------------------------- 1 | import { CopyBlock, obsidian } from "react-code-blocks"; 2 | 3 | export default function CodeComponent(props) { 4 | return ( 5 | 6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | import reportWebVitals from "./reportWebVitals"; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById("root") 11 | ); 12 | 13 | reportWebVitals(); 14 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Sort Demon", 3 | "name": "Sort Demon Sorting Visualiser", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#48846b", 14 | "background_color": "#242625" 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/components/AlgorithmsContainer/index.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import Alogrithm from "./Algorithm"; 3 | import Container from "./AlgorithmsContainer.styles"; 4 | 5 | const AlgorithmsContainer = ({ algorithms }) => { 6 | return ( 7 | 8 | {algorithms.map((el, id) => ( 9 | 10 | ))} 11 | 12 | ); 13 | }; 14 | 15 | export default AlgorithmsContainer; 16 | -------------------------------------------------------------------------------- /src/redux/action-types/index.js: -------------------------------------------------------------------------------- 1 | export const SHUFFLE = "SHUFFLE"; 2 | export const CHANGE_SORT_TYPE = "CHANGE_SORT_TYPE"; 3 | export const CHANGE_SPEED = "CHANGE_SPEED"; 4 | export const CHANGE_SIZE = "CHANGE_SIZE"; 5 | export const CHANGE_SORTING_ONGOING = "CHANGE_SORTING_ONGOING"; 6 | export const ADD_ALGORITHM = "ADD_ALGORITHM"; 7 | export const REMOVE_ALGORITHM = "REMOVE_ALGORITHM"; 8 | export const CHANGE_DESCRIPTION = "CHANGE_DESCRIPTION"; 9 | export const SET_DESC_REF = "SET_DESC_REF"; 10 | -------------------------------------------------------------------------------- /src/components/SortSettings/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { doShuffle } from "../../redux/Actions"; 3 | import { connect } from "react-redux"; 4 | import Settings from "./Settings"; 5 | 6 | const SortSettings = ({ shuffle }) => { 7 | shuffle(); 8 | 9 | return ( 10 | <> 11 | 12 | 13 | ); 14 | }; 15 | 16 | const actions = (dispatch) => ({ 17 | shuffle: () => dispatch(doShuffle), 18 | }); 19 | 20 | export default connect(null, actions)(SortSettings); 21 | -------------------------------------------------------------------------------- /src/utils/newElements.jsx: -------------------------------------------------------------------------------- 1 | export default function newElements(items, max) { 2 | return ( 3 | <> 4 | {items.map((el, inx) => { 5 | return ( 6 |
11 |
17 |
18 | ); 19 | })} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/hooks/useIntersection.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | const useIntersection = (element, rootMargin) => { 4 | const [isVisible, setState] = useState(false); 5 | 6 | useEffect(() => { 7 | const observer = new IntersectionObserver( 8 | ([entry]) => { 9 | setState(entry.isIntersecting); 10 | }, 11 | { rootMargin } 12 | ); 13 | 14 | element.current && observer.observe(element.current); 15 | 16 | return () => observer.unobserve(element.current); 17 | }, []); 18 | 19 | return isVisible; 20 | }; 21 | 22 | export default useIntersection; 23 | -------------------------------------------------------------------------------- /src/components/AlgorithmsContainer/AlgorithmsContainer.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const Container = styled.div` 4 | width: 100%; 5 | min-height: 100%; 6 | padding: 2rem; 7 | box-sizing: border-box; 8 | background-color: ${(props) => props.theme.colors.light}; 9 | display: grid; 10 | grid-template-columns: repeat(auto-fit, minmax(370px, 1fr)); 11 | gap: ${(props) => (props.len > 6 ? "1rem" : "2rem")}; 12 | position: relative; 13 | 14 | @media (max-width: 450px) { 15 | width: 100%; 16 | grid-template-columns: 1fr; 17 | padding: 3rem 0; 18 | } 19 | `; 20 | 21 | export default Container; 22 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/bozoSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* bozoSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | function isSorted() { 8 | for (let i = 0; i < n - 1; i++) { 9 | if (arr[i].val > arr[i + 1].val) { 10 | return false; 11 | } 12 | } 13 | return true; 14 | } 15 | 16 | while (!isSorted()) { 17 | let rand1 = Math.floor(Math.random() * n); 18 | let rand2 = Math.floor(Math.random() * n); 19 | let temp = arr[rand1].val; 20 | arr[rand1].val = arr[rand2].val; 21 | arr[rand2].val = temp; 22 | 23 | yield newElements(arr, arrMax); 24 | } 25 | 26 | for (let i = 0; i < arr.length; i++) { 27 | arr[i].active = true; 28 | yield newElements(arr, arrMax); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/gnomeSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* gnomeSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | let i = 0; 8 | 9 | while (i < n) { 10 | if (i === 0) { 11 | i++; 12 | } else if (arr[i].val >= arr[i - 1].val) { 13 | i++; 14 | } else { 15 | [arr[i].val, arr[i - 1].val] = [arr[i - 1].val, arr[i].val]; 16 | i--; 17 | } 18 | if (i !== n) arr[i].active = true; 19 | if (i !== 0) arr[i - 1].active = true; 20 | yield newElements(arr, arrMax); 21 | if (i !== n) arr[i].active = false; 22 | if (i !== 0) arr[i - 1].active = false; 23 | } 24 | for (let i = 0; i < arr.length; i++) { 25 | arr[i].active = true; 26 | yield newElements(arr, arrMax); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Theme.jsx: -------------------------------------------------------------------------------- 1 | import { ThemeProvider } from "styled-components"; 2 | import React from "react"; 3 | 4 | const lightTheme = { 5 | colors: { 6 | main: "#48846b", 7 | dark: "#242625", 8 | light: "#d4d0c1", 9 | absoluteDark: "#242625", 10 | absoluteLight: "#d4d0c1", 11 | }, 12 | fonts: { main: "Montserrat, sans-serif" }, 13 | }; 14 | 15 | const darkTheme = { 16 | colors: { 17 | main: "#48846b", 18 | dark: "#d4d0c1", 19 | light: "#242625", 20 | absoluteDark: "#242625", 21 | absoluteLight: "#d4d0c1", 22 | }, 23 | fonts: { main: "Montserrat, sans-serif" }, 24 | }; 25 | 26 | const Theme = ({ children, variation }) => { 27 | return ( 28 | 29 | {children} 30 | 31 | ); 32 | }; 33 | 34 | export default Theme; 35 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/bogoSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* bogoSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | function isSorted() { 8 | for (let i = 0; i < n - 1; i++) { 9 | if (arr[i].val > arr[i + 1].val) { 10 | return false; 11 | } 12 | } 13 | return true; 14 | } 15 | 16 | while (!isSorted()) { 17 | let random; 18 | for (let i = 0; i < n; i++) { 19 | random = Math.floor(Math.random() * n); 20 | let temp = arr[random].val; 21 | arr[random].val = arr[i].val; 22 | arr[i].val = temp; 23 | } 24 | 25 | yield newElements(arr, arrMax); 26 | } 27 | 28 | for (let i = 0; i < arr.length; i++) { 29 | arr[i].active = true; 30 | yield newElements(arr, arrMax); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/components/Footer/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import FooterStyled from "./Footer.styles"; 3 | import GitHubIcon from "@mui/icons-material/GitHub"; 4 | import MailOutlineIcon from "@mui/icons-material/MailOutline"; 5 | 6 | export default function Footer() { 7 | return ( 8 | 9 |
made by Jakub Koper
10 |
11 |
Contact:
12 |
13 |
14 | 15 | jakub.koper@wpc-huh.com 16 |
17 | 18 |
19 | 20 | Github 21 |
22 |
23 |
24 |
25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescList/DescList.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const DescListStyled = styled.div` 4 | padding: 4rem 2rem 2rem; 5 | ul { 6 | list-style: none; 7 | } 8 | button { 9 | background: none; 10 | border: none; 11 | font-family: ${(props) => props.theme.fonts.main}; 12 | color: ${(props) => props.theme.colors.light}; 13 | &:hover, 14 | &:focus { 15 | color: ${(props) => props.theme.colors.main}; 16 | } 17 | } 18 | 19 | .btn-subtitle { 20 | font-size: 1.1rem; 21 | margin: 0.5rem 0; 22 | letter-spacing: 0.7px; 23 | padding-right: 1.2rem; 24 | } 25 | 26 | .btn-desc-name { 27 | font-size: 1rem; 28 | margin: 0.25rem 0; 29 | } 30 | 31 | .active { 32 | color: ${(props) => props.theme.colors.main}; 33 | } 34 | @media (max-width: 290px) { 35 | padding-left: 0; 36 | padding-right: 0; 37 | } 38 | `; 39 | 40 | export default DescListStyled; 41 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/bubbleBogoSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* bubbleBogoSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | const isSorted = () => { 8 | for (let i = 0; i < n - 1; i++) { 9 | if (arr[i].val > arr[i + 1].val) { 10 | return false; 11 | } 12 | } 13 | return true; 14 | }; 15 | 16 | while (!isSorted()) { 17 | let rand1 = Math.floor(Math.random() * n); 18 | let rand2 = Math.floor(Math.random() * n); 19 | 20 | if (rand1 > rand2) { 21 | [rand1, rand2] = [rand2, rand1]; 22 | } 23 | 24 | if (arr[rand1].val > arr[rand2].val) { 25 | [arr[rand1].val, arr[rand2].val] = [arr[rand2].val, arr[rand1].val]; 26 | yield newElements(arr, arrMax); 27 | } 28 | } 29 | 30 | for (let i = 0; i < arr.length; i++) { 31 | arr[i].active = true; 32 | yield newElements(arr, arrMax); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 17 | 18 | 19 | SORT DEMON 20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/gnomeSortOptimized.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* gnomeSortOptimized(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | let i = 1; 8 | let j = 0; 9 | while (i < n) { 10 | if (arr[i].val >= arr[i - 1].val) { 11 | if (j !== 0) { 12 | i = j; 13 | j = 0; 14 | } 15 | i++; 16 | } else { 17 | [arr[i].val, arr[i - 1].val] = [arr[i - 1].val, arr[i].val]; 18 | if (i > 1) { 19 | if (j === 0) { 20 | j = i; 21 | } 22 | i--; 23 | } else { 24 | i++; 25 | } 26 | } 27 | if (i !== n) arr[i].active = true; 28 | if (i !== 0) arr[i - 1].active = true; 29 | yield newElements(arr, arrMax); 30 | if (i !== n) arr[i].active = false; 31 | if (i !== 0) arr[i - 1].active = false; 32 | } 33 | 34 | for (let i = 0; i < arr.length; i++) { 35 | arr[i].active = true; 36 | yield newElements(arr, arrMax); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/insertionSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* insertionSort(items, arrMax) { 4 | let i = 1; 5 | let arr = JSON.parse(JSON.stringify(items)); 6 | 7 | while (i < arr.length) { 8 | let current = arr[i].val; 9 | let j = i - 1; 10 | 11 | arr[i].active = true; 12 | arr[j].active = true; 13 | while (j >= 0 && arr[j].val > current) { 14 | arr[j + 1].val = arr[j].val; 15 | 16 | arr[j].active = false; 17 | j--; 18 | if (j >= 0) arr[j].active = true; 19 | 20 | yield newElements(arr, arrMax); 21 | } 22 | 23 | arr[j + 1].val = current; 24 | 25 | if (j >= 0) arr[j].active = false; 26 | arr[j + 1].active = false; 27 | arr[i].active = false; 28 | i++; 29 | if (i !== arr.length) arr[i].active = true; 30 | 31 | yield newElements(arr, arrMax); 32 | } 33 | 34 | for (let i = 0; i < arr.length; i++) { 35 | arr[i].active = true; 36 | yield newElements(arr, arrMax); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/combSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* combSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | let gap = n; 7 | let swapped = true; 8 | 9 | while (gap !== 1 || swapped === true) { 10 | gap = parseInt((gap * 10) / 13, 10); 11 | if (gap < 1) gap = 1; 12 | 13 | swapped = false; 14 | 15 | for (let i = 0; i < n - gap; i++) { 16 | if (arr[i].val > arr[i + gap].val) { 17 | [arr[i].val, arr[i + gap].val] = [arr[i + gap].val, arr[i].val]; 18 | 19 | swapped = true; 20 | } 21 | 22 | if (i !== n) arr[i].active = true; 23 | if (i + gap <= arr.length) arr[i + gap].active = true; 24 | yield newElements(arr, arrMax); 25 | if (i !== n) arr[i].active = false; 26 | if (i + gap <= arr.length) arr[i + gap].active = false; 27 | } 28 | } 29 | for (let i = 0; i < arr.length; i++) { 30 | arr[i].active = true; 31 | yield newElements(arr, arrMax); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/bubbleSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* bubbleSort(items, arrMax) { 4 | let i = 0; 5 | let j = 0; 6 | let arr = JSON.parse(JSON.stringify(items)); 7 | 8 | while (i < arr.length) { 9 | j = 0; 10 | 11 | arr[i].active = true; 12 | arr[j].active = true; 13 | 14 | while (j < arr.length - 1) { 15 | if (arr[j].val > arr[j + 1].val) { 16 | [arr[j].val, arr[j + 1].val] = [arr[j + 1].val, arr[j].val]; 17 | } 18 | 19 | if (j !== i) arr[j].active = false; 20 | j++; 21 | arr[j].active = true; 22 | if (j + 1 !== arr.length) arr[j + 1].active = true; 23 | 24 | yield newElements(arr, arrMax); 25 | } 26 | 27 | arr[j].active = false; 28 | arr[i].active = false; 29 | 30 | i++; 31 | 32 | if (i !== arr.length) arr[i].active = true; 33 | 34 | yield newElements(arr, arrMax); 35 | } 36 | 37 | for (let i = 0; i < arr.length; i++) { 38 | arr[i].active = true; 39 | yield newElements(arr, arrMax); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/FaithSort.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function FaithSort() { 5 | return ( 6 | <> 7 |

Faith Sort

8 |

Implementation

9 | 32 |

33 | Source:{" "} 34 | 35 | reddit 36 | 37 |

38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/countingSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* countingSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | let count = Array.from({ length: arrMax }, (_, i) => 0); 8 | for (let i = 0; i < n; ++i) { 9 | count[arr[i].val - 1]++; 10 | 11 | arr[i].active = true; 12 | yield newElements(arr, arrMax); 13 | arr[i].active = false; 14 | } 15 | 16 | for (let i = 1; i < count.length; i++) { 17 | count[i] += count[i - 1]; 18 | 19 | arr[i].active = true; 20 | yield newElements(arr, arrMax); 21 | arr[i].active = false; 22 | } 23 | for (let i = 0; i < n; i++) { 24 | let num; 25 | for (let j = 0; j < count.length; j++) { 26 | if (count[j] > i) { 27 | num = j + 1; 28 | break; 29 | } 30 | } 31 | arr[i].val = num; 32 | 33 | arr[i].active = true; 34 | yield newElements(arr, arrMax); 35 | arr[i].active = false; 36 | } 37 | 38 | for (let i = 0; i < arr.length; i++) { 39 | arr[i].active = true; 40 | yield newElements(arr, arrMax); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/components/Main/Main.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const MainContainer = styled.div` 4 | display: flex; 5 | width: 100%; 6 | height: fit-content; 7 | min-height: 100vh; 8 | padding: 3rem 0; 9 | background-color: ${(props) => props.theme.colors.light}; 10 | position: relative; 11 | 12 | .algo-container { 13 | min-height: 100%; 14 | flex: 1; 15 | } 16 | .sidebar { 17 | width: fit-content; 18 | height: 100%; 19 | } 20 | .open-sidebar { 21 | height: fit-content; 22 | position: sticky; 23 | top: 2rem; 24 | right: 2rem; 25 | padding: 0.3rem 0.5rem; 26 | display: flex; 27 | align-items: center; 28 | justify-content: center; 29 | background: ${(props) => props.theme.colors.light}; 30 | color: ${(props) => props.theme.colors.main}; 31 | border: 1px solid ${(props) => props.theme.colors.main}; 32 | float: left; 33 | :hover { 34 | background: ${(props) => props.theme.colors.main}; 35 | color: ${(props) => props.theme.colors.light}; 36 | border: 1px solid ${(props) => props.theme.colors.light}; 37 | } 38 | } 39 | `; 40 | 41 | export default MainContainer; 42 | -------------------------------------------------------------------------------- /src/components/AlgorithmsContainer/Algorithm/Algorithm.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const AlgorithmStyled = styled.div` 4 | background-color: none; 5 | color: ${(props) => props.theme.colors.dark}; 6 | display: flex; 7 | min-height: 300px; 8 | min-width: 220px; 9 | flex-direction: column; 10 | align-items: center; 11 | justify-content: space-evenly; 12 | padding: 1% 0 5%; 13 | h1 { 14 | font-size: ${(props) => 15 | props.len < 4 ? "2rem" : props.len < 7 ? "1.3rem" : "1rem"}; 16 | text-align: center; 17 | } 18 | 19 | .nodes { 20 | height: 90%; 21 | width: 80%; 22 | display: flex; 23 | justify-content: flex-end; 24 | flex: 1; 25 | } 26 | .node-container { 27 | display: flex; 28 | flex-direction: column; 29 | justify-content: flex-end; 30 | padding: 0 0; 31 | margin: 0 auto; 32 | } 33 | .node-coloured { 34 | background: ${(props) => props.theme.colors.dark}; 35 | width: 100%; 36 | } 37 | 38 | .active { 39 | background: ${(props) => props.theme.colors.main}; 40 | } 41 | @media (max-width: 450px) { 42 | padding: 0; 43 | width: 100vw; 44 | } 45 | `; 46 | 47 | export default AlgorithmStyled; 48 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/selectionSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* selectionSort(items, arrMax) { 4 | let i = 0; 5 | let j = 0; 6 | let arr = JSON.parse(JSON.stringify(items)); 7 | 8 | while (i < arr.length) { 9 | j = i + 1; 10 | let min = i; 11 | 12 | arr[i].active = true; 13 | if (i + 1 !== arr.length) arr[j].active = true; 14 | arr[min].active = true; 15 | 16 | while (j < arr.length) { 17 | if (arr[min].val > arr[j].val) { 18 | if (min !== i && min !== j) arr[min].active = false; 19 | min = j; 20 | arr[min].active = true; 21 | } 22 | 23 | if (j !== i && j !== min) arr[j].active = false; 24 | j++; 25 | if (j !== arr.length) arr[j].active = true; 26 | 27 | yield newElements(arr, arrMax); 28 | } 29 | 30 | [arr[i].val, arr[min].val] = [arr[min].val, arr[i].val]; 31 | 32 | arr[min].active = false; 33 | arr[i].active = false; 34 | i++; 35 | if (i !== arr.length) arr[i].active = true; 36 | 37 | yield newElements(arr, arrMax); 38 | } 39 | for (let i = 0; i < arr.length; i++) { 40 | arr[i].active = true; 41 | yield newElements(arr, arrMax); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/oddEvenSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* oddEvenSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | let isSorted = false; 7 | 8 | while (!isSorted) { 9 | isSorted = true; 10 | 11 | for (let i = 1; i <= n - 2; i = i + 2) { 12 | if (arr[i].val > arr[i + 1].val) { 13 | [arr[i].val, arr[i + 1].val] = [arr[i + 1].val, arr[i].val]; 14 | isSorted = false; 15 | } 16 | arr[i].active = true; 17 | arr[i + 1].active = true; 18 | yield newElements(arr, arrMax); 19 | arr[i].active = false; 20 | arr[i + 1].active = false; 21 | } 22 | 23 | for (let i = 0; i <= n - 2; i = i + 2) { 24 | if (arr[i].val > arr[i + 1].val) { 25 | [arr[i].val, arr[i + 1].val] = [arr[i + 1].val, arr[i].val]; 26 | isSorted = false; 27 | } 28 | arr[i].active = true; 29 | arr[i + 1].active = true; 30 | yield newElements(arr, arrMax); 31 | arr[i].active = false; 32 | arr[i + 1].active = false; 33 | } 34 | } 35 | 36 | for (let i = 0; i < arr.length; i++) { 37 | arr[i].active = true; 38 | yield newElements(arr, arrMax); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/components/Descreptions/Container/HiddenDescList.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const HiddenDescListStyled = styled.div` 4 | width: 100vw; 5 | height: 100%; 6 | background: rgba(0, 0, 0, 0.3); 7 | position: fixed; 8 | top: 0; 9 | left: 0; 10 | z-index: 2; 11 | .modal-bg { 12 | background: ${(props) => props.theme.colors.dark}; 13 | width: fit-content; 14 | height: 100%; 15 | overflow-y: auto; 16 | position: relative; 17 | &::-webkit-scrollbar { 18 | width: 10px; 19 | } 20 | &::-webkit-scrollbar-track { 21 | background: ${(props) => props.theme.colors.dark}; 22 | } 23 | &::-webkit-scrollbar-thumb { 24 | width: 5px; 25 | background: ${(props) => props.theme.colors.main}; 26 | border-radius: 5px; 27 | } 28 | } 29 | .close-modal { 30 | position: absolute; 31 | right: 1rem; 32 | top: 1rem; 33 | color: ${(props) => props.theme.colors.main}; 34 | background: none; 35 | border: none; 36 | :hover { 37 | color: ${(props) => props.theme.colors.light}; 38 | } 39 | } 40 | @media (max-width: 370px) { 41 | .modal-bg { 42 | width: 100%; 43 | } 44 | } 45 | `; 46 | 47 | export default HiddenDescListStyled; 48 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/radixSortBase10.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* radixSortBase10(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | for (let exp = 1; Math.floor(arrMax / exp) > 0; exp *= 10) { 8 | let output = new Array(n); 9 | let count = new Array(10); 10 | for (let i = 0; i < 10; i++) { 11 | count[i] = 0; 12 | 13 | arr[i].active = true; 14 | yield newElements(arr, arrMax); 15 | arr[i].active = false; 16 | } 17 | 18 | for (let i = 0; i < n; i++) count[Math.floor(arr[i].val / exp) % 10]++; 19 | 20 | for (let i = 1; i < 10; i++) count[i] += count[i - 1]; 21 | 22 | for (let i = n - 1; i >= 0; i--) { 23 | output[count[Math.floor(arr[i].val / exp) % 10] - 1] = arr[i].val; 24 | count[Math.floor(arr[i].val / exp) % 10]--; 25 | } 26 | 27 | for (let i = 0; i < n; i++) { 28 | arr[i].val = output[i]; 29 | 30 | arr[i].active = true; 31 | yield newElements(arr, arrMax); 32 | arr[i].active = false; 33 | } 34 | } 35 | 36 | for (let i = 0; i < arr.length; i++) { 37 | arr[i].active = true; 38 | yield newElements(arr, arrMax); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/bubbleSortOtimized.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* bubbleSortOptimized(items, arrMax) { 4 | let i = 0; 5 | let j = 0; 6 | let arr = JSON.parse(JSON.stringify(items)); 7 | 8 | while (i < arr.length) { 9 | let wasSwapped = false; 10 | j = 0; 11 | 12 | arr[i].active = true; 13 | arr[j].active = true; 14 | 15 | while (j < arr.length - 1 - i) { 16 | if (arr[j].val > arr[j + 1].val) { 17 | [arr[j].val, arr[j + 1].val] = [arr[j + 1].val, arr[j].val]; 18 | wasSwapped = true; 19 | } 20 | 21 | if (j !== i) arr[j].active = false; 22 | j++; 23 | arr[j].active = true; 24 | if (j + 1 !== arr.length) arr[j + 1].active = true; 25 | 26 | yield newElements(arr, arrMax); 27 | } 28 | 29 | if (j + 1 !== arr.length) arr[j + 1].active = false; 30 | arr[j].active = false; 31 | arr[i].active = false; 32 | 33 | i++; 34 | 35 | if (i !== arr.length) arr[i].active = true; 36 | 37 | yield newElements(arr, arrMax); 38 | 39 | if (!wasSwapped) { 40 | break; 41 | } 42 | } 43 | 44 | for (let i = 0; i < arr.length; i++) { 45 | arr[i].active = true; 46 | yield newElements(arr, arrMax); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/radixSortBase2.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* radixSortBase2(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | let base = 2; 7 | 8 | for (let exp = 1; Math.floor(arrMax / exp) > 0; exp *= base) { 9 | let output = new Array(n); 10 | let count = new Array(base); 11 | for (let i = 0; i < base; i++) { 12 | count[i] = 0; 13 | 14 | arr[i].active = true; 15 | yield newElements(arr, arrMax); 16 | arr[i].active = false; 17 | } 18 | 19 | for (let i = 0; i < n; i++) 20 | count[Math.floor(arr[i].val / exp) % base]++; 21 | 22 | for (let i = 1; i < 10; i++) count[i] += count[i - 1]; 23 | 24 | for (let i = n - 1; i >= 0; i--) { 25 | output[count[Math.floor(arr[i].val / exp) % base] - 1] = arr[i].val; 26 | count[Math.floor(arr[i].val / exp) % base]--; 27 | } 28 | 29 | for (let i = 0; i < n; i++) { 30 | arr[i].val = output[i]; 31 | 32 | arr[i].active = true; 33 | yield newElements(arr, arrMax); 34 | arr[i].active = false; 35 | } 36 | } 37 | 38 | for (let i = 0; i < arr.length; i++) { 39 | arr[i].active = true; 40 | yield newElements(arr, arrMax); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/radixSortBase5.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* radixSortBase5(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | let base = 5; 7 | 8 | for (let exp = 1; Math.floor(arrMax / exp) > 0; exp *= base) { 9 | let output = new Array(n); 10 | let count = new Array(base); 11 | for (let i = 0; i < base; i++) { 12 | count[i] = 0; 13 | 14 | arr[i].active = true; 15 | yield newElements(arr, arrMax); 16 | arr[i].active = false; 17 | } 18 | 19 | for (let i = 0; i < n; i++) 20 | count[Math.floor(arr[i].val / exp) % base]++; 21 | 22 | for (let i = 1; i < base; i++) count[i] += count[i - 1]; 23 | 24 | for (let i = n - 1; i >= 0; i--) { 25 | output[count[Math.floor(arr[i].val / exp) % base] - 1] = arr[i].val; 26 | count[Math.floor(arr[i].val / exp) % base]--; 27 | } 28 | 29 | for (let i = 0; i < n; i++) { 30 | arr[i].val = output[i]; 31 | 32 | arr[i].active = true; 33 | yield newElements(arr, arrMax); 34 | arr[i].active = false; 35 | } 36 | } 37 | 38 | for (let i = 0; i < arr.length; i++) { 39 | arr[i].active = true; 40 | yield newElements(arr, arrMax); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/redux/Actions/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | CHANGE_SIZE, 3 | CHANGE_SORT_TYPE, 4 | CHANGE_SPEED, 5 | SHUFFLE, 6 | CHANGE_SORTING_ONGOING, 7 | ADD_ALGORITHM, 8 | REMOVE_ALGORITHM, 9 | CHANGE_DESCRIPTION, 10 | SET_DESC_REF, 11 | } from "../action-types"; 12 | 13 | export const doShuffle = { type: SHUFFLE }; 14 | 15 | export const doChangeSortType = (sortType) => ({ 16 | type: CHANGE_SORT_TYPE, 17 | payload: sortType, 18 | }); 19 | 20 | export const doChangeSpeed = (speed) => ({ 21 | type: CHANGE_SPEED, 22 | payload: speed, 23 | }); 24 | 25 | export const doChangeSize = (size) => ({ 26 | type: CHANGE_SIZE, 27 | payload: size, 28 | }); 29 | 30 | export const doChangeSortingOngoing = (sortingOngoing) => ({ 31 | type: CHANGE_SORTING_ONGOING, 32 | payload: sortingOngoing, 33 | }); 34 | 35 | export const doAddAlgorithm = (algorithm) => ({ 36 | type: ADD_ALGORITHM, 37 | payload: algorithm, 38 | }); 39 | 40 | export const doRemoveAlgorithm = (idx) => ({ 41 | type: REMOVE_ALGORITHM, 42 | payload: idx, 43 | }); 44 | 45 | export const doChangeDescription = (name) => ({ 46 | type: CHANGE_DESCRIPTION, 47 | payload: name, 48 | }); 49 | 50 | export const doSetDescRef = (ref) => ({ 51 | type: SET_DESC_REF, 52 | payload: ref, 53 | }); 54 | -------------------------------------------------------------------------------- /src/components/Descreptions/Container/HiddenDescList.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import DescList from "../DescList"; 4 | import CloseIcon from "@mui/icons-material/Close"; 5 | import HiddenDescListStyled from "./HiddenDescList.styles"; 6 | import { motion, AnimatePresence } from "framer-motion"; 7 | 8 | export default function HiddenDescList({ open, setOpen }) { 9 | const outside = React.useRef(null); 10 | 11 | function onClose(e) { 12 | if (outside.current === e.target) { 13 | setOpen(false); 14 | } 15 | } 16 | 17 | return ReactDOM.createPortal( 18 | 19 | {open && ( 20 | 21 | 28 | 34 | 35 | 36 | 37 | )} 38 | , 39 | document.getElementById("portal") 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/components/Descreptions/Container/Description.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const DescreptionStyled = styled.div` 4 | padding: 2rem 4rem; 5 | margin: 0 3rem; 6 | background: ${(props) => props.theme.colors.dark}; 7 | color: ${(props) => props.theme.colors.light}; 8 | font-size: 1.1rem; 9 | .bold { 10 | font-weight: 600; 11 | color: ${(props) => props.theme.colors.main}; 12 | } 13 | p { 14 | line-height: 1.8; 15 | margin: 2rem 0; 16 | } 17 | h2 { 18 | text-align: center; 19 | font-size: 3rem; 20 | } 21 | a { 22 | font-weight: 600; 23 | color: ${(props) => props.theme.colors.main}; 24 | &:hover { 25 | color: ${(props) => props.theme.colors.light}; 26 | } 27 | } 28 | h3 { 29 | font-size: 2rem; 30 | margin-bottom: 0.3rem; 31 | } 32 | li { 33 | margin: 1rem; 34 | line-height: 1.6; 35 | } 36 | h4 { 37 | font-size: 1.8rem; 38 | margin: 5rem 0 0; 39 | color: ${(props) => props.theme.colors.light}; 40 | } 41 | img { 42 | display: block; 43 | margin: 3.5rem auto; 44 | max-width: 100%; 45 | background: ${(props) => props.theme.colors.absoluteLight}; 46 | } 47 | ol img { 48 | margin-left: -2rem; 49 | } 50 | @media (max-width: 900px) { 51 | padding: 2rem 0; 52 | margin: 0; 53 | margin-left: -1.5rem; 54 | } 55 | `; 56 | 57 | export default DescreptionStyled; 58 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/shellSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* shellSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let gap = arr.length; 6 | 7 | while (gap > 0) { 8 | let i = 0; 9 | let j = gap; 10 | 11 | while (j < arr.length) { 12 | if (arr[i].val > arr[j].val) { 13 | [arr[i].val, arr[j].val] = [arr[j].val, arr[i].val]; 14 | 15 | if (i < arr.length) arr[i].active = true; 16 | if (j < arr.length) arr[j].active = true; 17 | yield newElements(arr, arrMax); 18 | if (i < arr.length) arr[i].active = false; 19 | if (j < arr.length) arr[j].active = false; 20 | } 21 | 22 | i++; 23 | j++; 24 | 25 | let k = i; 26 | while (k - gap > -1) { 27 | if (arr[k - gap].val > arr[k].val) { 28 | [arr[k - gap].val, arr[k].val] = [ 29 | arr[k].val, 30 | arr[k - gap].val, 31 | ]; 32 | 33 | if (k >= 0) arr[k].active = true; 34 | if (k - gap >= 0) arr[k - gap].active = true; 35 | yield newElements(arr, arrMax); 36 | if (k >= 0) arr[k].active = false; 37 | if (k - gap >= 0) arr[k - gap].active = false; 38 | } 39 | k--; 40 | } 41 | } 42 | 43 | gap = Math.floor(gap / 2); 44 | } 45 | 46 | for (let i = 0; i < arr.length; i++) { 47 | arr[i].active = true; 48 | yield newElements(arr, arrMax); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/components/Sidebar/HiddenSidebar.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Sidebar from "."; 4 | import HiddenSidebarStyled from "./HiddenSidebar.styles"; 5 | import CloseIcon from "@mui/icons-material/Close"; 6 | import { motion, AnimatePresence } from "framer-motion"; 7 | 8 | export default function HiddenSidebar({ algorithms, open, setOpen }) { 9 | const outside = React.useRef(null); 10 | 11 | function onClose(e) { 12 | if (outside.current === e.target) { 13 | setOpen(false); 14 | } 15 | } 16 | 17 | return ReactDOM.createPortal( 18 | 19 | {open && ( 20 | 21 | 31 | 37 | 41 | 42 | 43 | )} 44 | , 45 | document.getElementById("portal") 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/components/Main/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "react-redux"; 3 | import AlgorithmsContainer from "../AlgorithmsContainer"; 4 | import Sidebar from "../Sidebar"; 5 | import MainContainer from "./Main.styles"; 6 | import MenuIcon from "@mui/icons-material/Menu"; 7 | import HiddenSidebar from "../Sidebar/HiddenSidebar"; 8 | 9 | function Main({ algorithms, width }) { 10 | const [open, setOpen] = React.useState(false); 11 | 12 | React.useEffect(() => { 13 | if (open) { 14 | document.body.classList.add("open-modal-2"); 15 | } else { 16 | document.body.classList.remove("open-modal-2"); 17 | } 18 | }, [open]); 19 | 20 | return ( 21 | 22 |
23 | 24 |
25 | 26 | {width > 1710 ? ( 27 |
28 | 29 |
30 | ) : ( 31 | 34 | )} 35 | 40 |
41 | ); 42 | } 43 | 44 | const props = (state) => ({ 45 | algorithms: state.algorithms, 46 | }); 47 | 48 | export default connect(props, null)(Main); 49 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/insertionSortBinary.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* insertionSortBinary(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | for (let i = 1; i < arr.length; i++) { 7 | let x = arr[i]; 8 | let j = binarySearch(arr, x, 0, i - 1); 9 | 10 | if (j > 0) arr[j].active = true; 11 | if (i > 0) arr[i].active = true; 12 | yield newElements(JSON.parse(JSON.stringify(arr)), arrMax); 13 | if (j > 0) arr[j].active = false; 14 | if (i > 0) arr[i].active = false; 15 | 16 | arr = [...arr.slice(0, j), x, ...arr.slice(j, i), ...arr.slice(i + 1)]; 17 | 18 | if (j > 0) arr[j].active = true; 19 | if (i > 0) arr[i].active = true; 20 | yield newElements(JSON.parse(JSON.stringify(arr)), arrMax); 21 | if (j > 0) arr[j].active = false; 22 | if (i > 0) arr[i].active = false; 23 | } 24 | 25 | for (let i = 0; i < arr.length; i++) { 26 | arr[i].active = true; 27 | yield newElements(arr, arrMax); 28 | } 29 | } 30 | 31 | function binarySearch(arr, item, low, high) { 32 | if (high <= low) { 33 | return item.val > arr[low].val ? low + 1 : low; 34 | } 35 | 36 | let mid = Math.floor((low + high) / 2); 37 | 38 | if (item.val === arr[mid].val) { 39 | return mid + 1; 40 | } 41 | 42 | if (item.val > arr[mid].val) { 43 | return binarySearch(arr, item, mid + 1, high); 44 | } 45 | 46 | return binarySearch(arr, item, low, mid - 1); 47 | } 48 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/pancakeSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* pancakeSort(items, arrMax) { 4 | let base = JSON.parse(JSON.stringify(items)); 5 | let arr = JSON.parse(JSON.stringify(base)); 6 | 7 | let changes = []; 8 | 9 | function flip(arr, i) { 10 | let og = i; 11 | let start = 0; 12 | while (start < i) { 13 | [arr[start].val, arr[i].val] = [arr[i].val, arr[start].val]; 14 | 15 | start++; 16 | i--; 17 | } 18 | arr[og].active = true; 19 | changes.push(JSON.parse(JSON.stringify(arr))); 20 | arr[og].active = false; 21 | } 22 | 23 | function findMax(arr, n) { 24 | let mi, i; 25 | for (mi = 0, i = 0; i < n; ++i) { 26 | if (arr[i].val > arr[mi].val) { 27 | mi = i; 28 | } 29 | } 30 | 31 | return mi; 32 | } 33 | 34 | function sortP(arr, n) { 35 | for (let curr_size = n; curr_size > 1; --curr_size) { 36 | let mi = findMax(arr, curr_size); 37 | 38 | if (mi !== curr_size - 1) { 39 | flip(arr, mi); 40 | 41 | flip(arr, curr_size - 1); 42 | } 43 | } 44 | 45 | return 0; 46 | } 47 | let w = JSON.parse(JSON.stringify(arr)); 48 | sortP(w, w.length); 49 | 50 | console.log(w); 51 | 52 | for (let el of changes) { 53 | yield newElements(el.slice(0, base.length), arrMax); 54 | } 55 | 56 | for (let i = 0; i < base.length; i++) { 57 | w[i].active = true; 58 | yield newElements(w.slice(0, base.length), arrMax); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/components/Header/index.jsx: -------------------------------------------------------------------------------- 1 | import { StyledHeader } from "./Header.styles"; 2 | import DarkModeIcon from "@mui/icons-material/DarkMode"; 3 | import LightModeIcon from "@mui/icons-material/LightMode"; 4 | import InfoIcon from "@mui/icons-material/Info"; 5 | import GitHubIcon from "@mui/icons-material/GitHub"; 6 | import { useState, useEffect } from "react"; 7 | import InfoModal from "./InfoModal"; 8 | 9 | export default function Header({ theme, toggleTheme }) { 10 | const [open, setOpen] = useState(false); 11 | 12 | useEffect(() => { 13 | if (open) { 14 | document.body.classList.add("open-modal-1"); 15 | } else { 16 | document.body.classList.remove("open-modal-1"); 17 | } 18 | }, [open]); 19 | 20 | return ( 21 | 22 | SORT DEMON 23 |
24 | 25 | 28 | 29 | 32 | 39 |
40 | 41 |
42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sort-demonstration", 3 | "version": "0.1.0", 4 | "homepage": "https://copperhuh.github.io/SortDemon/", 5 | "private": true, 6 | "dependencies": { 7 | "@emotion/react": "^11.8.1", 8 | "@emotion/styled": "^11.8.1", 9 | "@mui/icons-material": "^5.5.0", 10 | "@mui/material": "^5.5.0", 11 | "@mui/styles": "^5.5.1", 12 | "@testing-library/jest-dom": "^5.16.2", 13 | "@testing-library/react": "^12.1.4", 14 | "@testing-library/user-event": "^13.5.0", 15 | "framer-motion": "^6.2.8", 16 | "gh-pages": "^3.2.3", 17 | "react": "^17.0.2", 18 | "react-animate-height": "^2.0.23", 19 | "react-code-blocks": "^0.0.9-0", 20 | "react-dom": "^17.0.2", 21 | "react-redux": "^7.2.6", 22 | "react-scripts": "5.0.0", 23 | "redux": "^4.1.2", 24 | "styled-components": "^5.3.3", 25 | "web-vitals": "^2.1.4" 26 | }, 27 | "scripts": { 28 | "start": "react-scripts start", 29 | "build": "react-scripts build", 30 | "test": "react-scripts test", 31 | "predeploy": "npm run build", 32 | "deploy": "gh-pages -d build", 33 | "eject": "react-scripts eject" 34 | }, 35 | "eslintConfig": { 36 | "extends": [ 37 | "react-app", 38 | "react-app/jest" 39 | ] 40 | }, 41 | "browserslist": { 42 | "production": [ 43 | ">0.2%", 44 | "not dead", 45 | "not op_mini all" 46 | ], 47 | "development": [ 48 | "last 1 chrome version", 49 | "last 1 firefox version", 50 | "last 1 safari version" 51 | ] 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/quickSortRightPivot.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* quickSortRightPivot(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | let changes = []; 7 | function partition(arr, low, high) { 8 | let pivot = arr[high]; 9 | 10 | let i = low - 1; 11 | 12 | for (let j = low; j <= high - 1; j++) { 13 | if (arr[j].val < pivot.val) { 14 | i++; 15 | [arr[i].val, arr[j].val] = [arr[j].val, arr[i].val]; 16 | } 17 | if (i < arr.length && i >= 0) arr[i].active = true; 18 | arr[j].active = true; 19 | changes.push(JSON.parse(JSON.stringify(arr))); 20 | if (i < arr.length && i >= 0) arr[i].active = false; 21 | arr[j].active = false; 22 | } 23 | [arr[i + 1].val, arr[high].val] = [arr[high].val, arr[i + 1].val]; 24 | 25 | arr[i + 1].active = true; 26 | arr[high].active = true; 27 | changes.push(JSON.parse(JSON.stringify(arr))); 28 | arr[i + 1].active = false; 29 | arr[high].active = false; 30 | 31 | return i + 1; 32 | } 33 | 34 | function sortQ(arr, low, high) { 35 | if (low < high) { 36 | let pi = partition(arr, low, high); 37 | 38 | sortQ(arr, low, pi - 1); 39 | sortQ(arr, pi + 1, high); 40 | } 41 | } 42 | 43 | sortQ(arr, 0, arr.length - 1); 44 | for (let each of changes) { 45 | yield newElements(each, arrMax); 46 | } 47 | 48 | for (let i = 0; i < arr.length; i++) { 49 | arr[i].active = true; 50 | yield newElements(arr, arrMax); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/components/Sidebar/HiddenSidebar.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const HiddenSidebarStyled = styled.div` 4 | position: fixed; 5 | top: 0; 6 | right: 0; 7 | height: 100vh; 8 | width: 100vw; 9 | background: rgba(0, 0, 0, 0.3); 10 | display: flex; 11 | justify-content: right; 12 | .sidebar-bg { 13 | height: 100%; 14 | width: fit-content; 15 | overflow: auto; 16 | background: ${(props) => props.theme.colors.light}; 17 | padding-left: 1.5rem; 18 | position: relative; 19 | display: flex; 20 | opacity: 1 !important; 21 | } 22 | .close-sidebar { 23 | height: fit-content; 24 | position: sticky; 25 | top: 1.5rem; 26 | left: 0; 27 | width: fit-content; 28 | 29 | display: flex; 30 | align-items: center; 31 | justify-content: center; 32 | background: none; 33 | color: ${(props) => props.theme.colors.main}; 34 | border: none; 35 | :hover { 36 | color: ${(props) => props.theme.colors.dark}; 37 | } 38 | } 39 | &::-webkit-scrollbar { 40 | width: 10px; 41 | } 42 | &::-webkit-scrollbar-track { 43 | background: ${(props) => props.theme.colors.dark}; 44 | } 45 | &::-webkit-scrollbar-thumb { 46 | width: 5px; 47 | background: ${(props) => props.theme.colors.main}; 48 | border-radius: 5px; 49 | } 50 | @media (max-width: 450px) { 51 | .sidebar-bg { 52 | width: 100%; 53 | } 54 | } 55 | @media (max-width: 370px) { 56 | .sidebar-bg { 57 | padding: 0; 58 | } 59 | } 60 | `; 61 | 62 | export default HiddenSidebarStyled; 63 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/gravitySort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* gravitySort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | let max = arrMax; 8 | let beads = []; 9 | for (let i = 0; i < max * n; i++) { 10 | beads.push(0); 11 | } 12 | 13 | for (let i = 0; i < n; i++) { 14 | for (let j = 0; j < arr[i].val; j++) { 15 | beads[i * max + j] = 1; 16 | } 17 | } 18 | function format(arr) { 19 | let a = []; 20 | for (let i = 0; i < n; i++) { 21 | a.push({ val: 0, active: false }); 22 | } 23 | for (let i = 0; i < arr.length; i++) { 24 | if (arr[i] === 1) { 25 | a[Math.floor(i / max)].val++; 26 | } 27 | } 28 | return a; 29 | } 30 | yield newElements(JSON.parse(JSON.stringify(format(beads))), arrMax); 31 | 32 | for (let j = 0; j < max; j++) { 33 | yield newElements(JSON.parse(JSON.stringify(format(beads))), arrMax); 34 | 35 | let sum = 0; 36 | for (let i = 0; i < n; i++) { 37 | sum += beads[i * max + j]; 38 | beads[i * max + j] = 0; 39 | } 40 | 41 | for (let i = n - sum; i < n; i++) { 42 | beads[i * max + j] = 1; 43 | } 44 | yield newElements(JSON.parse(JSON.stringify(format(beads))), arrMax); 45 | } 46 | 47 | for (let i = 0; i < n; i++) { 48 | let j = 0; 49 | while (j < max && beads[i * max + j] === 1) { 50 | j++; 51 | } 52 | arr[i].val = j; 53 | } 54 | 55 | for (let i = 0; i < arr.length; i++) { 56 | arr[i].active = true; 57 | yield newElements(arr, arrMax); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/quickSortMiddlePivot.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* quickSortLeftPivot(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | let changes = []; 7 | 8 | function partition(arr, low, high) { 9 | let mid = Math.floor((low + high) / 2); 10 | let pivot = JSON.parse(JSON.stringify(arr[mid])); 11 | 12 | let i = low; 13 | 14 | for (let j = low; j <= high; j++) { 15 | if (arr[j].val < pivot.val) { 16 | [arr[i].val, arr[j].val] = [arr[j].val, arr[i].val]; 17 | i++; 18 | if (i > mid) { 19 | mid = j; 20 | } 21 | } 22 | if (i < arr.length && i >= 0) arr[i].active = true; 23 | arr[j].active = true; 24 | changes.push(JSON.parse(JSON.stringify(arr))); 25 | if (i < arr.length && i >= 0) arr[i].active = false; 26 | arr[j].active = false; 27 | } 28 | [arr[i].val, arr[mid].val] = [arr[mid].val, arr[i].val]; 29 | 30 | arr[i].active = true; 31 | arr[mid].active = true; 32 | changes.push(JSON.parse(JSON.stringify(arr))); 33 | arr[i].active = false; 34 | arr[mid].active = false; 35 | 36 | return i; 37 | } 38 | 39 | function sortQ(arr, low, high) { 40 | if (low < high) { 41 | let pi = partition(arr, low, high); 42 | 43 | sortQ(arr, low, pi - 1); 44 | sortQ(arr, pi + 1, high); 45 | } 46 | } 47 | 48 | sortQ(arr, 0, arr.length - 1); 49 | 50 | for (let each of changes) { 51 | yield newElements(each, arrMax); 52 | } 53 | 54 | for (let i = 0; i < arr.length; i++) { 55 | arr[i].active = true; 56 | yield newElements(arr, arrMax); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/components/Descreptions/Container/Container.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const DescContainer = styled.div` 4 | width: 100%; 5 | padding: 0 1rem 0 0; 6 | margin: auto; 7 | display: flex; 8 | background: ${(props) => props.theme.colors.dark}; 9 | position: relative; 10 | justify-content: center; 11 | 12 | .desc-list { 13 | width: fit-content; 14 | height: 100%; 15 | position: sticky; 16 | position: -webkit-sticky; 17 | top: 0; 18 | } 19 | 20 | .desc-content { 21 | max-width: min(950px, 95vw); 22 | height: 100%; 23 | } 24 | 25 | .scroll-top, 26 | .open-list { 27 | position: fixed; 28 | bottom: 3rem; 29 | right: 3rem; 30 | padding: 0.5rem; 31 | height: fit-content; 32 | display: ${(props) => (props.buttonVisible ? "flex" : "none")}; 33 | background: ${(props) => props.theme.colors.dark}; 34 | justify-content: center; 35 | align-items: center; 36 | border: 1px solid ${(props) => props.theme.colors.main}; 37 | color: ${(props) => props.theme.colors.main}; 38 | :hover { 39 | color: ${(props) => props.theme.colors.dark}; 40 | background: ${(props) => props.theme.colors.main}; 41 | } 42 | } 43 | .open-list { 44 | display: flex; 45 | margin: 2rem 0; 46 | top: 5rem; 47 | left: 5rem; 48 | z-index: 1; 49 | width: fit-content; 50 | position: sticky; 51 | float: left; 52 | } 53 | @media (max-width: 900px) { 54 | .open-list { 55 | left: 0; 56 | border-left: none; 57 | } 58 | svg { 59 | margin: 0; 60 | display: block; 61 | } 62 | } 63 | @media (max-width: 600px) { 64 | margin: 0; 65 | } 66 | `; 67 | 68 | export default DescContainer; 69 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/BubbleBogoSort.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function BubbleBogoSort() { 5 | return ( 6 | <> 7 |

Bubble Bogo Sort

8 |

9 | Bubble bogo sort is a version of{" "} 10 | Bubble sort in which you{" "} 11 | randomly choose two elements from 12 | the array, compare them and then switch them if needed. 13 |

14 | 15 | Note: The visualization of this algorithm may seem quite fast, 16 | but that's only because it doesn't show iterations, in which the 17 | two compared elements are not switched (which is especially 18 | common in the latter portion of the runtime) 19 | 20 |

Implementation

21 | { 26 | for (let i = 0; i < n - 1; i++) { 27 | if (arr[i] > arr[i + 1]) { 28 | return false; 29 | } 30 | } 31 | return true; 32 | }; 33 | 34 | while (!isSorted()) { 35 | let rand1 = Math.floor(Math.random() * n); 36 | let rand2 = Math.floor(Math.random() * n); 37 | 38 | if (rand1 > rand2) { 39 | [rand1, rand2] = [rand2, rand1]; 40 | } 41 | 42 | if (arr[rand1] > arr[rand2]) { 43 | [arr[rand1], arr[rand2]] = [arr[rand2], arr[rand1]]; 44 | } 45 | } 46 | }`} 47 | /> 48 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /src/hooks/useSortingAlgo.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useRef } from "react"; 2 | import { useDispatch, useSelector } from "react-redux"; 3 | import { CHANGE_SORTING_ONGOING } from "../redux/action-types"; 4 | import getSortingMethod from "../utils/getSortingMethod"; 5 | 6 | const useSortingAlgo = ( 7 | items, 8 | arrMax, 9 | newNodesRef, 10 | speedRef, 11 | sortingMethod 12 | ) => { 13 | let sort = getSortingMethod(sortingMethod); 14 | 15 | const [elements, setElements] = useState(null); 16 | 17 | async function getEls() { 18 | while (true) { 19 | await sleep(speedRef.current); 20 | if (!pausedRef.current) { 21 | break; 22 | } 23 | const elsObj = elsGenerator.next(); 24 | if (elsObj.done) { 25 | break; 26 | } 27 | setElements(elsObj); 28 | } 29 | } 30 | 31 | const sortingOngoing = useSelector((state) => state.sortingOngoing); 32 | 33 | useEffect(() => { 34 | dispatch({ type: CHANGE_SORTING_ONGOING, payload: false }); 35 | setElsGenerator(sort(items, arrMax)); 36 | }, [items]); 37 | 38 | useEffect(() => { 39 | pausedRef.current = sortingOngoing; 40 | if (sortingOngoing) { 41 | newNodesRef.current = false; 42 | getEls(); 43 | } 44 | return () => { 45 | mountedRef.current = false; 46 | }; 47 | }, [sortingOngoing]); 48 | 49 | const [elsGenerator, setElsGenerator] = useState(sort(items, arrMax)); 50 | 51 | const mountedRef = useRef(true); 52 | const pausedRef = useRef(sortingOngoing); 53 | 54 | const dispatch = useDispatch(); 55 | return [elements]; 56 | }; 57 | 58 | export default useSortingAlgo; 59 | 60 | function sleep(ms) { 61 | return new Promise((resolve) => setTimeout(resolve, ms)); 62 | } 63 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const FooterStyled = styled.div` 4 | width: 100%; 5 | padding: 5rem; 6 | text-align: center; 7 | background: ${(props) => props.theme.colors.light}; 8 | text-transform: uppercase; 9 | display: flex; 10 | justify-content: space-evenly; 11 | align-items: center; 12 | color: ${(props) => props.theme.colors.dark}; 13 | & > div { 14 | margin: auto; 15 | } 16 | span { 17 | text-transform: none; 18 | display: block; 19 | } 20 | .contact { 21 | display: flex; 22 | width: fit-content; 23 | margin: auto; 24 | justify-content: space-between; 25 | align-items: center; 26 | flex-direction: column; 27 | margin: 0 auto 1rem; 28 | } 29 | .contact-sub { 30 | display: flex; 31 | justify-content: left; 32 | align-items: center; 33 | margin-top: 1rem; 34 | } 35 | svg { 36 | margin-right: 1rem; 37 | } 38 | a { 39 | text-decoration: none; 40 | color: ${(props) => props.theme.colors.dark}; 41 | } 42 | a:hover { 43 | color: ${(props) => props.theme.colors.main}; 44 | } 45 | .contact-title { 46 | font-size: 1.7rem; 47 | } 48 | .made-by { 49 | font-size: 1.2rem; 50 | } 51 | .github { 52 | padding-bottom: 0; 53 | } 54 | @media (max-width: 850px) { 55 | padding: 5rem 2rem; 56 | } 57 | @media (max-width: 550px) { 58 | flex-direction: column; 59 | .made-by { 60 | margin-bottom: 1rem; 61 | } 62 | } 63 | @media (max-width: 350px) { 64 | padding: 5rem 0; 65 | .contact-sub { 66 | flex-direction: column; 67 | justify-content: center; 68 | } 69 | svg { 70 | margin: 0; 71 | margin-bottom: 0.4rem; 72 | } 73 | } 74 | `; 75 | 76 | export default FooterStyled; 77 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/doubleSelectionSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* doubleSelectionSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | let smallIndex; 7 | let largeIndex; 8 | let leftPass = 0; 9 | let rightPass = n - 1; 10 | while (leftPass <= rightPass) { 11 | smallIndex = leftPass; 12 | 13 | for (let i = leftPass + 1; i <= rightPass; i++) { 14 | if (arr[i].val < arr[smallIndex].val) { 15 | smallIndex = i; 16 | } 17 | if (smallIndex <= n) arr[smallIndex].active = true; 18 | if (i <= n) arr[i].active = true; 19 | yield newElements(arr, arrMax); 20 | if (smallIndex <= n) arr[smallIndex].active = false; 21 | if (i <= n) arr[i].active = false; 22 | } 23 | if (smallIndex !== leftPass) { 24 | [arr[leftPass].val, arr[smallIndex].val] = [ 25 | arr[smallIndex].val, 26 | arr[leftPass].val, 27 | ]; 28 | } 29 | 30 | leftPass++; 31 | largeIndex = rightPass; 32 | 33 | for (let j = rightPass - 1; j >= leftPass; j--) { 34 | if (arr[j].val > arr[largeIndex].val) { 35 | largeIndex = j; 36 | } 37 | if (largeIndex <= n) arr[largeIndex].active = true; 38 | if (j <= n) arr[j].active = true; 39 | yield newElements(arr, arrMax); 40 | if (largeIndex <= n) arr[largeIndex].active = false; 41 | if (j <= n) arr[j].active = false; 42 | } 43 | if (largeIndex !== rightPass) { 44 | [arr[largeIndex].val, arr[rightPass].val] = [ 45 | arr[rightPass].val, 46 | arr[largeIndex].val, 47 | ]; 48 | } 49 | 50 | rightPass--; 51 | } 52 | 53 | for (let i = 0; i < arr.length; i++) { 54 | arr[i].active = true; 55 | yield newElements(arr, arrMax); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/oddEvenMergeSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* oddEvenMergeSort(items, arrMax) { 4 | let base = JSON.parse(JSON.stringify(items)); 5 | let arr = JSON.parse(JSON.stringify(base)); 6 | 7 | let goal = 1; 8 | while (Math.pow(2, goal) < arr.length) { 9 | goal++; 10 | } 11 | 12 | let localMax = Math.pow(2, goal); 13 | for (let i = 1; i <= localMax - 1; i++) { 14 | if (arr.length <= i) { 15 | arr.push({ val: i, active: false }); 16 | } 17 | } 18 | let n = localMax; 19 | let changes = []; 20 | 21 | function sortM(lo, n) { 22 | if (n > 1) { 23 | let m = Math.floor(n / 2); 24 | sortM(lo, m); 25 | sortM(lo + m, m); 26 | oddEvenMerge(lo, n, 1); 27 | } 28 | } 29 | 30 | function oddEvenMerge(lo, n, r) { 31 | let m = r * 2; 32 | if (m < n) { 33 | oddEvenMerge(lo, n, m); 34 | oddEvenMerge(lo + r, n, m); 35 | for (let i = lo + r; i + r < lo + n; i += m) { 36 | compare(i, i + r); 37 | } 38 | } else { 39 | compare(lo, lo + r); 40 | } 41 | } 42 | 43 | function compare(i, j) { 44 | if (i >= 0 && j >= 0 && i < localMax && j < localMax) { 45 | if (arr[i].val > arr[j].val) { 46 | [arr[j].val, arr[i].val] = [arr[i].val, arr[j].val]; 47 | 48 | arr[i].active = true; 49 | arr[j].active = true; 50 | changes.push(JSON.parse(JSON.stringify(arr))); 51 | arr[i].active = false; 52 | arr[j].active = false; 53 | } 54 | } 55 | } 56 | 57 | sortM(0, n); 58 | 59 | for (let el of changes) { 60 | yield newElements(el.slice(0, base.length), arrMax); 61 | } 62 | 63 | for (let i = 0; i < base.length; i++) { 64 | arr[i].active = true; 65 | yield newElements(arr.slice(0, base.length), arrMax); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/pairwiseSortingNetwork.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* pairwiseSortingNetwork(items, arrMax) { 4 | let base = JSON.parse(JSON.stringify(items)); 5 | let arr = JSON.parse(JSON.stringify(base)); 6 | 7 | let n = arr.length; 8 | let changes = []; 9 | 10 | let a = 1; 11 | while (a < n) { 12 | let b = a; 13 | let c = 0; 14 | while (b < n) { 15 | if (arr[b - a].val > arr[b].val) { 16 | [arr[b].val, arr[b - a].val] = [arr[b - a].val, arr[b].val]; 17 | 18 | arr[b - a].active = true; 19 | arr[b].active = true; 20 | changes.push(JSON.parse(JSON.stringify(arr))); 21 | arr[b - a].active = false; 22 | arr[b].active = false; 23 | } 24 | 25 | b++; 26 | c++; 27 | if (c >= a) { 28 | c = 0; 29 | b += a; 30 | } 31 | } 32 | a *= 2; 33 | } 34 | 35 | a = Math.floor(a / 4); 36 | let e = 1; 37 | while (a > 0) { 38 | let d = e; 39 | while (d > 0) { 40 | let b = (d + 1) * a; 41 | let c = 0; 42 | while (b < n) { 43 | if (arr[b - d * a].val > arr[b].val) { 44 | [arr[b].val, arr[b - d * a].val] = [ 45 | arr[b - d * a].val, 46 | arr[b].val, 47 | ]; 48 | 49 | arr[b - d * a].active = true; 50 | arr[b].active = true; 51 | changes.push(JSON.parse(JSON.stringify(arr))); 52 | arr[b - d * a].active = false; 53 | arr[b].active = false; 54 | } 55 | 56 | c++; 57 | b++; 58 | if (c >= a) { 59 | c = 0; 60 | b += a; 61 | } 62 | } 63 | d = Math.floor(d / 2); 64 | } 65 | a = Math.floor(a / 2); 66 | e = 2 * e + 1; 67 | } 68 | 69 | for (let el of changes) { 70 | yield newElements(el.slice(0, base.length), arrMax); 71 | } 72 | 73 | for (let i = 0; i < base.length; i++) { 74 | arr[i].active = true; 75 | yield newElements(arr.slice(0, base.length), arrMax); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/circleSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* circleSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | let changes = []; 7 | function circleSortRec(arr, low, high) { 8 | let swapped = false; 9 | 10 | if (low === high) { 11 | return false; 12 | } 13 | 14 | let lo = low; 15 | let hi = high; 16 | 17 | while (lo < hi) { 18 | if (arr[lo].val > arr[hi].val) { 19 | [arr[lo].val, arr[hi].val] = [arr[hi].val, arr[lo].val]; 20 | swapped = true; 21 | } 22 | lo++; 23 | hi--; 24 | 25 | if (lo < arr.length) arr[lo].active = true; 26 | if (hi < arr.length) arr[hi].active = true; 27 | changes.push(JSON.parse(JSON.stringify(arr))); 28 | if (lo < arr.length) arr[lo].active = false; 29 | if (hi < arr.length) arr[hi].active = false; 30 | } 31 | 32 | if (lo === hi) { 33 | if (arr[lo].val > arr[hi + 1].val) { 34 | [arr[lo].val, arr[hi + 1].val] = [arr[hi + 1].val, arr[lo].val]; 35 | swapped = true; 36 | } 37 | 38 | if (lo < arr.length) arr[lo].active = true; 39 | if (hi < arr.length) arr[hi].active = true; 40 | changes.push(JSON.parse(JSON.stringify(arr))); 41 | if (lo < arr.length) arr[lo].active = false; 42 | if (hi < arr.length) arr[hi].active = false; 43 | } 44 | 45 | let mid = Math.floor((high - low) / 2); 46 | let firstHalf = circleSortRec(arr, low, low + mid); 47 | let secondHalf = circleSortRec(arr, low + mid + 1, high); 48 | 49 | return swapped || firstHalf || secondHalf; 50 | } 51 | 52 | function sortC(arr, n) { 53 | while (circleSortRec(arr, 0, n - 1)) {} 54 | } 55 | 56 | sortC(arr, arr.length); 57 | 58 | for (let each of changes) { 59 | yield newElements(each, arrMax); 60 | } 61 | 62 | for (let i = 0; i < arr.length; i++) { 63 | arr[i].active = true; 64 | yield newElements(arr, arrMax); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/components/AlgorithmsContainer/Algorithm/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState, useRef } from "react"; 2 | import AlgorithmStyled from "./Algorithm.styles"; 3 | import { connect } from "react-redux"; 4 | import useSortingAlgo from "../../../hooks/useSortingAlgo"; 5 | import { deCamelCase } from "../../../utils"; 6 | 7 | const Alogrithm = ({ items, arrMax, speed, sortingMethod, len }) => { 8 | let [savedItems, setSavedItems] = useState(items); 9 | const newNodesRef = useRef(true); 10 | const speedRef = useRef(speed); 11 | 12 | useEffect(() => { 13 | speedRef.current = speed; 14 | }, [speed]); 15 | 16 | useEffect(() => { 17 | setSavedItems(items); 18 | newNodesRef.current = true; 19 | }, [items]); 20 | 21 | const [elements] = useSortingAlgo( 22 | savedItems, 23 | arrMax, 24 | newNodesRef, 25 | speedRef, 26 | sortingMethod 27 | ); 28 | 29 | return ( 30 | 31 |

{deCamelCase(sortingMethod)}

32 |
33 | {newNodesRef.current 34 | ? items.map((el, inx) => { 35 | return ( 36 |
43 |
51 |
52 | ); 53 | }) 54 | : elements?.value} 55 |
56 |
57 | ); 58 | }; 59 | 60 | const select = (state) => ({ 61 | items: state.items.items, 62 | arrMax: state.items.arrMax, 63 | size: state.size, 64 | speed: state.speed, 65 | sortingOngoing: state.sortingOngoing, 66 | len: state.algorithms.length, 67 | }); 68 | 69 | export default connect(select, null)(Alogrithm); 70 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/hepSortMax.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* heapSortMax(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | let changes = []; 7 | 8 | function sortH(arr) { 9 | let n = arr.length; 10 | 11 | for (let i = Math.floor(n / 2) - 1; i >= 0; i--) { 12 | heapify(arr, n, i); 13 | arr[i].active = true; 14 | changes.push(JSON.parse(JSON.stringify(arr))); 15 | arr[i].active = false; 16 | } 17 | 18 | for (let i = n - 1; i > 0; i--) { 19 | [arr[0].val, arr[i].val] = [arr[i].val, arr[0].val]; 20 | 21 | arr[0].active = true; 22 | arr[i].active = true; 23 | changes.push(JSON.parse(JSON.stringify(arr))); 24 | arr[0].active = false; 25 | arr[i].active = false; 26 | 27 | heapify(arr, i, 0); 28 | 29 | arr[0].active = true; 30 | arr[i].active = true; 31 | changes.push(JSON.parse(JSON.stringify(arr))); 32 | arr[0].active = false; 33 | arr[i].active = false; 34 | } 35 | } 36 | 37 | function heapify(arr, n, i) { 38 | let largest = i; 39 | let l = 2 * i + 1; 40 | let r = 2 * i + 2; 41 | 42 | if (l < n && arr[l].val > arr[largest].val) { 43 | largest = l; 44 | } 45 | 46 | if (r < n && arr[r].val > arr[largest].val) { 47 | largest = r; 48 | } 49 | 50 | if (largest !== i) { 51 | [arr[largest].val, arr[i].val] = [arr[i].val, arr[largest].val]; 52 | 53 | heapify(arr, n, largest); 54 | arr[largest].active = true; 55 | arr[i].active = true; 56 | changes.push(JSON.parse(JSON.stringify(arr))); 57 | arr[0].active = false; 58 | arr[largest].active = false; 59 | } 60 | } 61 | let w = JSON.parse(JSON.stringify(arr)); 62 | sortH(w); 63 | 64 | for (let change of changes) { 65 | yield newElements(change, arrMax); 66 | } 67 | 68 | for (let i = 0; i < w.length; i++) { 69 | w[i].active = true; 70 | yield newElements(w, arrMax); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | export const getShuffledArr = (size, sortType) => { 2 | let res = []; 3 | let nums = []; 4 | 5 | if (sortType === "few-unique") { 6 | const step = Math.ceil(Math.min(size, 60) / 10) + 1; 7 | let base = [...Array(step + 1).keys()].slice(1); 8 | nums = []; 9 | 10 | while (nums.length < size) { 11 | nums.push(...base); 12 | } 13 | 14 | nums = nums.slice(0, size + 1); 15 | } 16 | 17 | if ( 18 | sortType === "random" || 19 | sortType === "reverse" || 20 | sortType === "nearly-sorted" 21 | ) { 22 | nums = [...Array(size + 1).keys()].slice(1); 23 | 24 | if (sortType === "reverse") { 25 | nums.reverse(); 26 | return zipWithActive(nums); 27 | } 28 | 29 | if (size > 2 && sortType === "nearly-sorted") { 30 | const firstInx = Math.floor(Math.random() * size); 31 | let secondInx = Math.floor(Math.random() * size); 32 | while (firstInx === secondInx) { 33 | secondInx = Math.floor(Math.random() * size); 34 | } 35 | 36 | const firstVal = nums[firstInx]; 37 | const secondVal = nums[secondInx]; 38 | 39 | nums[firstInx] = secondVal; 40 | nums[secondInx] = firstVal; 41 | 42 | return zipWithActive(nums); 43 | } 44 | } 45 | 46 | for (let i = 0; i < size; i++) { 47 | let random = Math.floor(Math.random() * nums.length); 48 | res.push(nums[random]); 49 | nums = [ 50 | ...nums.slice(0, random), 51 | ...nums.slice(random + 1, nums.length), 52 | ]; 53 | } 54 | 55 | return zipWithActive(res); 56 | }; 57 | 58 | const zipWithActive = (arr) => { 59 | let res = []; 60 | for (let each of arr) { 61 | res.push({ val: each, active: false }); 62 | } 63 | 64 | return { items: res, arrMax: Math.max(...arr) }; 65 | }; 66 | 67 | export const deCamelCase = (text) => { 68 | if (text === "RadixSortLSD") return "Radix Sort LSD"; 69 | const result = text.replace(/([A-Z])/g, " $1"); 70 | return result.charAt(0).toUpperCase() + result.slice(1); 71 | }; 72 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/mergeSortBottomUp.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* mergeSortBottomUp(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let merged = []; 6 | for (let one of arr) { 7 | merged.push([one]); 8 | } 9 | 10 | while (merged.length !== 1) { 11 | let n = 0; 12 | 13 | while (n < merged.length) { 14 | if (n + 1 !== merged.length) { 15 | let L = merged[n]; 16 | let R = merged[n + 1]; 17 | let combined = JSON.parse(JSON.stringify([...L, ...R])); 18 | merged = [ 19 | ...merged.slice(0, n), 20 | combined, 21 | ...merged.slice(n + 2), 22 | ]; 23 | 24 | let i = 0; 25 | let j = 0; 26 | let k = 0; 27 | 28 | merged[n][k].active = true; 29 | while (i < L.length && j < R.length) { 30 | if (L[i].val < R[j].val) { 31 | merged[n][k].val = L[i].val; 32 | i++; 33 | } else { 34 | merged[n][k].val = R[j].val; 35 | j++; 36 | } 37 | merged[n][k].active = false; 38 | k++; 39 | if (k !== merged[n].length) merged[n][k].active = true; 40 | 41 | yield newElements(merged.flat(), arrMax); 42 | } 43 | 44 | while (i < L.length) { 45 | merged[n][k].val = L[i].val; 46 | i++; 47 | 48 | merged[n][k].active = false; 49 | k++; 50 | if (k !== merged[n].length) merged[n][k].active = true; 51 | 52 | yield newElements(merged.flat(), arrMax); 53 | } 54 | while (j < R.length) { 55 | merged[n][k].val = R[j].val; 56 | j++; 57 | 58 | merged[n][k].active = false; 59 | k++; 60 | if (k !== merged[n].length) merged[n][k].active = true; 61 | 62 | yield newElements(merged.flat(), arrMax); 63 | } 64 | } 65 | 66 | n++; 67 | } 68 | } 69 | 70 | for (let i = 0; i < merged.flat().length; i++) { 71 | merged.flat()[i].active = true; 72 | yield newElements(merged.flat(), arrMax); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/quickSortLeftPivot.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* quickSortLeftPivot(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | let changes = []; 7 | 8 | function sortQ(arr, l, r) { 9 | if (l < r) { 10 | let pivot = arr[l]; 11 | let i = l; 12 | let j = r; 13 | while (i < j) { 14 | i++; 15 | while (i <= r && arr[i].val < pivot.val) { 16 | i++; 17 | if (i < arr.length && i >= 0) arr[i].active = true; 18 | arr[j].active = true; 19 | changes.push(JSON.parse(JSON.stringify(arr))); 20 | if (i < arr.length && i >= 0) arr[i].active = false; 21 | arr[j].active = false; 22 | } 23 | while (j >= l && arr[j].val > pivot.val) { 24 | j--; 25 | if (i < arr.length && i >= 0) arr[i].active = true; 26 | arr[j].active = true; 27 | changes.push(JSON.parse(JSON.stringify(arr))); 28 | if (i < arr.length && i >= 0) arr[i].active = false; 29 | arr[j].active = false; 30 | } 31 | if (i <= r && i < j) { 32 | [arr[i].val, arr[j].val] = [arr[j].val, arr[i].val]; 33 | } 34 | if (i < arr.length && i >= 0) arr[i].active = true; 35 | arr[j].active = true; 36 | changes.push(JSON.parse(JSON.stringify(arr))); 37 | if (i < arr.length && i >= 0) arr[i].active = false; 38 | arr[j].active = false; 39 | } 40 | [arr[l].val, arr[j].val] = [arr[j].val, arr[l].val]; 41 | 42 | arr[l].active = true; 43 | arr[j].active = true; 44 | changes.push(JSON.parse(JSON.stringify(arr))); 45 | arr[l].active = false; 46 | arr[j].active = false; 47 | 48 | sortQ(arr, l, j - 1); 49 | sortQ(arr, j + 1, r); 50 | } 51 | } 52 | 53 | sortQ(arr, 0, arr.length - 1); 54 | 55 | for (let each of changes) { 56 | yield newElements(each, arrMax); 57 | } 58 | 59 | for (let i = 0; i < arr.length; i++) { 60 | arr[i].active = true; 61 | yield newElements(arr, arrMax); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/components/Header/InfoModal.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const InfoModalStyled = styled.div` 4 | width: 100vw; 5 | height: 100vh; 6 | background: rgba(0, 0, 0, 0.3); 7 | position: fixed; 8 | top: 0; 9 | left: 0; 10 | display: flex; 11 | justify-content: center; 12 | align-items: center; 13 | .modal-bg { 14 | padding: 0.5rem 5rem 1rem; 15 | width: min(900px, 95%); 16 | max-height: 99vh; 17 | background: ${(props) => props.theme.colors.dark}; 18 | position: relative; 19 | display: flex; 20 | flex-direction: column; 21 | align-content: center; 22 | color: ${(props) => props.theme.colors.light}; 23 | overflow: auto; 24 | margin: 0; 25 | &::-webkit-scrollbar { 26 | width: 10px; 27 | } 28 | &::-webkit-scrollbar-track { 29 | background: ${(props) => props.theme.colors.dark}; 30 | } 31 | &::-webkit-scrollbar-thumb { 32 | width: 5px; 33 | background: ${(props) => props.theme.colors.main}; 34 | border-radius: 5px; 35 | } 36 | } 37 | .close-modal { 38 | background: none; 39 | color: ${(props) => props.theme.colors.main}; 40 | border: none; 41 | position: absolute; 42 | top: 1rem; 43 | right: 1rem; 44 | :hover { 45 | transform: scale(1.3); 46 | } 47 | } 48 | p { 49 | line-height: 1.6; 50 | margin: 0; 51 | } 52 | h3 { 53 | text-align: center; 54 | font-size: 2rem; 55 | } 56 | h4 { 57 | font-size: 1.3rem; 58 | padding: 0; 59 | margin: 2rem 0 0.4rem; 60 | } 61 | .center { 62 | text-align: center; 63 | margin: 0; 64 | } 65 | .margin-top { 66 | margin-top: 2rem; 67 | } 68 | .bold, 69 | .center { 70 | font-weight: 600; 71 | color: ${(props) => props.theme.colors.main}; 72 | } 73 | h4, 74 | h3, 75 | .center { 76 | text-transform: uppercase; 77 | } 78 | 79 | @media (max-width: 500px) { 80 | .modal-bg { 81 | padding: 0.5rem 3rem 5rem; 82 | } 83 | p { 84 | font-size: 0.8rem; 85 | } 86 | } 87 | `; 88 | 89 | export default InfoModalStyled; 90 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/bitonicSort.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-loop-func */ 2 | import newElements from "../newElements"; 3 | 4 | export default function* bitonicSort(items, arrMax) { 5 | let base = JSON.parse(JSON.stringify(items)); 6 | let arr = JSON.parse(JSON.stringify(base)); 7 | 8 | let goal = 1; 9 | while (Math.pow(2, goal) < base.length) { 10 | goal++; 11 | } 12 | 13 | let localMax = Math.pow(2, goal); 14 | for (let i = 1; i <= localMax; i++) { 15 | if (arr.length <= i) { 16 | arr.push({ val: i, active: false }); 17 | } 18 | } 19 | 20 | let changes = []; 21 | 22 | function compAndSwap(a, i, j, dir) { 23 | if ( 24 | (a[i].val > a[j].val && dir === 1) || 25 | (a[i].val < a[j].val && dir === 0) 26 | ) { 27 | [a[i].val, a[j].val] = [a[j].val, a[i].val]; 28 | 29 | a[i].active = true; 30 | a[j].active = true; 31 | changes.push(JSON.parse(JSON.stringify(a))); 32 | a[i].active = false; 33 | a[j].active = false; 34 | } 35 | } 36 | 37 | function bitonicMerge(a, low, cnt, dir) { 38 | if (cnt > 1) { 39 | var k = parseInt(cnt / 2); 40 | for (var i = low; i < low + k; i++) compAndSwap(a, i, i + k, dir); 41 | bitonicMerge(a, low, k, dir); 42 | bitonicMerge(a, low + k, k, dir); 43 | } 44 | } 45 | 46 | function sortB(a, low, cnt, dir) { 47 | if (cnt >= 1) { 48 | var k = parseInt(cnt / 2); 49 | 50 | sortB(a, low, k, 1); 51 | 52 | sortB(a, low + k, k, 0); 53 | 54 | bitonicMerge(a, low, cnt, dir); 55 | } 56 | changes.push(JSON.parse(JSON.stringify(a))); 57 | } 58 | let w = JSON.parse(JSON.stringify(arr)); 59 | sortB(w, 0, w.length, 1); 60 | 61 | let prev = w; 62 | for (let el of changes) { 63 | if ( 64 | !el.slice(0, base.length).every((x, idx) => x.val === prev[idx].val) 65 | ) { 66 | yield newElements(el.slice(0, base.length), arrMax); 67 | } 68 | prev = el; 69 | } 70 | 71 | for (let i = 0; i < base.length; i++) { 72 | w[i].active = true; 73 | yield newElements(w.slice(0, base.length), arrMax); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/cocktailShakerSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* cocktailShakerSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | let swapped = true; 7 | let start = 0; 8 | let end = arr.length; 9 | 10 | arr[start].active = true; 11 | arr[end - 1].active = true; 12 | yield newElements(arr, arrMax); 13 | 14 | while (swapped === true) { 15 | swapped = false; 16 | 17 | for (let i = start; i < end - 1; ++i) { 18 | if (arr[i].val > arr[i + 1].val) { 19 | [arr[i].val, arr[i + 1].val] = [arr[i + 1].val, arr[i].val]; 20 | 21 | swapped = true; 22 | } 23 | 24 | if (i !== end - 1 && i !== start) arr[i].active = true; 25 | if (i + 1 !== end - 1 && i + 1 !== start) arr[i + 1].active = true; 26 | yield newElements(arr, arrMax); 27 | if (i !== end - 1 && i !== start) arr[i].active = false; 28 | if (i + 1 !== end - 1 && i + 1 !== start) arr[i + 1].active = false; 29 | } 30 | 31 | if (swapped === false) break; 32 | 33 | swapped = false; 34 | 35 | if (end !== arr.length) arr[end - 1].active = false; 36 | end = end - 1; 37 | if (end !== arr.length) arr[end - 1].active = true; 38 | yield newElements(arr, arrMax); 39 | 40 | for (let i = end - 1; i >= start; i--) { 41 | if (arr[i].val > arr[i + 1].val) { 42 | [arr[i].val, arr[i + 1].val] = [arr[i + 1].val, arr[i].val]; 43 | 44 | swapped = true; 45 | } 46 | 47 | if (i !== end - 1 && i !== start) arr[i].active = true; 48 | if (i + 1 !== end - 1 && i + 1 !== start) arr[i + 1].active = true; 49 | yield newElements(arr, arrMax); 50 | if (i !== end - 1 && i !== start) arr[i].active = false; 51 | if (i + 1 !== end - 1 && i + 1 !== start) arr[i + 1].active = false; 52 | } 53 | 54 | arr[start].active = false; 55 | start = start + 1; 56 | arr[start].active = true; 57 | yield newElements(arr, arrMax); 58 | } 59 | 60 | for (let i = 0; i < arr.length; i++) { 61 | arr[i].active = true; 62 | yield newElements(arr, arrMax); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/redux/Reducers/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | CHANGE_SORT_TYPE, 3 | CHANGE_SPEED, 4 | CHANGE_SIZE, 5 | SHUFFLE, 6 | CHANGE_SORTING_ONGOING, 7 | ADD_ALGORITHM, 8 | REMOVE_ALGORITHM, 9 | CHANGE_DESCRIPTION, 10 | SET_DESC_REF, 11 | } from "../action-types"; 12 | import { getShuffledArr } from "../../utils"; 13 | 14 | const initialState = { 15 | items: getShuffledArr(20), 16 | size: 20, 17 | sortType: "random", 18 | speed: 50, 19 | sortingOngoing: false, 20 | algorithms: localStorage.getItem("algorithms") 21 | ? JSON.parse(localStorage.getItem("algorithms")) 22 | : ["BubbleSort"], 23 | description: localStorage.getItem("description") 24 | ? localStorage.getItem("description") 25 | : "BubbleSort", 26 | descRef: null, 27 | }; 28 | 29 | export const reducer = (state = initialState, action) => { 30 | switch (action.type) { 31 | case SHUFFLE: 32 | return { 33 | ...state, 34 | items: getShuffledArr(state.size, state.sortType), 35 | }; 36 | case CHANGE_SIZE: 37 | return { ...state, size: action.payload }; 38 | case CHANGE_SORT_TYPE: 39 | return { ...state, sortType: action.payload }; 40 | case CHANGE_SPEED: 41 | return { ...state, speed: action.payload }; 42 | case CHANGE_SORTING_ONGOING: 43 | return { ...state, sortingOngoing: action.payload }; 44 | case ADD_ALGORITHM: 45 | if (state.algorithms.length < 9) { 46 | localStorage.setItem( 47 | "algorithms", 48 | JSON.stringify([...state.algorithms, action.payload]) 49 | ); 50 | return { 51 | ...state, 52 | algorithms: [...state.algorithms, action.payload], 53 | }; 54 | } 55 | return state; 56 | case REMOVE_ALGORITHM: 57 | return { 58 | ...state, 59 | algorithms: [ 60 | ...state.algorithms.slice(0, action.payload), 61 | ...state.algorithms.slice(action.payload + 1), 62 | ], 63 | }; 64 | case CHANGE_DESCRIPTION: 65 | localStorage.setItem("description", action.payload); 66 | return { ...state, description: action.payload }; 67 | case SET_DESC_REF: 68 | return { ...state, descRef: action.payload }; 69 | default: 70 | return state; 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/heapSortMin.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* heapSortMin(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | 6 | let changes = []; 7 | 8 | function sortH(arr) { 9 | let n = arr.length; 10 | 11 | for (let i = Math.floor(n / 2) - 1; i >= 0; i--) { 12 | heapify(arr, n, i); 13 | arr[i].active = true; 14 | arr.reverse(); 15 | changes.push(JSON.parse(JSON.stringify(arr))); 16 | arr.reverse(); 17 | arr[i].active = false; 18 | } 19 | 20 | for (let i = n - 1; i >= 0; i--) { 21 | [arr[0].val, arr[i].val] = [arr[i].val, arr[0].val]; 22 | 23 | arr[0].active = true; 24 | arr[i].active = true; 25 | arr.reverse(); 26 | changes.push(JSON.parse(JSON.stringify(arr))); 27 | arr.reverse(); 28 | arr[0].active = false; 29 | arr[i].active = false; 30 | 31 | heapify(arr, i, 0); 32 | 33 | arr[0].active = true; 34 | arr[i].active = true; 35 | arr.reverse(); 36 | changes.push(JSON.parse(JSON.stringify(arr))); 37 | arr.reverse(); 38 | arr[0].active = false; 39 | arr[i].active = false; 40 | } 41 | } 42 | 43 | function heapify(arr, n, i) { 44 | let smallest = i; 45 | let l = 2 * i + 1; 46 | let r = 2 * i + 2; 47 | 48 | if (l < n && arr[l].val < arr[smallest].val) { 49 | smallest = l; 50 | } 51 | 52 | if (r < n && arr[r].val < arr[smallest].val) { 53 | smallest = r; 54 | } 55 | 56 | if (smallest !== i) { 57 | [arr[smallest].val, arr[i].val] = [arr[i].val, arr[smallest].val]; 58 | 59 | heapify(arr, n, smallest); 60 | arr[smallest].active = true; 61 | arr[i].active = true; 62 | arr.reverse(); 63 | changes.push(JSON.parse(JSON.stringify(arr))); 64 | arr.reverse(); 65 | arr[i].active = false; 66 | arr[smallest].active = false; 67 | } 68 | } 69 | let w = JSON.parse(JSON.stringify(arr)); 70 | sortH(w); 71 | w.reverse(); 72 | 73 | for (let change of changes) { 74 | yield newElements(change, arrMax); 75 | } 76 | 77 | for (let i = 0; i < w.length; i++) { 78 | w[i].active = true; 79 | yield newElements(w, arrMax); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/mergeSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* mergeSort(items, arrMax) { 4 | let base = JSON.parse(JSON.stringify(items)); 5 | let arr = JSON.parse(JSON.stringify(base)); 6 | let starter = JSON.parse(JSON.stringify(base)); 7 | 8 | let changes = []; 9 | 10 | function sortM(array) { 11 | if (array.length > 1) { 12 | let mid = Math.floor(array.length / 2); 13 | let L = array.slice(0, mid); 14 | let R = array.slice(mid); 15 | sortM(L); 16 | sortM(R); 17 | 18 | let i = 0; 19 | let j = 0; 20 | let k = 0; 21 | while (i < L.length && j < R.length) { 22 | if (L[i].val < R[j].val) { 23 | array[k] = L[i]; 24 | i++; 25 | } else { 26 | array[k] = R[j]; 27 | j++; 28 | } 29 | k++; 30 | } 31 | 32 | while (i < L.length) { 33 | array[k] = L[i]; 34 | i++; 35 | k++; 36 | } 37 | while (j < R.length) { 38 | array[k] = R[j]; 39 | j++; 40 | k++; 41 | } 42 | if (array !== []) { 43 | changes.push(JSON.parse(JSON.stringify([...array]))); 44 | } 45 | } 46 | } 47 | let w = JSON.parse(JSON.stringify(arr)); 48 | sortM(w); 49 | 50 | let steps = []; 51 | for (let one of changes) { 52 | let baseCopy = [...base]; 53 | let baseNums = baseCopy.map((el) => el.val); 54 | let indexes = []; 55 | for (let each of one) { 56 | indexes.push(baseNums.indexOf(each.val)); 57 | } 58 | indexes = indexes.sort((a, b) => a - b); 59 | baseCopy = [ 60 | ...baseCopy.slice(0, indexes[0]), 61 | ...one, 62 | ...baseCopy.slice(indexes[indexes.length - 1] + 1), 63 | ]; 64 | steps.push([baseCopy, indexes]); 65 | base = [...baseCopy]; 66 | } 67 | 68 | for (let el of steps) { 69 | for (let i = 0; i < el[0].length; i++) { 70 | if (el[1].includes(i) || el[0].length === el[1].length) { 71 | el[0][i].active = true; 72 | starter[i] = el[0][i]; 73 | yield newElements(starter, arrMax); 74 | starter[i].active = false; 75 | } 76 | } 77 | } 78 | 79 | for (let i = 0; i < w.length; i++) { 80 | w[i].active = true; 81 | yield newElements(w, arrMax); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/components/Descreptions/Container/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import DescList from "../DescList"; 3 | import DescContainer from "./Container.styles"; 4 | import DescreptionStyled from "./Description.styles"; 5 | import { connect } from "react-redux"; 6 | import { doSetDescRef } from "../../../redux/Actions"; 7 | import getDescription from "../../../utils/getDescription"; 8 | import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward"; 9 | import useIntersection from "../../../hooks/useIntersection"; 10 | import MenuIcon from "@mui/icons-material/Menu"; 11 | import HiddenDescList from "./HiddenDescList"; 12 | 13 | function Descriptions({ description, setDescRef, width }) { 14 | const descRef = React.useRef(null); 15 | const desc = getDescription(description); 16 | const [open, setOpen] = React.useState(false); 17 | 18 | React.useEffect(() => { 19 | setDescRef(descRef); 20 | }, []); 21 | 22 | React.useEffect(() => { 23 | if (open) { 24 | document.body.classList.add("open-modal-1"); 25 | } else { 26 | document.body.classList.remove("open-modal-1"); 27 | } 28 | }, [open]); 29 | 30 | const inViewport = useIntersection(descRef, "-120px"); 31 | return ( 32 | 33 | 34 | {width > 1350 ? ( 35 |
36 | 37 |
38 | ) : ( 39 | 42 | )} 43 |
44 | {desc} 45 |
46 | 52 |
53 | ); 54 | } 55 | 56 | const props = (state) => ({ 57 | description: state.description, 58 | }); 59 | 60 | const actions = (dispatch) => ({ 61 | setDescRef: (ref) => dispatch(doSetDescRef(ref)), 62 | }); 63 | 64 | export default connect(props, actions)(Descriptions); 65 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/flashSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* flashSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | var max = 0, 6 | min = arr[0].val; 7 | var n = arr.length; 8 | var m = ~~(0.45 * n); 9 | var l = new Array(m); 10 | 11 | for (var i = 1; i < n; ++i) { 12 | if (arr[i].val < min) { 13 | min = arr[i].val; 14 | } 15 | if (arr[i].val > arr[max].val) { 16 | max = i; 17 | } 18 | 19 | arr[i].active = true; 20 | yield newElements(arr, arrMax); 21 | arr[i].active = false; 22 | } 23 | 24 | if (min === arr[max]) { 25 | return arr; 26 | } 27 | 28 | var c1 = (m - 1) / (arr[max].val - min); 29 | 30 | for (var k = 0; k < m; k++) { 31 | l[k] = 0; 32 | } 33 | for (var j = 0; j < n; ++j) { 34 | k = ~~(c1 * (arr[j].val - min)); 35 | ++l[k]; 36 | 37 | arr[j].active = true; 38 | yield newElements(arr, arrMax); 39 | arr[j].active = false; 40 | } 41 | 42 | for (var p = 1; p < m; ++p) { 43 | l[p] = l[p] + l[p - 1]; 44 | } 45 | 46 | var hold = arr[max].val; 47 | arr[max].val = arr[0].val; 48 | arr[0].val = hold; 49 | 50 | var move = 0, 51 | t, 52 | flash; 53 | j = 0; 54 | k = m - 1; 55 | 56 | while (move < n - 1) { 57 | while (j > l[k] - 1) { 58 | ++j; 59 | k = ~~(c1 * (arr[j].val - min)); 60 | } 61 | if (k < 0) break; 62 | flash = arr[j].val; 63 | while (j !== l[k]) { 64 | k = ~~(c1 * (flash - min)); 65 | hold = arr[(t = --l[k])].val; 66 | arr[t].val = flash; 67 | flash = hold; 68 | ++move; 69 | 70 | arr[t].active = true; 71 | yield newElements(arr, arrMax); 72 | arr[t].active = false; 73 | } 74 | } 75 | 76 | for (j = 1; j < n; j++) { 77 | hold = arr[j].val; 78 | i = j - 1; 79 | while (i >= 0 && arr[i].val > hold) { 80 | arr[i + 1].val = arr[i--].val; 81 | 82 | arr[i + 1].active = true; 83 | yield newElements(arr, arrMax); 84 | arr[i + 1].active = false; 85 | } 86 | arr[i + 1].val = hold; 87 | 88 | arr[i + 1].active = true; 89 | yield newElements(arr, arrMax); 90 | arr[i + 1].active = false; 91 | } 92 | 93 | for (let i = 0; i < arr.length; i++) { 94 | arr[i].active = true; 95 | yield newElements(arr, arrMax); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/quickSortStable.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* quickSortStable(items, arrMax) { 4 | let base = JSON.parse(JSON.stringify(items)); 5 | let arr = JSON.parse(JSON.stringify(base)); 6 | let starter = JSON.parse(JSON.stringify(base)); 7 | 8 | let changes = []; 9 | 10 | function sortQ(ar) { 11 | if (ar.length <= 1) { 12 | return ar; 13 | } else { 14 | let mid = Math.floor(ar.length / 2); 15 | let pivot = JSON.parse(JSON.stringify(ar[mid])); 16 | 17 | let smaller = []; 18 | let greater = []; 19 | 20 | for (let indx = 0; indx < ar.length; indx++) { 21 | if (indx !== mid) { 22 | if (ar[indx].val < pivot.val) smaller.push(ar[indx]); 23 | else if (ar[indx].val > pivot.val) { 24 | greater.push(ar[indx]); 25 | } else { 26 | if (indx < mid) { 27 | smaller.push(ar[indx]); 28 | } else { 29 | greater.push(ar[indx]); 30 | } 31 | } 32 | } 33 | } 34 | changes.push( 35 | JSON.parse(JSON.stringify([...smaller, pivot, ...greater])) 36 | ); 37 | return JSON.parse( 38 | JSON.stringify([...sortQ(smaller), pivot, ...sortQ(greater)]) 39 | ); 40 | } 41 | } 42 | let w = JSON.parse(JSON.stringify(arr)); 43 | w = sortQ(w); 44 | 45 | let steps = []; 46 | for (let one of changes) { 47 | let baseCopy = [...base]; 48 | let baseNums = baseCopy.map((el) => el.val); 49 | let indexes = []; 50 | for (let each of one) { 51 | indexes.push(baseNums.indexOf(each.val)); 52 | } 53 | indexes = indexes.sort((a, b) => a - b); 54 | baseCopy = [ 55 | ...baseCopy.slice(0, indexes[0]), 56 | ...one, 57 | ...baseCopy.slice(indexes[indexes.length - 1] + 1), 58 | ]; 59 | steps.push([baseCopy, indexes]); 60 | base = [...baseCopy]; 61 | } 62 | 63 | for (let el of steps) { 64 | for (let i = 0; i < el[0].length; i++) { 65 | if (el[1].includes(i) || el[0].length === el[1].length) { 66 | el[0][i].active = true; 67 | starter[i] = el[0][i]; 68 | yield newElements(starter, arrMax); 69 | starter[i].active = false; 70 | } 71 | } 72 | } 73 | 74 | for (let i = 0; i < w.length; i++) { 75 | w[i].active = true; 76 | yield newElements(w, arrMax); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/OddEvenSort.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function OddEvenSort() { 5 | return ( 6 | <> 7 |

Odd Even Sort

8 |

9 | An Odd Even Sort or brick sort is 10 | a simple sorting algorithm, which is developed for use on 11 | parallel processors with local interconnection.{" "} 12 |

13 |

14 | This algorithm is divided into two phases - Odd and Even Phase. 15 | The algorithm runs until the array elements are sorted and in 16 | each iteration two phases occurs - Odd and Even Phases.{" "} 17 |

18 |

19 | In the odd phase, we perform a bubble sort on odd indexed 20 | elements and in the even phase, we perform a bubble sort on even 21 | indexed elements. 22 |

23 | Odd Even Sort 27 |

28 | Time Complexity : O(n*n) 29 |
30 | Auxiliary Space : O(1) 31 |
32 | In Place: Yes 33 |
34 | Stable: Yes 35 |
36 |

37 |

Implementation

38 | arr[i + 1]) { 48 | [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]; 49 | isSorted = false; 50 | } 51 | } 52 | 53 | for (let i = 0; i <= n - 2; i = i + 2) { 54 | if (arr[i] > arr[i + 1]) { 55 | [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]; 56 | isSorted = false; 57 | } 58 | } 59 | } 60 | }`} 61 | /> 62 |

63 | Source:{" "} 64 | 65 | GeeksforGeeks 66 | 67 | ,{" "} 68 | 69 | RIP Tutorial 70 | 71 |

72 | 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /src/components/Sidebar/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { deCamelCase } from "../../utils"; 3 | import SidebarStyled from "./Sidebar.styles"; 4 | import DoDisturbAltIcon from "@mui/icons-material/DoDisturbAlt"; 5 | import AddIcon from "@mui/icons-material/Add"; 6 | import AddAlgoModal from "./AddAlgoModal"; 7 | import { connect } from "react-redux"; 8 | import { doChangeDescription, doRemoveAlgorithm } from "../../redux/Actions"; 9 | 10 | function Sidebar({ 11 | algorithms, 12 | removeAlgorithm, 13 | changeDescription, 14 | descRef, 15 | hiddenSidebarSetOpen, 16 | }) { 17 | const [open, setOpen] = React.useState(false); 18 | 19 | let elements = algorithms.map((el, id) => { 20 | return ( 21 |
22 |
23 | 29 | 35 |
36 |
37 | ); 38 | }); 39 | 40 | const handleClick = (name) => { 41 | changeDescription(name); 42 | if (hiddenSidebarSetOpen !== undefined) hiddenSidebarSetOpen(false); 43 | descRef.current.scrollIntoView(); 44 | }; 45 | 46 | React.useEffect(() => { 47 | if (open) { 48 | document.body.classList.add("open-modal-1"); 49 | } else { 50 | document.body.classList.remove("open-modal-1"); 51 | } 52 | }, [open]); 53 | 54 | return ( 55 | <> 56 | 57 | {elements} 58 |
59 |
60 | 66 |
67 |
68 |
69 | 70 | 71 | ); 72 | } 73 | 74 | const actions = (dispatch) => ({ 75 | changeDescription: (name) => dispatch(doChangeDescription(name)), 76 | removeAlgorithm: (id) => dispatch(doRemoveAlgorithm(id)), 77 | }); 78 | 79 | const props = (state) => ({ 80 | descRef: state.descRef, 81 | }); 82 | 83 | export default connect(props, actions)(Sidebar); 84 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/bucketSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* bucketSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let x = 30; 6 | let n = Math.floor(arrMax / x) + 1; 7 | 8 | let buckets = new Array(n); 9 | 10 | for (let i = 0; i < n; i++) { 11 | buckets[i] = []; 12 | } 13 | 14 | for (let i = 0; i < arr.length; i++) { 15 | let idx = Math.floor((arr[i].val - 1) / x); 16 | 17 | buckets[idx].push(arr[i]); 18 | yield newElements( 19 | [ 20 | ...JSON.parse(JSON.stringify(buckets)).flat(), 21 | ...JSON.parse(JSON.stringify(arr)).slice(i + 1), 22 | ], 23 | arrMax 24 | ); 25 | } 26 | 27 | for (let k = 0; k < n; k++) { 28 | for (let i = 1; i < buckets[k].length; i++) { 29 | let x = buckets[k][i]; 30 | let j = binarySearch(buckets[k], x, 0, i - 1); 31 | 32 | if (j > 0) buckets[k][j].active = true; 33 | if (i > 0) buckets[k][i].active = true; 34 | yield newElements( 35 | JSON.parse(JSON.stringify(buckets)).flat(), 36 | arrMax 37 | ); 38 | if (j > 0) buckets[k][j].active = false; 39 | if (i > 0) buckets[k][i].active = false; 40 | 41 | buckets[k] = [ 42 | ...buckets[k].slice(0, j), 43 | x, 44 | ...buckets[k].slice(j, i), 45 | ...buckets[k].slice(i + 1), 46 | ]; 47 | 48 | if (j > 0) buckets[k][j].active = true; 49 | if (i > 0) buckets[k][i].active = true; 50 | yield newElements( 51 | JSON.parse(JSON.stringify(buckets)).flat(), 52 | arrMax 53 | ); 54 | if (j > 0) buckets[k][j].active = false; 55 | if (i > 0) buckets[k][i].active = false; 56 | } 57 | } 58 | 59 | let index = 0; 60 | for (let i = 0; i < n; i++) { 61 | for (let j = 0; j < buckets[i].length; j++) { 62 | arr[index++] = buckets[i][j]; 63 | } 64 | } 65 | 66 | for (let i = 0; i < arr.length; i++) { 67 | arr[i].active = true; 68 | yield newElements(arr, arrMax); 69 | } 70 | } 71 | 72 | function binarySearch(arr, item, low, high) { 73 | if (high <= low) { 74 | return item.val > arr[low].val ? low + 1 : low; 75 | } 76 | 77 | let mid = Math.floor((low + high) / 2); 78 | 79 | if (item.val === arr[mid].val) { 80 | return mid + 1; 81 | } 82 | 83 | if (item.val > arr[mid].val) { 84 | return binarySearch(arr, item, mid + 1, high); 85 | } 86 | 87 | return binarySearch(arr, item, low, mid - 1); 88 | } 89 | -------------------------------------------------------------------------------- /src/components/Header/Header.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledHeader = styled.div` 4 | width: 100%; 5 | height: 12%; 6 | padding: 0 2rem; 7 | box-sizing: border-box; 8 | background-color: ${(props) => props.theme.colors.dark}; 9 | position: relative; 10 | display: flex; 11 | align-items: center; 12 | justify-content: right; 13 | span { 14 | color: ${(props) => props.theme.colors.main}; 15 | font-weight: 700; 16 | font-size: 3rem; 17 | padding-left: 2rem; 18 | letter-spacing: 0.5rem; 19 | position: absolute; 20 | left: 50%; 21 | top: 50%; 22 | transform: translateX(-50%) translateY(-50%); 23 | } 24 | 25 | .btns { 26 | display: flex; 27 | justify-content: center; 28 | align-items: center; 29 | } 30 | 31 | button { 32 | display: flex; 33 | align-items: center; 34 | justify-content: center; 35 | color: ${(props) => props.theme.colors.main}; 36 | border: 0.24rem solid ${(props) => props.theme.colors.main}; 37 | background-color: ${(props) => props.theme.colors.dark}; 38 | padding: 0.3rem; 39 | margin-left: 0.8rem; 40 | border-radius: 100px; 41 | :hover { 42 | color: ${(props) => props.theme.colors.light}; 43 | border: 0.24rem solid ${(props) => props.theme.colors.light}; 44 | background-color: ${(props) => props.theme.colors.main}; 45 | } 46 | } 47 | 48 | .switch-theme-btn { 49 | color: ${(props) => props.theme.colors.main}; 50 | border: 0.24rem solid ${(props) => props.theme.colors.light}; 51 | background-color: ${(props) => props.theme.colors.light}; 52 | :hover { 53 | color: ${(props) => props.theme.colors.dark}; 54 | border: 0.24rem solid ${(props) => props.theme.colors.main}; 55 | background-color: ${(props) => props.theme.colors.main}; 56 | } 57 | } 58 | 59 | @media (max-width: 970px) { 60 | span { 61 | position: initial; 62 | transform: none; 63 | flex: 1; 64 | text-align: left; 65 | padding: 0; 66 | } 67 | } 68 | @media (max-width: 550px) { 69 | span { 70 | flex: none; 71 | width: 100%; 72 | text-align: center; 73 | margin: 3rem 0 0.5rem; 74 | } 75 | button { 76 | margin: 0; 77 | } 78 | .btns { 79 | width: 80%; 80 | justify-content: space-evenly; 81 | } 82 | flex-direction: column; 83 | justify-content: space-evenly; 84 | align-items: center; 85 | height: 15%; 86 | } 87 | `; 88 | -------------------------------------------------------------------------------- /src/utils/SortGenerators/cycleSort.js: -------------------------------------------------------------------------------- 1 | import newElements from "../newElements"; 2 | 3 | export default function* cycleSort(items, arrMax) { 4 | let arr = JSON.parse(JSON.stringify(items)); 5 | let n = arr.length; 6 | 7 | for (let cycle_start = 0; cycle_start <= n - 2; cycle_start++) { 8 | let item = arr[cycle_start]; 9 | let pos = cycle_start; 10 | 11 | for (let i = cycle_start + 1; i < n; i++) { 12 | if (arr[i].val < item.val) { 13 | pos++; 14 | } 15 | } 16 | 17 | if (pos === cycle_start) { 18 | continue; 19 | } 20 | 21 | while (item.val === arr[pos].val) { 22 | pos++; 23 | 24 | arr[pos].active = true; 25 | arr[cycle_start].active = true; 26 | yield newElements(arr, arrMax); 27 | arr[pos].active = false; 28 | arr[cycle_start].active = false; 29 | } 30 | 31 | if (pos !== cycle_start) { 32 | [arr[pos].val, item.val] = [item.val, arr[pos].val]; 33 | } 34 | 35 | while (pos !== cycle_start) { 36 | pos = cycle_start; 37 | 38 | for (let i = cycle_start + 1; i < n; i++) { 39 | if (arr[i].val < item.val) { 40 | pos++; 41 | if (pos === cycle_start) { 42 | break; 43 | } 44 | arr[pos].active = true; 45 | arr[i].active = true; 46 | yield newElements(arr, arrMax); 47 | arr[pos].active = false; 48 | arr[i].active = false; 49 | } 50 | } 51 | 52 | if (pos === cycle_start) { 53 | break; 54 | } 55 | 56 | while (item.val === arr[pos].val) { 57 | pos++; 58 | 59 | arr[pos].active = true; 60 | arr[cycle_start].active = true; 61 | yield newElements(arr, arrMax); 62 | arr[pos].active = false; 63 | arr[cycle_start].active = false; 64 | 65 | if (pos === cycle_start) { 66 | break; 67 | } 68 | } 69 | 70 | if (item.val !== arr[pos].val) { 71 | [arr[pos].val, item.val] = [item.val, arr[pos].val]; 72 | } 73 | 74 | arr[pos].active = true; 75 | arr[cycle_start].active = true; 76 | yield newElements(arr, arrMax); 77 | arr[pos].active = false; 78 | arr[cycle_start].active = false; 79 | } 80 | arr[pos].active = true; 81 | arr[cycle_start].active = true; 82 | yield newElements(arr, arrMax); 83 | arr[pos].active = false; 84 | arr[cycle_start].active = false; 85 | } 86 | 87 | for (let i = 0; i < arr.length; i++) { 88 | arr[i].active = true; 89 | yield newElements(arr, arrMax); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/components/Sidebar/Sidebar.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const SidebarStyled = styled.div` 4 | width: 100%; 5 | height: 100%; 6 | overflow-y: auto; 7 | &::-webkit-scrollbar { 8 | width: 5px; 9 | } 10 | &::-webkit-scrollbar-track { 11 | background: ${(props) => props.theme.colors.dark}; 12 | } 13 | &::-webkit-scrollbar-thumb { 14 | width: 3px; 15 | background: ${(props) => props.theme.colors.main}; 16 | border-radius: 5px; 17 | } 18 | 19 | .sort-container { 20 | box-sizing: border-box; 21 | height: fit-content; 22 | width: 100%; 23 | display: flex; 24 | padding: 1rem 0; 25 | padding-left: 1rem; 26 | margin-left: 0; 27 | } 28 | 29 | .btns { 30 | display: flex; 31 | width: 87%; 32 | height: 100%; 33 | justify-content: space-between; 34 | } 35 | 36 | button { 37 | background: ${(props) => props.theme.colors.main}; 38 | border: none; 39 | font-family: ${(props) => props.theme.fonts.main}; 40 | color: ${(props) => props.theme.colors.light}; 41 | text-transform: uppercase; 42 | font-size: 1.2rem; 43 | margin: 0.3rem; 44 | border: 1px solid ${(props) => props.theme.colors.main}; 45 | 46 | &:hover { 47 | background: ${(props) => props.theme.colors.light}; 48 | color: ${(props) => props.theme.colors.main}; 49 | border: 1px solid ${(props) => props.theme.colors.main}; 50 | } 51 | } 52 | 53 | .sort-info-shortcut { 54 | padding: 0.5rem 1rem; 55 | flex: 1; 56 | } 57 | 58 | .sort-remove { 59 | padding: 1rem; 60 | display: flex; 61 | align-items: center; 62 | justify-content: center; 63 | background: ${(props) => props.theme.colors.light}; 64 | color: ${(props) => props.theme.colors.main}; 65 | border: 1px solid ${(props) => props.theme.colors.main}; 66 | 67 | &:hover { 68 | background: ${(props) => props.theme.colors.main}; 69 | color: ${(props) => props.theme.colors.light}; 70 | border: 1px solid ${(props) => props.theme.colors.main}; 71 | } 72 | } 73 | 74 | .add-btn { 75 | margin: 0; 76 | border: none; 77 | .sort-add { 78 | padding: 0.2rem 0; 79 | display: flex; 80 | align-items: center; 81 | justify-content: center; 82 | border: none; 83 | width: 100%; 84 | height: 100%; 85 | margin: 0; 86 | background: none; 87 | color: ${(props) => props.theme.colors.main}; 88 | &:hover { 89 | transform: scale(1.2); 90 | } 91 | } 92 | } 93 | `; 94 | 95 | export default SidebarStyled; 96 | -------------------------------------------------------------------------------- /src/components/Sidebar/AddAlogoModal.styles.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const ModalStyled = styled.div` 4 | position: fixed; 5 | top: 0; 6 | left: 0; 7 | height: 100%; 8 | width: 100%; 9 | background: rgba(0, 0, 0, 0.3); 10 | display: flex; 11 | justify-content: center; 12 | align-items: center; 13 | .close-modal { 14 | position: absolute; 15 | top: 2rem; 16 | right: 3rem; 17 | } 18 | .modal-container { 19 | max-width: min(90%, 900px); 20 | height: 90vh; 21 | background-color: ${(props) => props.theme.colors.dark}; 22 | color: ${(props) => props.theme.colors.light}; 23 | overflow: auto; 24 | display: flex; 25 | flex-direction: column; 26 | justify-content: space-evenly; 27 | padding: 2rem 5rem 2rem 2rem; 28 | transition: all 0.5s; 29 | &::-webkit-scrollbar { 30 | width: 10px; 31 | } 32 | &::-webkit-scrollbar-track { 33 | background: ${(props) => props.theme.colors.dark}; 34 | } 35 | &::-webkit-scrollbar-thumb { 36 | width: 7px; 37 | background: ${(props) => props.theme.colors.main}; 38 | border-radius: 5px; 39 | } 40 | } 41 | 42 | button { 43 | background: none; 44 | color: ${(props) => props.theme.colors.light}; 45 | border: none; 46 | font-family: ${(props) => props.theme.fonts.main}; 47 | font-size: 1.3rem; 48 | } 49 | 50 | .section-title { 51 | margin: 0 2.2rem; 52 | position: relative; 53 | } 54 | svg { 55 | position: absolute; 56 | right: -2rem; 57 | top: 50%; 58 | transform: translateY(-50%); 59 | } 60 | .btns { 61 | list-style: none; 62 | margin-left: 1rem; 63 | } 64 | .algo-btn { 65 | margin: 0.3rem 0; 66 | } 67 | button:hover, 68 | .active { 69 | color: ${(props) => props.theme.colors.main}; 70 | } 71 | @media (max-width: 630px) { 72 | .section-title { 73 | margin: 0 2.4rem; 74 | } 75 | } 76 | @media (max-width: 490px) { 77 | .modal-container { 78 | padding: 0 1rem; 79 | width: 95vw; 80 | padding-left: 6rem; 81 | } 82 | button { 83 | text-align: left; 84 | } 85 | } 86 | @media (max-width: 430px) { 87 | .modal-container { 88 | padding-left: 5rem; 89 | } 90 | } 91 | @media (max-width: 400px) { 92 | .modal-container { 93 | padding-left: 3rem; 94 | } 95 | } 96 | @media (max-width: 350px) { 97 | .modal-container { 98 | padding-left: 1rem; 99 | } 100 | } 101 | `; 102 | 103 | export default ModalStyled; 104 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/QuantumBogoSort.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function QuantumBogoSort() { 5 | return ( 6 | <> 7 |

Quantum Bogo Sort

8 |

9 | QuantumBogoSort is a quantum 10 | sorting algorithm which can sort any list in O(1), using the 11 | "many worlds" interpretation of{" "} 12 | quantum mechanics. 13 |

14 |

Algorithm

15 |
    16 |
  1. 17 |

    18 | Quantumly randomise the list, such that there is no way 19 | of knowing what order the list is in until it is 20 | observed. This will divide the universe into O(n!) 21 | universes; however, the division has no cost, as it 22 | happens constantly anyway. 23 |

    24 |
  2. 25 |
  3. 26 |

    27 | If the list is not sorted, destroy the universe. (This 28 | operation is left as an exercise to the reader.) 29 |

    30 |
  4. 31 |
  5. 32 |

    33 | All remaining universes contain lists which are sorted. 34 |

    35 |
  6. 36 |
37 |

Stability

38 |

39 | As described above, is not a StableSort. A stable version might 40 | be produced as follows: 41 |

42 |
    43 |
  1. 44 |

    45 | Configure the quantum randomiser to produce random code, 46 | rather than shuffle lists. Instruct it to generate some 47 | code. 48 |

    49 |
  2. 50 |
  3. 51 |

    52 | If the resulting code is not a stable QuantumBogoSort, 53 | destroy the universe. 54 |

    55 |
  4. 56 |
  5. 57 |

    58 | All remaining universes now have a stable 59 | QuantumBogoSort algorithm. 60 |

    61 |
  6. 62 |
63 |

64 | Auxilary Space: O(1) 65 |
66 | Auxilary Space: O(1) 67 |
68 | Stable: No, but can be easily 69 | implemented 70 |
71 | In Place: Somewhere 72 |

73 |

Implementation

74 | 79 |

80 | Source: wik.c2 81 |

82 | 83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/BubbleSortOptimized.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function BubbleSortOptimized() { 5 | return ( 6 | <> 7 |

Bubble Sort Optimized

8 |

9 | In normal BubbleSort, all the 10 | comparisons are made even if the array is already sorted. 11 |

12 |

This increases the execution time.

13 |

14 | To solve this, we can introduce an extra variable ' 15 | swapped'. The value of 'swapped' 16 | is set true if there occurs swapping of elements. Otherwise, it 17 | is set false. 18 |

19 |

20 | After an iteration, if there is no swapping, the value of ' 21 | swapped' will be{" "} 22 | false. This means elements are 23 | already sorted and there is no need to perform further 24 | iterations. 25 |

26 |

27 | We can optimize BubbleSort{" "} 28 | further, by shortening each inner loop's instance by one, 29 | since we know that with each instance the greatest element will 30 | be placed in its correct position at the end. 31 |

32 |

33 | This will reduce the execution time and helps to optimize the 34 | bubble sort. 35 |

36 |

37 | Time Complexity: 38 | O(n*n) 39 |
40 | Auxiliary Space: O(1) 41 |
42 | In Place: Yes 43 |
44 | Stable: Yes 45 |

46 |

Implementation

47 | arr[j + 1]) { 56 | [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; 57 | wasSwapped = true; 58 | } 59 | j++; 60 | } 61 | i++; 62 | 63 | if (!wasSwapped) { 64 | break; 65 | } 66 | } 67 | }`} 68 | /> 69 |

70 | Source:{" "} 71 | 72 | Programiz 73 | 74 |

75 | 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/QuickSortStable.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function QuickSortStable() { 5 | return ( 6 | <> 7 |

Quick Sort Stable

8 |

9 | Normal QuickSort is an unstable 10 | algorithm because we do swapping of elements according to 11 | pivot’s position (without considering their original positions).{" "} 12 |

13 |

14 | Quicksort can be stable but it typically isn’t implemented that 15 | way. Making it stable either requires order N storage (as in a 16 | naive implementation) or a bit of extra logic for an in-place 17 | version. 18 |
19 | In below implementation, we use extra space. The idea is to make 20 | two separate lists:{" "} 21 |

22 |
    23 |
  1. First list contains items smaller than pivot.
  2. 24 |
  3. Second list contains items greater than pivot.
  4. 25 |
26 |

27 | Time Complexity: O(n log n) 28 |
29 | Auxiliary Space: O(n) 30 |
31 | Stable: Yes 32 |
33 | In Place: No 34 |

35 |

Implementation

36 | pivot) { 52 | greater.push(arr[i]); 53 | } else { 54 | if (i < mid) { 55 | smaller.push(arr[i]); 56 | } else { 57 | greater.push(arr[i]); 58 | } 59 | } 60 | } 61 | } 62 | return [ 63 | ...quickSortStable(smaller), 64 | pivot, 65 | ...quickSortStable(greater), 66 | ]; 67 | } 68 | }`} 69 | /> 70 |

71 | Source:{" "} 72 | 73 | GeeksforGeeks 74 | 75 |

76 | 77 | ); 78 | } 79 | -------------------------------------------------------------------------------- /src/components/SortSettings/SettingsHidden.jsx: -------------------------------------------------------------------------------- 1 | import { StyledSortSettingsHidden } from "./SortSettings.styles"; 2 | import PlayArrowIcon from '@mui/icons-material/PlayArrow'; 3 | import PauseIcon from '@mui/icons-material/Pause'; 4 | import RestartAltIcon from '@mui/icons-material/RestartAlt'; 5 | import ShuffleIcon from '@mui/icons-material/Shuffle'; 6 | import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; 7 | import React from "react"; 8 | import { connect } from "react-redux"; 9 | import { doChangeSortingOngoing } from "../../redux/Actions"; 10 | 11 | const SettingsHidden = ({toggleShow, shuffle, changeSortingOngoing}) => { 12 | 13 | const onStart = () => { 14 | changeSortingOngoing(true) 15 | } 16 | 17 | const onPause = () => { 18 | changeSortingOngoing(false) 19 | } 20 | 21 | const onReset = () => { 22 | changeSortingOngoing(false) 23 | shuffle() 24 | } 25 | 26 | return ( 27 | 28 |
29 | 30 | 33 |
34 | 38 |
39 |
40 | 44 |
45 |
46 | 50 |
51 |
52 | 56 |
57 |
58 |
59 | ) 60 | } 61 | 62 | const settingsActions = (dispatch) => ({ 63 | changeSortingOngoing: (sortingOngoing) => dispatch(doChangeSortingOngoing(sortingOngoing)), 64 | }) 65 | 66 | export default connect(null, settingsActions)(SettingsHidden) -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/GnomeSort.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function GnomeSort() { 5 | return ( 6 | <> 7 |

Gnome Sort

8 |

9 | Gnome Sort is based on the concept 10 | of a Garden Gnome sorting his flower pots. A garden gnome sorts 11 | the flower pots by the following method- 12 |

13 |
    14 |
  • 15 | He looks at the flower pot next to him and the previous one; 16 | if they are in the right order he steps one pot forward, 17 | otherwise he swaps them and steps one pot backwards. 18 |
  • 19 |
  • 20 | If there is no previous pot (he is at the starting of the 21 | pot line), he steps forwards; if there is no pot next to him 22 | (he is at the end of the pot line), he is done. 23 |
  • 24 |
25 |

Algorithm Steps

26 |
    27 |
  1. 28 | If you are at the start of the array then go to the right 29 | element (from arr[0] to arr[1]). 30 |
  2. 31 |
  3. 32 | If the current array element is larger or equal to the 33 | previous array element then go one step right 34 |
  4. 35 |
  5. 36 | If the current array element is smaller than the previous 37 | array element then swap these two elements and go one step 38 | backwards 39 |
  6. 40 |
  7. 41 | Repeat steps 2) and 3) till ‘i’ reaches the end of the array 42 | (i.e- ‘n - 1’) 43 |
  8. 44 |
  9. 45 | If the end of the array is reached then stop and the array 46 | is sorted. 47 |
  10. 48 |
49 | Gnome Sort 53 |

54 | Time Complexity : O(n*n) 55 |
56 | Auxiliary Space : O(1) 57 |
58 | In Place: Yes 59 |
60 | Stable: Yes 61 |

62 |

Implementation

63 | = arr[i - 1]) { 72 | i++; 73 | } else { 74 | [arr[i], arr[i - 1]] = [arr[i - 1], arr[i]]; 75 | i--; 76 | } 77 | } 78 | }`} 79 | /> 80 |

81 | Source:{" "} 82 | 83 | GeeksforGeeks 84 | 85 |

86 | 87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/GnomeSortOptimized.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function GnomeSortOptimized() { 5 | return ( 6 | <> 7 |

Gnome Sort Optimized

8 |

9 | Gnome sort is a sorting algorithm 10 | which is similar to insertion sort 11 | , except that moving an element to its proper place is 12 | accomplished by a series of swaps, as in{" "} 13 | bubble sort.{" "} 14 |

15 |

16 | It is conceptually simple, requiring no nested loops. The 17 | running time is O(n*n), but in practice the algorithm can run as 18 | fast as Insertion sort. 19 |

20 |

21 | The algorithm always finds the first place where two adjacent 22 | elements are in the wrong order, and swaps them. It takes 23 | advantage of the fact that performing a swap can introduce a new 24 | out-of-order adjacent pair only right before or after the two 25 | swapped elements. It does not assume that elements forward of 26 | the current position are sorted, so it only needs to check the 27 | position directly before the swapped elements. 28 |

29 |

30 | An optimized version uses variable "j" to allow the 31 | gnome to skip back to where it left off after moving to the 32 | left, avoiding some iterations and comparisons. 33 |

34 |

35 | With this optimization, gnome sort{" "} 36 | becomes a variant of{" "} 37 | insertion sort. 38 |

39 |

40 | Time Complexity: O(n*n) 41 |
42 | Auxiliary Space: O(1) 43 |
44 | In Place: Yes 45 |
46 | Stable: Yes 47 |

48 |

Implementation

49 | = arr[i - 1]) { 57 | if (j !== 0) { 58 | i = j; 59 | j = 0; 60 | } 61 | i++; 62 | } else { 63 | [arr[i], arr[i - 1]] = [arr[i - 1], arr[i]]; 64 | if (i > 1) { 65 | if (j === 0) { 66 | j = i; 67 | } 68 | i--; 69 | } else { 70 | i++; 71 | } 72 | } 73 | } 74 | }`} 75 | /> 76 |

77 | Source: en-academic 78 |

79 | 80 | ); 81 | } 82 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/InsertionSortBinary.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function InsertionSortBinary() { 5 | return ( 6 | <> 7 |

Insertion Sort Binary

8 |

9 | In a simple insertion sort{" "} 10 | algorithm, we maintain a sorted and an unsorted subarray of the 11 | given array. In each iteration, one value from the unsorted part 12 | is picked and is inserted in its correct position in the sorted 13 | part. To achieve this, for every element, we iterate over the 14 | sorted part of the array to find the position to insert the 15 | element. 16 |

17 |

18 | Binary insertion sort is a sorting 19 | algorithm similar to insertion sort, but instead of using linear 20 | search to find the position where the element should be 21 | inserted, we use binary search. 22 | Thus, we reduce the number of 23 | comparisons for inserting one element{" "} 24 | from O(N) to O(log N).{" "} 25 |

26 |

27 | We first use binary search on the sorted subarray to find the 28 | position of the element that is{" "} 29 | just greater than our key. Let’s 30 | call this position “pos.” We then right shift all elements from 31 | position pos to i-1 and then make Array[pos] = key.{" "} 32 |

33 |

34 | Time Complexity: O(n*n) 35 |
36 | Auxilary Space: O(1) 37 |
38 | Stable: Yes 39 |
40 | In Place: Yes 41 |

42 |

Implementation

43 | arr[low] ? low + 1 : low; 61 | } 62 | 63 | let mid = Math.floor((low + high) / 2); 64 | 65 | if (item === arr[mid]) { 66 | return mid + 1; 67 | } 68 | 69 | if (item > arr[mid]) { 70 | return binarySearch(arr, item, mid + 1, high); 71 | } 72 | 73 | return binarySearch(arr, item, low, mid - 1); 74 | }`} 75 | /> 76 |

77 | Source:{" "} 78 | 79 | interviewkickstart 80 | 81 |

82 | 83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/DoubleSelectionSort.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CodeComponent from "../CodeComponent"; 3 | 4 | export default function DoubleSelectionSort() { 5 | return ( 6 | <> 7 |

Double Selection Sort

8 |

9 | Selection Sort is not known to be 10 | a good algorithm because it is an in-place comparison sort based 11 | sorting algorithm. However, efforts have been made to improve 12 | the performance of the algorithm particularly where auxiliary 13 | memory is limited. With{" "} 14 | Double Selection Sort, the average 15 | number of comparisons is slightly reduced. 16 |

17 |

18 | The double selection sort starts 19 | from two elements and searches the 20 | entire list until it finds the{" "} 21 | minimum value and{" "} 22 | maximum value. The sort places the 23 | minimum value in the first place{" "} 24 | and maximum value in the{" "} 25 | last place, selects the second and 26 | second last element and searches for the second smallest and 27 | largest element. This process continues until the complete list 28 | is sorted. In other words, a take on an elementary sorting 29 | algorithm that is designed to minimize the number of exchanges 30 | that are performed. It works by making N-1 passes over the 31 | shrinking unsorted portion of the array, each time selecting the 32 | smallest and largest value. Those values are then moved into 33 | their final sorted position with one exchange a piece 34 |

35 |

36 | Time Complexity: O(n*n) 37 |
38 | Auxilary Space: O(1) 39 |
40 | Stable: Yes 41 |
42 | In Place: Yes 43 |

44 |

Implementation

45 | = l; j--) { 66 | if (arr[j] > arr[max]) { 67 | max = j; 68 | } 69 | } 70 | if (max !== r) { 71 | [arr[max], arr[r]] = [arr[r], arr[max]]; 72 | } 73 | r--; 74 | } 75 | }`} 76 | /> 77 |

78 | Source:{" "} 79 | 80 | Improving the performance of selection sort using a modified 81 | double-ended selection sorting 82 | 83 |

84 | 85 | ); 86 | } 87 | -------------------------------------------------------------------------------- /src/components/Descreptions/DescComponents/IntelligentDesignSort.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function IntelligentDesignSort() { 4 | return ( 5 | <> 6 |

Intelligent Design Sort

7 |

8 | Intelligent design sort is a 9 | sorting algorithm based on the theory of{" "} 10 | 11 | intelligent design 12 | 13 | . 14 |

15 |

Algorithm

16 |

17 | The probability of the original input list being in the exact 18 | order it's in is 1/(n!). There is such a small 19 | likelihood of this that it's clearly absurd to say that this 20 | happened by chance, so it must have been consciously put in that 21 | order by an intelligent Sorter. Therefore it's safe to 22 | assume that it's already optimally Sorted in some way that 23 | transcends our naïve mortal understanding of "ascending 24 | order". Any attempt to change that order to conform to our 25 | own preconceptions would actually make it less sorted. 26 |

27 |

Analysis

28 |

29 | This algorithm is constant in time, and sorts the list in-place, 30 | requiring no additional memory at all. In fact, it 31 | doesn't even require any of that suspicious 32 | technological computer stuff. Praise the Sorter! 33 |

34 |

Community Feedback

35 |

Gary Rogers writes:

36 |
37 |

38 | Making the sort constant in time denies the power of The 39 | Sorter. The Sorter exists outside of time, thus the sort is 40 | timeless. To require time to validate the sort dimishes the 41 | role of the Sorter. Thus... this particular sort is flawed, 42 | and can not be attributed to 'The Sorter'. 43 |

44 |
45 |

Heresy!

46 |

In contrast, Krishna Kumar writes:

47 |
48 |

49 | A corollary: All elements are created equal under the 50 | Sorter. 51 |

52 |

53 | Proof: Take a random permutation of the input list; this 54 | second list is also Sorted by the same argument as above. 55 | This means that any two elements in the two lists with the 56 | same index are equal to each other. But the second list was 57 | a random permutation; which indicates that every element in 58 | the original list is equal to every other element. QED. 59 |

60 |
61 |

So it seems the Sorter is benevolent in His munificence!

62 |

63 | Auxilary Space: SUPERB 64 |
65 | Auxilary Space: AWE-INSPIRING 66 |
67 | Stable: THOROUGHLY 68 |
69 | In Place: CERTAINLY 70 |

71 |

72 | Source:{" "} 73 | 74 | dangermouse 75 | 76 |

77 | 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from "styled-components"; 2 | import Header from "./components/Header"; 3 | import SortSettings from "./components/SortSettings"; 4 | import Theme from "./Theme"; 5 | import Main from "./components/Main"; 6 | import React from "react"; 7 | import { Provider } from "react-redux"; 8 | import { store } from "./redux/Store"; 9 | import Descriptions from "./components/Descreptions/Container"; 10 | import Footer from "./components/Footer"; 11 | 12 | const GlobalStyles = createGlobalStyle` 13 | *{ 14 | box-sizing: border-box; 15 | } 16 | html, body{ 17 | overflow-x: hidden; 18 | overflow-y: auto; 19 | max-width: 100%; 20 | scroll-behavior: smooth; 21 | box-sizing: border-box; 22 | } 23 | button{ 24 | user-select: none; 25 | } 26 | .open-modal-1, .open-modal-2{ 27 | overflow: hidden; 28 | padding-right: 10px !important; 29 | } 30 | button, a{ 31 | transition: all 0.2s; 32 | 33 | &:hover, &:focus, a{ 34 | transition: all 0.2s; 35 | } 36 | } 37 | body { 38 | margin: 0; 39 | padding: 0; 40 | height: 100vh; 41 | width: 100vw; 42 | font-family: 'Montserrat', sans-serif; 43 | background: ${(props) => props.theme.colors.dark}; 44 | overflow-x: hidden; 45 | 46 | &::-webkit-scrollbar{ 47 | width: 10px; 48 | } 49 | &::-webkit-scrollbar-track{ 50 | background: ${(props) => props.theme.colors.dark}; 51 | } 52 | &::-webkit-scrollbar-thumb{ 53 | width: 7px; 54 | background: ${(props) => props.theme.colors.main}; 55 | border-radius: 5px; 56 | } 57 | } 58 | #root{ 59 | height: 100%; 60 | width: 100%; 61 | } 62 | ::-moz-selection { 63 | background: ${(props) => props.theme.colors.main}; 64 | color: ${(props) => props.theme.colors.light}; 65 | } 66 | ::-webkit-selection { 67 | background: ${(props) => props.theme.colors.main}; 68 | color: ${(props) => props.theme.colors.light}; 69 | } 70 | ::selection { 71 | background: ${(props) => props.theme.colors.main}; 72 | color: ${(props) => props.theme.colors.light}; 73 | } 74 | 75 | @media (max-width: 720px) { 76 | html{ 77 | font-size: 14px; 78 | } 79 | } 80 | @media (max-width: 630px) { 81 | html{ 82 | font-size: 12px; 83 | } 84 | } 85 | `; 86 | function App() { 87 | const [themeVariation, setThemeVariation] = React.useState("light"); 88 | const [width, setWidth] = React.useState(window.innerWidth); 89 | 90 | React.useEffect(() => { 91 | const handleWindowResize = () => setWidth(window.innerWidth); 92 | window.addEventListener("resize", handleWindowResize); 93 | 94 | return () => window.removeEventListener("resize", handleWindowResize); 95 | }, []); 96 | 97 | const toggleTheme = () => { 98 | setThemeVariation((prevTheme) => 99 | prevTheme === "light" ? "dark" : "light" 100 | ); 101 | }; 102 | return ( 103 | 104 | 105 | 106 | 107 |
108 | 109 |
110 | 111 |