diff --git a/.classpath b/.classpath deleted file mode 100644 index 7bc08230..00000000 --- a/.classpath +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.gitattributes b/.gitattributes index 412eeda7..817f4c9b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,22 +1,8 @@ # Auto detect text files and perform LF normalization * text=auto -# Custom for Visual Studio -*.cs diff=csharp -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union +antw text eol=lf +run text eol=lf -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain +antw.bat text eol=crlf +run.bat text eol=crlf diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml new file mode 100644 index 00000000..c8027638 --- /dev/null +++ b/.github/workflows/checkstyle.yml @@ -0,0 +1,15 @@ +name: checkstyle +on: [pull_request, push, workflow_dispatch] + +jobs: + checkstyle: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 8 + uses: actions/setup-java@v2.1.0 + with: + java-version: 8 + distribution: zulu + - name: Run checkstyle with Maven + run: mvn -Dcheckstyle.violationSeverity=warning checkstyle:check diff --git a/.github/workflows/ant.yml b/.github/workflows/maven.yml similarity index 54% rename from .github/workflows/ant.yml rename to .github/workflows/maven.yml index 33871861..60aadb47 100644 --- a/.github/workflows/ant.yml +++ b/.github/workflows/maven.yml @@ -1,17 +1,12 @@ -name: ant -on: [pull_request, push] +name: maven +on: [pull_request, push, workflow_dispatch] jobs: build: strategy: matrix: # Use these Java versions - java: [ - 8, # Minimum supported - 11, # Current Java LTS - 15, # Last version - 16 # Most recent version - ] + java: [8, 11, 17, 21] # and run on both Linux and Windows os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} @@ -22,16 +17,11 @@ jobs: with: java-version: ${{ matrix.java }} distribution: zulu - - name: Build with Ant - run: ant -noinput -buildfile build.xml - - name: Build standalone JAR - if: ${{ matrix.java == 8 && matrix.os == 'ubuntu-latest' }} - run: | - cd dist - ant -noinput -buildfile build.xml + - name: Build with Maven + run: mvn clean install - name: Upload artifact uses: actions/upload-artifact@v2 if: ${{ matrix.java == 8 && matrix.os == 'ubuntu-latest' }} with: name: standalone-jar - path: dist/arrayVisualizer.jar + path: target/ArrayV-*.jar diff --git a/.gitignore b/.gitignore index 0621b167..9714ab20 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,12 @@ *.class -/bin/ +target __pycache__ cache antiqsort_* network_*.svg +sorting_networks +/stats-config.txt +dependency-reduced-pom.xml +/scripts +.idea/ +*.iml diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..b901097f --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..2cc7d4a5 Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..642d572c --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/.project b/.project deleted file mode 100644 index 39ed6686..00000000 --- a/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - ArrayVisualizer-master - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - - - 1603996993926 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - - diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index e50443cf..00000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,15 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning -org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 7103be72..00000000 --- a/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs deleted file mode 100644 index b196c64a..00000000 --- a/.settings/org.eclipse.ltk.core.refactoring.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..d90744e5 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "vscjava.vscode-java-pack", + "shengchen.vscode-checkstyle" + ] +} \ No newline at end of file diff --git a/.vscode/java-formatter.xml b/.vscode/java-formatter.xml new file mode 100644 index 00000000..a957a9aa --- /dev/null +++ b/.vscode/java-formatter.xml @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.vscode/launch.json b/.vscode/launch.json index e0ffc96f..80c6acab 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,17 +9,19 @@ "type": "java", "name": "Debug ArrayV", "request": "launch", - "mainClass": "main.ArrayVisualizer", - "vmArgs": ["-Dsun.java2d.d3d=false", "-cp", "bin;lib/classgraph-4.8.47.jar"] + "mainClass": "io.github.arrayv.main.ArrayVisualizer", + "projectName": "ArrayV", + "vmArgs": ["-Dsun.java2d.d3d=false"] }, { // should match run.bat "type": "java", "name": "Debug ArrayV (custom max length)", "request": "launch", - "mainClass": "main.ArrayVisualizer", + "mainClass": "io.github.arrayv.main.ArrayVisualizer", + "projectName": "ArrayV", "args": ["${input:length}"], - "vmArgs": ["-Dsun.java2d.d3d=false", "-cp", "bin;lib/classgraph-4.8.47.jar"] + "vmArgs": ["-Dsun.java2d.d3d=false"] } ], "inputs": [ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..215bcb13 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive", + "java.checkstyle.configuration": "${workspaceFolder}/checkstyle.xml", + "java.checkstyle.version": "9.3", + "java.completion.filteredTypes": [ + "com.sun.*", + "sun.*", + "jdk.*", + "org.graalvm.*", + "io.micrometer.shaded.*" + ] +} diff --git a/LICENSE b/LICENSE index a24663ba..4a3569f4 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ MIT License Copyright (c) 2019 w0rthy Copyright (c) 2020 MusicTheorist -Copyright (c) 2020-2021 ArrayV 4.0 Team +Copyright (c) 2020-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index bfb5250b..f1c53f90 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,48 @@ -# w0rthy's Array Visualizer, Revamped +# ArrayV -![GitHub Workflow Status](https://img.shields.io/github/workflow/status/gaming32/ArrayV-v4.0/ant) -![GitHub all releases](https://img.shields.io/github/downloads/gaming32/ArrayV-v4.0/total?color=green) ![Discord](https://img.shields.io/discord/592082838791127075?color=%237289DA&label=Discord&logo=discord&logoColor=white) +![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/Gaming32/ArrayV/maven.yml?branch=main) +![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/Gaming32/ArrayV/checkstyle.yml?branch=main&label=checkstyle) -Over 225 sorting algorithms animated with 13 unique graphic designs +Over 200 sorting algorithms animated with 15 unique graphic designs -[Join the Discord server!](https://discord.com/invite/2xGkKC2) +[Join the Discord server!](https://discord.gg/thestudio) -This new version of the program features additions inspired by Timo Bingmann's "The Sound of Sorting" and w0rthy's updates to the original visualizer. - -To compile (After -cp, use ";" with Windows and ":" with Mac/Linux): +To compile use: +```shell +./mvnw clean verify ``` -ant -java -cp bin;lib/classgraph-4.8.47.jar main.ArrayVisualizer + +To run use: +```shell +./run ``` -To build a runnable jar, simply run Apache Ant inside the 'dist' directory (but make sure you did the above first)! -If you don't want to use Apache Ant or the Java command line, a runnable jar that is up to a month old is available from the `dist` directory. - -### Features: -- 40+ new sorting algorithms -- Updated visuals and sound effects -- You can select different array sizes now -- New shuffle types, including reversed, mostly similar numbers, almost sorted, and already sorted -- Skip Sort button -- Softer sounds toggle -- A real time in milliseconds estimate -- Toggle shuffle animation -- Toggle Timo Bingmann's "end sweep" animation -- Refactored / optimized code - -## ?/?/???? - Version 4.0 -- I really am not sure - -## 6/8/2020 - Version 3.5 +Alternatively, you can double click on "run" or "run.bat" on Windows. + +You can always download the most up-to-date pre-built JAR from [GitHub Actions](https://nightly.link/Gaming32/ArrayV/workflows/maven/main/standalone-jar.zip) (link via [nightly.link](https://nightly.link)). + +## Legacy changelog + +### 6/8/2020 - Version 3.5 - NEW VISUALS: Sine Wave and Wave Dots!! - New sort: Bogobogosort - The bogo shuffle method is now unbiased - MultipleSortThreads further refactored - Visuals, VisualStyles enum, and Renderer significantly refactored (more to come!) -## 6/4/2020 - Version 3.2 +### 6/4/2020 - Version 3.2 - New sort: Optimized Cocktail Shaker Sort - Significant refactoring for MultipleSortThreads and RunAllSorts - "Run All" button approx. time simplified - Modified delays for Binary Gnomesort - Documentation of GCC's median-of-three pivot selection in Introsort -## 6/3/2020 - Version 3.12 +### 6/3/2020 - Version 3.12 - Counting Sort fixed - Optimized Bubblesort now optimized for already sorted inputs - Speeds for Quicksorts and Weave Merge during "Run All Sorts" improved -## 6/2/2020 - Version 3.11 +### 6/2/2020 - Version 3.11 - Minor update to MIT license - Fixed typo in Flipped Min Heapsort - Improved highlights on Heapsorts (Already sorted heaps now display redundant comparisons) @@ -60,18 +50,18 @@ If you don't want to use Apache Ant or the Java command line, a runnable jar tha - Quicksorts exhibiting worst-case behavior during "Run All Sorts" run much faster - Same tweak as above to Weave Merge Sort -## 5/30/2020 - Version 3.1 +### 5/30/2020 - Version 3.1 - Error messages with detailed information will now appear within the program! - Sound effects are now consistent on all platforms - New sort: "Flipped Min Heap Sort" by 'landfillbaby'! - Minor changes to code organization - New webhook to my Discord server! Check it out here: https://discord.com/invite/2xGkKC2 -## 5/22/2020 - Version 3.01 +### 5/22/2020 - Version 3.01 - Quick bug fix to the "Linked Dots" visual; The first line is no longer horizontal. -## 5/21/2020 - Version 3.0 is now released! +### 5/21/2020 - Version 3.0 is now released! - Sound effects are much more pleasant at slower speeds - Revamped "Run All Sorts" (It is now easier to create your own sequence of sorts!) - More accurate delay algorithm @@ -92,7 +82,7 @@ If you don't want to use Apache Ant or the Java command line, a runnable jar tha - Weird static line bug with linked dots squashed - Other miscellaneous fixes and changes here and there -## 10/19/2019 - Version 2.1 +### 10/19/2019 - Version 2.1 - Both Odd-Even Mergesorts now display comparisons - PDQSort's Insertion Sorts have been slowed down - New sorts, courtesy of Piotr Grochowski (https://github.com/PiotrGrochowski/ArrayVisualizer): @@ -100,7 +90,7 @@ If you don't want to use Apache Ant or the Java command line, a runnable jar tha - Recursive Pairwise Sorting Network - Recursive Combsort -## 10/13/2019 - Version 2.0 is now released! +### 10/13/2019 - Version 2.0 is now released! - Now includes 73 sorting algorithms, with 2 more that will be finished in the future - NEW SORTS: - Unoptimized Bubble Sort @@ -113,7 +103,7 @@ If you don't want to use Apache Ant or the Java command line, a runnable jar tha - Introspective CircleSort - Orson Peters' "Pattern-Defeating Quicksort" (PDQSort) - Branchless PDQSort - - Morween's implementation of "Poplar Heapsort" + - Morwenn's implementation of "Poplar Heapsort" - Recursive Binary Quicksort - Iterative Binary Quicksort - Iterative Bitonic Sort @@ -173,11 +163,3 @@ If you don't want to use Apache Ant or the Java command line, a runnable jar tha - getters/setters - method parameters - Small organizational changes - -**If you are experiencing performance issues in Windows 10, look here: https://superuser.com/questions/988379/how-do-i-run-java-apps-upscaled-on-a-high-dpi-display** - -An executable .jar file is available in the dist folder. Have fun! - -Videos this program is featured in: - -https://www.youtube.com/playlist?list=PL5w_-zMAJC8tSgmfaltMMj7Kn390eRzMq diff --git a/Shuffles copy.java b/Shuffles copy.java deleted file mode 100644 index bae50fa5..00000000 --- a/Shuffles copy.java +++ /dev/null @@ -1,680 +0,0 @@ -package utils; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Queue; - -import main.ArrayVisualizer; -import sorts.exchange.CircleSort; -import sorts.hybrid.GrailSort; -import sorts.select.BaseNMaxHeapSort; -import sorts.select.PoplarHeapSort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -public enum Shuffles { - RANDOM { - // If you want to learn why the random shuffle was changed, - // I highly encourage you read this. It's quite fascinating: - // http://datagenetics.com/blog/november42014/index.html - - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - this.shuffleRandomly(array, 0, currentLen, 1, ArrayVisualizer, Delays, Highlights, Writes); - - /* - CircleSort circleSort = new CircleSort(ArrayVisualizer); - circleSort.singleRoutine(array, currentLen); - */ - } - }, - SHUFFLED_ODDS { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for(int i = 1; i < currentLen; i += 2){ - int randomIndex = (((int) ((Math.random() * (currentLen - i)) / 2)) * 2) + i; - Writes.swap(array, i, randomIndex, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(2); - } - } - }, - REVERSE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - Writes.changeReversals(1); - for (int left = 0, right = currentLen - 1; left < right; left++, right--) { - // swap the values at the left and right indices - Writes.swap(array, left, right, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - - /* - for(int i = 0; i < Math.max(currentLen / 20, 1); i++){ - Writes.swap(array, (int)(Math.random()*currentLen), (int)(Math.random()*currentLen), 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(10); - } - */ - } - }, - RECURSIVE_REVERSE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for (int gap = currentLen; gap > 0; gap /= 2) { - for (int i = 0; i + gap <= currentLen; i += gap) { - Writes.reversal(array, i, i + gap - 1, ArrayVisualizer.shuffleEnabled() ? 0.5 : 0, true, false); - } - } - } - }, - SIMILAR { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for(int i = 0; i < currentLen - 8; i++) { - array[i] = currentLen / 2; - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - for(int i = currentLen - 8; i < currentLen; i++) { - array[i] = (int) (Math.random() < 0.5 ? currentLen * 0.75 : currentLen * 0.25); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - this.shuffleRandomly(array, 0, currentLen, 1, ArrayVisualizer, Delays, Highlights, Writes); - } - }, - ALMOST { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for(int i = 0; i < Math.max(currentLen / 20, 1); i++){ - Writes.swap(array, (int)(Math.random()*currentLen), (int)(Math.random()*currentLen), 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(2); - } - - /* - int step = (int) Math.sqrt(currentLen); - - //TODO: *Strongly* consider randomSwap method - for(int i = 0; i < currentLen; i += step){ - int randomIndex = (int) (Math.random() * step); - randomIndex = Math.max(randomIndex, 1); - randomIndex = Math.min(randomIndex, currentLen - i - 1); - Writes.swap(array, i, i + randomIndex, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(2); - } - */ - } - }, - DECREASING_RANDOM { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for (int i = 0; i < currentLen; i++) { - Writes.write(array, i, (int)(Math.random() * (currentLen - i) + i), 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - LOGARITHM_SLOPES { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - Writes.write(array, 0, 0, 0, true, false); - for(int i = 1; i < currentLen; i++) { - int log = (int) (Math.log(i) / Math.log(2)); - int power = (int) Math.pow(2, log); - int value = 2 * (i - power) + 1; - Writes.write(array, i, value, 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - TRIANGULAR { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int n; - for(n = 0; (1 << n) < currentLen; n++); - - int[] temp = new int[currentLen]; - int[] c = circleGen(n, 0, Writes); - - for(int i = 1; i <= n; i++) - c = concat(c, circleGen(n, i, Writes), Writes); - - for(int i = 0; i < currentLen; i++) - if(c[i] < currentLen) Writes.write(temp, c[i], array[i], 0.1, true, true); - - for(int i = 0; i < currentLen; i++) { - Writes.write(array, i, temp[i], 1, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - - public int[] addToAll(int[] a, int n, Writes Writes) { - for(int i = 0; i < a.length; i++) - Writes.write(a, i, a[i] + n, 0.1, true, true); - - return a; - } - - public int[] concat(int[] a, int[] b, Writes Writes) { - int[] c = new int[a.length + b.length]; - int j = 0; - for(int i = 0; i < a.length; i++, j++) - Writes.write(c, j, a[i], 0.1, true, true); - for(int i = 0; i < b.length; i++, j++) - Writes.write(c, j, b[i], 0.1, true, true); - - return c; - } - - public int[] circleGen(int n, int k, Writes Writes) { - if(n == 0) { - int c[] = {0, 1}; - return c; - } - else if(k == 0) { - int c[] = {0}; - return c; - } - else if(k == n) { - int c[] = {(1 << n) - 1}; - return c; - } - else - return concat(circleGen(n-1, k, Writes), addToAll(circleGen(n-1, k-1, Writes), 1 << (n-1), Writes), Writes); - } - }, - HEAD { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int j = 0, k = currentLen; - int[] temp = new int[currentLen]; - - for(int i = 0; j < k; i++) { - Highlights.markArray(2, i); - if(Math.random() < 1/8d) - Writes.write(temp, --k, array[i], 0, true, true); - else - Writes.write(temp, j++, array[i], 0, true, true); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.5); - } - Highlights.clearMark(2); - - for(int i = 0; i < currentLen; i++) { - Writes.write(array, i, temp[i], 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.5); - } - - for(int i = k; i < currentLen; i++){ - int randomIndex = (int) (Math.random() * (currentLen - i)) + i; - Writes.swap(array, i, randomIndex, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(4); - } - - GrailSort grailSort = new GrailSort(ArrayVisualizer); - grailSort.rotateLength(array, k, currentLen - k); - } - }, - TAIL { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int j = 0, k = currentLen; - int[] temp = new int[currentLen]; - - for(int i = 0; j < k; i++) { - Highlights.markArray(2, i); - if(Math.random() < 1/8d) - Writes.write(temp, --k, array[i], 0, true, true); - else - Writes.write(temp, j++, array[i], 0, true, true); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.5); - } - Highlights.clearMark(2); - - for(int i = 0; i < currentLen; i++) - Writes.write(array, i, temp[i], ArrayVisualizer.shuffleEnabled() ? 0.5 : 0, true, false); - - for(int i = k; i < currentLen; i++){ - int randomIndex = (int) (Math.random() * (currentLen - i)) + i; - Writes.swap(array, i, randomIndex, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(4); - } - - } - }, - HALF_REVERSE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - Writes.changeReversals(1); - int left = 0; - int right = currentLen - 1; - for (int i = 0; i < (currentLen / 4); i++) { - // swap the values at the left and right indices - Writes.swap(array, left++, right--, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - PERLIN { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - float step = 1f / Math.min(currentLen, 3072); - float randomStart = (float) (Math.random() * currentLen); - int octave = (int) (Math.log(currentLen) / Math.log(2)); - - for(int i = 0; i < currentLen; i++) { - int value = (int) (PerlinNoise.returnFracBrownNoise(randomStart, octave) * currentLen); - Writes.write(array, i, value, 0, true, false); - randomStart += step; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.333); - } - - int minimum = Integer.MAX_VALUE; - for(int i = 0; i < currentLen; i++) { - if(array[i] < minimum) { - minimum = array[i]; - } - } - minimum = Math.abs(minimum); - for(int i = 0; i < currentLen; i++) { - Writes.write(array, i, array[i] + minimum, 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.333); - } - - double maximum = Double.MIN_VALUE; - for(int i = 0; i < currentLen; i++) { - if(array[i] > maximum) { - maximum = array[i]; - } - } - double scale = currentLen / maximum; - if(scale < 1.0 || scale > 1.8) { - for(int i = 0; i < currentLen; i++) { - Writes.write(array, i, (int) (array[i] * scale), 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.333); - } - } - - for(int i = 0; i < currentLen; i++) { - Writes.write(array, i, (int)Math.min(array[i], currentLen - 1), 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - PERLIN_CURVE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for(int i = 0; i < currentLen; i++) { - int value = 0 - (int) (PerlinNoise.returnNoise((float) i / currentLen) * currentLen); - Writes.write(array, i, value, 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - HEAPIFIED { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - BaseNMaxHeapSort heapSort = new BaseNMaxHeapSort(ArrayVisualizer); - heapSort.makeHeap(array, 0, currentLen, 2, ArrayVisualizer.shuffleEnabled() ? 1 : 0); - } - }, - INTERLACE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for(int i = 0; i < currentLen / 2; i += 2) { - Writes.swap(array, i, currentLen - i - 1, 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - POPLAR_HEAP { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - Writes.changeReversals(1); - for (int left = 0, right = currentLen - 1; left < right; left++, right--) { - // swap the values at the left and right indices - Writes.swap(array, left, right, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - PoplarHeapSort poplarHeapSort = new PoplarHeapSort(ArrayVisualizer); - poplarHeapSort.poplarHeapify(array, 0, currentLen); - } - }, - BINARY_TREE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - // credit to sam walko/anon - class Subarray { - private int start; - private int end; - Subarray(int start, int end) { - this.start = start; - this.end = end; - } - } - - Queue q = new LinkedList(); - q.add(new Subarray(0, currentLen)); - int i = 0; - - while(!q.isEmpty()) { - Subarray sub = q.poll(); - if(sub.start != sub.end) { - int mid = (sub.start + sub.end)/2; - Writes.write(array, i, mid, 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - i++; - q.add(new Subarray(sub.start, mid)); - q.add(new Subarray(mid+1, sub.end)); - } - } - } - }, - REVERSE_SAWTOOTH { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int offset = 0; - for(int i = 0; i < 4; i++) { - int value = currentLen; - for(int j = offset; j < offset + (currentLen / 4); j++) { - Writes.write(array, j, value, 0, true, false); - value -= 4; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - offset += (currentLen / 4); - } - } - }, - REVERSE_FINAL { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int value = currentLen; - for(int i = 0; i < currentLen / 2; i++) { - Writes.write(array, i, value, 0, true, false); - value -= 2; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - value = currentLen; - for(int i = currentLen / 2; i < currentLen; i++) { - Writes.write(array, i, value, 0, true, false); - value -= 2; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - TWO_LAYER { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int[] referenceArray = new int[currentLen]; - for(int i = 0; i < currentLen; i++) { - referenceArray[i] = array[i]; - } - - int leftIndex = 1; - int rightIndex = currentLen - 1; - - for(int i = 1; i < currentLen; i++) { - if(i % 2 == 0) { - Writes.write(array, i, referenceArray[leftIndex++], 0, true, false); - } - else { - Writes.write(array, i, referenceArray[rightIndex--], 0, true, false); - } - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - FINAL_PAIRWISE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - Reads Reads = ArrayVisualizer.getReads(); - - //shuffle - for(int i = 0; i < currentLen; i++){ - int randomIndex = (int) (Math.random() * (currentLen - i)) + i; - Writes.swap(array, i, randomIndex, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.5); - } - - //create pairs - for(int i = 1; i < currentLen; i+=2) { - if(Reads.compareIndices(array, i - 1, i, ArrayVisualizer.shuffleEnabled() ? 0.5 : 0, true) > 0) { - Writes.swap(array, i-1, i, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.5); - } - } - - Highlights.clearMark(2); - - int[] temp = new int[currentLen]; - - //sort the smaller and larger of the pairs separately with pigeonhole sort - for(int m = 0; m < 2; m++) { - for(int k = m; k < currentLen; k+=2) - Writes.write(temp, array[k], temp[array[k]] + 1, ArrayVisualizer.shuffleEnabled() ? 0.5 : 0, true, true); - - int i = 0, j = m; - while(true) { - while(i < currentLen && temp[i] == 0) i++; - if(i >= currentLen) break; - - Writes.write(array, j, i, 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(0.5); - - j+=2; - Writes.write(temp, i, temp[i] - 1, 0, false, true); - } - } - } - }, - BELL { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - double step = 8d / currentLen; - double position = -4; - int constant = 1264; - double factor = currentLen / 512d; - - for(int i = 0; i < currentLen; i++) { - double square = Math.pow(position, 2); - double negativeSquare = 0 - square; - double halfNegSquare = negativeSquare / 2d; - double numerator = constant * factor * Math.pow(Math.E, halfNegSquare); - - double doublePi = 2 * Math.PI; - double denominator = Math.sqrt(doublePi); - - Writes.write(array, i, (int) (numerator / denominator), 0, true, false); - position += step; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - SAWTOOTH { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int offset = 0; - for(int i = 0; i < 4; i++) { - int value = 0; - for(int j = offset; j < offset + (currentLen / 4); j++) { - Writes.write(array, j, value, 0, true, false); - value += 4; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - offset += (currentLen / 4); - } - } - }, - REVERSE_MERGE { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for(int i = 0; i < currentLen / 2; i++) { - Writes.swap(array, i, i + (currentLen / 2), 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(2); - } - } - }, - FINAL_BITONIC { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int value = currentLen; - for(int i = 0; i < currentLen / 2; i++) { - Writes.write(array, i, value, 0, true, false); - value -= 2; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - for(int i = currentLen / 2; i < currentLen; i++) { - Writes.write(array, i, value, 0, true, false); - value += 2; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - PIPEORGAN { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - int value = 0; - for(int i = 0; i < currentLen / 2; i++) { - Writes.write(array, i, (int)Math.min(value, currentLen - 1), 0, true, false); - value += 2; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - for(int i = currentLen / 2; i < currentLen; i++) { - Writes.write(array, i, (int)Math.min(value, currentLen - 1), 0, true, false); - value -= 2; - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }, - FINAL_RADIX { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - //Arrays.sort(array); - - int value = 0; - for(int i = 0; i < currentLen; i += 2) { - Writes.write(array, i, value++, 0, false, false); - if(ArrayVisualizer.shuffleEnabled()) { - Highlights.markArray(1, i); - Delays.sleep(1); - } - } - for(int i = 1; i < currentLen; i += 2) { - Writes.write(array, i, value++, 0, false, false); - if(ArrayVisualizer.shuffleEnabled()) { - Highlights.markArray(1, i); - Delays.sleep(1); - } - } - } - }, - ALREADY { - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - for(int i = 0; i < currentLen; i++) { - Highlights.markArray(1, i); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); - } - } - }; - - protected void shuffleRandomly(int[] array, int start, int len, double sleep, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - for(int i = 0; i < len; i++){ - int randomIndex = (int) (Math.random() * (len - i)) + i; - Writes.swap(array, start + i, start + randomIndex, 0, true, false); - Writes.write(ArrayVisualizer.getShadowArray(), array[start + i], start + i, 0, false, true); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(sleep); - } - } - - public abstract void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes); -} \ No newline at end of file diff --git a/SortPrompt_old.java b/SortPrompt_old.java deleted file mode 100644 index 53052f76..00000000 --- a/SortPrompt_old.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package prompts; - -import java.io.File; - -import javax.swing.JFrame; - -import dialogs.ImportSortDialog; -import frames.AppFrame; -import frames.UtilFrame; -import main.ArrayVisualizer; -import main.SortAnalyzer; -import main.SortAnalyzer.SortPair; -import panes.JErrorPane; -import threads.RunAllSorts; -import threads.RunComparisonSort; -import threads.RunDistributionSort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -/** - * - * @author S630690 - */ - -final public class SortPrompt extends javax.swing.JFrame implements AppFrame { - - private static final long serialVersionUID = 1L; - - private int[] array; - - private ArrayVisualizer ArrayVisualizer; - private JFrame Frame; - private UtilFrame UtilFrame; - - @SuppressWarnings("unchecked") - public SortPrompt(int[] array, ArrayVisualizer arrayVisualizer, JFrame frame, UtilFrame utilFrame) { - this.array = array; - this.ArrayVisualizer = arrayVisualizer; - this.Frame = frame; - this.UtilFrame = utilFrame; - - setAlwaysOnTop(true); - setUndecorated(true); - initComponents(); - jList2.setListData(SortPair.getListNames(ArrayVisualizer.getComparisonSorts())); - jList1.setListData(SortPair.getListNames(ArrayVisualizer.getDistributionSorts())); - reposition(); - setVisible(true); - } - - @Override - public void reposition() { - setLocation(Frame.getX()+(Frame.getWidth()-getWidth())/2,Frame.getY()+(Frame.getHeight()-getHeight())/2); - } - - - @SuppressWarnings({ "unchecked", "rawtypes" }) - // //GEN-BEGIN:initComponents - private void initComponents() { - - this.jLabel1 = new javax.swing.JLabel(); - this.jLabel2 = new javax.swing.JLabel(); - this.jScrollPane1 = new javax.swing.JScrollPane(); - this.jList2 = new javax.swing.JList(); - this.jScrollPane2 = new javax.swing.JScrollPane(); - this.jList1 = new javax.swing.JList(); - this.jButton1 = new javax.swing.JButton(); - this.jButton2 = new javax.swing.JButton(); - - setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - - jLabel1.setText("Comparative"); - - jLabel2.setText("Distributive"); - - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - - jList2.setModel(new javax.swing.AbstractListModel() { - - private static final long serialVersionUID = 1L; - - String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; - @Override - public int getSize() { return strings.length; } - @Override - public Object getElementAt(int i) { return strings[i]; } - }); - - jList2.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - jList2ValueChanged(evt); - } - }); - - jScrollPane1.setViewportView(this.jList2); - - jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - - jList1.setModel(new javax.swing.AbstractListModel() { - - private static final long serialVersionUID = 1L; - - String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; - @Override - public int getSize() { return strings.length; } - @Override - public Object getElementAt(int i) { return strings[i]; } - }); - - jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - jList1ValueChanged(evt); - } - }); - - jScrollPane2.setViewportView(this.jList1); - - jButton1.setText("Run All (approx. 30-90 minutes)"); - jButton1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(); - } - }); - - jButton2.setText("Import Sort"); - jButton2.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton2ActionPerformed(); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(40, 40, 40) - .addComponent(this.jLabel1) - .addGap(76, 76, 76) - .addComponent(this.jLabel2) - .addGap(35, 35, 35)) - .addGroup(layout.createSequentialGroup() - .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() - .addComponent(this.jButton1)) - .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() - .addComponent(this.jButton2)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(this.jLabel1) - .addComponent(this.jLabel2)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(this.jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) - .addComponent(this.jScrollPane1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton1) - .addGap(5, 5, 5) - .addComponent(this.jButton2) - .addGap(0, 0, 0)) - ); - - pack(); - }// //GEN-END:initComponents - - private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed - new Thread(){ - @Override - public void run(){ - RunAllSorts RunAllSorts = new RunAllSorts(ArrayVisualizer); - RunAllSorts.reportAllSorts(array); - } - }.start(); - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jButton1ActionPerformed - - private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed - new Thread(){ - @Override - public void run(){ - File f = new ImportSortDialog().getFile(); - if (f == null) { - return; - } - ArrayVisualizer.getSortAnalyzer().importSort(f); - } - }.start(); - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jButton1ActionPerformed - - private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_jList1ValueChanged - // TODO add your handling code here: - final int selection = evt.getFirstIndex(); - new Thread(){ - @Override - public void run(){ - RunDistributionSort sortThread = new RunDistributionSort(ArrayVisualizer); - sortThread.ReportDistributionSort(array, selection); - } - }.start(); - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jList1ValueChanged - - private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_jList2ValueChanged - // TODO add your handling code here: - final int selection = evt.getFirstIndex(); - new Thread(){ - @Override - public void run() { - RunComparisonSort sortThread = new RunComparisonSort(ArrayVisualizer); - sortThread.ReportComparativeSort(array, selection); - } - }.start(); - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jList2ValueChanged - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton jButton1; - private javax.swing.JButton jButton2; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - @SuppressWarnings("rawtypes") - private javax.swing.JList jList1; - @SuppressWarnings("rawtypes") - private javax.swing.JList jList2; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JScrollPane jScrollPane2; - // End of variables declaration//GEN-END:variables -} \ No newline at end of file diff --git a/add_trailing_newlines.py b/add_trailing_newlines.py new file mode 100644 index 00000000..23f78b1e --- /dev/null +++ b/add_trailing_newlines.py @@ -0,0 +1,53 @@ +import os + +# linesep = os.linesep.encode('ascii') +linesep = b'\n' + + +def dir_parts(dir: str) -> tuple[str]: + return tuple(os.path.normpath(dir).split(os.sep)) + + +def is_in_dir(dir: str, in_: tuple[str]) -> bool: + return tuple(dir.split(os.sep, len(in_)))[:len(in_)] == in_ + + +def is_in_dirs(dir: str, in_: tuple[tuple[str]]) -> bool: + return any(is_in_dir(dir, i) for i in in_) + + +def add_trailing_newlines(path: str) -> bool: + with open(path, 'r+b') as fp: + fp.seek(-len(linesep), 2) + if fp.read(len(linesep)) != linesep: + fp.write(linesep) + return True + return False + + +skip_parts = ( + '.git', + 'bin', + 'dist', + 'cache', + '__pycache__', + 'lib', + 'sorting_networks', + 'src/main/resources', + 'wrapper' +) +skip_parts = tuple(dir_parts(d) for d in skip_parts) + +for (dir, dirs, files) in os.walk('.'): + if dir == '.': + dir = '' + else: + dir = os.path.normpath(dir) + if is_in_dirs(dir, skip_parts): + continue + for file in files: + file = os.path.join(dir, file) + if add_trailing_newlines(file): + print('Wrote ', file) + else: + print('Skipped', file) diff --git a/build.xml b/build.xml deleted file mode 100644 index 8b89a70a..00000000 --- a/build.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 00000000..077fed54 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dist/arrayVisualizer.jar b/dist/arrayVisualizer.jar deleted file mode 100644 index 0fb63324..00000000 Binary files a/dist/arrayVisualizer.jar and /dev/null differ diff --git a/dist/build.xml b/dist/build.xml deleted file mode 100644 index e0b5a38c..00000000 --- a/dist/build.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/lib/classgraph-4.8.47-javadoc.jar b/lib/classgraph-4.8.47-javadoc.jar deleted file mode 100644 index 62aed633..00000000 Binary files a/lib/classgraph-4.8.47-javadoc.jar and /dev/null differ diff --git a/lib/classgraph-4.8.47-sources.jar b/lib/classgraph-4.8.47-sources.jar deleted file mode 100644 index 0542dbc8..00000000 Binary files a/lib/classgraph-4.8.47-sources.jar and /dev/null differ diff --git a/lib/classgraph-4.8.47.jar b/lib/classgraph-4.8.47.jar deleted file mode 100644 index 7a1a1f9a..00000000 Binary files a/lib/classgraph-4.8.47.jar and /dev/null differ diff --git a/monthly-scripts/Apr2021sorts.txt b/monthly-scripts/Apr2021sorts.txt deleted file mode 100644 index 2404b65f..00000000 --- a/monthly-scripts/Apr2021sorts.txt +++ /dev/null @@ -1,40 +0,0 @@ -SetCategory "New Sorts in April 2021" - -BozoSort 0 7 1e-9 -MedianQuickBogoSort 0 12 1e-9 -MergeBogoSort 0 9 1e-9 -OptimizedGuessSort 0 5 1e-9 -QuickBogoSort 0 9 1e-9 - -RandomGuessSort 0 5 1e-9 -SelectionBogoSort 0 64 1e-9 -SmartBogoBogoSort 0 7 1e-9 -SmartGuessSort 0 8 1e-9 -ApollyonSort 0 1024 1 - -ChinottoSort 0 512 1.25 -CocktailGrateSort 0 128 1.5 -FireSort 0 256 0.25 -GnomeWeaveHighSort 0 126 0.025 -GnomeWeaveLowSort 0 126 0.025 - -GrateSort 0 64 1 -IterativeQuickSort 0 2048 1 -PseudoHeapSort 0 1024 1.5 -QuadStoogeSort 0 64 0.005 -ReflectionSort 0 128 0.25 - -ReverseGrateSort 0 128 1 -SlopeSort 0 128 0.025 -StupidFireSort 0 128 0.25 -TriSearchGnomeSort 0 128 1 -WiggleSort 0 512 1.25 - -AdaptiveGrailSort 0 2048 1 -BinaryPDMergeSort 0 2048 1 -BubbleMergeSort 0 2048 1 -ThreadedPDMergeSort 0 2048 1 -AdaptiveBinaryInsertionSort 0 128 0.025 - -GambitInsertionSort 0 128 0.025 -ReverseInsertionSort 0 128 0.005 diff --git a/monthly-scripts/Feb2021sorts.txt b/monthly-scripts/Feb2021sorts.txt deleted file mode 100644 index b40a7b4d..00000000 --- a/monthly-scripts/Feb2021sorts.txt +++ /dev/null @@ -1,27 +0,0 @@ -SetCategory "New Sorts in February 2021" - -MergeExchangeSort 0 1024 1 -GuessSort 0 6 5 -LMSDRadixSort 4 2048 1.25 -FunSort 0 256 2 -NapoleonSort 0 6 0.005 - -SmarterBubble 0 512 1.5 -SmarterCocktail 0 512 1.25 -StableStoogeSort 0 64 0.005 -StudioOptiStoogeSort 0 512 1 -ooPQuickSort 0 2048 1 - -FlanSort 0 2048 1 -OptimizedPDMergeSort 0 2048 1 -AATreeSort 0 2048 1 -AVLTreeSort 0 2048 1 -FibonacciInsertionSort 0 128 0.025 - -HanoiSort 0 8 0.025 -RoomSort 0 512 0.05 -SplaySort 0 2048 1 -StableHanoiSort 0 8 0.025 -OutOfPlaceWeaveMergeSort 0 2048 1 - -StableSelectionSort 0 128 0.5 diff --git a/monthly-scripts/Jan2021sorts.txt b/monthly-scripts/Jan2021sorts.txt deleted file mode 100644 index dcb5d955..00000000 --- a/monthly-scripts/Jan2021sorts.txt +++ /dev/null @@ -1,21 +0,0 @@ -SetCategory "New Sorts in January 2021" - -CreaseSort 0 1024 1 -ForcedStableQuickSort 0 2048 1 -TableSort 0 1024 0.75 -ImprovedBlockSelectionSort 0 2048 1 -LazierSort 0 1024 0.4 - -LaziestSort 0 1024 1 -MedianOfSixteenAdaptiveQuickSort 0 1024 0.25 -MergeInsertionSort 0 2048 1.75 -OptimizedWeaveMergeSort 0 1024 0.4 -QuickSPSort 0 512 0.4 - -DoubleInsertionSort 0 128 0.002 -UnstableInsertionSort 0 128 0.2 -ModuloMergeSort 0 2048 3 -Split16Merge 0 512 0.75 -StrandSort 0 2048 1 - -TwinSort 0 2048 1.5 diff --git a/monthly-scripts/Mar2021sorts.txt b/monthly-scripts/Mar2021sorts.txt deleted file mode 100644 index e7c7c250..00000000 --- a/monthly-scripts/Mar2021sorts.txt +++ /dev/null @@ -1,61 +0,0 @@ -SetCategory "New Sorts in March 2021" - -BitonicSortParallel 0 1024 1 -BoseNelsonSortParallel 0 1024 1 -DiamondSortIterative 0 1024 1 -DiamondSortRecursive 0 1024 1 -OddEvenMergeSortParallel 0 1024 1 - -OptimizedOddEvenMergeSort 0 1024 1 -PairwiseMergeSortIterative 0 1024 1 -PairwiseMergeSortRecursive 0 1024 1 -WeaveSortParallel 0 1024 1 -OptimizedIndexSort 0 2048 1 - -QuickBinaryRadixSort 0 2048 1 -StacklessAmericanFlagSort 128 2048 0.75 -StacklessBinaryQuickSort 0 2048 1 -ClassicThreeSmoothCombSort 0 1024 1.25 -IndexQuickSort 0 1024 0.75 - -LRQuickSortParallel 0 2048 1 -ReverseBubbleSort 0 512 1.5 -ReverseGnomeSort 0 128 0.025 -StableQuickSortParallel 0 2048 1 -StacklessQuickSort 0 2048 1 - -ThreeSmoothCombSortParallel 0 1024 1.25 -BubblescanQuickSort 0 2048 1 -BufferPartitionMergeSort 0 2048 1 -ParallelBlockMergeSort 0 2048 1 -ParallelGrailSort 0 2048 1 - -RemiSort 0 2048 1 -StacklessDualPivotQuickSort 0 2048 0.75 -ClassicLibrarySort 0 2048 1 -ClassicTreeSort 0 2048 1 -CocktailShellSort 0 256 0.1 - -ShellSortParallel 0 256 0.1 -ShuffledTreeSort 0 2048 1 -TreeSort 0 2048 1 -BufferedStoogeSort 0 256 0.2 -IndexMergeSort 0 2048 1 - -IterativeTopDownMergeSort 0 2048 1.5 -MergeSortParallel 0 2048 1.5 -NewShuffleMergeSort 0 1024 1 -OptimizedPancakeSort 0 2048 1 -RotateMergeSortParallel 0 512 0.2 - -WeavedMergeSort 0 2048 1.5 -BurntPancakeSort 0 128 0.015 -CubeRootQuickSort 0 2048 1 -BingoSort 0 128 0.1 -ClassicTournamentSort 0 2048 1.5 - -ReverseSandpaperSort 0 128 0.05 -ReverseSelectionSort 0 128 0.01 -SandpaperSort 0 128 0.05 -StableCycleSort 0 128 0.01 -TriangularHeapSort 0 2048 1.5 diff --git a/monthly-scripts/May2021sorts.txt b/monthly-scripts/May2021sorts.txt deleted file mode 100644 index 7a97dfd2..00000000 --- a/monthly-scripts/May2021sorts.txt +++ /dev/null @@ -1,55 +0,0 @@ -SetCategory "New Sorts in May 2021" - -MatrixSortParallel 0 256 0.667 -RotateLSDRadixSort 4 2048 1.25 -RotateMSDRadixSort 4 2048 1.25 -SimplisticGravitySort 0 2048 1 -AwkwardSort 0 512 0.5 - -CompleteGraphSort 0 1024 0.25 -DandelionSort 0 512 2 -FloatSort 0 256 1 -HeadPullSort 0 20 3 -LinkedIterativeQuickSort 0 2048 1 - -MerryGoRoundSort 0 512 6 -OddEvenWeaveHighSort 0 300 0.125 -OddEvenWeaveLowSort 0 300 0.125 -SafeBogoSort 0 1024 1 -ShoveSort 0 64 0.5 - -SplitCenterSort 0 2048 1 -SwaplessBubbleSort 0 512 1 -TernarySlowSort 0 64 2 -XSort 0 256 0.125 -CircularGrailSort 0 2048 1 - -IntroPseudoHeapSort 0 1024 1.5 -OptimizedLazyStableSort 0 256 0.2 -PDLaziestSort 0 1024 1 -SimpleHybridQuickSort 0 2048 0.5 -StacklessTimSort 0 2048 1 - -SynchronousSqrtSort 0 2048 1 -AdaptiveInsertionSort 0 128 0.3333 -BinaryDoubleInsertionSort 0 128 0.025 -BlockInsertionSort 0 128 0.1 -CiuraCocktailShellSort 0 256 0.07 - -PatternDefeatingInsertionSort 0 128 0.3333 -PancakeInsertionSort 0 128 0.025 -TernaryLLQuickSort 0 2048 1 -TernaryLRQuickSort 0 2048 1 -AnarchySort 0 256 0.25 - -BinomialHeapSort 0 2048 1 -BinomialSmoothSort 0 2048 1 -BottomUpHeapSort 0 2048 1 -ForcedStableHeapSort 0 2048 1 -HeavyHeapSort 0 2048 1 - -MinMaxHeapSort 0 2048 1 -OutOfPlaceHeapSort 0 2048 1 -EctaSort 0 2048 1 -StrandSort 0 2048 1 -AsynchronousSort 0 1024 1.5 diff --git a/mvnw b/mvnw new file mode 100755 index 00000000..41c0f0c2 --- /dev/null +++ b/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 00000000..86115719 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..f790fcbb --- /dev/null +++ b/pom.xml @@ -0,0 +1,212 @@ + + + + 4.0.0 + + io.github.arrayv + ArrayV + 5.2-SNAPSHOT + + ArrayV + Sorting algorithm visualizer written in Java + https://github.com/Gaming32/ArrayV + + + UTF-8 + 1.8 + 1.8 + + + + + io.github.classgraph + classgraph + 4.8.171 + + + org.apache.groovy + groovy + 4.0.21 + + + + + + MIT License + https://opensource.org/licenses/MIT + + + + + + + src/main/resources + + buildInfo.properties + + false + + + src/main/resources + + buildInfo.properties + + true + + + + + io.github.git-commit-id + git-commit-id-maven-plugin + 4.9.9 + + + + revision + + + + + flat + + true + + false + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + io.github.arrayv.main.ArrayVisualizer + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.3.2 + + + io/github/arrayv/groovyapi/**/*.java + io/github/arrayv/main/**/*.java + io/github/arrayv/sortdata/**/*.java + io/github/arrayv/sorts/templates/Sort.java + io/github/arrayv/utils/**/*.java + + + https://javadoc.io/doc/io.github.classgraph/classgraph/4.8.139 + https://docs.groovy-lang.org/4.0.0/html/api + + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.2 + + + package + + shade + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.1.2 + + checkstyle.xml + true + true + + + + validate + validate + + check + + + warning + false + + + + + + com.puppycrawl.tools + checkstyle + 9.3 + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.13.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/run b/run new file mode 100755 index 00000000..3e6dbb47 --- /dev/null +++ b/run @@ -0,0 +1,9 @@ +./mvnw dependency:build-classpath -Dmdep.outputFile=target/classpath -Dmdep.regenerateFile=true -q +echo -n -cp target/classes:> target/cmdargs +cat target/classpath >> target/cmdargs +if [ "$1" != "" ] +then + java @target/cmdargs io.github.arrayv.main.ArrayVisualizer "%1" +else + java @target/cmdargs io.github.arrayv.main.ArrayVisualizer +fi diff --git a/run.bat b/run.bat index d712e88b..ddd5868b 100644 --- a/run.bat +++ b/run.bat @@ -1 +1,6 @@ -java -Dsun.java2d.d3d=false -cp bin;lib/classgraph-4.8.47.jar;cache main.ArrayVisualizer %1 +@echo off +call mvnw dependency:build-classpath -Dmdep.outputFile=target\classpath -Dmdep.regenerateFile=true -q + target\cmdargs +type target\classpath >> target\cmdargs +title ArrayV +java @target\cmdargs io.github.arrayv.main.ArrayVisualizer %1 diff --git a/run.sh b/run.sh deleted file mode 100644 index 04a70cb2..00000000 --- a/run.sh +++ /dev/null @@ -1 +0,0 @@ -java -Dsun.java2d.d3d=false -cp bin:lib/classgraph-4.8.47.jar:cache main.ArrayVisualizer $1 diff --git a/src/SortPrompt.form b/src/SortPrompt.form deleted file mode 100644 index 08d82518..00000000 --- a/src/SortPrompt.form +++ /dev/null @@ -1,138 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/UtilFrame.form b/src/UtilFrame.form deleted file mode 100644 index 13edae8e..00000000 --- a/src/UtilFrame.form +++ /dev/null @@ -1,123 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/ViewPrompt.form b/src/ViewPrompt.form deleted file mode 100644 index 9860af11..00000000 --- a/src/ViewPrompt.form +++ /dev/null @@ -1,169 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/dialogs/ExportShuffleDialog.java b/src/dialogs/ExportShuffleDialog.java deleted file mode 100644 index e70ca657..00000000 --- a/src/dialogs/ExportShuffleDialog.java +++ /dev/null @@ -1,12 +0,0 @@ -package dialogs; - -final public class ExportShuffleDialog extends FileDialog { - public ExportShuffleDialog() { - super(); - - fileDialog.setDialogTitle("Choose where to export the current shuffle graph..."); - - fileDialog.showSaveDialog(null); - this.file = fileDialog.getSelectedFile(); - } -} \ No newline at end of file diff --git a/src/dialogs/FileDialog.java b/src/dialogs/FileDialog.java deleted file mode 100644 index e7b7a94d..00000000 --- a/src/dialogs/FileDialog.java +++ /dev/null @@ -1,46 +0,0 @@ -package dialogs; - -import java.io.File; - -import javax.swing.JFileChooser; -import javax.swing.UIManager; -import javax.swing.filechooser.FileFilter; - -public abstract class FileDialog { - protected static JFileChooser fileDialog; - protected File file; - protected static volatile boolean initialized; - - public FileDialog() { - while (!FileDialog.initialized) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - FileDialog.fileDialog.resetChoosableFileFilters(); - } - - public static void initialize() { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } - catch (Exception e) { - e.printStackTrace(); - } - FileDialog.fileDialog = new JFileChooser(); - FileDialog.fileDialog.setCurrentDirectory(new File(System.getProperty("user.dir"))); - FileDialog.fileDialog.setMultiSelectionEnabled(false); - FileDialog.initialized = true; - } - - protected void removeAllFilesOption() { - FileFilter allFiles = FileDialog.fileDialog.getChoosableFileFilters()[0]; - FileDialog.fileDialog.removeChoosableFileFilter(allFiles); - } - - public File getFile() { - return this.file; - } -} \ No newline at end of file diff --git a/src/dialogs/LoadCustomDistributionDialog.java b/src/dialogs/LoadCustomDistributionDialog.java deleted file mode 100644 index 23c0e1e1..00000000 --- a/src/dialogs/LoadCustomDistributionDialog.java +++ /dev/null @@ -1,12 +0,0 @@ -package dialogs; - -final public class LoadCustomDistributionDialog extends FileDialog { - public LoadCustomDistributionDialog() { - super(); - - fileDialog.setDialogTitle("Choose a distribution file..."); - - fileDialog.showDialog(null, "Select"); - this.file = fileDialog.getSelectedFile(); - } -} \ No newline at end of file diff --git a/src/dialogs/LoadingDialog.java b/src/dialogs/LoadingDialog.java deleted file mode 100644 index ba624d01..00000000 --- a/src/dialogs/LoadingDialog.java +++ /dev/null @@ -1,31 +0,0 @@ -package dialogs; - -import java.awt.Dialog.ModalityType; - -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JOptionPane; - -public class LoadingDialog { - /** - * - */ - @SuppressWarnings("unused") - private static final long serialVersionUID = 1L; - private JOptionPane pane; - private JDialog dialog; - - public LoadingDialog(String resource, JFrame parent) { - this.pane = new JOptionPane("Loading " + resource + "...", JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION, null, new Object[] {}, null); - this.dialog = this.pane.createDialog(parent, "Info"); - this.dialog.setModalityType(ModalityType.MODELESS); - this.dialog.setAlwaysOnTop(this.dialog.isAlwaysOnTopSupported()); - this.dialog.pack(); - this.dialog.setVisible(true); - } - - public void closeDialog() { - this.dialog.setVisible(false); - this.dialog.dispose(); - } -} \ No newline at end of file diff --git a/src/dialogs/RunScriptDialog.java b/src/dialogs/RunScriptDialog.java deleted file mode 100644 index 19dce4bc..00000000 --- a/src/dialogs/RunScriptDialog.java +++ /dev/null @@ -1,12 +0,0 @@ -package dialogs; - -final public class RunScriptDialog extends FileDialog { - public RunScriptDialog() { - super(); - - fileDialog.setDialogTitle("Choose a script file..."); - - fileDialog.showDialog(null, "Select"); - this.file = fileDialog.getSelectedFile(); - } -} \ No newline at end of file diff --git a/src/dialogs/SaveArrayDialog.java b/src/dialogs/SaveArrayDialog.java deleted file mode 100644 index 01430984..00000000 --- a/src/dialogs/SaveArrayDialog.java +++ /dev/null @@ -1,12 +0,0 @@ -package dialogs; - -final public class SaveArrayDialog extends FileDialog { - public SaveArrayDialog() { - super(); - - fileDialog.setDialogTitle("Choose where to save the contents of the main array..."); - - fileDialog.showSaveDialog(null); - this.file = fileDialog.getSelectedFile(); - } -} \ No newline at end of file diff --git a/src/frames/ArrayFrame.java b/src/frames/ArrayFrame.java deleted file mode 100644 index 470d46d3..00000000 --- a/src/frames/ArrayFrame.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package frames; - -import java.awt.Toolkit; -import java.awt.event.MouseListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.util.Hashtable; - -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.SwingConstants; -import javax.swing.UIManager; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import java.awt.event.MouseEvent; - -import main.ArrayManager; -import main.ArrayVisualizer; -import panes.JEnhancedOptionPane; -import panes.JErrorPane; -import utils.Highlights; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -/** - * - * @author S630690 - */ - -final public class ArrayFrame extends javax.swing.JFrame { - final private static long serialVersionUID = 1L; - - private int[] array; - - private ArrayManager ArrayManager; - private ArrayVisualizer ArrayVisualizer; - private AppFrame abstractFrame; - private Highlights Highlights; - private JFrame Frame; - private UtilFrame UtilFrame; - - private boolean lockToPow2; - - public ArrayFrame(int[] array, ArrayVisualizer arrayVisualizer) { - this.array = array; - - this.ArrayVisualizer = arrayVisualizer; - this.ArrayManager = ArrayVisualizer.getArrayManager(); - - this.Highlights = ArrayVisualizer.getHighlights(); - this.Frame = ArrayVisualizer.getMainWindow(); - this.UtilFrame = ArrayVisualizer.getUtilFrame(); - - setUndecorated(true); - initComponents(); - setLocation(Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth(), Frame.getX() + Frame.getWidth()), Frame.getY() + 29); - setAlwaysOnTop(false); - setVisible(true); - } - - public void reposition(){ - toFront(); - setLocation(Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth() - UtilFrame.getWidth(), Frame.getX() + Frame.getWidth()), Frame.getY() + 29); - if(this.abstractFrame != null && abstractFrame.isVisible()) - abstractFrame.reposition(); - } - - public void setLengthSlider(int length) { - boolean mutable = ArrayManager.isLengthMutable(); - ArrayManager.toggleMutableLength(true); - jSlider1.setValue(calculateSliderValue(length)); - ArrayManager.toggleMutableLength(mutable); - } - - public void setUniqueSlider(int length) { - boolean mutable = ArrayManager.isLengthMutable(); - ArrayManager.toggleMutableLength(true); - jSlider2.setValue(calculateSliderValue(length)); - ArrayManager.toggleMutableLength(mutable); - } - - private int getSomethingSize(String title, String message) throws Exception { - String input = JEnhancedOptionPane.showInputDialog(title, message, new Object[] {"Ok", "Cancel"}); - int integer = Integer.parseInt(input); - return Math.abs(integer); - } - - private int calculateLength(int sliderValue) { - int newLength = (int)Math.pow(2, sliderValue / 100000.0); - return newLength; - } - - private int calculateSliderValue(int length) { - int sliderValue = (int)Math.ceil(Math.log(length) / Math.log(2) * 100000); - return sliderValue; - } - - // //GEN-BEGIN:initComponents - private void initComponents() { - try { - String os = System.getProperty("os.name"); - if (!os.equals("Linux")) { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - - KeyListener kListener = new KeyListener() { - @Override - public void keyTyped(KeyEvent e) { } - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) - lockToPow2 = true; - } - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) - lockToPow2 = false; - } - }; - this.addKeyListener(kListener); - - int usePower = ArrayVisualizer.MAX_LENGTH_POWER * 100000; - int useDefault = (int)Math.min(1100000, usePower); - this.jLabel1 = new javax.swing.JLabel(); - this.jLabel2 = new javax.swing.JLabel(); - this.jSlider1 = new javax.swing.JSlider(SwingConstants.VERTICAL, 100000, usePower, useDefault); - this.jSlider2 = new javax.swing.JSlider(SwingConstants.VERTICAL, 100000, usePower, useDefault); - - jLabel1.setText("Array Size"); - jLabel2.setText("Unique Elements"); - - setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); - - Hashtable labels = new Hashtable<>(); - int pow = 1; - int value = ArrayVisualizer.getMinimumLength(); - while(value <= ArrayVisualizer.getMaximumLength()) { - labels.put(pow * 100000, new JLabel(Integer.toString(value))); - pow += 1; - value *= 2; - } - - jSlider1.setMajorTickSpacing(100000); - jSlider1.setLabelTable(labels); - jSlider1.setPaintLabels(true); - jSlider1.setPaintTicks(true); - //jSlider.setSnapToTicks(true); - jSlider1.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent event) { - if(ArrayManager.isLengthMutable()) { - int value = jSlider1.getValue(); - if (lockToPow2) { - value = (int)(Math.round(value / 100000.0) * 100000); - jSlider1.setValue(value); - } - int oldValue1 = calculateSliderValue(ArrayVisualizer.getCurrentLength()); - ArrayVisualizer.setCurrentLength(calculateLength(value)); - // double mult = (double)jSlider2.getValue() / (double)oldValue1; - double divver = (double)oldValue1 / (double)jSlider2.getValue(); - jSlider2.setValue((int)(value / divver)); - //ArrayVisualizer.setEqualItems((int) Math.pow(2, jSlider.getValue())); - ArrayManager.initializeArray(array); - } - else { - int currentLength = ArrayVisualizer.getCurrentLength(); - jSlider1.setValue(calculateSliderValue(currentLength)); - } - //if(ArrayVisualizer.getVisualStyles() == visuals.VisualStyles.CIRCULAR && jSlider1.getValue() == 1) jSlider1.setValue(2); - - Highlights.clearAllMarks(); - } - }); - jSlider1.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() == 2) { - int newSize = 0; - try { - newSize = getSomethingSize("Array Size", "Enter new array size:"); - } - catch(Exception e) { } - if (newSize >= 2) { - jSlider1.setValue(calculateSliderValue(newSize)); - ArrayVisualizer.setCurrentLength(newSize); - ArrayManager.initializeArray(array); - } - } - } - @Override - public void mousePressed(MouseEvent e) { } - @Override - public void mouseReleased(MouseEvent e) { } - @Override - public void mouseEntered(MouseEvent e) { } - @Override - public void mouseExited(MouseEvent e) { } - }); - jSlider1.addKeyListener(kListener); - - jSlider2.setMajorTickSpacing(100000); - jSlider2.setLabelTable(labels); - jSlider2.setPaintLabels(true); - jSlider2.setPaintTicks(true); - //jSlider2.setSnapToTicks(true); - jSlider2.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent event) { - if(ArrayManager.isLengthMutable()) { - if (jSlider2.getValue() > jSlider1.getValue()) { - jSlider2.setValue(jSlider1.getValue()); - } - else { - int value = jSlider2.getValue(); - if (lockToPow2) { - value = (int)(Math.round(value / 100000.0) * 100000); - jSlider2.setValue(value); - } - ArrayVisualizer.setUniqueItems(calculateLength(value)); - //ArrayVisualizer.setEqualItems((int) Math.pow(2, jSlider2.getValue())); - ArrayManager.initializeArray(array); - } - } - else { - int currentItems = ArrayVisualizer.getUniqueItems(); - jSlider2.setValue(calculateSliderValue(currentItems)); - } - - Highlights.clearAllMarks(); - } - }); - jSlider2.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() == 2) { - int newSize = 0; - try { - newSize = getSomethingSize("Unique Elements", "Enter new number of unique elements:"); - } - catch(Exception e) { } - if (newSize >= 2) { - jSlider2.setValue(calculateSliderValue(newSize)); - ArrayVisualizer.setUniqueItems(newSize); - ArrayManager.initializeArray(array); - } - } - } - @Override - public void mousePressed(MouseEvent e) { } - @Override - public void mouseReleased(MouseEvent e) { } - @Override - public void mouseEntered(MouseEvent e) { } - @Override - public void mouseExited(MouseEvent e) { } - }); - jSlider2.addKeyListener(kListener); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) - .addComponent(this.jLabel1) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) - .addComponent(this.jSlider1) - .addGap(0, 10, Short.MAX_VALUE)))) - .addGap(175, 175, 175) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.jLabel2) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.jSlider2) - .addGap(0, 10, Short.MAX_VALUE)))) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) - .addGroup(layout.createSequentialGroup() - .addGap(5, 5, 5) - .addComponent(this.jLabel1) - .addGap(5, 5, 5) - .addComponent(this.jSlider1, UtilFrame.getHeight() - 26, UtilFrame.getHeight() - 26, UtilFrame.getHeight() - 26)) - .addGroup(layout.createSequentialGroup() - .addGap(5, 5, 5) - .addComponent(this.jLabel2) - .addGap(5, 5, 5) - .addComponent(this.jSlider2, UtilFrame.getHeight() - 26, UtilFrame.getHeight() - 26, UtilFrame.getHeight() - 26)) - ); - - pack(); - }// //GEN-END:initComponents - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JSlider jSlider1; - private javax.swing.JSlider jSlider2; - // End of variables declaration//GEN-END:variables -} \ No newline at end of file diff --git a/src/frames/ImageFrame.java b/src/frames/ImageFrame.java deleted file mode 100644 index 565c877f..00000000 --- a/src/frames/ImageFrame.java +++ /dev/null @@ -1,116 +0,0 @@ -package frames; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.border.EmptyBorder; - -import visuals.image.CustomImage; -import javax.swing.SwingConstants; - -public class ImageFrame extends JFrame { - - public static ImageFrame defaultFrame; - - /** - * - */ - private static final long serialVersionUID = 1L; - private volatile JPanel contentPane; - - private volatile JLabel lblNewLabel_2; - - /** - * Create the frame. - */ - public ImageFrame(CustomImage visual) { - ImageFrame.defaultFrame = this; - - setBounds(100, 100, 450, 300); - contentPane = new JPanel(); - contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); - setContentPane(contentPane); - GridBagLayout gbl_contentPane = new GridBagLayout(); - gbl_contentPane.columnWidths = new int[]{0, 0, 0}; - gbl_contentPane.rowHeights = new int[]{0, 32, 0, 0, 0}; - gbl_contentPane.columnWeights = new double[]{1.0, 1.0, Double.MIN_VALUE}; - gbl_contentPane.rowWeights = new double[]{0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE}; - contentPane.setLayout(gbl_contentPane); - - JLabel lblNewLabel = new JLabel("Current image:"); - GridBagConstraints gbc_lblNewLabel = new GridBagConstraints(); - gbc_lblNewLabel.anchor = GridBagConstraints.EAST; - gbc_lblNewLabel.insets = new Insets(0, 0, 5, 5); - gbc_lblNewLabel.gridx = 0; - gbc_lblNewLabel.gridy = 0; - contentPane.add(lblNewLabel, gbc_lblNewLabel); - - JLabel lblNewLabel_1 = new JLabel(visual.getCurrentImageName()); - GridBagConstraints gbc_lblNewLabel_1 = new GridBagConstraints(); - gbc_lblNewLabel_1.anchor = GridBagConstraints.WEST; - gbc_lblNewLabel_1.insets = new Insets(0, 0, 5, 0); - gbc_lblNewLabel_1.gridx = 1; - gbc_lblNewLabel_1.gridy = 0; - contentPane.add(lblNewLabel_1, gbc_lblNewLabel_1); - - this.lblNewLabel_2 = new JLabel(" "); - lblNewLabel_2.setHorizontalAlignment(SwingConstants.CENTER); - GridBagConstraints gbc_lblNewLabel_2 = new GridBagConstraints(); - gbc_lblNewLabel_2.fill = GridBagConstraints.BOTH; - gbc_lblNewLabel_2.insets = new Insets(0, 0, 5, 0); - gbc_lblNewLabel_2.gridwidth = 2; - gbc_lblNewLabel_2.gridx = 0; - gbc_lblNewLabel_2.gridy = 1; - contentPane.add(this.lblNewLabel_2, gbc_lblNewLabel_2); - - JButton btnNewButton = new JButton("Load default artwork"); - btnNewButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - visual.loadDefaultArtwork(ImageFrame.this); - } - }); - GridBagConstraints gbc_btnNewButton = new GridBagConstraints(); - gbc_btnNewButton.fill = GridBagConstraints.VERTICAL; - gbc_btnNewButton.gridheight = 2; - gbc_btnNewButton.anchor = GridBagConstraints.EAST; - gbc_btnNewButton.insets = new Insets(0, 0, 5, 5); - gbc_btnNewButton.gridx = 0; - gbc_btnNewButton.gridy = 2; - contentPane.add(btnNewButton, gbc_btnNewButton); - - JButton btnNewButton_1 = new JButton("Choose image..."); - btnNewButton_1.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - visual.loadCustomImage(ImageFrame.this); - } - }); - GridBagConstraints gbc_btnNewButton_1 = new GridBagConstraints(); - gbc_btnNewButton_1.fill = GridBagConstraints.VERTICAL; - gbc_btnNewButton_1.gridheight = 2; - gbc_btnNewButton_1.insets = new Insets(0, 0, 5, 0); - gbc_btnNewButton_1.anchor = GridBagConstraints.WEST; - gbc_btnNewButton_1.gridx = 1; - gbc_btnNewButton_1.gridy = 2; - contentPane.add(btnNewButton_1, gbc_btnNewButton_1); - } - - public void updatePreview(CustomImage visual) { - BufferedImage img = visual.getImage(); - Image scaledImg = img.getScaledInstance((int) (this.lblNewLabel_2.getWidth() * 0.75), this.lblNewLabel_2.getHeight(), Image.SCALE_SMOOTH); - ImageIcon imageIcon = new ImageIcon(scaledImg); - this.lblNewLabel_2.setIcon(imageIcon); - this.lblNewLabel_2.setText(""); - } -} \ No newline at end of file diff --git a/src/frames/SoundFrame.java b/src/frames/SoundFrame.java deleted file mode 100644 index 09b4a45f..00000000 --- a/src/frames/SoundFrame.java +++ /dev/null @@ -1,143 +0,0 @@ -package frames; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.DropMode; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JSeparator; -import javax.swing.border.EmptyBorder; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -import utils.Sounds; -import javax.swing.ListSelectionModel; -import javax.swing.JScrollPane; - -public class SoundFrame extends JFrame { - - /** - * - */ - private static final long serialVersionUID = 1L; - private JPanel contentPane; - - private int instrumentChoice; - - /** - * Create the frame. - */ - public SoundFrame(Sounds sounds) { - this.instrumentChoice = sounds.getInstrumentChoice(); - - setBounds(100, 100, 450, 300); - contentPane = new JPanel(); - contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); - setContentPane(contentPane); - GridBagLayout gbl_contentPane = new GridBagLayout(); - gbl_contentPane.columnWidths = new int[]{0, 0, 0}; - gbl_contentPane.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0}; - gbl_contentPane.columnWeights = new double[]{1.0, 1.0, Double.MIN_VALUE}; - gbl_contentPane.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, Double.MIN_VALUE}; - contentPane.setLayout(gbl_contentPane); - - JLabel lblNewLabel = new JLabel("Current soundbank:"); - GridBagConstraints gbc_lblNewLabel = new GridBagConstraints(); - gbc_lblNewLabel.insets = new Insets(0, 0, 5, 5); - gbc_lblNewLabel.gridx = 0; - gbc_lblNewLabel.gridy = 0; - contentPane.add(lblNewLabel, gbc_lblNewLabel); - - JButton btnNewButton = new JButton("Default sounds"); - btnNewButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sounds.selectDefaultSoundbank(SoundFrame.this); - } - }); - GridBagConstraints gbc_btnNewButton = new GridBagConstraints(); - gbc_btnNewButton.insets = new Insets(0, 0, 5, 0); - gbc_btnNewButton.gridx = 1; - gbc_btnNewButton.gridy = 0; - contentPane.add(btnNewButton, gbc_btnNewButton); - - JLabel lblNewLabel_1 = new JLabel(sounds.getSelectedSoundbank()); - GridBagConstraints gbc_lblNewLabel_1 = new GridBagConstraints(); - gbc_lblNewLabel_1.insets = new Insets(0, 0, 5, 5); - gbc_lblNewLabel_1.gridx = 0; - gbc_lblNewLabel_1.gridy = 1; - contentPane.add(lblNewLabel_1, gbc_lblNewLabel_1); - - JButton btnNewButton_1 = new JButton("Choose soundbank..."); - btnNewButton_1.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sounds.selectCustomSoundbank(SoundFrame.this); - } - }); - GridBagConstraints gbc_btnNewButton_1 = new GridBagConstraints(); - gbc_btnNewButton_1.insets = new Insets(0, 0, 5, 0); - gbc_btnNewButton_1.gridx = 1; - gbc_btnNewButton_1.gridy = 1; - contentPane.add(btnNewButton_1, gbc_btnNewButton_1); - - JSeparator separator = new JSeparator(); - GridBagConstraints gbc_separator = new GridBagConstraints(); - gbc_separator.insets = new Insets(0, 0, 5, 5); - gbc_separator.gridx = 0; - gbc_separator.gridy = 2; - contentPane.add(separator, gbc_separator); - - JLabel lblNewLabel_2 = new JLabel("Choose a sample / instrument:"); - GridBagConstraints gbc_lblNewLabel_2 = new GridBagConstraints(); - gbc_lblNewLabel_2.anchor = GridBagConstraints.WEST; - gbc_lblNewLabel_2.insets = new Insets(0, 0, 5, 5); - gbc_lblNewLabel_2.gridx = 0; - gbc_lblNewLabel_2.gridy = 3; - contentPane.add(lblNewLabel_2, gbc_lblNewLabel_2); - - JScrollPane scrollPane = new JScrollPane(); - GridBagConstraints gbc_scrollPane = new GridBagConstraints(); - gbc_scrollPane.insets = new Insets(0, 0, 5, 0); - gbc_scrollPane.gridwidth = 2; - gbc_scrollPane.fill = GridBagConstraints.BOTH; - gbc_scrollPane.gridx = 0; - gbc_scrollPane.gridy = 5; - contentPane.add(scrollPane, gbc_scrollPane); - - JList list = new JList(); - scrollPane.setViewportView(list); - list.setListData(sounds.getInstrumentList()); - list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - list.setSelectedIndex(this.instrumentChoice); - list.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - if(SoundFrame.this.instrumentChoice != list.getSelectedIndex()) { - SoundFrame.this.instrumentChoice = list.getSelectedIndex(); - sounds.testInstrument(SoundFrame.this.instrumentChoice); - } - } - }); - - JButton btnNewButton_2 = new JButton("Select sound"); - btnNewButton_2.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sounds.setInstrumentChoice(SoundFrame.this.instrumentChoice); - } - }); - GridBagConstraints gbc_btnNewButton_2 = new GridBagConstraints(); - gbc_btnNewButton_2.anchor = GridBagConstraints.EAST; - gbc_btnNewButton_2.gridx = 1; - gbc_btnNewButton_2.gridy = 6; - contentPane.add(btnNewButton_2, gbc_btnNewButton_2); - } -} \ No newline at end of file diff --git a/src/frames/UtilFrame.java b/src/frames/UtilFrame.java deleted file mode 100644 index f13b1283..00000000 --- a/src/frames/UtilFrame.java +++ /dev/null @@ -1,643 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package frames; - -import java.awt.Toolkit; -import java.util.Hashtable; -import java.util.Random; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.SwingConstants; -import javax.swing.UIManager; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import main.ArrayManager; -import main.ArrayVisualizer; -import panes.JEnhancedOptionPane; -import panes.JErrorPane; -import prompts.ShufflePrompt; -import prompts.SortPrompt; -import prompts.ViewPrompt; -import utils.Delays; -import utils.Highlights; -import utils.SortingNetworkGenerator; -import utils.Sounds; -import utils.Timer; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -/** - * - * @author S630690 - */ -final public class UtilFrame extends javax.swing.JFrame { - final private static long serialVersionUID = 1L; - - private boolean jCheckBox9WarningShown = true; //set to false to enable warning - - private int[] array; - - private ArrayManager ArrayManager; - private ArrayVisualizer ArrayVisualizer; - private Delays Delays; - private AppFrame abstractFrame; - private Highlights Highlights; - private JFrame Frame; - private Timer RealTimer; - private Sounds Sounds; - - public UtilFrame(int[] array, ArrayVisualizer arrayVisualizer) { - this.array = array; - - this.ArrayVisualizer = arrayVisualizer; - this.ArrayManager = ArrayVisualizer.getArrayManager(); - - this.Delays = ArrayVisualizer.getDelays(); - this.Frame = ArrayVisualizer.getMainWindow(); - this.Highlights = ArrayVisualizer.getHighlights(); - this.RealTimer = ArrayVisualizer.getTimer(); - this.Sounds = ArrayVisualizer.getSounds(); - - setUndecorated(true); - initComponents(); - setLocation(Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth(), Frame.getX() + Frame.getWidth()), Frame.getY() + 29); - setAlwaysOnTop(false); - setVisible(true); - } - - private int getCustomInput(String text, String defaultOptionMessage) throws Exception { - String input = JEnhancedOptionPane.showInputDialog("Customize Sort", text, new Object[] {"Enter", defaultOptionMessage}); - int integer = Integer.parseInt(input); - return Math.abs(integer); - } - - public void reposition(ArrayFrame af){ - toFront(); - setLocation(Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth(), Frame.getX() + Frame.getWidth() + af.getWidth()), Frame.getY() + 29); - if(this.abstractFrame != null && abstractFrame.isVisible()) - abstractFrame.reposition(); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - // //GEN-BEGIN:initComponents - private void initComponents() { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - - this.jLabel1 = new javax.swing.JLabel(); - this.jButton1 = new javax.swing.JButton(); - this.jButton2 = new javax.swing.JButton(); - this.jButton3 = new javax.swing.JButton(); - this.jCheckBox1 = new javax.swing.JCheckBox(); - this.jCheckBox2 = new javax.swing.JCheckBox(); - this.jButton4 = new javax.swing.JButton(); - this.jButton7 = new javax.swing.JButton(); - this.jCheckBox3 = new javax.swing.JCheckBox(); - this.jCheckBox4 = new javax.swing.JCheckBox(); - this.jButton5 = new javax.swing.JButton(); - this.jCheckBox5 = new javax.swing.JCheckBox(); - this.jButton6 = new javax.swing.JButton(); - this.jCheckBox6 = new javax.swing.JCheckBox(); - this.jCheckBox7 = new javax.swing.JCheckBox(); - this.jCheckBox8 = new javax.swing.JCheckBox(); - this.jCheckBox9 = new javax.swing.JCheckBox(); - this.jSlider = new javax.swing.JSlider(SwingConstants.VERTICAL, 1, 12, 11); - this.jComboBox1 = new javax.swing.JComboBox(); - - jLabel1.setText("Settings"); - - setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); - - Hashtable labels = new Hashtable<>(); - labels.put(1, new JLabel("2")); - labels.put(2, new JLabel("4")); - labels.put(3, new JLabel("8")); - labels.put(4, new JLabel("16")); - labels.put(5, new JLabel("32")); - labels.put(6, new JLabel("64")); - labels.put(7, new JLabel("128")); - labels.put(8, new JLabel("256")); - labels.put(9, new JLabel("512")); - labels.put(10, new JLabel("1024")); - labels.put(11, new JLabel("2048")); - labels.put(12, new JLabel("4096")); - - jSlider.setMajorTickSpacing(1); - jSlider.setLabelTable(labels); - jSlider.setPaintLabels(true); - jSlider.setPaintTicks(true); - jSlider.setSnapToTicks(true); - jSlider.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent event) { - ArrayVisualizer.setCurrentLength((int) Math.pow(2, jSlider.getValue())); - } - }); - - jButton1ResetText(); - jButton1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(); - } - }); - - jButton2ResetText(); - jButton2.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton2ActionPerformed(); - } - }); - - jButton3.setText("Change Speed"); - jButton3.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton3ActionPerformed(); - } - }); - - jButton4.setText("Cancel Delays"); - jButton4.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton4ActionPerformed(); - } - }); - - jButton7.setText("Cancel Sort"); - jButton7.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton7ActionPerformed(); - } - }); - - jCheckBox1.setSelected(true); - jCheckBox1.setText("Show Shuffle"); - jCheckBox1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox1ActionPerformed(); - } - }); - - jCheckBox2.setSelected(false); - jCheckBox2.setText("Linked Dots"); - jCheckBox2.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox2ActionPerformed(); - } - }); - - jCheckBox3.setSelected(true); - jCheckBox3.setText("End Sweep Anim"); - jCheckBox3.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox3ActionPerformed(); - } - }); - - jCheckBox4.setSelected(true); - jCheckBox4.setText("Calc Real Time"); - jCheckBox4.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox4ActionPerformed(); - } - }); - - jButton5.setText("Clear Stats"); - jButton5.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton5ActionPerformed(); - } - }); - - jCheckBox5.setSelected(false); - jCheckBox5.setText("Softer Sounds"); - jCheckBox5.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox5ActionPerformed(); - } - }); - - jButton6ResetText(); - jButton6.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton6ActionPerformed(); - } - }); - - jCheckBox6.setSelected(true); - jCheckBox6.setText("Display Stats"); - jCheckBox6.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox6ActionPerformed(); - } - }); - - jCheckBox7.setSelected(true); - jCheckBox7.setText("Enable Sounds"); - jCheckBox7.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox7ActionPerformed(); - } - }); - - jCheckBox8.setSelected(false); - jCheckBox8.setText("Enable Color"); - jCheckBox8.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox8ActionPerformed(); - } - }); - - jCheckBox9.setSelected(false); - jCheckBox9.setText("Show Aux Arrays"); - jCheckBox9.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jCheckBox9ActionPerformed(); - } - }); - - jComboBox1.setModel(new DefaultComboBoxModel<>(new String[] { - "Sorting", - "AntiQSort", - "Stability Check", - "Sorting Networks", - "Reversed Sorting" - // "*Simple* Benchmarking" - })); - jComboBox1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jComboBox1ActionPerformed(); - } - }); - if (ArrayVisualizer.disabledStabilityCheck) { - jComboBox1.removeItem("Stability Check"); - } - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) - .addComponent(this.jLabel1) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) - .addComponent(this.jCheckBox1) - .addComponent(this.jCheckBox2) - .addComponent(this.jCheckBox3) - .addComponent(this.jCheckBox4) - .addComponent(this.jCheckBox6) - .addComponent(this.jCheckBox7) - .addComponent(this.jCheckBox8) - .addComponent(this.jCheckBox9) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.jCheckBox5) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - .addComponent(this.jButton7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jComboBox1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))) - .addGap(0, 10, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) - .addGroup(layout.createSequentialGroup() - .addGap(5, 5, 5) - .addComponent(this.jLabel1) - .addGap(7, 7, 7) - .addComponent(this.jComboBox1) - .addGap(10, 10, 10) - .addComponent(this.jButton2) - .addGap(5, 5, 5) - .addComponent(this.jCheckBox2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jCheckBox8) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jCheckBox9) - .addGap(7, 7, 7) - .addComponent(this.jButton3) - .addGap(12, 12, 12) - .addComponent(this.jButton1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jButton7) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jButton4) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jButton6) - .addGap(7, 7, 7) - .addComponent(this.jCheckBox1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jCheckBox7) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jCheckBox5) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(this.jCheckBox3) - .addGap(8, 8, 8) - .addComponent(this.jButton5) - .addGap(5, 5, 5) - .addComponent(this.jCheckBox6) - .addComponent(this.jCheckBox4)) - ); - - pack(); - }// //GEN-END:initComponents - - public void setMode(String mode) { - this.jComboBox1.setSelectedItem(mode); - } - - private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed - //CHANGE SORT - if(this.abstractFrame != null && abstractFrame.isVisible()){ - boolean tmp = this.abstractFrame instanceof SortPrompt; - abstractFrame.dispose(); - jButton1ResetText(); - if(tmp) - return; - } - this.abstractFrame = new SortPrompt(this.array, this.ArrayVisualizer, this.Frame, this); - jButton1.setText("Close"); - jButton2ResetText(); - jButton6ResetText(); - }//GEN-LAST:event_jButton1ActionPerformed - - public void jButton1ResetText() { - jButton1.setText("Choose Sort"); - } - - private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton2ActionPerformed - //CHANGE VIEW - if(this.abstractFrame != null && abstractFrame.isVisible()){ - boolean tmp = this.abstractFrame instanceof ViewPrompt; - jButton2ResetText(); - abstractFrame.dispose(); - if(tmp) - return; - } - this.abstractFrame = new ViewPrompt(this.ArrayVisualizer, this.Frame, this); - jButton2.setText("Close"); - jButton1ResetText(); - jButton6ResetText(); - }//GEN-LAST:event_jButton2ActionPerformed - - public void jButton2ResetText() { - jButton2.setText("Visual Style"); - } - - private void jButton3ActionPerformed() {//GEN-FIRST:event_jButton3ActionPerformed - boolean speedPromptAllowed; - - if(this.abstractFrame == null) { - speedPromptAllowed = true; - } - else if(!this.abstractFrame.isVisible()) { - speedPromptAllowed = true; - } - else { - speedPromptAllowed = false; - } - - if(speedPromptAllowed) { - boolean showPrompt = true; - while(showPrompt) { - try { - double oldRatio = Delays.getSleepRatio(); - String userInput = JOptionPane.showInputDialog(null, "Modify the visual's speed below (Ex. 10 = Ten times faster)", oldRatio); - if(userInput == null) { - showPrompt = false; - } - else { - double newRatio = Double.parseDouble(userInput); - if(newRatio == 0) throw new Exception("Divide by zero"); - Delays.setSleepRatio(newRatio); - Delays.updateCurrentDelay(oldRatio, Delays.getSleepRatio()); - showPrompt = false; - } - } - catch(Exception e) { - showPrompt = true; - JOptionPane.showMessageDialog(null, "Not a number! (" + e.getMessage() + ")", "Error", JOptionPane.ERROR_MESSAGE); - } - } - } - }//GEN-LAST:event_jButton3ActionPerformed - - private void jCheckBox1ActionPerformed() {//GEN-FIRST:event_jCheckBox2ActionPerformed - ArrayVisualizer.toggleShuffleAnimation(jCheckBox1.isSelected()); - }//GEN-LAST:event_jCheckBox1ActionPerformed - - private void jCheckBox2ActionPerformed() {//GEN-FIRST:event_jCheckBox3ActionPerformed - ArrayVisualizer.toggleLinkedDots(jCheckBox2.isSelected()); - }//GEN-LAST:event_jCheckBox2ActionPerformed - - private void jCheckBox3ActionPerformed() {//GEN-FIRST:event_jCheckBox3ActionPerformed - Highlights.toggleFancyFinishes(jCheckBox3.isSelected()); - }//GEN-LAST:event_jCheckBox3ActionPerformed - - private void jButton4ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - Delays.changeSkipped(true); - }//GEN-LAST:event_jButton4ActionPerformed - - private void jButton7ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - ArrayVisualizer.setCanceled(true); - }//GEN-LAST:event_jButton4ActionPerformed - - private void jCheckBox4ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - RealTimer.toggleRealTimer(jCheckBox4.isSelected()); - }//GEN-LAST:event_jCheckBox4ActionPerformed - - private void jButton5ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - ArrayVisualizer.resetAllStatistics(); - }//GEN-LAST:event_jButton6ActionPerformed - - private void jCheckBox5ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - if(jCheckBox5.isSelected()) { - Sounds.toggleSofterSounds(true); - } - else { - Sounds.toggleSofterSounds(false); - } - }//GEN-LAST:event_jCheckBox5ActionPerformed - - private void jButton6ActionPerformed() {//GEN-FIRST:event_jButton2ActionPerformed - //CHANGE SIZE - if(this.abstractFrame != null && abstractFrame.isVisible()){ - boolean tmp = this.abstractFrame instanceof ShufflePrompt; - abstractFrame.dispose(); - jButton6ResetText(); - if(tmp) - return; - } - this.abstractFrame = new ShufflePrompt(this.ArrayManager, this.Frame, this); - jButton6.setText("Close"); - jButton1ResetText(); - jButton2ResetText(); - }//GEN-LAST:event_jButton7ActionPerformed - - public void jButton6ResetText() { - jButton6.setText("Choose Shuffle"); - } - - private void jCheckBox6ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - ArrayVisualizer.toggleStatistics(jCheckBox6.isSelected()); - }//GEN-LAST:event_jCheckBox6ActionPerformed - - private void jCheckBox7ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - Sounds.toggleSounds(jCheckBox7.isSelected()); - }//GEN-LAST:event_jCheckBox7ActionPerformed - - private void jCheckBox8ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - ArrayVisualizer.toggleColor(jCheckBox8.isSelected()); - }//GEN-LAST:event_jCheckBox8ActionPerformed - - private void jCheckBox9ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - if (!jCheckBox9WarningShown && jCheckBox9.isSelected()) { - if (JOptionPane.showConfirmDialog( - null, - "This will cause some sorts have extreme strobing/flashing." - + "
It is highly recommended to NOT enable the \"" + jCheckBox9.getText() + "\" option if you may be at risk of seizures." - + "
Are you sure you wish to enable this option?", - "Seizure Warning", - JOptionPane.YES_NO_OPTION, - JOptionPane.WARNING_MESSAGE - ) == JOptionPane.NO_OPTION) { - jCheckBox9.setSelected(false); - return; - } - jCheckBox9WarningShown = true; - } - ArrayVisualizer.toggleExternalArrays(jCheckBox9.isSelected()); - }//GEN-LAST:event_jCheckBox8ActionPerformed - - private void jComboBox1ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed - switch ((String)jComboBox1.getSelectedItem()) { - case "Sorting": - if (ArrayVisualizer.enableBenchmarking(false)) - break; - jButton6.setEnabled(true); - ArrayVisualizer.setComparator(0); - break; - - case "AntiQSort": - if (ArrayVisualizer.enableBenchmarking(false)) - break; - if(this.abstractFrame != null && abstractFrame.isVisible()){ - abstractFrame.dispose(); - jButton6ResetText(); - } - jButton6.setEnabled(false); - ArrayVisualizer.setComparator(1); - break; - - case "Stability Check": - if (ArrayVisualizer.enableBenchmarking(false)) - break; - jButton6.setEnabled(true); - ArrayVisualizer.setComparator(2); - break; - - case "Sorting Networks": - if (ArrayVisualizer.enableBenchmarking(false)) - break; - jButton6.setEnabled(true); - ArrayVisualizer.setComparator(4); - if (!SortingNetworkGenerator.verifyPythonVersionAndDialog()) - jComboBox1.setSelectedIndex(0); // Failure to find Python installation - if (ArrayVisualizer.getCurrentLength() > 256) { - JOptionPane.showMessageDialog(null, "Large sorting networks take too long and will not be generated. Array lengths less than or equal to 256 are recommended.", - "Sorting Network Visualizer", JOptionPane.WARNING_MESSAGE); - ArrayVisualizer.getArrayFrame().setLengthSlider(256); - } - break; - - case "Reversed Sorting": - if (ArrayVisualizer.enableBenchmarking(false)) - break; - jButton6.setEnabled(true); - ArrayVisualizer.setComparator(3); - break; - - case "*Simple* Benchmarking": - jButton6.setEnabled(true); - ArrayVisualizer.setComparator(0); - ArrayVisualizer.enableBenchmarking(true); - break; - } - }//GEN-LAST:event_jCheckBox8ActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel jLabel1; - private javax.swing.JButton jButton1; - private javax.swing.JButton jButton2; - private javax.swing.JButton jButton3; - private javax.swing.JButton jButton4; - private javax.swing.JButton jButton5; - private javax.swing.JButton jButton6; - private javax.swing.JButton jButton7; - private javax.swing.JCheckBox jCheckBox1; - private javax.swing.JCheckBox jCheckBox2; - private javax.swing.JCheckBox jCheckBox3; - private javax.swing.JCheckBox jCheckBox4; - private javax.swing.JCheckBox jCheckBox5; - private javax.swing.JCheckBox jCheckBox6; - private javax.swing.JCheckBox jCheckBox7; - private javax.swing.JCheckBox jCheckBox8; - private javax.swing.JCheckBox jCheckBox9; - private javax.swing.JSlider jSlider; - @SuppressWarnings("rawtypes") - private javax.swing.JComboBox jComboBox1; -} \ No newline at end of file diff --git a/src/main/SortAnalyzer.java b/src/main/SortAnalyzer.java deleted file mode 100644 index 110bcbb1..00000000 --- a/src/main/SortAnalyzer.java +++ /dev/null @@ -1,331 +0,0 @@ -package main; - -import java.io.File; -import java.lang.reflect.Constructor; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; - -import javax.tools.ToolProvider; -import javax.swing.JOptionPane; -import javax.tools.JavaCompiler; -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ClassInfo; -import io.github.classgraph.ScanResult; -import panes.JErrorPane; -import sorts.templates.Sort; -import sorts.templates.SortComparator; - -/* - * -The MIT License (MIT) - -Copyright (c) 2019 Luke Hutchison - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class SortAnalyzer { - private ArrayList comparisonSorts; - private ArrayList distributionSorts; - private ArrayList invalidSorts; - private ArrayList suggestions; - - private String sortErrorMsg; - - private ArrayVisualizer arrayVisualizer; - - public static class SortPair { - public int id; - public Class sortClass; - public String listName; - public String category; - public boolean usesComparisons; - - public static String[] getListNames(SortPair[] sorts) { - String[] result = new String[sorts.length]; - for (int i = 0; i < sorts.length; i++) { - result[i] = sorts[i].listName; - } - return result; - } - - public static String[] getCategories(SortPair[] sorts) { - HashSet result = new HashSet<>(); - for (int i = 0; i < sorts.length; i++) { - result.add(sorts[i].category); - } - String[] resultArray = result.toArray(new String[result.size()]); - Arrays.sort(resultArray); - return resultArray; - } - } - - public SortAnalyzer(ArrayVisualizer arrayVisualizer) { - this.comparisonSorts = new ArrayList<>(); - this.distributionSorts = new ArrayList<>(); - this.invalidSorts = new ArrayList<>(); - this.suggestions = new ArrayList<>(); - - this.arrayVisualizer = arrayVisualizer; - } - - private boolean compileSingle(String name, ClassLoader loader) { - try { - Class sortClass; - try { - if (loader == null) - sortClass = Class.forName(name); - else - sortClass = Class.forName(name, true, loader); - } catch (ClassNotFoundException e) { - return true; - } - // System.out.println(sortClass.getConstructors()[0].getParameterTypes()[0].hashCode()); - Constructor newSort = sortClass.getConstructor(new Class[] {ArrayVisualizer.class}); - // Constructor newSort = sortClass.getConstructors()[0]; - Sort sort = (Sort) newSort.newInstance(this.arrayVisualizer); - - try { - if(verifySort(sort)) { - String suggestion = checkForSuggestions(sort); - if(!suggestion.isEmpty()) { - suggestions.add(suggestion); - } - if(sort.isComparisonBased()) { - comparisonSorts.add(sort); - } - else { - distributionSorts.add(sort); - } - } - else { - throw new Exception(); - } - } - catch(Exception e) { - invalidSorts.add(sort.getClass().getName() + " (" + this.sortErrorMsg + ")"); - return false; - } - } - catch(Exception e) { - JErrorPane.invokeErrorMessage(e, "Could not compile " + name); - invalidSorts.add(name + " (failed to compile)"); - return false; - } - return true; - } - - public void analyzeSorts() { - ClassGraph classGraph = new ClassGraph(); - classGraph.whitelistPackages("sorts"); - classGraph.blacklistPackages("sorts.templates"); - classGraph.blacklistPaths("cache/*"); - - try (ScanResult scanResult = classGraph.scan()) { - List sortFiles; - sortFiles = scanResult.getAllClasses(); - - for(int i = 0; i < sortFiles.size(); i++) { - if (sortFiles.get(i).getName().contains("$")) continue; // Ignore inner classes - this.compileSingle(sortFiles.get(i).getName(), null); - } - sortSorts(); - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - } - - public boolean importSort(File file, boolean showConfirmation) { - Pattern packagePattern = Pattern.compile("^\\s*package ([a-zA-Z\\.]+);"); - String contents; - try { - contents = new String(Files.readAllBytes(file.toPath())); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - return false; - } - Matcher matcher = packagePattern.matcher(contents); - if (!matcher.find()) { - JErrorPane.invokeCustomErrorMessage("No package specifed"); - return false; - } - String packageName = matcher.group(1); - String name = packageName + "." + file.getName().split("\\.")[0]; - File tempPath = new File("./cache/" + String.join("/", packageName.split("\\."))); - tempPath.mkdirs(); - File destPath = new File(tempPath.getAbsolutePath() + "/" + file.getName()); - try { - Files.copy(file.toPath(), destPath.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - return false; - } - - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - int success = compiler.run(null, null, null, destPath.getAbsolutePath()); - if (success != 0) { - JErrorPane.invokeCustomErrorMessage("Failed to compile: " + destPath.getPath() + "\nError code " + success); - return false; - } - - try { - if (!compileSingle(name, URLClassLoader.newInstance(new URL[] { new File("./cache/").toURI().toURL() }))) - return false; - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - return false; - } - - if (showConfirmation) { - sortSorts(); - arrayVisualizer.refreshSorts(); - JOptionPane.showMessageDialog(null, "Successfully imported sort " + name, "Import Sort", JOptionPane.INFORMATION_MESSAGE); - } - return true; - } - - public boolean importSort(File file) { - return importSort(file, true); - } - - public void sortSorts() { - SortComparator sortComparator = new SortComparator(); - Collections.sort(comparisonSorts, sortComparator); - Collections.sort(distributionSorts, sortComparator); - } - - private boolean verifySort(Sort sort) { - if(!sort.isSortEnabled()) { - this.sortErrorMsg = "manually disabled"; - return false; - } - if(sort.getSortListName().equals("")) { - this.sortErrorMsg = "missing 'Choose Sort' name"; - return false; - } - if(sort.getRunAllSortsName().equals("")) { - this.sortErrorMsg = "missing 'Run All' name"; - return false; - } - if(sort.getRunSortName().equals("")) { - this.sortErrorMsg = "missing 'Run Sort' name"; - return false; - } - if(sort.getCategory().equals("")) { - this.sortErrorMsg = "missing category"; - return false; - } - - return true; - } - - private static String checkForSuggestions(Sort sort) { - StringBuilder suggestions = new StringBuilder(); - boolean warned = false; - - if(sort.isBogoSort() && !sort.isUnreasonablySlow()) { - suggestions.append("- " + sort.getRunSortName() + " is a bogosort. It should be marked 'unreasonably slow'.\n"); - warned = true; - } - if(sort.isUnreasonablySlow() && sort.getUnreasonableLimit() == 0) { - suggestions.append("- A warning will pop up every time you select " + sort.getRunSortName() + ". You might want to change its 'unreasonable limit'.\n"); - warned = true; - } - if(!sort.isUnreasonablySlow() && sort.getUnreasonableLimit() != 0) { - suggestions.append("- You might want to set " + sort.getRunSortName() + "'s 'unreasonable limit' to 0. It's not marked 'unreasonably slow'.\n"); - warned = true; - } - if(sort.isRadixSort() && !sort.usesBuckets()) { - suggestions.append("- " + sort.getRunSortName() + " is a radix sort and should also be classified as a bucket sort.\n"); - warned = true; - } - if(sort.isRadixSort() && sort.isComparisonBased()) { - suggestions.append("- " + sort.getRunSortName() + " is a radix sort. It probably shouldn't be labelled as a comparison-based sort.\n"); - warned = true; - } - - if(warned) { - suggestions.deleteCharAt(suggestions.length() - 1); - } - return suggestions.toString(); - } - - public SortPair[] getComparisonSorts() { - SortPair[] ComparisonSorts = new SortPair[comparisonSorts.size()]; - - for(int i = 0; i < ComparisonSorts.length; i++) { - ComparisonSorts[i] = new SortPair(); - ComparisonSorts[i].id = i; - ComparisonSorts[i].sortClass = comparisonSorts.get(i).getClass(); - ComparisonSorts[i].listName = comparisonSorts.get(i).getSortListName(); - ComparisonSorts[i].category = comparisonSorts.get(i).getCategory(); - ComparisonSorts[i].usesComparisons = true; - } - - return ComparisonSorts; - } - public SortPair[] getDistributionSorts() { - SortPair[] DistributionSorts = new SortPair[distributionSorts.size()]; - - for(int i = 0; i < DistributionSorts.length; i++) { - DistributionSorts[i] = new SortPair(); - DistributionSorts[i].id = i; - DistributionSorts[i].sortClass = distributionSorts.get(i).getClass(); - DistributionSorts[i].listName = distributionSorts.get(i).getSortListName(); - DistributionSorts[i].category = distributionSorts.get(i).getCategory(); - DistributionSorts[i].usesComparisons = false; - } - - return DistributionSorts; - } - public String[] getInvalidSorts() { - if(invalidSorts.size() < 1) { - return null; - } - - String[] InvalidSorts = new String[invalidSorts.size()]; - InvalidSorts = invalidSorts.toArray(InvalidSorts); - - return InvalidSorts; - } - public String[] getSuggestions() { - if(suggestions.size() < 1) { - return null; - } - - String[] allSuggestions = new String[suggestions.size()]; - allSuggestions = suggestions.toArray(allSuggestions); - - return allSuggestions; - } -} \ No newline at end of file diff --git a/src/dialogs/CustomImageDialog.java b/src/main/java/io/github/arrayv/dialogs/CustomImageDialog.java similarity index 82% rename from src/dialogs/CustomImageDialog.java rename to src/main/java/io/github/arrayv/dialogs/CustomImageDialog.java index ef4b812f..f03d7706 100644 --- a/src/dialogs/CustomImageDialog.java +++ b/src/main/java/io/github/arrayv/dialogs/CustomImageDialog.java @@ -1,8 +1,9 @@ -package dialogs; +package io.github.arrayv.dialogs; +import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; -final public class CustomImageDialog extends FileDialog { +public final class CustomImageDialog extends FileDialog { public CustomImageDialog() { super(); @@ -23,7 +24,8 @@ public CustomImageDialog() { fileDialog.setDialogTitle("Choose an image..."); - fileDialog.showOpenDialog(null); - this.file = fileDialog.getSelectedFile(); + this.file = fileDialog.showOpenDialog(null) == JFileChooser.APPROVE_OPTION + ? fileDialog.getSelectedFile() + : null; } -} \ No newline at end of file +} diff --git a/src/resources/image/ImgFetcher.java b/src/main/java/io/github/arrayv/dialogs/ExportShuffleDialog.java similarity index 70% rename from src/resources/image/ImgFetcher.java rename to src/main/java/io/github/arrayv/dialogs/ExportShuffleDialog.java index db348825..74c6d511 100644 --- a/src/resources/image/ImgFetcher.java +++ b/src/main/java/io/github/arrayv/dialogs/ExportShuffleDialog.java @@ -1,14 +1,11 @@ -package resources.image; +package io.github.arrayv.dialogs; -import java.io.File; - -import resources.Fetcher; +import javax.swing.*; /* - * MIT License -Copyright (c) 2020 aphitorite +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -27,16 +24,16 @@ of this software and associated documentation files (the "Software"), to deal LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ +*/ -//TODO: Create abstract "fetcher" class for both sound effects and custom image -final public class ImgFetcher extends Fetcher { - public ImgFetcher() { - super("pic.jpg"); - } - - public ImgFetcher(File file) { - super(file); +public final class ExportShuffleDialog extends FileDialog { + public ExportShuffleDialog() { + super(); + + fileDialog.setDialogTitle("Choose where to export the current shuffle graph..."); + + this.file = fileDialog.showSaveDialog(null) == JFileChooser.APPROVE_OPTION + ? fileDialog.getSelectedFile() + : null; } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/dialogs/FileDialog.java b/src/main/java/io/github/arrayv/dialogs/FileDialog.java new file mode 100644 index 00000000..f2661540 --- /dev/null +++ b/src/main/java/io/github/arrayv/dialogs/FileDialog.java @@ -0,0 +1,62 @@ +package io.github.arrayv.dialogs; + +/* +MIT License + +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import javax.swing.*; +import javax.swing.filechooser.FileFilter; +import java.io.File; + +public abstract class FileDialog { + protected static JFileChooser fileDialog; + protected File file; + protected static volatile boolean initialized; + + public FileDialog() { + while (!FileDialog.initialized) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + FileDialog.fileDialog.resetChoosableFileFilters(); + } + + public static void initialize() { + FileDialog.fileDialog = new JFileChooser(); + FileDialog.fileDialog.setCurrentDirectory(new File(System.getProperty("user.dir"))); + FileDialog.fileDialog.setMultiSelectionEnabled(false); + FileDialog.initialized = true; + } + + protected void removeAllFilesOption() { + FileFilter allFiles = FileDialog.fileDialog.getChoosableFileFilters()[0]; + FileDialog.fileDialog.removeChoosableFileFilter(allFiles); + } + + public File getFile() { + return this.file; + } +} diff --git a/src/dialogs/ImportShuffleDialog.java b/src/main/java/io/github/arrayv/dialogs/ImportShuffleDialog.java similarity index 72% rename from src/dialogs/ImportShuffleDialog.java rename to src/main/java/io/github/arrayv/dialogs/ImportShuffleDialog.java index f1d2ae2a..656e3762 100644 --- a/src/dialogs/ImportShuffleDialog.java +++ b/src/main/java/io/github/arrayv/dialogs/ImportShuffleDialog.java @@ -1,6 +1,6 @@ -package dialogs; +package io.github.arrayv.dialogs; -final public class ImportShuffleDialog extends FileDialog { +public final class ImportShuffleDialog extends FileDialog { public ImportShuffleDialog() { super(); @@ -9,4 +9,4 @@ public ImportShuffleDialog() { fileDialog.showOpenDialog(null); this.file = fileDialog.getSelectedFile(); } -} \ No newline at end of file +} diff --git a/src/dialogs/ImportSortDialog.java b/src/main/java/io/github/arrayv/dialogs/ImportSortDialog.java similarity index 59% rename from src/dialogs/ImportSortDialog.java rename to src/main/java/io/github/arrayv/dialogs/ImportSortDialog.java index 9587b28a..5050e7fc 100644 --- a/src/dialogs/ImportSortDialog.java +++ b/src/main/java/io/github/arrayv/dialogs/ImportSortDialog.java @@ -1,8 +1,9 @@ -package dialogs; +package io.github.arrayv.dialogs; +import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; -final public class ImportSortDialog extends FileDialog { +public final class ImportSortDialog extends FileDialog { public ImportSortDialog() { super(); @@ -12,7 +13,8 @@ public ImportSortDialog() { fileDialog.setDialogTitle("Choose a sort file to import..."); - fileDialog.showOpenDialog(null); - this.file = fileDialog.getSelectedFile(); + this.file = fileDialog.showOpenDialog(null) == JFileChooser.APPROVE_OPTION + ? fileDialog.getSelectedFile() + : null; } -} \ No newline at end of file +} diff --git a/src/resources/sorting_network_master/LICENSE b/src/main/java/io/github/arrayv/dialogs/LoadCustomDistributionDialog.java similarity index 67% rename from src/resources/sorting_network_master/LICENSE rename to src/main/java/io/github/arrayv/dialogs/LoadCustomDistributionDialog.java index 5c0026a1..9bb72edb 100644 --- a/src/resources/sorting_network_master/LICENSE +++ b/src/main/java/io/github/arrayv/dialogs/LoadCustomDistributionDialog.java @@ -1,6 +1,11 @@ -The MIT License (MIT) +package io.github.arrayv.dialogs; -Copyright (c) 2015 Brian Pursley +import javax.swing.*; + +/* +MIT License + +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +23,17 @@ of this software and associated documentation files (the "Software"), to deal AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. +*/ + +public final class LoadCustomDistributionDialog extends FileDialog { + public LoadCustomDistributionDialog() { + super(); + + fileDialog.setDialogTitle("Choose a distribution file..."); + + this.file = fileDialog.showDialog(null, "Select") == JFileChooser.APPROVE_OPTION + ? fileDialog.getSelectedFile() + : null; + } +} diff --git a/src/sorts/distribute/ImmediateShatterSort.java b/src/main/java/io/github/arrayv/dialogs/LoadingDialog.java similarity index 52% rename from src/sorts/distribute/ImmediateShatterSort.java rename to src/main/java/io/github/arrayv/dialogs/LoadingDialog.java index 8d8d4201..6670cfc2 100644 --- a/src/sorts/distribute/ImmediateShatterSort.java +++ b/src/main/java/io/github/arrayv/dialogs/LoadingDialog.java @@ -1,13 +1,10 @@ -package sorts.distribute; - -import main.ArrayVisualizer; -import sorts.templates.ShatterSorting; +package io.github.arrayv.dialogs; /* - * MIT License -Copyright (c) 2019 w0rthy +Copyright (c) 2020 Musicombo +Copyright (c) 2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,27 +23,26 @@ of this software and associated documentation files (the "Software"), to deal LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -final public class ImmediateShatterSort extends ShatterSorting { - public ImmediateShatterSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Immediate Shatter"); - this.setRunAllSortsName("Immediate Shatter Sort"); - this.setRunSortName("Immediate Shatter Sort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(false); // It is a bucket sort, but there is no user input - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); +*/ + +import javax.swing.*; +import java.awt.Dialog.ModalityType; + +public class LoadingDialog { + private JOptionPane pane; + private JDialog dialog; + + public LoadingDialog(String resource, JFrame parent) { + this.pane = new JOptionPane("Loading " + resource + "...", JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION, null, new Object[] { }, null); + this.dialog = this.pane.createDialog(parent, "Info"); + this.dialog.setModalityType(ModalityType.MODELESS); + this.dialog.setAlwaysOnTop(this.dialog.isAlwaysOnTopSupported()); + this.dialog.pack(); + this.dialog.setVisible(true); } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.shatterPartition(array, sortLength, 1); + + public void closeDialog() { + this.dialog.setVisible(false); + this.dialog.dispose(); } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/dialogs/RunScriptDialog.java b/src/main/java/io/github/arrayv/dialogs/RunScriptDialog.java new file mode 100644 index 00000000..066a27e6 --- /dev/null +++ b/src/main/java/io/github/arrayv/dialogs/RunScriptDialog.java @@ -0,0 +1,43 @@ +package io.github.arrayv.dialogs; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; + +/* +MIT License + +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +public final class RunScriptDialog extends FileDialog { + public RunScriptDialog() { + super(); + + fileDialog.setDialogTitle("Choose a script file..."); + FileNameExtensionFilter groovyFiles = new FileNameExtensionFilter("Groovy Script Files (.groovy)", "groovy"); + this.removeAllFilesOption(); + fileDialog.addChoosableFileFilter(groovyFiles); + + this.file = fileDialog.showDialog(null, "Select") == JFileChooser.APPROVE_OPTION + ? fileDialog.getSelectedFile() + : null; + } +} diff --git a/src/resources/sorting_network_master/SortingNetworkFetcher.java b/src/main/java/io/github/arrayv/dialogs/SaveArrayDialog.java similarity index 70% rename from src/resources/sorting_network_master/SortingNetworkFetcher.java rename to src/main/java/io/github/arrayv/dialogs/SaveArrayDialog.java index 8ea2c3f8..d80c7276 100644 --- a/src/resources/sorting_network_master/SortingNetworkFetcher.java +++ b/src/main/java/io/github/arrayv/dialogs/SaveArrayDialog.java @@ -1,14 +1,11 @@ -package resources.sorting_network_master; +package io.github.arrayv.dialogs; -import java.io.File; - -import resources.Fetcher; +import javax.swing.*; /* - * MIT License -Copyright (c) 2021 ArrayV 4.0 Team +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -27,16 +24,16 @@ of this software and associated documentation files (the "Software"), to deal LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ +*/ -//TODO: Create abstract "fetcher" class for both sound effects and custom image -final public class SortingNetworkFetcher extends Fetcher { - public SortingNetworkFetcher() { - super("sortingnetwork.py"); - } - - public SortingNetworkFetcher(File file) { - super(file); +public final class SaveArrayDialog extends FileDialog { + public SaveArrayDialog() { + super(); + + fileDialog.setDialogTitle("Choose where to save the contents of the main array..."); + + this.file = fileDialog.showSaveDialog(null) == JFileChooser.APPROVE_OPTION + ? fileDialog.getSelectedFile() + : null; } -} \ No newline at end of file +} diff --git a/src/dialogs/ShuffleDialog.java b/src/main/java/io/github/arrayv/dialogs/ShuffleDialog.java similarity index 53% rename from src/dialogs/ShuffleDialog.java rename to src/main/java/io/github/arrayv/dialogs/ShuffleDialog.java index 01c21e41..e0da3ac8 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/main/java/io/github/arrayv/dialogs/ShuffleDialog.java @@ -1,12 +1,21 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package dialogs; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Point; +package io.github.arrayv.dialogs; + +import io.github.arrayv.frames.AppFrame; +import io.github.arrayv.main.ArrayManager; +import io.github.arrayv.panels.ShufflePanel; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.utils.Distributions; +import io.github.arrayv.utils.ShuffleGraph; +import io.github.arrayv.utils.ShuffleInfo; +import io.github.arrayv.utils.Shuffles; +import io.github.arrayv.utils.shuffleutils.GraphReader; +import io.github.arrayv.utils.shuffleutils.GraphReader.MalformedGraphFileException; +import io.github.arrayv.utils.shuffleutils.GraphWriter; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; @@ -14,31 +23,12 @@ import java.util.List; import java.util.stream.Collectors; -import javax.swing.GroupLayout; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import frames.AppFrame; -import frames.UtilFrame; -import main.ArrayManager; -import panels.ShufflePanel; -import panes.JErrorPane; -import utils.Distributions; -import utils.ShuffleGraph; -import utils.ShuffleInfo; -import utils.Shuffles; -import utils.shuffle_utils.GraphReader; -import utils.shuffle_utils.GraphWriter; -import utils.shuffle_utils.GraphReader.MalformedGraphFileException; - /* - * + * MIT License Copyright (c) 2019 w0rthy -Copyright (c) 2021 ArrayV 4.0 Team +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -60,64 +50,50 @@ of this software and associated documentation files (the "Software"), to deal * */ -/** - * - * @author S630690 - */ -final public class ShuffleDialog extends javax.swing.JDialog implements AppFrame { - - /** - * - */ +public final class ShuffleDialog extends javax.swing.JDialog implements AppFrame { private static final long serialVersionUID = 1L; - - private ArrayManager ArrayManager; - private JFrame Frame; - private UtilFrame UtilFrame; - private List distributions; + + private final ArrayManager arrayManager; + private final List distributions; private static boolean perShuffleDelay = false; - + private boolean bypassEvents; - + /** * Creates new form SortPrompt */ @SuppressWarnings("unchecked") - public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFrame) { + public ShuffleDialog(ArrayManager arrayManager, JFrame frame) { super(frame, "ArrayV Advanced Shuffle Editor", true); - this.ArrayManager = ArrayManager; - this.Frame = frame; - this.UtilFrame = utilFrame; - + this.arrayManager = arrayManager; + initComponents(); bypassEvents = true; - this.shuffleEditor.graph = ArrayManager.getShuffle(); - jList4.setListData(ArrayManager.getDistributionIDs()); - for(int i = 0; i < ArrayManager.getDistributions().length; i++) { - if(ArrayManager.getDistribution().equals(ArrayManager.getDistributions()[i])) { + this.shuffleEditor.setShuffle(arrayManager.getShuffle()); + jList4.setListData(arrayManager.getDistributionIDs()); + for (int i = 0; i < arrayManager.getDistributions().length; i++) { + if (arrayManager.getDistribution().equals(arrayManager.getDistributions()[i])) { jList4.setSelectedIndex(i); break; } } - distributions = Arrays.stream(ArrayManager.getDistributions()) - .filter(dist -> dist.getName() != "Custom") + distributions = Arrays.stream(arrayManager.getDistributions()) + .filter(dist -> !dist.getName().equals("Custom")) .collect(Collectors.toList()); Object[] distributionNames = distributions.stream() - .map(Distributions::getName) - .collect(Collectors.toList()) - .toArray(); + .map(Distributions::getName).toArray(); jList1.setListData(distributionNames); jList3.setListData(distributionNames); - jList2.setListData(ArrayManager.getShuffleIDs()); + jList2.setListData(arrayManager.getShuffleIDs()); jTextField1.setText(Double.toString( perShuffleDelay ? - shuffleEditor.graph.sleepRatio / shuffleEditor.graph.size() : - shuffleEditor.graph.sleepRatio + shuffleEditor.getShuffle().getSleepRatio() / shuffleEditor.getShuffle().size() : + shuffleEditor.getShuffle().getSleepRatio() )); jCheckBox1.setSelected(perShuffleDelay); bypassEvents = false; @@ -125,8 +101,9 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { - if (perShuffleDelay = jCheckBox1.isSelected()) { - shuffleEditor.graph.sleepRatio *= shuffleEditor.graph.size(); + perShuffleDelay = jCheckBox1.isSelected(); + if (perShuffleDelay) { + shuffleEditor.getShuffle().setSleepRatio(shuffleEditor.getShuffle().getSleepRatio() * shuffleEditor.getShuffle().size()); } } }); @@ -134,7 +111,7 @@ public void windowClosed(WindowEvent e) { setMinimumSize(new Dimension(765, 310)); setAlwaysOnTop(false); reposition(); - setVisible(true); + setVisible(true); } @Override @@ -152,70 +129,55 @@ private void initComponents() { this.shuffleEditor = new ShufflePanel(); - this.jButton1 = new javax.swing.JButton(); - this.jButton2 = new javax.swing.JButton(); - this.jButton3 = new javax.swing.JButton(); + javax.swing.JButton jButton1 = new javax.swing.JButton(); + javax.swing.JButton jButton2 = new javax.swing.JButton(); + javax.swing.JButton jButton3 = new javax.swing.JButton(); this.jTextField1 = new javax.swing.JTextField(); - this.jLabel5 = new javax.swing.JLabel(); + javax.swing.JLabel jLabel5 = new javax.swing.JLabel(); this.jCheckBox1 = new javax.swing.JCheckBox(); - this.jScrollPane4 = new javax.swing.JScrollPane(); + javax.swing.JScrollPane jScrollPane4 = new javax.swing.JScrollPane(); this.jList4 = new javax.swing.JList(); - this.jLabel4 = new javax.swing.JLabel(); + javax.swing.JLabel jLabel4 = new javax.swing.JLabel(); - this.jScrollPane1 = new javax.swing.JScrollPane(); + javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); - this.jLabel1 = new javax.swing.JLabel(); + javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); - this.jScrollPane3 = new javax.swing.JScrollPane(); + javax.swing.JScrollPane jScrollPane3 = new javax.swing.JScrollPane(); this.jList3 = new javax.swing.JList(); - this.jLabel3 = new javax.swing.JLabel(); + javax.swing.JLabel jLabel3 = new javax.swing.JLabel(); - this.jScrollPane2 = new javax.swing.JScrollPane(); + javax.swing.JScrollPane jScrollPane2 = new javax.swing.JScrollPane(); this.jList2 = new javax.swing.JList(); - this.jLabel2 = new javax.swing.JLabel(); + javax.swing.JLabel jLabel2 = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); jButton1.setText("Import..."); - jButton1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(); - } - }); - + jButton1.addActionListener(evt -> jButton1ActionPerformed()); + jButton2.setText("Export..."); - jButton2.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton2ActionPerformed(); - } - }); - + jButton2.addActionListener(evt -> jButton2ActionPerformed()); + jButton3.setText("Clear Disconnected Nodes"); - jButton3.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton3ActionPerformed(); - } - }); + jButton3.addActionListener(evt -> jButton3ActionPerformed()); jLabel5.setText("Sleep Ratio"); jTextField1.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { - jTextField1TextChanged(e); + jTextField1TextChanged(); } @Override public void removeUpdate(DocumentEvent e) { - jTextField1TextChanged(e); + jTextField1TextChanged(); } @Override public void changedUpdate(DocumentEvent e) { - jTextField1TextChanged(e); + jTextField1TextChanged(); } }); @@ -229,57 +191,45 @@ public void changedUpdate(DocumentEvent e) { jScrollPane3.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane3.setViewportView(this.jList3); - + jScrollPane2.setViewportView(this.jList2); jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jList4.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - try { - jList4ValueChanged(evt); - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } + jList4.addListSelectionListener(evt -> { + try { + jList4ValueChanged(); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); } }); jLabel4.setText("Base Distribution"); - jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - try { - jList1ValueChanged(evt); - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } + jList1.addListSelectionListener(evt -> { + try { + jList1ValueChanged(); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); } }); jLabel1.setText("Distribution Stretch"); - jList3.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - try { - jList3ValueChanged(evt); - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } + jList3.addListSelectionListener(evt -> { + try { + jList3ValueChanged(); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); } }); jLabel3.setText("Distribution Warp"); - jList2.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - try { - jList2ValueChanged(evt); - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } + jList2.addListSelectionListener(evt -> { + try { + jList2ValueChanged(); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); } }); @@ -291,10 +241,10 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { layout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jLabel4) - .addComponent(this.jScrollPane4, 175, 175, 175) - .addComponent(this.jButton3) - .addComponent(this.jLabel5) + .addComponent(jLabel4) + .addComponent(jScrollPane4, 175, 175, 175) + .addComponent(jButton3) + .addComponent(jLabel5) .addComponent(this.jTextField1) .addComponent(this.jCheckBox1)) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) @@ -305,34 +255,34 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGroup(layout.createSequentialGroup() .addGap(10, 75, 75) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jLabel1) - .addComponent(this.jScrollPane1, 175, 175, 175)) + .addComponent(jLabel1) + .addComponent(jScrollPane1, 175, 175, 175)) .addGap(10, 75, 75) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jLabel3) - .addComponent(this.jScrollPane3, 175, 175, 175)) + .addComponent(jLabel3) + .addComponent(jScrollPane3, 175, 175, 175)) .addGap(10, 75, 75) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jLabel2) - .addComponent(this.jScrollPane2, 175, 175, 175)) + .addComponent(jLabel2) + .addComponent(jScrollPane2, 175, 175, 175)) .addGap(10, 75, 75)) .addGroup(layout.createSequentialGroup() .addGap(150, 150, 150) - .addComponent(this.jButton1) + .addComponent(jButton1) .addGap(20, 20, 20) - .addComponent(this.jButton2) + .addComponent(jButton2) .addGap(150, 150, 150))) ); layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(10, 30, 30) - .addComponent(this.jLabel4) - .addComponent(this.jScrollPane4, 175, 175, 175) + .addComponent(jLabel4) + .addComponent(jScrollPane4, 175, 175, 175) .addGap(20, 20, 20) - .addComponent(this.jButton3) + .addComponent(jButton3) .addGap(20, 20, 20) - .addComponent(this.jLabel5) + .addComponent(jLabel5) .addComponent(this.jTextField1, 20, 20, 20) .addComponent(this.jCheckBox1)) .addGroup(layout.createSequentialGroup() @@ -341,18 +291,18 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() - .addComponent(this.jLabel1) - .addComponent(this.jScrollPane1, 175, 175, 175)) + .addComponent(jLabel1) + .addComponent(jScrollPane1, 175, 175, 175)) .addGroup(layout.createSequentialGroup() - .addComponent(this.jLabel3) - .addComponent(this.jScrollPane3, 175, 175, 175)) + .addComponent(jLabel3) + .addComponent(jScrollPane3, 175, 175, 175)) .addGroup(layout.createSequentialGroup() - .addComponent(this.jLabel2) - .addComponent(this.jScrollPane2, 175, 175, 175))) + .addComponent(jLabel2) + .addComponent(jScrollPane2, 175, 175, 175))) .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jButton1) - .addComponent(this.jButton2)) + .addComponent(jButton1) + .addComponent(jButton2)) .addGap(10, 10, 10)) ); pack(); @@ -372,42 +322,42 @@ private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme JErrorPane.invokeCustomErrorMessage("Error Parsing File: " + e.getMessage()); return; } - ArrayManager.setShuffle(newShuffle); + arrayManager.setShuffle(newShuffle); if (jCheckBox1.isSelected()) { - shuffleEditor.graph.sleepRatio /= shuffleEditor.graph.size(); + shuffleEditor.getShuffle().setSleepRatio(shuffleEditor.getShuffle().getSleepRatio() / shuffleEditor.getShuffle().size()); } jTextField1.setForeground(Color.BLACK); - jTextField1.setText(Double.toString(newShuffle.sleepRatio)); - this.shuffleEditor.graph = newShuffle; + jTextField1.setText(Double.toString(newShuffle.getSleepRatio())); + this.shuffleEditor.setShuffle(newShuffle); this.shuffleEditor.repaint(); }//GEN-LAST:event_jButton1ActionPerformed private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed FileDialog fileDialog = new ExportShuffleDialog(); - double oldSleepRatio = shuffleEditor.graph.sleepRatio; + double oldSleepRatio = shuffleEditor.getShuffle().getSleepRatio(); if (jCheckBox1.isSelected()) { - shuffleEditor.graph.sleepRatio *= shuffleEditor.graph.size(); + shuffleEditor.getShuffle().setSleepRatio(shuffleEditor.getShuffle().getSleepRatio() * shuffleEditor.getShuffle().size()); } try { - new GraphWriter(shuffleEditor.graph).write(fileDialog.file); + new GraphWriter(shuffleEditor.getShuffle()).write(fileDialog.file); } catch (IOException e) { - shuffleEditor.graph.sleepRatio = oldSleepRatio; + shuffleEditor.getShuffle().setSleepRatio(oldSleepRatio); e.printStackTrace(); JErrorPane.invokeCustomErrorMessage("IO Error: " + e.getMessage()); return; } - shuffleEditor.graph.sleepRatio = oldSleepRatio; + shuffleEditor.getShuffle().setSleepRatio(oldSleepRatio); JOptionPane.showMessageDialog(null, "Successfully exported current shuffle to file \"" + fileDialog.file.getAbsolutePath() + "\"", "Advanced Shuffle Editor", JOptionPane.INFORMATION_MESSAGE); }//GEN-LAST:event_jButton1ActionPerformed private void jButton3ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed - shuffleEditor.graph.removeAllDisconnected(); + shuffleEditor.getShuffle().removeAllDisconnected(); shuffleEditor.repaint(); }//GEN-LAST:event_jButton1ActionPerformed - private void jTextField1TextChanged(DocumentEvent e) {//GEN-FIRST:event_jList1ValueChanged + private void jTextField1TextChanged() {//GEN-FIRST:event_jList1ValueChanged String text = jTextField1.getText(); if (text.length() == 0) return; double sleepRatio; @@ -418,64 +368,54 @@ private void jTextField1TextChanged(DocumentEvent e) {//GEN-FIRST:event_jList1Va return; } jTextField1.setForeground(Color.BLACK); - shuffleEditor.graph.sleepRatio = sleepRatio; + shuffleEditor.getShuffle().setSleepRatio(sleepRatio); }//GEN-LAST:event_jList1ValueChanged private void addToGraph(ShuffleInfo shuffle) { - Point safePos = shuffleEditor.graph.findSafeCoordinates(100, 100, 20, 20); - shuffleEditor.graph.addDisconnected(shuffle, safePos.x, safePos.y); + Point safePos = shuffleEditor.getShuffle().findSafeCoordinates(100, 100, 20, 20); + shuffleEditor.getShuffle().addDisconnected(shuffle, safePos.x, safePos.y); } - private void jList4ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged - // TODO add your handling code here: + private void jList4ValueChanged() {//GEN-FIRST:event_jList1ValueChanged if (bypassEvents) return; int selection = jList4.getSelectedIndex(); - Distributions[] distributions = ArrayManager.getDistributions(); + Distributions[] distributions = arrayManager.getDistributions(); if (selection >= 0 && selection < distributions.length) - ArrayManager.setDistribution(distributions[selection]); + arrayManager.setDistribution(distributions[selection]); }//GEN-LAST:event_jList1ValueChanged - private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged - // TODO add your handling code here: + private void jList1ValueChanged() {//GEN-FIRST:event_jList1ValueChanged if (bypassEvents) return; String selection = (String)jList1.getSelectedValue(); - Distributions distribution = distributions.stream() - .filter(d -> d.getName().equals(selection)) - .findFirst() - .orElse(null); - if (distribution != null) - addToGraph(new ShuffleInfo(distribution, false)); + distributions.stream() + .filter(d -> d.getName().equals(selection)) + .findFirst().ifPresent(distribution -> addToGraph(new ShuffleInfo(distribution, false))); shuffleEditor.repaint(); bypassEvents = true; jList1.clearSelection(); bypassEvents = false; }//GEN-LAST:event_jList1ValueChanged - private void jList3ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged - // TODO add your handling code here: + private void jList3ValueChanged() {//GEN-FIRST:event_jList1ValueChanged if (bypassEvents) return; String selection = (String)jList3.getSelectedValue(); - Distributions distribution = distributions.stream() - .filter(d -> d.getName().equals(selection)) - .findFirst() - .orElse(null); - if (distribution != null) - addToGraph(new ShuffleInfo(distribution, true)); + distributions.stream() + .filter(d -> d.getName().equals(selection)) + .findFirst().ifPresent(distribution -> addToGraph(new ShuffleInfo(distribution, true))); shuffleEditor.repaint(); bypassEvents = true; jList3.clearSelection(); bypassEvents = false; }//GEN-LAST:event_jList1ValueChanged - private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged - // TODO add your handling code here: + private void jList2ValueChanged() {//GEN-FIRST:event_jList1ValueChanged if (bypassEvents) return; int selection = jList2.getSelectedIndex(); - Shuffles[] shuffles = ArrayManager.getShuffles(); + Shuffles[] shuffles = arrayManager.getShuffles(); if (selection >= 0 && selection < shuffles.length) addToGraph(new ShuffleInfo(shuffles[selection])); shuffleEditor.repaint(); @@ -487,32 +427,19 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws // Variables declaration - do not modify//GEN-BEGIN:variables private ShufflePanel shuffleEditor; - private javax.swing.JButton jButton1; - private javax.swing.JButton jButton2; - private javax.swing.JButton jButton3; - private javax.swing.JTextField jTextField1; - private javax.swing.JLabel jLabel5; private javax.swing.JCheckBox jCheckBox1; @SuppressWarnings("rawtypes") private javax.swing.JList jList4; - private javax.swing.JScrollPane jScrollPane4; - private javax.swing.JLabel jLabel4; @SuppressWarnings("rawtypes") private javax.swing.JList jList1; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JLabel jLabel1; @SuppressWarnings("rawtypes") private javax.swing.JList jList3; - private javax.swing.JScrollPane jScrollPane3; - private javax.swing.JLabel jLabel3; @SuppressWarnings("rawtypes") private javax.swing.JList jList2; - private javax.swing.JScrollPane jScrollPane2; - private javax.swing.JLabel jLabel2; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} diff --git a/src/dialogs/SoundbankDialog.java b/src/main/java/io/github/arrayv/dialogs/SoundbankDialog.java similarity index 77% rename from src/dialogs/SoundbankDialog.java rename to src/main/java/io/github/arrayv/dialogs/SoundbankDialog.java index 58196aad..a8822596 100644 --- a/src/dialogs/SoundbankDialog.java +++ b/src/main/java/io/github/arrayv/dialogs/SoundbankDialog.java @@ -1,8 +1,9 @@ -package dialogs; +package io.github.arrayv.dialogs; +import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; -final public class SoundbankDialog extends FileDialog { +public final class SoundbankDialog extends FileDialog { public SoundbankDialog() { super(); @@ -19,7 +20,8 @@ public SoundbankDialog() { fileDialog.setDialogTitle("Choose a MIDI soundbank..."); - fileDialog.showDialog(null, "Select"); - this.file = fileDialog.getSelectedFile(); + this.file = fileDialog.showDialog(null, "Select") == JFileChooser.APPROVE_OPTION + ? fileDialog.getSelectedFile() + : null; } -} \ No newline at end of file +} diff --git a/src/frames/AppFrame.java b/src/main/java/io/github/arrayv/frames/AppFrame.java similarity index 86% rename from src/frames/AppFrame.java rename to src/main/java/io/github/arrayv/frames/AppFrame.java index 7a20cff4..b0b4b519 100644 --- a/src/frames/AppFrame.java +++ b/src/main/java/io/github/arrayv/frames/AppFrame.java @@ -1,10 +1,12 @@ -package frames; +package io.github.arrayv.frames; /* - * + * MIT License Copyright (c) 2019 w0rthy +Copyright (c) 2020 Musicombo +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,12 +28,8 @@ of this software and associated documentation files (the "Software"), to deal * */ -/** - * - * @author S630690 - */ public interface AppFrame { - abstract void reposition(); - abstract boolean isVisible(); - abstract void dispose(); -} \ No newline at end of file + void reposition(); + boolean isVisible(); + void dispose(); +} diff --git a/src/main/java/io/github/arrayv/frames/ArrayFrame.java b/src/main/java/io/github/arrayv/frames/ArrayFrame.java new file mode 100644 index 00000000..c382b123 --- /dev/null +++ b/src/main/java/io/github/arrayv/frames/ArrayFrame.java @@ -0,0 +1,310 @@ +package io.github.arrayv.frames; + +import io.github.arrayv.main.ArrayManager; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JEnhancedOptionPane; +import io.github.arrayv.utils.Highlights; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.Hashtable; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class ArrayFrame extends javax.swing.JFrame { + private static final long serialVersionUID = 1L; + + private final int[] array; + + private final ArrayManager arrayManager; + private final ArrayVisualizer arrayVisualizer; + private final Highlights Highlights; + private final JFrame frame; + private final UtilFrame utilFrame; + + private boolean lockToPow2; + + public ArrayFrame(int[] array, ArrayVisualizer arrayVisualizer) { + this.array = array; + + this.arrayVisualizer = arrayVisualizer; + this.arrayManager = arrayVisualizer.getArrayManager(); + + this.Highlights = arrayVisualizer.getHighlights(); + this.frame = arrayVisualizer.getMainWindow(); + this.utilFrame = arrayVisualizer.getUtilFrame(); + + setUndecorated(true); + initComponents(); + setBounds( + Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth(), frame.getX() + frame.getWidth()), + frame.getY() + 29, + getWidth(), + arrayVisualizer.getUtilFrame().getHeight() + ); + setAlwaysOnTop(false); + setVisible(true); + } + + public void reposition(){ + toFront(); + setLocation(Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth() - utilFrame.getWidth(), frame.getX() + frame.getWidth()), frame.getY() + 29); + } + + public void setLengthSlider(int length) { + boolean mutable = arrayManager.isLengthMutable(); + arrayManager.toggleMutableLength(true); + jSlider1.setValue(calculateSliderValue(length)); + arrayManager.toggleMutableLength(mutable); + } + + public void setUniqueSlider(int length) { + boolean mutable = arrayManager.isLengthMutable(); + arrayManager.toggleMutableLength(true); + jSlider2.setValue(calculateSliderValue(length)); + arrayManager.toggleMutableLength(mutable); + } + + private int getSomethingSize(String title, String message) { + String input = JEnhancedOptionPane.showInputDialog(title, message, new Object[] {"Ok", "Cancel"}); + //noinspection DataFlowIssue + int integer = Integer.parseInt(input); + return Math.abs(integer); + } + + private int calculateLength(int sliderValue) { + return (int)Math.pow(2, sliderValue / 100000.0); + } + + private int calculateSliderValue(int length) { + return (int)Math.ceil(Math.log(length) / Math.log(2) * 100000); + } + + // //GEN-BEGIN:initComponents + private void initComponents() { + KeyListener kListener = new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { + } + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) + lockToPow2 = true; + } + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) + lockToPow2 = false; + } + }; + this.addKeyListener(kListener); + + int usePower = ArrayVisualizer.getMaxLengthPower() * 100000; + int useDefault = Math.min(1100000, usePower); + // Variables declaration - do not modify//GEN-BEGIN:variables + JLabel jLabel1 = new JLabel(); + JLabel jLabel2 = new JLabel(); + this.jSlider1 = new javax.swing.JSlider(SwingConstants.VERTICAL, 100000, usePower, useDefault); + this.jSlider2 = new javax.swing.JSlider(SwingConstants.VERTICAL, 100000, usePower, useDefault); + + jLabel1.setText("Array Size"); + jLabel2.setText("Unique Elements"); + + setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); + + Hashtable labels = new Hashtable<>(); + int pow = 1; + int value = arrayVisualizer.getMinimumLength(); + while (value <= arrayVisualizer.getMaximumLength()) { + labels.put(pow * 100000, new JLabel(Integer.toString(value))); + pow += 1; + value *= 2; + } + + jSlider1.setMajorTickSpacing(100000); + jSlider1.setLabelTable(labels); + jSlider1.setPaintLabels(true); + jSlider1.setPaintTicks(true); + //jSlider.setSnapToTicks(true); + jSlider1.addChangeListener(event -> { + if (arrayManager.isLengthMutable()) { + int value1 = jSlider1.getValue(); + if (lockToPow2) { + value1 = (int)(Math.round(value1 / 100000.0) * 100000); + jSlider1.setValue(value1); + } + int oldValue1 = calculateSliderValue(arrayVisualizer.getCurrentLength()); + arrayVisualizer.setCurrentLength(calculateLength(value1)); + // double mult = (double)jSlider2.getValue() / (double)oldValue1; + double divver = (double)oldValue1 / (double)jSlider2.getValue(); + jSlider2.setValue((int)(value1 / divver)); + //ArrayVisualizer.setEqualItems((int) Math.pow(2, jSlider.getValue())); + arrayManager.initializeArray(array); + } else { + int currentLength = arrayVisualizer.getCurrentLength(); + jSlider1.setValue(calculateSliderValue(currentLength)); + } + //if (ArrayVisualizer.getVisualStyles() == visuals.VisualStyles.CIRCULAR && jSlider1.getValue() == 1) jSlider1.setValue(2); + + Highlights.clearAllMarks(); + }); + jSlider1.addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent event) { + if (event.getClickCount() == 2) { + int newSize = 0; + try { + newSize = getSomethingSize("Array Size", "Enter new array size:"); + } catch (Exception ignored) { + } + if (newSize >= 2) { + jSlider1.setValue(calculateSliderValue(newSize)); + arrayVisualizer.setCurrentLength(newSize); + arrayManager.initializeArray(array); + } + } + } + @Override + public void mousePressed(MouseEvent e) { + } + @Override + public void mouseReleased(MouseEvent e) { + } + @Override + public void mouseEntered(MouseEvent e) { + } + @Override + public void mouseExited(MouseEvent e) { + } + }); + jSlider1.addKeyListener(kListener); + + jSlider2.setMajorTickSpacing(100000); + jSlider2.setLabelTable(labels); + jSlider2.setPaintLabels(true); + jSlider2.setPaintTicks(true); + //jSlider2.setSnapToTicks(true); + jSlider2.addChangeListener(event -> { + if (arrayManager.isLengthMutable()) { + if (jSlider2.getValue() > jSlider1.getValue()) { + jSlider2.setValue(jSlider1.getValue()); + } else { + int value12 = jSlider2.getValue(); + if (lockToPow2) { + value12 = (int)(Math.round(value12 / 100000.0) * 100000); + jSlider2.setValue(value12); + } + arrayVisualizer.setUniqueItems(calculateLength(value12)); + //ArrayVisualizer.setEqualItems((int) Math.pow(2, jSlider2.getValue())); + arrayManager.initializeArray(array); + } + } else { + int currentItems = arrayVisualizer.getUniqueItems(); + jSlider2.setValue(calculateSliderValue(currentItems)); + } + + Highlights.clearAllMarks(); + }); + jSlider2.addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent event) { + if (event.getClickCount() == 2) { + int newSize = 0; + try { + newSize = getSomethingSize("Unique Elements", "Enter new number of unique elements:"); + } catch (Exception ignored) { + } + if (newSize >= 2) { + jSlider2.setValue(calculateSliderValue(newSize)); + arrayVisualizer.setUniqueItems(newSize); + arrayManager.initializeArray(array); + } + } + } + @Override + public void mousePressed(MouseEvent e) { + } + @Override + public void mouseReleased(MouseEvent e) { + } + @Override + public void mouseEntered(MouseEvent e) { + } + @Override + public void mouseExited(MouseEvent e) { + } + }); + jSlider2.addKeyListener(kListener); + + final int sliderGap = UIManager.getLookAndFeel().getClass().getName().equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel") ? 250 : 175; + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) + .addComponent(jLabel1) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) + .addComponent(this.jSlider1) + .addGap(0, 10, Short.MAX_VALUE)))) + .addGap(sliderGap, sliderGap, sliderGap) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + .addComponent(jLabel2) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + .addComponent(this.jSlider2) + .addGap(0, 10, Short.MAX_VALUE)))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) + .addGroup(layout.createSequentialGroup() + .addGap(5, 5, 5) + .addComponent(jLabel1) + .addGap(5, 5, 5) + .addComponent(this.jSlider1, utilFrame.getHeight() - 26, utilFrame.getHeight() - 26, utilFrame.getHeight() - 26)) + .addGroup(layout.createSequentialGroup() + .addGap(5, 5, 5) + .addComponent(jLabel2) + .addGap(5, 5, 5) + .addComponent(this.jSlider2, utilFrame.getHeight() - 26, utilFrame.getHeight() - 26, utilFrame.getHeight() - 26)) + ); + + pack(); + }// //GEN-END:initComponents + + private javax.swing.JSlider jSlider1; + private javax.swing.JSlider jSlider2; + // End of variables declaration//GEN-END:variables +} diff --git a/src/main/java/io/github/arrayv/frames/ImageFrame.java b/src/main/java/io/github/arrayv/frames/ImageFrame.java new file mode 100644 index 00000000..a086d84b --- /dev/null +++ b/src/main/java/io/github/arrayv/frames/ImageFrame.java @@ -0,0 +1,122 @@ +package io.github.arrayv.frames; + +/* +MIT License + +Copyright (c) 2020 Musicombo +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import io.github.arrayv.visuals.image.CustomImage; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.image.BufferedImage; + +public class ImageFrame extends JFrame { + private static ImageFrame defaultFrame; + + /** + * + */ + private static final long serialVersionUID = 1L; + + private final JLabel lblNewLabel2; + + /** + * Create the frame. + */ + public ImageFrame(CustomImage visual) { + ImageFrame.defaultFrame = this; + + setBounds(100, 100, 450, 300); + JPanel contentPane = new JPanel(); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + GridBagLayout gblContentPane = new GridBagLayout(); + gblContentPane.columnWidths = new int[]{0, 0, 0}; + gblContentPane.rowHeights = new int[]{0, 32, 0, 0, 0}; + gblContentPane.columnWeights = new double[]{1.0, 1.0, Double.MIN_VALUE}; + gblContentPane.rowWeights = new double[]{0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE}; + contentPane.setLayout(gblContentPane); + + JLabel lblNewLabel = new JLabel("Current image:"); + GridBagConstraints gbcLblNewLabel = new GridBagConstraints(); + gbcLblNewLabel.anchor = GridBagConstraints.EAST; + gbcLblNewLabel.insets = new Insets(0, 0, 5, 5); + gbcLblNewLabel.gridx = 0; + gbcLblNewLabel.gridy = 0; + contentPane.add(lblNewLabel, gbcLblNewLabel); + + JLabel lblNewLabel1 = new JLabel(visual.getCurrentImageName()); + GridBagConstraints gbcLblNewLabel1 = new GridBagConstraints(); + gbcLblNewLabel1.anchor = GridBagConstraints.WEST; + gbcLblNewLabel1.insets = new Insets(0, 0, 5, 0); + gbcLblNewLabel1.gridx = 1; + gbcLblNewLabel1.gridy = 0; + contentPane.add(lblNewLabel1, gbcLblNewLabel1); + + this.lblNewLabel2 = new JLabel(" "); + lblNewLabel2.setHorizontalAlignment(SwingConstants.CENTER); + GridBagConstraints gbcLblNewLabel2 = new GridBagConstraints(); + gbcLblNewLabel2.fill = GridBagConstraints.BOTH; + gbcLblNewLabel2.insets = new Insets(0, 0, 5, 0); + gbcLblNewLabel2.gridwidth = 2; + gbcLblNewLabel2.gridx = 0; + gbcLblNewLabel2.gridy = 1; + contentPane.add(this.lblNewLabel2, gbcLblNewLabel2); + + JButton btnNewButton = new JButton("Load default artwork"); + btnNewButton.addActionListener(e -> visual.loadDefaultArtwork(ImageFrame.this)); + GridBagConstraints gbcBtnNewButton = new GridBagConstraints(); + gbcBtnNewButton.fill = GridBagConstraints.VERTICAL; + gbcBtnNewButton.gridheight = 2; + gbcBtnNewButton.anchor = GridBagConstraints.EAST; + gbcBtnNewButton.insets = new Insets(0, 0, 5, 5); + gbcBtnNewButton.gridx = 0; + gbcBtnNewButton.gridy = 2; + contentPane.add(btnNewButton, gbcBtnNewButton); + + JButton btnNewButton1 = new JButton("Choose image..."); + btnNewButton1.addActionListener(e -> visual.loadCustomImage(ImageFrame.this)); + GridBagConstraints gbcBtnNewButton1 = new GridBagConstraints(); + gbcBtnNewButton1.fill = GridBagConstraints.VERTICAL; + gbcBtnNewButton1.gridheight = 2; + gbcBtnNewButton1.insets = new Insets(0, 0, 5, 0); + gbcBtnNewButton1.anchor = GridBagConstraints.WEST; + gbcBtnNewButton1.gridx = 1; + gbcBtnNewButton1.gridy = 2; + contentPane.add(btnNewButton1, gbcBtnNewButton1); + } + + public void updatePreview(CustomImage visual) { + BufferedImage img = visual.getImage(); + Image scaledImg = img.getScaledInstance((int) (this.lblNewLabel2.getWidth() * 0.75), this.lblNewLabel2.getHeight(), Image.SCALE_SMOOTH); + ImageIcon imageIcon = new ImageIcon(scaledImg); + this.lblNewLabel2.setIcon(imageIcon); + this.lblNewLabel2.setText(""); + } + + public static ImageFrame getDefaultFrame() { + return defaultFrame; + } +} diff --git a/src/main/java/io/github/arrayv/frames/SoundFrame.java b/src/main/java/io/github/arrayv/frames/SoundFrame.java new file mode 100644 index 00000000..54163ee3 --- /dev/null +++ b/src/main/java/io/github/arrayv/frames/SoundFrame.java @@ -0,0 +1,134 @@ +package io.github.arrayv.frames; + +/* +MIT License + +Copyright (c) 2020 Musicombo +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import io.github.arrayv.utils.Sounds; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; + +public class SoundFrame extends JFrame { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private int instrumentChoice; + + /** + * Create the frame. + */ + public SoundFrame(Sounds sounds) { + this.instrumentChoice = sounds.getInstrumentChoice(); + + setBounds(100, 100, 450, 300); + JPanel contentPane = new JPanel(); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + GridBagLayout gblContentPane = new GridBagLayout(); + gblContentPane.columnWidths = new int[]{0, 0, 0}; + gblContentPane.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0}; + gblContentPane.columnWeights = new double[]{1.0, 1.0, Double.MIN_VALUE}; + gblContentPane.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, Double.MIN_VALUE}; + contentPane.setLayout(gblContentPane); + + JLabel lblNewLabel = new JLabel("Current soundbank:"); + GridBagConstraints gbcLblNewLabel = new GridBagConstraints(); + gbcLblNewLabel.insets = new Insets(0, 0, 5, 5); + gbcLblNewLabel.gridx = 0; + gbcLblNewLabel.gridy = 0; + contentPane.add(lblNewLabel, gbcLblNewLabel); + + JButton btnNewButton = new JButton("Default sounds"); + btnNewButton.addActionListener(e -> sounds.selectDefaultSoundbank(SoundFrame.this)); + GridBagConstraints gbcBtnNewButton = new GridBagConstraints(); + gbcBtnNewButton.insets = new Insets(0, 0, 5, 0); + gbcBtnNewButton.gridx = 1; + gbcBtnNewButton.gridy = 0; + contentPane.add(btnNewButton, gbcBtnNewButton); + + JLabel lblNewLabel1 = new JLabel(sounds.getSelectedSoundbank()); + GridBagConstraints gbcLblNewLabel1 = new GridBagConstraints(); + gbcLblNewLabel1.insets = new Insets(0, 0, 5, 5); + gbcLblNewLabel1.gridx = 0; + gbcLblNewLabel1.gridy = 1; + contentPane.add(lblNewLabel1, gbcLblNewLabel1); + + JButton btnNewButton1 = new JButton("Choose soundbank..."); + btnNewButton1.addActionListener(e -> sounds.selectCustomSoundbank(SoundFrame.this)); + GridBagConstraints gbcBtnNewButton1 = new GridBagConstraints(); + gbcBtnNewButton1.insets = new Insets(0, 0, 5, 0); + gbcBtnNewButton1.gridx = 1; + gbcBtnNewButton1.gridy = 1; + contentPane.add(btnNewButton1, gbcBtnNewButton1); + + JSeparator separator = new JSeparator(); + GridBagConstraints gbcSeparator = new GridBagConstraints(); + gbcSeparator.insets = new Insets(0, 0, 5, 5); + gbcSeparator.gridx = 0; + gbcSeparator.gridy = 2; + contentPane.add(separator, gbcSeparator); + + JLabel lblNewLabel2 = new JLabel("Choose a sample / instrument:"); + GridBagConstraints gbcLblNewLabel2 = new GridBagConstraints(); + gbcLblNewLabel2.anchor = GridBagConstraints.WEST; + gbcLblNewLabel2.insets = new Insets(0, 0, 5, 5); + gbcLblNewLabel2.gridx = 0; + gbcLblNewLabel2.gridy = 3; + contentPane.add(lblNewLabel2, gbcLblNewLabel2); + + JScrollPane scrollPane = new JScrollPane(); + GridBagConstraints gbcScrollPane = new GridBagConstraints(); + gbcScrollPane.insets = new Insets(0, 0, 5, 0); + gbcScrollPane.gridwidth = 2; + gbcScrollPane.fill = GridBagConstraints.BOTH; + gbcScrollPane.gridx = 0; + gbcScrollPane.gridy = 5; + contentPane.add(scrollPane, gbcScrollPane); + + JList list = new JList<>(); + scrollPane.setViewportView(list); + list.setListData(sounds.getInstrumentList()); + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setSelectedIndex(this.instrumentChoice); + list.addListSelectionListener(e -> { + if (SoundFrame.this.instrumentChoice != list.getSelectedIndex()) { + SoundFrame.this.instrumentChoice = list.getSelectedIndex(); + sounds.testInstrument(SoundFrame.this.instrumentChoice); + } + }); + + JButton btnNewButton2 = new JButton("Select sound"); + btnNewButton2.addActionListener(e -> sounds.setInstrumentChoice(SoundFrame.this.instrumentChoice)); + GridBagConstraints gbcBtnNewButton2 = new GridBagConstraints(); + gbcBtnNewButton2.anchor = GridBagConstraints.EAST; + gbcBtnNewButton2.gridx = 1; + gbcBtnNewButton2.gridy = 6; + contentPane.add(btnNewButton2, gbcBtnNewButton2); + } +} diff --git a/src/main/java/io/github/arrayv/frames/UtilFrame.java b/src/main/java/io/github/arrayv/frames/UtilFrame.java new file mode 100644 index 00000000..e808afd3 --- /dev/null +++ b/src/main/java/io/github/arrayv/frames/UtilFrame.java @@ -0,0 +1,508 @@ +package io.github.arrayv.frames; + +import io.github.arrayv.dialogs.RunScriptDialog; +import io.github.arrayv.main.ArrayManager; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.prompts.ShufflePrompt; +import io.github.arrayv.prompts.SortPrompt; +import io.github.arrayv.prompts.ViewPrompt; +import io.github.arrayv.utils.Delays; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Sounds; +import io.github.arrayv.utils.Timer; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.IOException; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class UtilFrame extends javax.swing.JFrame { + private static final long serialVersionUID = 1L; + + private boolean jCheckBox9WarningShown = true; //set to false to enable warning + + private final int[] array; + + private final ArrayManager arrayManager; + private final ArrayVisualizer arrayVisualizer; + private final Delays Delays; + private final Highlights Highlights; + private final JFrame frame; + private final Timer Timer; + private final Sounds Sounds; + + private AppFrame abstractFrame; + + public UtilFrame(int[] array, ArrayVisualizer arrayVisualizer) { + this.array = array; + + this.arrayVisualizer = arrayVisualizer; + this.arrayManager = arrayVisualizer.getArrayManager(); + + this.Delays = arrayVisualizer.getDelays(); + this.frame = arrayVisualizer.getMainWindow(); + this.Highlights = arrayVisualizer.getHighlights(); + this.Timer = arrayVisualizer.getTimer(); + this.Sounds = arrayVisualizer.getSounds(); + + setUndecorated(true); + initComponents(); + setLocation(Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth(), frame.getX() + frame.getWidth()), frame.getY() + 29); + setAlwaysOnTop(false); + setVisible(true); + } + + public void reposition(ArrayFrame af){ + toFront(); + setLocation(Math.min((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - getWidth(), frame.getX() + frame.getWidth() + af.getWidth()), frame.getY() + 29); + if (this.abstractFrame != null && abstractFrame.isVisible()) + abstractFrame.reposition(); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + // //GEN-BEGIN:initComponents + private void initComponents() { + // Variables declaration - do not modify//GEN-BEGIN:variables + javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); + this.jButton1 = new javax.swing.JButton(); + this.jButton2 = new javax.swing.JButton(); + JButton jButton3 = new JButton(); + this.jCheckBox1 = new javax.swing.JCheckBox(); + this.jCheckBox2 = new javax.swing.JCheckBox(); + JButton jButton4 = new JButton(); + JButton jButton7 = new JButton(); + this.jCheckBox3 = new javax.swing.JCheckBox(); + this.jCheckBox4 = new javax.swing.JCheckBox(); + JButton jButton5 = new JButton(); + this.jCheckBox5 = new javax.swing.JCheckBox(); + this.jButton6 = new javax.swing.JButton(); + this.jCheckBox6 = new javax.swing.JCheckBox(); + this.jCheckBox7 = new javax.swing.JCheckBox(); + this.jCheckBox8 = new javax.swing.JCheckBox(); + this.jCheckBox9 = new javax.swing.JCheckBox(); + this.jComboBox1 = new javax.swing.JComboBox(); + + jLabel1.setText("Settings"); + + setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); + + jButton1ResetText(); + jButton1.addActionListener(evt -> jButton1ActionPerformed()); + + jButton2ResetText(); + jButton2.addActionListener(evt -> jButton2ActionPerformed()); + + jButton3.setText("Change Speed"); + jButton3.addActionListener(evt -> jButton3ActionPerformed()); + + jButton4.setText("Cancel Delays"); + jButton4.addActionListener(evt -> jButton4ActionPerformed()); + + jButton7.setText("Cancel Sort"); + jButton7.addActionListener(evt -> jButton7ActionPerformed()); + + jCheckBox1.setSelected(true); + jCheckBox1.setText("Show Shuffle"); + jCheckBox1.addActionListener(evt -> jCheckBox1ActionPerformed()); + + jCheckBox2.setSelected(false); + jCheckBox2.setText("Linked Dots"); + jCheckBox2.addActionListener(evt -> jCheckBox2ActionPerformed()); + + jCheckBox3.setSelected(true); + jCheckBox3.setText("End Sweep Anim"); + jCheckBox3.addActionListener(evt -> jCheckBox3ActionPerformed()); + + jCheckBox4.setSelected(true); + jCheckBox4.setText("Calc Real Time"); + jCheckBox4.addActionListener(evt -> jCheckBox4ActionPerformed()); + + jButton5.setText("Clear Stats"); + jButton5.addActionListener(evt -> jButton5ActionPerformed()); + + jCheckBox5.setSelected(false); + jCheckBox5.setText("Softer Sounds"); + jCheckBox5.addActionListener(evt -> jCheckBox5ActionPerformed()); + + jButton6ResetText(); + jButton6.addActionListener(evt -> jButton6ActionPerformed()); + + jCheckBox6.setSelected(true); + jCheckBox6.setText("Display Stats"); + jCheckBox6.addActionListener(evt -> jCheckBox6ActionPerformed()); + + jCheckBox7.setSelected(true); + jCheckBox7.setText("Enable Sounds"); + jCheckBox7.addActionListener(evt -> jCheckBox7ActionPerformed()); + + jCheckBox8.setSelected(false); + jCheckBox8.setText("Enable Color"); + jCheckBox8.addActionListener(evt -> jCheckBox8ActionPerformed()); + + jCheckBox9.setSelected(false); + jCheckBox9.setText("Show Aux Arrays"); + jCheckBox9.addActionListener(evt -> jCheckBox9ActionPerformed()); + + jComboBox1.setModel(new DefaultComboBoxModel<>(new String[] { + "Sorting", + "AntiQSort", + "Stability Check", + "Sorting Networks", + "Reversed Sorting" + // "*Simple* Benchmarking" + })); + jComboBox1.addActionListener(evt -> jComboBox1ActionPerformed()); + if (arrayVisualizer.isDisabledStabilityCheck()) { + jComboBox1.removeItem("Stability Check"); + } + + JButton runScriptButton = new JButton("Run Script"); + runScriptButton.addActionListener(e -> { + File scriptFile = new RunScriptDialog().getFile(); + if (scriptFile == null) return; + try { + arrayVisualizer.getScriptManager().runInThread(scriptFile); + } catch (IOException e1) { + JErrorPane.invokeErrorMessage(e1, "Run Script"); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) + .addComponent(jLabel1) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) + .addComponent(this.jCheckBox1) + .addComponent(this.jCheckBox2) + .addComponent(this.jCheckBox3) + .addComponent(this.jCheckBox4) + .addComponent(this.jCheckBox6) + .addComponent(this.jCheckBox7) + .addComponent(this.jCheckBox8) + .addComponent(this.jCheckBox9) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + .addComponent(this.jCheckBox5) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jButton7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(this.jButton6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButton5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButton4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButton3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(this.jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(this.jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(runScriptButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(this.jComboBox1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))) + .addGap(0, 10, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) + .addGroup(layout.createSequentialGroup() + .addGap(5, 5, 5) + .addComponent(jLabel1) + .addGap(7, 7, 7) + .addComponent(this.jComboBox1) + .addGap(10, 10, 10) + .addComponent(this.jButton2) + .addGap(5, 5, 5) + .addComponent(this.jCheckBox2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(this.jCheckBox8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(this.jCheckBox9) + .addGap(7, 7, 7) + .addComponent(jButton3) + .addGap(12, 12, 12) + .addComponent(this.jButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton7) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(this.jButton6) + .addGap(7, 7, 7) + .addComponent(this.jCheckBox1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(this.jCheckBox7) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(this.jCheckBox5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(this.jCheckBox3) + .addGap(8, 8, 8) + .addComponent(jButton5) + .addGap(5, 5, 5) + .addComponent(this.jCheckBox6) + .addComponent(this.jCheckBox4) + .addGap(5, 5, 5) + .addComponent(runScriptButton) + .addGap(8, 8, 8)) + ); + + pack(); + }// //GEN-END:initComponents + + public void setMode(String mode) { + this.jComboBox1.setSelectedItem(mode); + } + + private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + //CHANGE SORT + if (this.abstractFrame != null && abstractFrame.isVisible()){ + boolean tmp = this.abstractFrame instanceof SortPrompt; + abstractFrame.dispose(); + jButton1ResetText(); + if (tmp) + return; + } + this.abstractFrame = new SortPrompt(this.array, this.arrayVisualizer, this.frame, this); + jButton1.setText("Close"); + jButton2ResetText(); + jButton6ResetText(); + }//GEN-LAST:event_jButton1ActionPerformed + + public void jButton1ResetText() { + jButton1.setText("Choose Sort"); + } + + public void jButton1Enable() { + jButton1.setEnabled(true); + } + + public void jButton1Disable() { + jButton1.setEnabled(false); + } + + private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton2ActionPerformed + //CHANGE VIEW + if (this.abstractFrame != null && abstractFrame.isVisible()){ + boolean tmp = this.abstractFrame instanceof ViewPrompt; + jButton2ResetText(); + abstractFrame.dispose(); + if (tmp) + return; + } + this.abstractFrame = new ViewPrompt(this.arrayVisualizer, this.frame, this); + jButton2.setText("Close"); + jButton1ResetText(); + jButton6ResetText(); + }//GEN-LAST:event_jButton2ActionPerformed + + public void jButton2ResetText() { + jButton2.setText("Visual Style"); + } + + private void jButton3ActionPerformed() {//GEN-FIRST:event_jButton3ActionPerformed + boolean speedPromptAllowed; + + if (this.abstractFrame == null) { + speedPromptAllowed = true; + } else { + speedPromptAllowed = !this.abstractFrame.isVisible(); + } + + if (speedPromptAllowed) { + boolean showPrompt = true; + while (showPrompt) { + try { + double oldRatio = Delays.getSleepRatio(); + String userInput = JOptionPane.showInputDialog(null, "Modify the visual's speed below (Ex. 10 = Ten times faster)", oldRatio); + if (userInput != null) { + double newRatio = Double.parseDouble(userInput); + if (newRatio == 0) throw new Exception("Divide by zero"); + Delays.setSleepRatio(newRatio); + Delays.updateCurrentDelay(oldRatio, Delays.getSleepRatio()); + } + showPrompt = false; + } catch (Exception e) { + JOptionPane.showMessageDialog(null, "Not a number! (" + e.getMessage() + ")", "Error", JOptionPane.ERROR_MESSAGE); + } + } + } + }//GEN-LAST:event_jButton3ActionPerformed + + private void jCheckBox1ActionPerformed() {//GEN-FIRST:event_jCheckBox2ActionPerformed + arrayVisualizer.toggleShuffleAnimation(jCheckBox1.isSelected()); + }//GEN-LAST:event_jCheckBox1ActionPerformed + + private void jCheckBox2ActionPerformed() {//GEN-FIRST:event_jCheckBox3ActionPerformed + arrayVisualizer.toggleLinkedDots(jCheckBox2.isSelected()); + }//GEN-LAST:event_jCheckBox2ActionPerformed + + private void jCheckBox3ActionPerformed() {//GEN-FIRST:event_jCheckBox3ActionPerformed + Highlights.toggleFancyFinishes(jCheckBox3.isSelected()); + }//GEN-LAST:event_jCheckBox3ActionPerformed + + private void jButton4ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + Delays.changeSkipped(true); + }//GEN-LAST:event_jButton4ActionPerformed + + private void jButton7ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + arrayVisualizer.setCanceled(true); + }//GEN-LAST:event_jButton4ActionPerformed + + private void jCheckBox4ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + Timer.toggleRealTimer(jCheckBox4.isSelected()); + }//GEN-LAST:event_jCheckBox4ActionPerformed + + private void jButton5ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + arrayVisualizer.resetAllStatistics(); + }//GEN-LAST:event_jButton6ActionPerformed + + private void jCheckBox5ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + Sounds.setSofterSounds(jCheckBox5.isSelected()); + }//GEN-LAST:event_jCheckBox5ActionPerformed + + private void jButton6ActionPerformed() {//GEN-FIRST:event_jButton2ActionPerformed + //CHANGE SIZE + if (this.abstractFrame != null && abstractFrame.isVisible()){ + boolean tmp = this.abstractFrame instanceof ShufflePrompt; + abstractFrame.dispose(); + jButton6ResetText(); + if (tmp) + return; + } + this.abstractFrame = new ShufflePrompt(this.arrayManager, this.frame, this); + jButton6.setText("Close"); + jButton1ResetText(); + jButton2ResetText(); + }//GEN-LAST:event_jButton7ActionPerformed + + public void jButton6ResetText() { + jButton6.setText("Choose Shuffle"); + } + + private void jCheckBox6ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + arrayVisualizer.toggleStatistics(jCheckBox6.isSelected()); + }//GEN-LAST:event_jCheckBox6ActionPerformed + + private void jCheckBox7ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + Sounds.toggleSounds(jCheckBox7.isSelected()); + }//GEN-LAST:event_jCheckBox7ActionPerformed + + private void jCheckBox8ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + arrayVisualizer.toggleColor(jCheckBox8.isSelected()); + }//GEN-LAST:event_jCheckBox8ActionPerformed + + private void jCheckBox9ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + if (!jCheckBox9WarningShown && jCheckBox9.isSelected()) { + if (JOptionPane.showConfirmDialog( + null, + "This will cause some sorts have extreme strobing/flashing." + + "
It is highly recommended to NOT enable the \"" + jCheckBox9.getText() + "\" option if you may be at risk of seizures." + + "
Are you sure you wish to enable this option?", + "Seizure Warning", + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE + ) == JOptionPane.NO_OPTION) { + jCheckBox9.setSelected(false); + return; + } + jCheckBox9WarningShown = true; + } + arrayVisualizer.toggleExternalArrays(jCheckBox9.isSelected()); + }//GEN-LAST:event_jCheckBox8ActionPerformed + + private void jComboBox1ActionPerformed() {//GEN-FIRST:event_jButton4ActionPerformed + //noinspection DataFlowIssue + switch ((String)jComboBox1.getSelectedItem()) { + case "Sorting": + if (arrayVisualizer.enableBenchmarking(false)) + break; + jButton6.setEnabled(true); + arrayVisualizer.setComparator(0); + break; + + case "AntiQSort": + if (arrayVisualizer.enableBenchmarking(false)) + break; + if (this.abstractFrame != null && abstractFrame.isVisible()){ + abstractFrame.dispose(); + jButton6ResetText(); + } + jButton6.setEnabled(false); + arrayVisualizer.setComparator(1); + break; + + case "Stability Check": + if (arrayVisualizer.enableBenchmarking(false)) + break; + jButton6.setEnabled(true); + arrayVisualizer.setComparator(2); + break; + + case "Sorting Networks": + if (arrayVisualizer.enableBenchmarking(false)) + break; + jButton6.setEnabled(true); + arrayVisualizer.setComparator(4); + if (arrayVisualizer.getCurrentLength() > 1024) { + JOptionPane.showMessageDialog( + null, + "Large sorting networks can take a long time (and high RAM usage) to visualize.\n" + + "A length of 1024 or less is recommended.", + "Sorting Network Visualizer", JOptionPane.WARNING_MESSAGE + ); + } + break; + + case "Reversed Sorting": + if (arrayVisualizer.enableBenchmarking(false)) + break; + jButton6.setEnabled(true); + arrayVisualizer.setComparator(3); + break; + + case "*Simple* Benchmarking": + jButton6.setEnabled(true); + arrayVisualizer.setComparator(0); + arrayVisualizer.enableBenchmarking(true); + break; + } + }//GEN-LAST:event_jCheckBox8ActionPerformed + + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JButton jButton6; + private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JCheckBox jCheckBox2; + private javax.swing.JCheckBox jCheckBox3; + private javax.swing.JCheckBox jCheckBox4; + private javax.swing.JCheckBox jCheckBox5; + private javax.swing.JCheckBox jCheckBox6; + private javax.swing.JCheckBox jCheckBox7; + private javax.swing.JCheckBox jCheckBox8; + private javax.swing.JCheckBox jCheckBox9; + @SuppressWarnings("rawtypes") + private javax.swing.JComboBox jComboBox1; +} diff --git a/src/main/java/io/github/arrayv/groovyapi/ArrayVEventHandler.java b/src/main/java/io/github/arrayv/groovyapi/ArrayVEventHandler.java new file mode 100644 index 00000000..65180b5d --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/ArrayVEventHandler.java @@ -0,0 +1,94 @@ +package io.github.arrayv.groovyapi; + +import io.github.arrayv.main.ArrayVisualizer; + +/** + * Represents an event handler. This is basically an {@link EventType}–{@link Runnable} pair with + * special {@link #register} and {@link #unregister()} methods. + */ +public final class ArrayVEventHandler { + /** + * The type of event. Event handlers are registered under these types and called when the type is called. + */ + public enum EventType { + /** + * Run when all scripts embedded in ArrayV and located in the scripts folder are loaded. + * This is useful when you want to wait till all scripts are loaded before invoking some + * sort of action dependent on other scripts. + */ + DEFAULT_SCRIPTS_INSTALLED, + + /** + * This is run when the main thread has finished setting everything up and is about to terminate. + */ + ARRAYV_FULLY_LOADED + } + + private final EventType eventType; + private final Runnable callback; + + /** + * Construct an event handler object + * @param eventType {@link #getEventType} + * @param cb {@link #getCallback} + */ + public ArrayVEventHandler(EventType eventType, Runnable cb) { + this.eventType = eventType; + this.callback = cb; + } + + /** + * The type of the event to handle + * @return The event type of this wrapper + */ + public EventType getEventType() { + return eventType; + } + + /** + * The event callback + * @return The callback of the wrapper + */ + public Runnable getCallback() { + return callback; + } + + /** + * Run the callback. This is generally for use by {@link ScriptManager#runEventHandlers} + * @see ScriptManager#runEventHandlers + */ + public void handle() { + callback.run(); + } + + /** + * Register this event handler. This is equivalent to (but preferred over) + * {@code arrayv.scriptManager.registerEventHandlers(this)}. + * @see ScriptManager#registerEventHandlers + */ + public void register() { + ArrayVisualizer.getInstance().getScriptManager().registerEventHandlers(this); + } + + /** + * Unregister this event handler. This is equivalent to (but preferred over) + * {@code arrayv.scriptManager.unregisterEventHandlers(this)}. + * @see ScriptManager#unregisterEventHandlers + */ + public void unregister() { + ArrayVisualizer.getInstance().getScriptManager().unregisterEventHandlers(this); + } + + @Override + public int hashCode() { + return 31 * eventType.hashCode() + callback.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof ArrayVEventHandler)) return false; + ArrayVEventHandler other = (ArrayVEventHandler)o; + return eventType.equals(other.eventType) && callback.equals(other.callback); + } +} diff --git a/src/main/java/io/github/arrayv/groovyapi/ArrayVScript.java b/src/main/java/io/github/arrayv/groovyapi/ArrayVScript.java new file mode 100644 index 00000000..f2c5325a --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/ArrayVScript.java @@ -0,0 +1,28 @@ +package io.github.arrayv.groovyapi; + +import groovy.lang.MissingPropertyException; +import groovy.lang.Script; +import io.github.arrayv.sortdata.SortInfo; + +/** + * This is the base class for all Groovy scripts in ArrayV. It is primarily used for accessing sorts + * directly using their internal name, instead of having to use {@link GroovyLocals#getSort(String)}. + * This class may be extended in the future. + */ +public abstract class ArrayVScript extends Script { + /** + * Accesses sorts by internal name when the specified property isn't found. + */ + @Override + public Object getProperty(String property) { + try { + return super.getProperty(property); + } catch (MissingPropertyException mpe) { + SortInfo sort = GroovyLocals.getSort(property); + if (sort == null) { + throw new MissingPropertyException(property, getClass()); + } + return sort; + } + } +} diff --git a/src/main/java/io/github/arrayv/groovyapi/GroovyLocals.java b/src/main/java/io/github/arrayv/groovyapi/GroovyLocals.java new file mode 100644 index 00000000..e886f4d3 --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/GroovyLocals.java @@ -0,0 +1,377 @@ +package io.github.arrayv.groovyapi; + +import groovy.lang.Closure; +import groovy.lang.DelegatesTo; +import groovy.transform.stc.ClosureParams; +import groovy.transform.stc.FromAbstractTypeMethods; +import io.github.arrayv.groovyapi.ScriptManager.ScriptThread; +import io.github.arrayv.main.ArrayManager; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.prompts.SortPrompt; +import io.github.arrayv.sortdata.SortInfo; +import io.github.arrayv.sortdata.SortNameType; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.utils.Sounds; +import org.codehaus.groovy.runtime.MethodClosure; + +import java.util.Map; + +/** + * This class defines methods and properties directly accessible from within Groovy scripts. + * Methods and properties in this class can be directly named without prefixing them with {@code GroovyLocals.}. + */ +public final class GroovyLocals { + // No instancing! + private GroovyLocals() { + } + + /** + *

Property for the main {@link ArrayVisualizer} instance.

+ * Intended to be used like this (example): + *
+     * println arrayv.sortAnalyzer
+     * 
+ * @return The main {@link ArrayVisualizer} instance + */ + public static ArrayVisualizer getArrayv() { + return ArrayVisualizer.getInstance(); + } + + /** + * Get a sort by its internal name, which is usually the name of the sort class. + * @param internalName The internal name to find the sort by + * @return The sort with this internal name or {@code null} if no sort with the given internal name was found + */ + public static SortInfo getSort(String internalName) { + return getSort(internalName, SortNameType.INTERNAL_NAME); + } + + /** + * Get a sort by name + * @param name The name of the sort + * @param nameType The type of name to search by (such as list name, run name, etc.). + * See {@link SortNameType} for more details + * @return The sort with this name or {@code null} if no sort with the given name and name type was found + */ + public static SortInfo getSort(String name, SortNameType nameType) { + return getArrayv().getSortAnalyzer().getSortByName(nameType, name); + } + + /** + *

Creates (and adds) a new sorting algorithm to this ArrayV instance.

+ * Here's an example: + *
+     * def sortFn(array, length) {
+     *     // Sorting algorithm code here
+     * }
+     *
+     * newSort(this::sortFn) {
+     *     listName "My Custom Sort"
+     *     category "Examples"
+     *     unreasonableLimit 1024
+     * }
+     * 
+ * @param sort The sort method/function/closure to add. + * This closure can follow any of the signatures listed in {@link SortFunctionSignatures} + * @param metadata The closure used to define metadata. + * See above for an example, and {@link SortInfo.Builder} for the list of metadata methods you can use. + * @return The {@link SortInfo} object associated with the newly created algorithm + */ + public static SortInfo newSort( + @ClosureParams( + value = FromAbstractTypeMethods.class, + options = {"io.github.arrayv.groovyapi.GroovyLocals$SortFunctionSignatures"} + ) Closure sort, + @DelegatesTo(SortInfo.Builder.class) Closure metadata + ) { + switch (sort.getMaximumNumberOfParameters()) { + case 2: + case 3: + break; + default: + throw new IllegalArgumentException( + "Illegal number of arguments for Groovy sort function: " + + sort.getMaximumNumberOfParameters() + + ". Must be one of: 2, 3" + ); + } + + SortInfo.Builder builder = SortInfo.builder(); + + // Initialize metadata + metadata = metadata.rehydrate(builder, metadata, metadata); + metadata.setResolveStrategy(Closure.DELEGATE_FIRST); + metadata.call(); + + if (sort instanceof MethodClosure) { + // The method has a name! + builder.internalName(((MethodClosure)sort).getMethod()); + } + + SortInfo[] sortInfo = new SortInfo[1]; + + final class GroovySort extends Sort { + // @checkstyle:off RedundantModifierCheck + // This needs to be public so it can be accessed from reflection/java.lang.invoke + public GroovySort() { + // @checkstyle:on RedundantModifierCheck + super(ArrayVisualizer.getInstance()); + } + + @Override + public void runSort(int[] array, int sortLength, int bucketCount) { + switch (sort.getMaximumNumberOfParameters()) { + case 2: + sort.call(array, sortLength); + break; + case 3: + sort.call(array, sortLength, bucketCount); + break; + } + } + } + builder.instanceSupplier(GroovySort::new); + + return registerSort(sortInfo[0] = builder.build()); + } + + /** + * Registers a sort with the sort list + * @param sort The sort to register + * @return The {@code sort} parameter, but likely with a different id + */ + public static SortInfo registerSort(SortInfo sort) { + sort = getArrayv().getSortAnalyzer().insortSort(sort); + getArrayv().refreshSorts(); + return sort; + } + + /** + * Registers a sort with the sort list + * @param sort The sort instance to convert to a {@link SortInfo} + * @return The registered {@link SortInfo} object + */ + public static SortInfo registerSort(Sort sort) { + return registerSort(new SortInfo(sort)); + } + + /** + * Registers a sort with the sort list + * @param sort The sort class to convert to a {@link SortInfo} + * @return The registered {@link SortInfo} object + */ + public static SortInfo registerSort(Class sort) { + return registerSort(new SortInfo(sort)); + } + + /** + * Prepares to run a sorting algorithm + * @param sort The sorting algorithm to run + * @return A {@link RunSortBuilder} for setting up sort running parameters + */ + public static RunSortBuilder run(SortInfo sort) { + return new RunSortBuilder(null, sort); + } + + /** + * Effectively an alias for {@link #run(SortInfo)}, but designed around a special + * case dealing with TimSort and DualPivotQuickSort, as Groovy loads the java.util classes instead + * @param sort The class to coerce to a {@link SortInfo} using {@code getSort(sort.getSimpleName())} + * @return A {@link RunSortBuilder} for setting up sort running parameters + */ + public static RunSortBuilder run(Class sort) { + return new RunSortBuilder(null, getSort(sort.getSimpleName())); + } + + /** + * Runs a sort, but adds the ability to pass Groovy map arguments, + * e.g.: {@code run(BubbleSort, numbers: 2048, speed: 0.75)} + * @param options Groovy map arguments. See {@link RunSortBuilder} for valid keys + * @param sort The sorting algorithm to run + * @return A {@link RunSortBuilder} for setting up sort running parameters + */ + public static RunSortBuilder run(Map options, SortInfo sort) { + return new RunSortBuilder(options, sort); + } + + /** + * Combination of {@link #run(Class)} and {@link #run(Map, SortInfo)} + * @param options + * @param sort + * @return + */ + public static RunSortBuilder run(Map options, Class sort) { + return new RunSortBuilder(options, getSort(sort.getSimpleName())); + } + + /** + * Get the current category display + * @return The current category + */ + public static String getCategory() { + return getArrayv().getCategory(); + } + + /** + * Set the current category display + * @param category The category to display + */ + public static void setCategory(String category) { + getArrayv().setCategory(category); + } + + /** + * Setus up a run group. Run groups run in a separate thread and keep track of the number of sorts remaining. + * This particular method simply joins on the new thread. If you wish for finer-grained control, see {@link #runGroupInThread(Integer, Runnable)}. + * @param sortCount The total number of sorts in this group + * @param run A closure around the code to run. Generally built of mostly {@link #run} calls + */ + public static void runGroup(Integer sortCount, Runnable run) { + try { + runGroupInThread(sortCount, run).join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Setus up a run group. Run groups run in a separate thread and keep track of the number of sorts remaining. + * This is identical to {@link #runGroup}, except that it returns the new thread instead of simply joining on it. + * @param sortCount The total number of sorts in this group + * @param run A closure around the code to run. Generally built of mostly {@link #run} calls + * @return The newly created group thread + */ + public static Thread runGroupInThread(Integer sortCount, Runnable run) { + return runGroupInThread(sortCount, run, false); + } + + /** + * Similar to {@link #runGroupInThread(Integer, Runnable)}, except that it has an extra {@code isRunAll parameter}. + * This method is generally intended only to be used internally by {@link SortPrompt#jButton1ActionPerformed}. + * @param sortCount The total number of sorts in this group + * @param run A closure around the code to run. Generally built of mostly {@link #run} calls + * @param isRunAll If this is {@code true}, the group will behave as if it was Showcase Sorts. + * @return The newly created group thread + */ + public static Thread runGroupInThread(Integer sortCount, Runnable run, boolean isRunAll) { + final ArrayVisualizer arrayVisualizer = getArrayv(); + final ArrayManager arrayManager = arrayVisualizer.getArrayManager(); + final Sounds Sounds = arrayVisualizer.getSounds(); + final String threadName = + (isRunAll ? "RunAll" : "SortGroup") + ( + (Thread.currentThread() instanceof ScriptThread) + ? ("-" + ((ScriptThread)Thread.currentThread()).getScript().getClass().getName()) + : "" + ); + + Sounds.toggleSound(true); + Thread sortingThread = new Thread(() -> { + RunGroupContext.CONTEXT.set(new RunGroupContext(sortCount, arrayVisualizer.getCurrentLength())); + try { + arrayManager.toggleMutableLength(false); + + run.run(); + + if (isRunAll) { + arrayVisualizer.setCategory("Showcase Sorts"); + arrayVisualizer.setHeading("Finished!!"); + } else { + arrayVisualizer.setCategory("Run " + arrayVisualizer.getCategory()); + arrayVisualizer.setHeading("Done"); + } + arrayVisualizer.updateNow(); + + arrayManager.toggleMutableLength(true); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + Sounds.toggleSound(false); + + arrayVisualizer.setSortingThread(null); + RunGroupContext rgc; + if ((rgc = RunGroupContext.CONTEXT.get()) != null) { + ScriptThread.runClosers(rgc.closers); + } + }, threadName); + + arrayVisualizer.setSortingThread(sortingThread); + arrayVisualizer.runSortingThread(); + return sortingThread; + } + + /** + * Registers an event handler and returns the handler object. + * See {@link ArrayVEventHandler} for more details. + * @param eventType The type of the event to handle + * @param cb The callback to run for the event + * @return The registered event handler + */ + public static ArrayVEventHandler registerEventHandler(ArrayVEventHandler.EventType eventType, Runnable cb) { + ArrayVEventHandler handler = new ArrayVEventHandler(eventType, cb); + handler.register(); + return handler; + } + + /** + *

Register a closer.

+ * + *

Ok, so what is a closer? A closer is ArrayV's Groovy API's equivalent of finalizers. Closers + * fix many of the flaws of finalizers. Closers are guaranteed to be called when the thread + * exits, whereas finalizers may never be called. Closers are also guaranteed to be called + * in the thread they are registered in, whereas finalizers may be called from any any thread. + * Furthermore, finalizers have been deprecated and are scheduled to be removed at some point in + * the future.

+ * @param closer The closer to register + */ + public static void registerCloser(Runnable closer) { + Thread cThread = Thread.currentThread(); + RunGroupContext rgc = RunGroupContext.CONTEXT.get(); + boolean forCThread = cThread instanceof ScriptThread; + boolean forRgc = rgc != null; + if (forCThread && forRgc) { + // Could be called in multiple places + final boolean[] hasBeenRun = {false}; + final Runnable originalCloser = closer; + closer = () -> { + if (hasBeenRun[0]) return; + try { + originalCloser.run(); + } finally { + hasBeenRun[0] = true; + } + }; + } + if (forCThread) { + ((ScriptThread)cThread).closers.add(closer); + } + if (forRgc) { + rgc.closers.add(closer); + } + if (!forCThread && !forRgc) { + throw new IllegalArgumentException("Can't register a closer here"); + } + } + + /** + * This abstract class declares which signatures the closures passed into {@link GroovyLocals#newSort} can use. + */ + public abstract static class SortFunctionSignatures { + /** + * This signature takes all the information that is standard with {@link Sort#runSort} + * @param array The main array, which is sized at the maximum arrays size + * @param length The current length of the array. + * Accessing any indices outside of the range [0, length) is considered illegal. + * @param buckets Any extra parameter passed to the sort + */ + public abstract void standardOptions(int[] array, int length, int buckets); + + /** + * Same as {@link #standardOptions}, but takes no buckets argument. + * This is primarily useful if your sort takes no additional user input. + * @param array + * @param length + */ + public abstract void standardOptionsNoBuckets(int[] array, int length); + } +} diff --git a/src/main/java/io/github/arrayv/groovyapi/RunGroupContext.java b/src/main/java/io/github/arrayv/groovyapi/RunGroupContext.java new file mode 100644 index 00000000..56a6b84f --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/RunGroupContext.java @@ -0,0 +1,65 @@ +package io.github.arrayv.groovyapi; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; + +/** + * This class is used for holding run group thread local information. + */ +public final class RunGroupContext { + /** + * The {@link ThreadLocal} object used for getting and setting the thread RunGroupContext + */ + public static final ThreadLocal CONTEXT = new ThreadLocal<>(); + + private final int sortCount; + private final int startingLength; + final Set closers; + private int sortNumber; + + /** + * Creates a RunGroupContext with the specified number of sorts and a base length + * @param sortCount See {@link #getSortCount} + * @param startingLength See {@link #getStartingLength} + */ + public RunGroupContext(int sortCount, int startingLength) { + this.sortCount = sortCount; + this.startingLength = startingLength; + this.closers = Collections.newSetFromMap(new IdentityHashMap<>()); + this.sortNumber = 0; + } + + /** + * The number of sorts in the current run group + * @return The number of sorts in the current run group + */ + public int getSortCount() { + return sortCount; + } + + /** + * The base length for the current run group + * @return The base length for the current run group + */ + public int getStartingLength() { + return startingLength; + } + + /** + * The current sorting algorithm index + * @return The current sorting algorithm index + */ + public int getSortNumber() { + return sortNumber; + } + + /** + * Increments and returns the new sorting algorithm index + * @return The newly incremented indexed + * @see #getSortNumber + */ + public int nextSort() { + return ++sortNumber; + } +} diff --git a/src/main/java/io/github/arrayv/groovyapi/RunSortBuilder.java b/src/main/java/io/github/arrayv/groovyapi/RunSortBuilder.java new file mode 100644 index 00000000..e47625b4 --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/RunSortBuilder.java @@ -0,0 +1,285 @@ +package io.github.arrayv.groovyapi; + +import io.github.arrayv.frames.ArrayFrame; +import io.github.arrayv.groovyapi.ScriptManager.ScriptThread; +import io.github.arrayv.groovyapi.exts.RunSortInfoExtension; +import io.github.arrayv.main.ArrayManager; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.sortdata.SortInfo; +import io.github.arrayv.utils.Delays; +import io.github.arrayv.utils.StopSort; +import io.github.arrayv.utils.Timer; + +import javax.swing.*; +import java.util.*; + +/** + *

This class is used for running sorting algorithms. You can construct an instance using the + * {@link GroovyLocals#run(SortInfo)} method, and other {@code run} methods.

+ * + *

This class is configured using a map of options. This map can contain a strict set of keys + * Here is the list of allowed keys and their types:

+ *
    + *
  • {@code numbers} ({@code Integer}) — The number of values to sort
  • + *
  • {@code buckets} ({@code Integer}) — An extra value to pass to the sorting + * algorithm
  • + *
  • {@code speed} ({@code Number}) — The time multiplier of the visual
  • + *
+ *

{@link Map.Entry} values to put into the option map can be obtained using {@link RunSortInfoExtension}.

+ * + * @see GroovyLocals#run(SortInfo) + * @see RunSortInfoExtension + */ +public final class RunSortBuilder { + private static final Set ALLOWED_KEYS = new HashSet<>(Arrays.asList( + "numbers", + "buckets", + "speed" + )); + + private final SortInfo sort; + private final Map opts; + private volatile boolean closed; + private final Runnable closer = () -> { + if (closed) return; + removeClosers(); + final String message = this + " never run from Groovy script"; + System.err.println("WARNING: " + message); + JOptionPane.showMessageDialog( + null, + message, + RunSortBuilder.class.getName(), + JOptionPane.WARNING_MESSAGE + ); + }; + private Map unmodifiableOpts = null; + + RunSortBuilder(Map options, SortInfo sort) { + this.closed = false; + this.sort = sort; + if (options == null) { + this.opts = new HashMap<>(ALLOWED_KEYS.size()); + } else { + this.opts = new HashMap<>(options); + } + + if (Thread.currentThread() instanceof ScriptThread) { + ((ScriptThread)Thread.currentThread()).closers.add(closer); + } + RunGroupContext rgc; + if ((rgc = RunGroupContext.CONTEXT.get()) != null) { + rgc.closers.add(closer); + } + } + + /** + * The sorting algorithm this builder will run + * @return The sorting algorithm this builder will run + * @see SortInfo + */ + public SortInfo getSort() { + return sort; + } + + /** + * The options configured for this builder + * @return The options configured for this builder + */ + public Map getOpts() { + return unmodifiableOpts == null ? (unmodifiableOpts = Collections.unmodifiableMap(opts)) : unmodifiableOpts; + } + + @Override + public String toString() { + return "RunSortBuilder[sort=" + sort + ", opts=" + opts + "]"; + } + + /** + * Merge the specified options with the options map + * @param opts The options to merge, generally using Groovy's named argument syntax + * @return {@code this} for chaining + * @see RunSortInfoExtension + */ + public RunSortBuilder with(Map opts) { + if (opts != null) { + for (Map.Entry opt : opts.entrySet()) { + put(opt); + } + } + return this; + } + + /** + * Merge the specified options with the options map + * @param opts The options to merge, generally obtained with {@link RunSortInfoExtension} + * @return {@code this} for chaining + * @see RunSortInfoExtension + */ + @SafeVarargs + public final RunSortBuilder with(Map.Entry... opts) { + for (Map.Entry opt : opts) { + put(opt); + } + return this; + } + + /** + * Merge the specified options with the options map, and run the sort + * @param opts The options to merge, generally using Groovy's named argument syntax + * @see RunSortInfoExtension + */ + public RunSortBuilder go(Map opts) { + return with(opts).finish(); + } + + /** + * Merge the specified options with the options map, and run the sort + * @param opts The options to merge, generally obtained with {@link RunSortInfoExtension} + * @see RunSortInfoExtension + */ + @SafeVarargs + public final RunSortBuilder go(Map.Entry... opts) { + return with(opts).finish(); + } + + private void put(Map.Entry opt) { + if (!ALLOWED_KEYS.contains(opt.getKey())) { + throw new IllegalArgumentException("Invalid RunSortBuilder key: " + opt.getKey()); + } + opts.put(opt.getKey(), opt.getValue()); + } + + /** + * The configured length of the array (key of {@code "numbers"}) + * @return The configured length + * @see RunSortInfoExtension#getNumbers + */ + public int getLength() { + // @checkstyle:off LeftCurlyCheck - It's more readable this way, I think + return ((Number)opts.computeIfAbsent("numbers", k -> { throw new NullPointerException("numbers"); })).intValue(); + // @checkstyle:on LeftCurlyCheck + } + + /** + * The extra value to pass to the sort (key of {@code "buckets"}) + * @return The extra value + * @see RunSortInfoExtension#getBuckets + */ + public int getBuckets() { + return ((Number)opts.getOrDefault("buckets", 0)).intValue(); + } + + /** + * The speed multiplier of the visual (key of {@code "speed"}) + * @return The speed multiplier + * @see RunSortInfoExtension#getSpeed + */ + public double getSpeed() { + return ((Number)opts.getOrDefault("speed", 1.0)).doubleValue(); + } + + private int calculateLength(int defaultLength, int startingLength) { + if (startingLength != -1) { + return (int)Math.max(defaultLength / 2048d * startingLength, 2); + } + return Math.max(defaultLength, 2); + } + + private int calculateLengthSlow(int defaultLength, int unreasonableLimit, int startingLength) { + return Math.min(calculateLength(defaultLength, startingLength), unreasonableLimit); + } + + private double calculateSpeed(double defaultSpeed, int length, int startingLength) { + if (startingLength != -1) { + if (length < startingLength / 2) { + return defaultSpeed * Math.pow(startingLength / 2048d, 2); + } else { + return defaultSpeed * (startingLength / 2048d); + } + } + return defaultSpeed; + } + + private void removeClosers() { + if (Thread.currentThread() instanceof ScriptThread) { + ((ScriptThread)Thread.currentThread()).closers.remove(closer); + } + RunGroupContext rgc; + if ((rgc = RunGroupContext.CONTEXT.get()) != null) { + rgc.closers.remove(closer); + } + // Set this just in case we removed the wrong closer. + // This happens if we initialized this instance in a different thread + // from the one where we are calling finish(). + closed = true; + } + + private RunSortBuilder finish() { + removeClosers(); + if (RunGroupContext.CONTEXT.get() == null) { + final ArrayVisualizer arrayVisualizer = ArrayVisualizer.getInstance(); + Thread sortThread = new Thread(this::run0, "ScriptedSort"); + arrayVisualizer.setSortingThread(sortThread); + arrayVisualizer.runSortingThread(); + try { + sortThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + run0(); + } + return this; + } + + private void run0() { + final ArrayVisualizer arrayVisualizer = ArrayVisualizer.getInstance(); + final ArrayManager arrayManager = arrayVisualizer.getArrayManager(); + final ArrayFrame arrayFrame = arrayVisualizer.getArrayFrame(); + final int[] array = arrayVisualizer.getArray(); + final Delays Delays = arrayVisualizer.getDelays(); + final Timer Timer = arrayVisualizer.getTimer(); + + final RunGroupContext runGroupContext = RunGroupContext.CONTEXT.get(); + final int startingLength = runGroupContext != null ? runGroupContext.getStartingLength() : -1; + + Delays.setSleepRatio(2.5); + + int sortLength; + if (sort.hasUnreasonableLimit()) { + sortLength = calculateLengthSlow(getLength(), sort.getUnreasonableLimit(), startingLength); + } else { + sortLength = calculateLength(getLength(), startingLength); + } + if (sortLength != arrayVisualizer.getCurrentLength()) { + arrayFrame.setLengthSlider(sortLength); + } + + arrayManager.refreshArray(array, arrayVisualizer.getCurrentLength(), arrayVisualizer); + + if (runGroupContext != null) { + arrayVisualizer.setHeading(sort.getRunAllName() + " (Sort " + runGroupContext.nextSort() + " of " + runGroupContext.getSortCount() + ")"); + } else { + arrayVisualizer.setHeading(sort.getRunAllName()); + } + + double sortSpeed = calculateSpeed(getSpeed(), arrayVisualizer.getCurrentLength(), startingLength); + Delays.setSleepRatio(sortSpeed); + + Timer.enableRealTimer(); + + try { + sort.getFreshInstance().runSort(array, arrayVisualizer.getCurrentLength(), getBuckets()); + } catch (StopSort ignored) { + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + + arrayVisualizer.endSort(); + try { + Thread.sleep(1000); + } catch (InterruptedException ignored) { + } + } +} diff --git a/src/main/java/io/github/arrayv/groovyapi/ScriptManager.java b/src/main/java/io/github/arrayv/groovyapi/ScriptManager.java new file mode 100644 index 00000000..ea372e71 --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/ScriptManager.java @@ -0,0 +1,330 @@ +package io.github.arrayv.groovyapi; + +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; +import org.codehaus.groovy.control.CompilationFailedException; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.MultipleCompilationErrorsException; +import org.codehaus.groovy.control.customizers.ImportCustomizer; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.*; + +/** + * This class is used to load and run Groovy scripts. + * All ArrayV Groovy scripts are executed from this class. + */ +public final class ScriptManager { + /** + * A {@link Thread} subclass that manages the execution of a Groovy script. + * A common use for this class is using it to get the current thread's + * {@link Script} or the path to the script file. + * @see Thread + */ + public static final class ScriptThread extends Thread { + private final File path; + private final Script script; + final Set closers; + + private ScriptThread(File path, Script script) { + super(script::run, "Script-" + script.getClass().getName()); + this.path = path; + this.script = script; + this.closers = Collections.newSetFromMap(new IdentityHashMap<>()); + } + + static void runClosers(Set closers) { + RuntimeException ex = null; + for (Runnable closer : closers) { + try { + closer.run(); + } catch (RuntimeException e) { + if (ex == null) { + ex = e; + } else { + ex.addSuppressed(e); + } + } + } + if (ex != null) { + throw ex; + } + } + + /** + * The path to the .groovy script file running in this thread + * @return The path to the script + */ + public File getPath() { + return path; + } + + /** + * The {@link Script} running in this thread + * @return The {@link Script} running in this thread + * @see Script + */ + public Script getScript() { + return script; + } + + /** + * Run the thread. This is an extension of {@link Thread#run()} that + * runs closers at the end. See {@link GroovyLocals#registerCloser} + * for a description on what closers are. + */ + @Override + public void run() { + super.run(); + runClosers(closers); + } + } + + private static final File INSTALLED_SCRIPTS_ROOT = new File("scripts"); + + private final GroovyShell shell; + private final Map> events; + private Map defaultScripts; + + /** + * Construct a ScriptManager instance. This may only be called from {@link ArrayVisualizer}. + * If you wish to get a reference to the ArrayV ScriptManager, use + * {@code ArrayVisualizer.getInstance().getScriptManager()}. + * @throws IllegalStateException When you call this constructor. + */ + public ScriptManager() throws IllegalStateException { + // Index 0 is Thread, and index 1 is ScriptManager + if (!Thread.currentThread().getStackTrace()[2].getClassName().equals(ArrayVisualizer.class.getName())) { + throw new IllegalStateException("Only ArrayVisualizer can create a ScriptManager instance. " + + "As such, there can only one ScriptManager instance. You can get obtain it with " + + "ArrayVisualizer.getInstance().getScriptManager()"); + } + final CompilerConfiguration compilerConfig = new CompilerConfiguration(); + compilerConfig.addCompilationCustomizers( + new ImportCustomizer() + .addStarImports("io.github.arrayv.sortdata") + .addStarImports("io.github.arrayv.groovyapi") + .addStaticStars("io.github.arrayv.groovyapi.GroovyLocals") + .addImports("io.github.arrayv.groovyapi.ArrayVEventHandler.EventType") + ); + compilerConfig.setScriptBaseClass("io.github.arrayv.groovyapi.ArrayVScript"); + compilerConfig.getClasspath().add(INSTALLED_SCRIPTS_ROOT.getPath()); + this.shell = new GroovyShell(compilerConfig); + this.events = new EnumMap<>(ArrayVEventHandler.EventType.class); + this.defaultScripts = null; + } + + /** + * The {@link GroovyShell} associated with the script manager + * @return The GroovyShell associated with the script manager + * @see GroovyShell + */ + public GroovyShell getGroovyShell() { + return shell; + } + + private Set getEventHandlers0(ArrayVEventHandler.EventType eventType) { + return events.computeIfAbsent(eventType, k -> new HashSet<>()); + } + + /** + * Get the event handlers for the specified event type + * @param eventType The type of event to obtain handlers for + * @return The event handlers + */ + public Set getEventHandlers(ArrayVEventHandler.EventType eventType) { + return Collections.unmodifiableSet(getEventHandlers0(eventType)); + } + + /** + * Run the event handlers for the specified event type + * @param eventType The type of event to handle + */ + public void runEventHandlers(ArrayVEventHandler.EventType eventType) { + RuntimeException e = null; + for (ArrayVEventHandler handler : getEventHandlers0(eventType)) { + try { + handler.handle(); + } catch (Exception e1) { + if (e == null) { + e = new RuntimeException(e1); + } else { + e.addSuppressed(e1); + } + } + } + if (e != null) { + throw e; + } + } + + /** + * Register event handlers. {@link ArrayVEventHandler#register} is preferred + * over this unless you're registering multiple handlers at once. + * @param handlers The event handlers to register + */ + public void registerEventHandlers(ArrayVEventHandler... handlers) { + for (ArrayVEventHandler handler : handlers) { + getEventHandlers0(handler.getEventType()).add(handler); + } + } + + /** + * Unegister event handlers. {@link ArrayVEventHandler#unregister} is preferred + * over this unless you're unregistering multiple handlers at once. + * @param handlers The event handlers to unregister + */ + public void unregisterEventHandlers(ArrayVEventHandler... handlers) { + for (ArrayVEventHandler handler : handlers) { + getEventHandlers0(handler.getEventType()).remove(handler); + } + } + + private Script handleCompilationFailure(CompilationFailedException e) { + if (e instanceof MultipleCompilationErrorsException) { + JErrorPane.invokeMonospaceErrorMessage(e.getMessage(), "Run Script"); + } else { + JErrorPane.invokeErrorMessage(e, "Run Script"); + } + throw e; + } + + /** + * Compile and run the script at the specified path + * @param path The path of the script + * @return The loaded {@link Script} object + */ + public Script loadScript(File path) throws IOException { + Script script; + try { + script = shell.parse(path); + } catch (CompilationFailedException e) { + return handleCompilationFailure(e); + } + script.run(); + return script; + } + + /** + * Compile and run the script at the specified URL + * @param url The URL of the script + * @return The loaded {@link Script} object + */ + public Script loadScript(URL url) throws IOException { + Script script; + try { + script = shell.parse(url.toURI()); + } catch (URISyntaxException e) { + throw new Error(e); + } catch (CompilationFailedException e) { + return handleCompilationFailure(e); + } + script.run(); + return script; + } + + /** + * Compile and run the specified script in a new thread + * @param path The path of the script + * @return The {@link ScriptThread} the script was run in + * @see ScriptThread + */ + public ScriptThread runInThread(File path) throws IOException { + Script script; + try { + script = shell.parse(path); + } catch (CompilationFailedException e) { + handleCompilationFailure(e); + return null; // UNREACHABLE + } + ScriptThread thread = new ScriptThread(path, script); + thread.start(); + return thread; + } + + /** + *

Load the default scripts. These are the union of the scripts embedded + * in the ArrayV JAR and the scripts in the {@code scripts} directory.

+ * + *

This method may only be called once, from {@link ArrayVisualizer}

+ * + * @throws IllegalStateException When you call this method. + */ + public Map loadDefaultScripts() throws IOException, IllegalStateException { + if (defaultScripts != null) { + throw new IllegalStateException("Cannot load default scripts more than once (i.e. you should not be calling this method)"); + } + defaultScripts = new HashMap<>(); + loadBuiltinScripts(); + loadInstalledScripts(); + return defaultScripts; + } + + private void loadInstalledScripts() throws IOException { + if (!INSTALLED_SCRIPTS_ROOT.exists()) { + INSTALLED_SCRIPTS_ROOT.mkdir(); + return; + } + //noinspection DataFlowIssue + for (File subFile : INSTALLED_SCRIPTS_ROOT.listFiles()) { + if (!subFile.isFile() || !subFile.getPath().endsWith(".groovy")) { + continue; + } + Script script = loadScript(subFile); + defaultScripts.put(script.getClass().getName(), script); + } + } + + /** + * The default scripts. See {@link #loadDefaultScripts()} for a description + * of what default scripts are + * @return The default scripts + * @see #loadDefaultScripts() + */ + public Map getDefaultScripts() { + if (defaultScripts == null) { + throw new Error("Cannot return default scripts before they're loaded"); + } + return Collections.unmodifiableMap(defaultScripts); + } + + private void loadBuiltinScripts() throws IOException { + ClassLoader classLoader = getClass().getClassLoader(); + for (String scriptPath : findBuiltinScripts(classLoader)) { + URL scriptUrl = classLoader.getResource(scriptPath); + assert scriptUrl != null; + Script script = loadScript(scriptUrl); + defaultScripts.put(script.getClass().getName(), script); + } + } + + // Modified from https://github.com/apache/groovy/blob/master/src/main/java/org/codehaus/groovy/control/SourceExtensionHandler.java + private static Set findBuiltinScripts(ClassLoader loader) throws IOException { + Set scripts = new LinkedHashSet<>(); + Enumeration globalServices = loader.getResources("META-INF/arrayv/io.github.arrayv.groovyapi.BuiltinScripts"); + if (!globalServices.hasMoreElements()) { + globalServices = loader.getResources("META-INF/arrayv/io.github.arrayv.groovyapi.BuiltinScripts"); + } + while (globalServices.hasMoreElements()) { + URL service = globalServices.nextElement(); + try (BufferedReader svcIn = new BufferedReader(new InputStreamReader(service.openStream()))) { + String scriptBasePath = svcIn.readLine(); + while (scriptBasePath != null) { + scriptBasePath = scriptBasePath.trim(); + if (!scriptBasePath.isEmpty() && !scriptBasePath.startsWith("#")) { + scripts.add(scriptBasePath); + } + scriptBasePath = svcIn.readLine(); + } + } + } + return scripts; + } +} diff --git a/src/main/java/io/github/arrayv/groovyapi/exts/RunSortInfoExtension.java b/src/main/java/io/github/arrayv/groovyapi/exts/RunSortInfoExtension.java new file mode 100644 index 00000000..c8198223 --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/exts/RunSortInfoExtension.java @@ -0,0 +1,47 @@ +package io.github.arrayv.groovyapi.exts; + +import io.github.arrayv.groovyapi.RunSortBuilder; + +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.Map; + +/** + * Extension for creating {@link Map.Entry}s to configure {@link RunSortBuilder} with + *
+ * See {@link RunSortBuilder} for more info on these keys + */ +public final class RunSortInfoExtension { + private RunSortInfoExtension() { + } + + /** + * Create a {@code numbers} key + * @param self The number of numbers + * @return A {@link Map.Entry} for {@code numbers} + */ + public static Map.Entry getNumbers(Integer self) { + return create("numbers", self); + } + + /** + * Create a {@code buckets} key + * @param self The extra value to pass to the sort + * @return A {@link Map.Entry} for {@code buckets} + */ + public static Map.Entry getBuckets(Integer self) { + return create("buckets", self); + } + + /** + * Create a {@code speed} key + * @param self The speed multiplier for the visual + * @return A {@link Map.Entry} for {@code speed} + */ + public static Map.Entry getSpeed(Number self) { + return create("speed", self); + } + + private static Map.Entry create(String key, Object self) { + return new SimpleImmutableEntry<>(key, self); + } +} diff --git a/src/main/java/io/github/arrayv/groovyapi/package-info.java b/src/main/java/io/github/arrayv/groovyapi/package-info.java new file mode 100644 index 00000000..a6136c69 --- /dev/null +++ b/src/main/java/io/github/arrayv/groovyapi/package-info.java @@ -0,0 +1,22 @@ +/** + *

This package defines the Groovy API. + * This package contains both things intended to be used from Groovy + * scripts and things intended to be used for the usage of Groovy scripts.

+ * + *

All the classes in this package are automatically imported from Groovy scripts.

+ * + *

The contents of this package is summarized here:

+ *
    + *
  • {@link GroovyLocals} — The contents of this is imported statically into all Groovy scripts.
  • + *
  • {@link ScriptManager} — This is primarily a Java-facing API intended for loading Groovy scripts.
  • + *
  • {@link RunSortBuilder} — This is used for running sorting algorithms. Instances can be created through + * any of the {@code run} methods of {@link GroovyLocals}.
  • + *
  • {@link ArrayVScript} — This is the base class for all Groovy scripts in ArrayV. It is primarily used + * for accessing sorts directly using their internal name (instead of having to use + * {@link GroovyLocals#getSort(String)}), although it may be extended in the future.
  • + *
  • {@link ArrayVEventHandler} — This is used for registering event handlers with the Groovy API's event + * system. The event system doesn't have that much content yet, though.
  • + *
  • {@link RunGroupContext} — This class is used for holding run group thread local information.
  • + *
+ */ +package io.github.arrayv.groovyapi; diff --git a/src/main/ArrayManager.java b/src/main/java/io/github/arrayv/main/ArrayManager.java similarity index 68% rename from src/main/ArrayManager.java rename to src/main/java/io/github/arrayv/main/ArrayManager.java index bda796a1..83415c1c 100644 --- a/src/main/ArrayManager.java +++ b/src/main/java/io/github/arrayv/main/ArrayManager.java @@ -1,22 +1,16 @@ -package main; +package io.github.arrayv.main; -import java.util.Arrays; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.utils.*; -import panes.JErrorPane; -import utils.Delays; -import utils.Highlights; -import utils.ShuffleGraph; -import utils.ShuffleInfo; -import utils.Shuffles; -import utils.Distributions; -import utils.Writes; +import java.util.Arrays; /* * MIT License Copyright (c) 2019 w0rthy -Copyright (c) 2020 ArrayV 4.0 Team +Copyright (c) 2020-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -38,25 +32,25 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ArrayManager { - private utils.Shuffles[] shuffleTypes; - private utils.Distributions[] distributionTypes; - private String[] shuffleIDs; - private String[] distributionIDs; +public final class ArrayManager { + private final io.github.arrayv.utils.Shuffles[] shuffleTypes; + private final io.github.arrayv.utils.Distributions[] distributionTypes; + private final String[] shuffleIDs; + private final String[] distributionIDs; private boolean hadDistributionAllocationError; - private volatile boolean MUTABLE; + private volatile boolean mutableLength; - private ArrayVisualizer ArrayVisualizer; - private Delays Delays; - private Highlights Highlights; + private final ArrayVisualizer arrayVisualizer; + private final Delays Delays; + private final Highlights Highlights; private ShuffleGraph shuffle; private Distributions distribution; - private Writes Writes; + private final Writes Writes; public ArrayManager(ArrayVisualizer arrayVisualizer) { - this.ArrayVisualizer = arrayVisualizer; + this.arrayVisualizer = arrayVisualizer; this.shuffle = ShuffleGraph.single(Shuffles.RANDOM); this.distribution = Distributions.LINEAR; @@ -65,9 +59,9 @@ public ArrayManager(ArrayVisualizer arrayVisualizer) { hadDistributionAllocationError = false; - this.Delays = ArrayVisualizer.getDelays(); - this.Highlights = ArrayVisualizer.getHighlights(); - this.Writes = ArrayVisualizer.getWrites(); + this.Delays = arrayVisualizer.getDelays(); + this.Highlights = arrayVisualizer.getHighlights(); + this.Writes = arrayVisualizer.getWrites(); this.shuffleIDs = new String[this.shuffleTypes.length]; for (int i = 0; i < this.shuffleTypes.length; i++) @@ -77,24 +71,25 @@ public ArrayManager(ArrayVisualizer arrayVisualizer) { for (int i = 0; i < this.distributionTypes.length; i++) this.distributionIDs[i] = this.distributionTypes[i].getName(); - this.MUTABLE = true; + this.mutableLength = true; } public boolean isLengthMutable() { - return this.MUTABLE; + return this.mutableLength; } - public void toggleMutableLength(boolean Bool) { - this.MUTABLE = Bool; + + public void toggleMutableLength(boolean mutableLength) { + this.mutableLength = mutableLength; } //TODO: Fix minimum to zero public void initializeArray(int[] array) { - if(ArrayVisualizer.doingStabilityCheck()) { - ArrayVisualizer.resetStabilityTable(); - ArrayVisualizer.resetIndexTable(); + if (arrayVisualizer.doingStabilityCheck()) { + arrayVisualizer.resetStabilityTable(); + arrayVisualizer.resetIndexTable(); } - int currentLen = ArrayVisualizer.getCurrentLength(); + int currentLen = arrayVisualizer.getCurrentLength(); int[] temp; try { @@ -105,14 +100,14 @@ public void initializeArray(int[] array) { hadDistributionAllocationError = true; temp = array; } - distribution.initializeArray(temp, this.ArrayVisualizer); + distribution.initializeArray(temp, this.arrayVisualizer); - double uniqueFactor = (double)currentLen/ArrayVisualizer.getUniqueItems(); - for(int i = 0; i < currentLen; i++) + double uniqueFactor = (double)currentLen/arrayVisualizer.getUniqueItems(); + for (int i = 0; i < currentLen; i++) temp[i] = (int)(uniqueFactor*(int)(temp[i]/uniqueFactor))+(int)uniqueFactor/2; System.arraycopy(temp, 0, array, 0, currentLen); - ArrayVisualizer.updateNow(); + arrayVisualizer.updateNow(); } public String[] getShuffleIDs() { @@ -160,96 +155,93 @@ public Distributions getDistribution() { } public void setDistribution(Distributions choice) { this.distribution = choice; - this.distribution.selectDistribution(ArrayVisualizer.getArray(), ArrayVisualizer); - if (!ArrayVisualizer.isActive()) - this.initializeArray(ArrayVisualizer.getArray()); + this.distribution.selectDistribution(arrayVisualizer.getArray(), arrayVisualizer); + if (!arrayVisualizer.isActive()) + this.initializeArray(arrayVisualizer.getArray()); } public boolean containsShuffle(Shuffles shuffle) { return this.shuffle.contains(new ShuffleInfo(shuffle)); } - public void shuffleArray(int[] array, int currentLen, ArrayVisualizer ArrayVisualizer) { + public void shuffleArray(int[] array, int currentLen, ArrayVisualizer arrayVisualizer) { this.initializeArray(array); - String tmp = ArrayVisualizer.getHeading(); - ArrayVisualizer.setHeading("Shuffling..."); + String tmp = arrayVisualizer.getHeading(); + arrayVisualizer.setHeading("Shuffling..."); double speed = Delays.getSleepRatio(); - if(ArrayVisualizer.isActive()) { - double sleepRatio = ArrayVisualizer.getCurrentLength()/1024d; - sleepRatio *= shuffle.sleepRatio; + if (arrayVisualizer.isActive()) { + double sleepRatio = arrayVisualizer.getCurrentLength()/1024d; + sleepRatio *= shuffle.getSleepRatio(); Delays.setSleepRatio(sleepRatio); } - shuffle.shuffleArray(array, this.ArrayVisualizer); + shuffle.shuffleArray(array, this.arrayVisualizer); Delays.setSleepRatio(speed); Highlights.clearAllMarks(); - ArrayVisualizer.setHeading(tmp); + arrayVisualizer.setHeading(tmp); } private void stableShuffle(int[] array, int length) { - boolean delay = ArrayVisualizer.shuffleEnabled(); - double sleep = delay ? 1 : 0; - double speed = Delays.getSleepRatio(); - if(ArrayVisualizer.isActive()) { - double sleepRatio = ArrayVisualizer.getCurrentLength()/1024d; + if (arrayVisualizer.isActive()) { + double sleepRatio = arrayVisualizer.getCurrentLength()/1024d; Delays.setSleepRatio(sleepRatio); } int[] counts = new int[length]; int[] prefixSum = new int[length]; - int[] table = ArrayVisualizer.getStabilityTable(); + int[] table = arrayVisualizer.getStabilityTable(); - for(int i = 0; i < length; i++) + for (int i = 0; i < length; i++) counts[array[i]]++; prefixSum[0] = counts[0]; - for(int i = 1; i < length; i++) + for (int i = 1; i < length; i++) prefixSum[i] = counts[i] + prefixSum[i-1]; - for(int i = 0, j = 0; j < length; i++) { - while(counts[i] > 0) { + for (int i = 0, j = 0; j < length; i++) { + while (counts[i] > 0) { table[j++] = i; counts[i]--; } } - for(int i = length-1; i >= 0; i--) + for (int i = length-1; i >= 0; i--) Writes.write(array, i, --prefixSum[array[i]], 0.5, true, false); - ArrayVisualizer.setIndexTable(); + arrayVisualizer.setIndexTable(); Delays.setSleepRatio(speed); } - public void refreshArray(int[] array, int currentLen, ArrayVisualizer ArrayVisualizer) { + public void refreshArray(int[] array, int currentLen, ArrayVisualizer arrayVisualizer) { try { Thread.sleep(1000); } catch (InterruptedException e) { JErrorPane.invokeErrorMessage(e); } - ArrayVisualizer.resetAllStatistics(); + arrayVisualizer.resetAllStatistics(); Highlights.clearAllMarks(); - ArrayVisualizer.setHeading(""); - if (!ArrayVisualizer.useAntiQSort()) { - this.shuffleArray(array, currentLen, ArrayVisualizer); + arrayVisualizer.setHeading(""); + if (!arrayVisualizer.useAntiQSort()) { + this.shuffleArray(array, currentLen, arrayVisualizer); - if(ArrayVisualizer.doingStabilityCheck()) + if (arrayVisualizer.doingStabilityCheck()) this.stableShuffle(array, currentLen); - int[] validateArray = ArrayVisualizer.getValidationArray(); + int[] validateArray = arrayVisualizer.getValidationArray(); if (validateArray != null) { System.arraycopy(array, 0, validateArray, 0, currentLen); Arrays.sort(validateArray, 0, currentLen); - if (ArrayVisualizer.reversedComparator()) { + if (arrayVisualizer.reversedComparator()) { for (int i = 0, j = currentLen - 1; i < j; i++, j--) { int temp = validateArray[i]; validateArray[i] = validateArray[j]; @@ -267,6 +259,6 @@ public void refreshArray(int[] array, int currentLen, ArrayVisualizer ArrayVisua JErrorPane.invokeErrorMessage(e); } - ArrayVisualizer.resetAllStatistics(); + arrayVisualizer.resetAllStatistics(); } -} \ No newline at end of file +} diff --git a/src/main/ArrayVisualizer.java b/src/main/java/io/github/arrayv/main/ArrayVisualizer.java similarity index 52% rename from src/main/ArrayVisualizer.java rename to src/main/java/io/github/arrayv/main/ArrayVisualizer.java index e8c55783..68c3f3a2 100644 --- a/src/main/ArrayVisualizer.java +++ b/src/main/java/io/github/arrayv/main/ArrayVisualizer.java @@ -1,67 +1,59 @@ -package main; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.KeyEventDispatcher; -import java.awt.Stroke; -import java.awt.Toolkit; +package io.github.arrayv.main; + +import io.github.arrayv.dialogs.FileDialog; +import io.github.arrayv.dialogs.SaveArrayDialog; +import io.github.arrayv.frames.ArrayFrame; +import io.github.arrayv.frames.SoundFrame; +import io.github.arrayv.frames.UtilFrame; +import io.github.arrayv.groovyapi.ArrayVEventHandler; +import io.github.arrayv.groovyapi.ScriptManager; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.sortdata.SortInfo; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.utils.Timer; +import io.github.arrayv.utils.*; +import io.github.arrayv.visuals.Visual; +import io.github.arrayv.visuals.VisualStyles; +import io.github.arrayv.visuals.bars.BarGraph; +import io.github.arrayv.visuals.bars.DisparityBarGraph; +import io.github.arrayv.visuals.bars.Rainbow; +import io.github.arrayv.visuals.bars.SineWave; +import io.github.arrayv.visuals.circles.ColorCircle; +import io.github.arrayv.visuals.circles.DisparityChords; +import io.github.arrayv.visuals.circles.DisparityCircle; +import io.github.arrayv.visuals.circles.Spiral; +import io.github.arrayv.visuals.dots.DisparityDots; +import io.github.arrayv.visuals.dots.ScatterPlot; +import io.github.arrayv.visuals.dots.SpiralDots; +import io.github.arrayv.visuals.dots.WaveDots; +import io.github.arrayv.visuals.image.CustomImage; +import io.github.arrayv.visuals.misc.HoopStack; +import io.github.arrayv.visuals.misc.PixelMesh; + +import javax.swing.*; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDropEvent; -import java.awt.dnd.DnDConstants; -import java.awt.datatransfer.DataFlavor; -import java.awt.KeyboardFocusManager; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.WindowEvent; -import java.io.File; +import java.awt.event.*; +import java.io.*; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Hashtable; import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.WindowConstants; - -import dialogs.FileDialog; -import dialogs.SaveArrayDialog; -import frames.ArrayFrame; -import frames.SoundFrame; -import frames.UtilFrame; -import main.SortAnalyzer.SortPair; -import panes.JErrorPane; -import threads.RunScriptedSorts; -import utils.*; -import visuals.Visual; -import visuals.VisualStyles; -import visuals.bars.*; -import visuals.circles.*; -import visuals.dots.*; -import visuals.image.*; -import visuals.misc.*; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; /* - * + * The MIT License (MIT) Copyright (c) 2019 w0rthy Copyright (c) 2019 Luke Hutchison Copyright (c) 2020 MusicTheorist -Copyright (c) 2021 ArrayV 4.0 Team +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -83,73 +75,107 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ArrayVisualizer { +public final class ArrayVisualizer { + // @checkstyle:off StaticVariableName + private static ArrayVisualizer INSTANCE = null; + // @checkstyle:on StaticVariableName + + private enum StatisticType { + LINE_BREAK, + SORT_IDENTITY, + ARRAY_LENGTH, + FRAMERATE, + SORT_DELAY, + VISUAL_TIME, + EST_SORT_TIME, + COMPARISONS, + SWAPS, + REVERSALS, + MAIN_WRITE, + AUX_WRITE, + AUX_ALLOC, + SEGMENTS; + + // @checkstyle:off IndentationCheck - It doesn't like {{ syntax + private static final Map CONFIG_KEYS = Collections.unmodifiableMap(new HashMap() {{ + put("", LINE_BREAK); + put("sort", SORT_IDENTITY); + put("length", ARRAY_LENGTH); + put("fps", FRAMERATE); + put("delay", SORT_DELAY); + put("vtime", VISUAL_TIME); + put("stime", EST_SORT_TIME); + put("comps", COMPARISONS); + put("swaps", SWAPS); + put("revs", REVERSALS); + put("wmain", MAIN_WRITE); + put("waux", AUX_WRITE); + put("auxlen", AUX_ALLOC); + put("segments", SEGMENTS); + }}); + // @checkstyle:on IndentationCheck + } + final JFrame window; - final private int MIN_ARRAY_VAL; - final private int MAX_ARRAY_VAL; + private final int minArrayVal; + private final int maxArrayVal; + + private final Properties buildInfo; final int[] array; final int[] validateArray; final int[] stabilityTable; final int[] indexTable; final ArrayList arrays; + private final StatisticType[] statsConfig; - private SortPair[] AllSorts; // First row of Comparison/DistributionSorts arrays consists of class names - private SortPair[] ComparisonSorts; // First row of Comparison/DistributionSorts arrays consists of class names - private SortPair[] DistributionSorts; // Second row consists of user-friendly names - private String[] InvalidSorts; + private SortInfo[] sorts; + private String[] invalidSorts; private String[] sortSuggestions; private volatile int sortLength; private volatile int uniqueItems; - private ArrayManager ArrayManager; - private SortAnalyzer SortAnalyzer; + private final ArrayManager arrayManager; + private final SortAnalyzer sortAnalyzer; - private UtilFrame UtilFrame; - private ArrayFrame ArrayFrame; + private final UtilFrame utilFrame; + private final ArrayFrame arrayFrame; private Visual[] visualClasses; private Thread sortingThread; - private Thread visualsThread; + private final Thread visualsThread; private volatile boolean visualsEnabled; - public final boolean disabledStabilityCheck; + private final boolean disabledStabilityCheck; private String category; private String heading; private String extraHeading; private Font typeFace; - private DecimalFormat formatter; - private DecimalFormatSymbols symbols; + private final DecimalFormat formatter; private volatile int currentGap; - private boolean SHUFFLEANIM; - - private volatile boolean ANALYZE; + private boolean showShuffleAnimation; - private volatile boolean POINTER; + private volatile boolean highlightAsAnalysis; - private Statistics statSnapshot; + private final Statistics statSnapshot; private String fontSelection; + private double fontSelectionScale; - private volatile boolean TEXTDRAW; - private volatile boolean COLOR; - private volatile boolean DISPARITYDRAW; - private volatile boolean LINEDRAW; - private volatile boolean PIXELDRAW; - private volatile boolean RAINBOW; - private volatile boolean SPIRALDRAW; - private volatile boolean WAVEDRAW; - private volatile boolean EXTARRAYS; - - private volatile boolean ANTIQSORT; - private volatile boolean STABILITY; - private volatile boolean NETWORKS; - private volatile boolean REVERSED; + private volatile boolean showStatistics; + private volatile boolean showColor; + private volatile boolean showLines; + private volatile boolean showExternalArrays; + + private volatile boolean useAntiQSort; + private volatile boolean stabilityChecking; + private volatile boolean visualizingNetworks; + private volatile boolean reversedComparator; private volatile boolean isCanceled; @@ -162,27 +188,39 @@ final public class ArrayVisualizer { private Graphics2D mainRender; private Graphics2D extraRender; - private Delays Delays; - private Highlights Highlights; - private MultipleScript MultipleScript; - private Reads Reads; - private Renderer Renderer; - private Sounds Sounds; - private Timer Timer; - private VisualStyles VisualStyles; - private Writes Writes; - private AntiQSort AntiQSort; + private final Delays Delays; + private final Highlights Highlights; + private final Reads Reads; + private final Renderer renderer; + private final Sounds Sounds; + private final Timer Timer; + private final Writes Writes; + private final AntiQSort antiQSort; + private final ScriptManager scriptManager; + + private VisualStyles visualStyle; - private volatile boolean updateVisuals; - private volatile int updateVisualsForced; - public volatile boolean benchmarking; + private final AtomicInteger updateVisualsForced; + private volatile boolean benchmarking; - public static int MAX_LENGTH_POWER = 15; + private static int maxLengthPower = 15; private volatile boolean hidden; private volatile boolean frameSkipped; - public ArrayVisualizer() { + public ArrayVisualizer() throws IOException { + if (INSTANCE != null) { + throw new IllegalStateException("Cannot create more than one ArrayVisualizer"); + } + INSTANCE = this; + + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + e.printStackTrace(); + } + UIManager.getLookAndFeelDefaults().put("Slider.paintValue", Boolean.FALSE); // GTK PLAF fix + this.window = new JFrame(); this.window.addKeyListener(new KeyListener() { @Override @@ -192,6 +230,10 @@ public void keyTyped(KeyEvent e) { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_K || e.getKeyCode() == KeyEvent.VK_SPACE) { ArrayVisualizer.this.getDelays().togglePaused(); + } else if (e.getKeyCode() == KeyEvent.VK_B) { + Delays.beginStepping(); + } else if (e.getKeyCode() == KeyEvent.VK_F12) { + System.gc(); } } @Override @@ -206,11 +248,11 @@ public synchronized void drop(DropTargetDropEvent e) { List droppedFiles = (List)e.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); int success = 0; for (File file : droppedFiles) { - if (ArrayVisualizer.this.SortAnalyzer.importSort(file, false)) { + if (ArrayVisualizer.this.sortAnalyzer.importSort(file, false)) { success++; } } - ArrayVisualizer.this.SortAnalyzer.sortSorts(); + ArrayVisualizer.this.sortAnalyzer.sortSorts(); ArrayVisualizer.this.refreshSorts(); if (success == 0) { JErrorPane.invokeCustomErrorMessage("Failed to import all " + droppedFiles.size() + " sorts"); @@ -227,41 +269,19 @@ public synchronized void drop(DropTargetDropEvent e) { } }); - KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() { - @Override - public boolean dispatchKeyEvent(KeyEvent e) { - if (e.getID() != KeyEvent.KEY_PRESSED) - return false; - if (e.getKeyCode() == KeyEvent.VK_O && (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) { - if (ArrayVisualizer.this.isActive()) - return false; - Thread thread = new Thread(){ - @Override - public void run(){ - RunScriptedSorts RunScriptedSorts = new RunScriptedSorts(ArrayVisualizer.this); - try { - RunScriptedSorts.runThread(ArrayVisualizer.this.getArray(), 0, 0, false); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - } - }; - thread.start(); - return true; - } - else if (e.getKeyCode() == KeyEvent.VK_S && (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) { - int[] snapshot = Arrays.copyOfRange(ArrayVisualizer.this.getArray(), 0, ArrayVisualizer.this.getCurrentLength()); - FileDialog selected = new SaveArrayDialog(); - ArrayFileWriter.writeArray(selected.getFile(), snapshot, snapshot.length); - return true; - } - else if (e.getKeyCode() == KeyEvent.VK_F5) { - ArrayVisualizer.this.updateNow(); - return true; - } + KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(e -> { + if (e.getID() != KeyEvent.KEY_PRESSED) return false; + if (e.getKeyCode() == KeyEvent.VK_S && (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) { + int[] snapshot = Arrays.copyOfRange(ArrayVisualizer.this.getArray(), 0, ArrayVisualizer.this.getCurrentLength()); + FileDialog selected = new SaveArrayDialog(); + ArrayFileWriter.writeArray(selected.getFile(), snapshot, snapshot.length); + return true; + } else if (e.getKeyCode() == KeyEvent.VK_F5) { + ArrayVisualizer.this.updateNow(); + return true; } + return false; }); this.window.addComponentListener(new ComponentListener() { @@ -287,65 +307,154 @@ public void componentHidden(ComponentEvent e) { } }); - new Thread() { + new Thread("FileDialogInitializer") { @Override public void run() { FileDialog.initialize(); } }.start(); - - this.MIN_ARRAY_VAL = 2; - this.MAX_ARRAY_VAL = (int)Math.pow(2, MAX_LENGTH_POWER); - + + this.buildInfo = new Properties(); + try (InputStream is = getClass().getResourceAsStream("/buildInfo.properties")) { + if (is != null) { + this.buildInfo.load(is); + } + } catch (IOException e) { + System.err.println("Unable to read buildInfo.properties"); + e.printStackTrace(); + } + + this.minArrayVal = 2; + this.maxArrayVal = (int)Math.pow(2, maxLengthPower); + int[] array; try { - array = new int[this.MAX_ARRAY_VAL]; + array = new int[this.maxArrayVal]; } catch (OutOfMemoryError e) { JErrorPane.invokeCustomErrorMessage("Failed to allocate main array. The program will now exit."); System.exit(1); array = null; } this.array = array; - - this.sortLength = this.MAX_ARRAY_VAL; - + + this.sortLength = this.maxArrayVal; + this.arrays = new ArrayList<>(); this.arrays.add(this.array); - - this.sortLength = Math.min(2048, this.MAX_ARRAY_VAL); + + this.fontSelection = "Times New Roman"; + this.fontSelectionScale = 25; + List statsInfoList = new ArrayList<>(); + Throwable statsLoadException = null; + while (true) { + try (Scanner statsScanner = new Scanner(new File("stats-config.txt"))) { + while (statsScanner.hasNextLine()) { + String line = statsScanner.nextLine().trim(); + if (line.length() > 0 && line.charAt(0) == '#') continue; + if (line.startsWith("FONT:")) { + String font = line.substring(5); + int starIndex; + if ((starIndex = font.indexOf('*')) != -1) { + fontSelectionScale = Double.parseDouble(font.substring(starIndex + 1).trim()); + font = font.substring(0, starIndex); + } + fontSelection = font.trim(); + continue; + } + StatisticType type = StatisticType.CONFIG_KEYS.get(line.toLowerCase()); + if (type == null) { + System.err.println("Unknown statistic type: " + line.toLowerCase()); + continue; + } + statsInfoList.add(type); + } + } catch (FileNotFoundException e) { + try (InputStream in = getClass().getResourceAsStream("/stats-config.txt")) { + assert in != null; + try (OutputStream out = new FileOutputStream("stats-config.txt")) { + byte[] buf = new byte[8192]; + int length; + while ((length = in.read(buf)) > 0) { + out.write(buf, 0, length); + } + } catch (Exception e2) { + statsLoadException = e2; + } + } catch (Exception e2) { + statsLoadException = e2; + } + continue; + } catch (Exception e) { + statsLoadException = e; + } + break; + } + if (statsLoadException != null) { + JErrorPane.invokeErrorMessage(statsLoadException, "ArrayVisualizer"); + JOptionPane.showMessageDialog( + this.window, + "Unable to load stats-config, using default config", + "ArrayVisualizer", + JOptionPane.WARNING_MESSAGE + ); + // @checkstyle:off IndentationCheck - There's custom indentation here to make things more readable + statsConfig = new StatisticType[] { + StatisticType.SORT_IDENTITY, + StatisticType.ARRAY_LENGTH, + StatisticType.LINE_BREAK, + StatisticType.SORT_DELAY, + StatisticType.VISUAL_TIME, + StatisticType.EST_SORT_TIME, + StatisticType.LINE_BREAK, + StatisticType.COMPARISONS, + StatisticType.SWAPS, + StatisticType.REVERSALS, + StatisticType.LINE_BREAK, + StatisticType.MAIN_WRITE, + StatisticType.AUX_WRITE, + StatisticType.AUX_ALLOC, + StatisticType.SEGMENTS + }; + // @checkstyle:on IndentationCheck + } else { + statsConfig = statsInfoList.toArray(new StatisticType[0]); + } + + this.sortLength = Math.min(2048, this.maxArrayVal); this.uniqueItems = this.sortLength; - + this.formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US); - this.symbols = this.formatter.getDecimalFormatSymbols(); + DecimalFormatSymbols symbols = this.formatter.getDecimalFormatSymbols(); this.formatter.setRoundingMode(RoundingMode.HALF_UP); - this.symbols.setGroupingSeparator(','); - this.formatter.setDecimalFormatSymbols(this.symbols); - - this.Highlights = new Highlights(this, this.MAX_ARRAY_VAL); + symbols.setGroupingSeparator(','); + this.formatter.setDecimalFormatSymbols(symbols); + + this.Highlights = new Highlights(this, this.maxArrayVal); this.Sounds = new Sounds(this.array, this); this.Delays = new Delays(this); this.Timer = new Timer(this); this.Reads = new Reads(this); - this.Renderer = new Renderer(this); + this.renderer = new Renderer(this); this.Writes = new Writes(this); - this.AntiQSort = new AntiQSort(this); + this.antiQSort = new AntiQSort(this); + this.scriptManager = new ScriptManager(); + + Highlights.postInit(); - new Rotations(this); - SoundFrame test = new SoundFrame(this.Sounds); test.setVisible(true); - - this.ArrayManager = new ArrayManager(this); - this.SortAnalyzer = new SortAnalyzer(this); - - this.SortAnalyzer.analyzeSorts(); + + this.arrayManager = new ArrayManager(this); + this.sortAnalyzer = new SortAnalyzer(this); + + this.sortAnalyzer.analyzeSorts(); this.refreshSorts(); int[] stabilityTable, indexTable, validateArray; boolean disabledStabilityCheck; try { - stabilityTable = new int[this.MAX_ARRAY_VAL]; - indexTable = new int[this.MAX_ARRAY_VAL]; + stabilityTable = new int[this.maxArrayVal]; + indexTable = new int[this.maxArrayVal]; disabledStabilityCheck = false; } catch (OutOfMemoryError e) { JErrorPane.invokeCustomErrorMessage("Failed to allocate arrays for stability check. This feature will be disabled."); @@ -354,55 +463,49 @@ public void run() { disabledStabilityCheck = true; } try { - validateArray = new int[this.MAX_ARRAY_VAL]; + validateArray = new int[this.maxArrayVal]; } catch (OutOfMemoryError e) { JErrorPane.invokeCustomErrorMessage("Failed to allocate array for improved validation. This feature will be disabled."); validateArray = null; } - this.validateArray = validateArray;; + this.validateArray = validateArray; this.stabilityTable = stabilityTable; this.indexTable = indexTable; + //noinspection ConstantValue this.disabledStabilityCheck = disabledStabilityCheck; + //noinspection ConstantValue if (!this.disabledStabilityCheck) { this.resetStabilityTable(); this.resetIndexTable(); } - this.MultipleScript = new MultipleScript(this); - this.category = ""; this.heading = ""; this.extraHeading = ""; - this.fontSelection = "Times New Roman"; - this.typeFace = new Font(this.fontSelection, Font.PLAIN, (int) (this.getWindowRatio() * 25)); - + this.typeFace = new Font(fontSelection, Font.PLAIN, (int) (this.getWindowRatio() * fontSelectionScale)); + this.statSnapshot = new Statistics(this); - - this.UtilFrame = new UtilFrame(this.array, this); - this.ArrayFrame = new ArrayFrame(this.array, this); - - this.UtilFrame.reposition(this.ArrayFrame); - - this.SHUFFLEANIM = true; - this.ANALYZE = false; - this.POINTER = false; - this.TEXTDRAW = true; - - this.COLOR = false; - this.DISPARITYDRAW = false; - this.LINEDRAW = false; - this.PIXELDRAW = false; - this.RAINBOW = false; - this.SPIRALDRAW = false; - this.EXTARRAYS = false; - - this.ANTIQSORT = false; - this.STABILITY = false; - this.NETWORKS = false; - + + this.utilFrame = new UtilFrame(this.array, this); + this.arrayFrame = new ArrayFrame(this.array, this); + + this.utilFrame.reposition(this.arrayFrame); + + this.showShuffleAnimation = true; + this.highlightAsAnalysis = false; + this.showStatistics = true; + + this.showColor = false; + this.showLines = false; + this.showExternalArrays = false; + + this.useAntiQSort = false; + this.stabilityChecking = false; + this.visualizingNetworks = false; + this.isCanceled = false; - this.updateVisualsForced = 0; + this.updateVisualsForced = new AtomicInteger(); this.benchmarking = false; this.cx = 0; @@ -410,25 +513,27 @@ public void run() { this.ch = 0; this.cw = 0; - this.ArrayManager.initializeArray(this.array); - + scriptManager.loadDefaultScripts(); + scriptManager.runEventHandlers(ArrayVEventHandler.EventType.DEFAULT_SCRIPTS_INSTALLED); + + this.arrayManager.initializeArray(this.array); + //TODO: Overhaul visual code to properly reflect Swing (JavaFX?) style and conventions - this.toggleVisualUpdates(false); //DRAW THREAD - this.visualsThread = new Thread() { + this.visualsThread = new Thread("VisualsThread") { @SuppressWarnings("unused") @Override public void run() { ArrayVisualizer.this.visualsEnabled = true; - - utils.Renderer.initializeVisuals(ArrayVisualizer.this); - + + io.github.arrayv.utils.Renderer.initializeVisuals(ArrayVisualizer.this); + Graphics background = ArrayVisualizer.this.window.getGraphics(); background.setColor(Color.BLACK); int coltmp = 255; - + ArrayVisualizer.this.visualClasses = new Visual[15]; - + ArrayVisualizer.this.visualClasses[0] = new BarGraph(ArrayVisualizer.this); ArrayVisualizer.this.visualClasses[1] = new Rainbow(ArrayVisualizer.this); ArrayVisualizer.this.visualClasses[2] = new DisparityBarGraph(ArrayVisualizer.this); @@ -444,9 +549,9 @@ public void run() { ArrayVisualizer.this.visualClasses[12] = new PixelMesh(ArrayVisualizer.this); ArrayVisualizer.this.visualClasses[13] = new Spiral(ArrayVisualizer.this); ArrayVisualizer.this.visualClasses[14] = new SpiralDots(ArrayVisualizer.this); - - while(ArrayVisualizer.this.visualsEnabled) { - if (ArrayVisualizer.this.updateVisualsForced == 0) { + + while (ArrayVisualizer.this.visualsEnabled) { + if (ArrayVisualizer.this.updateVisualsForced.get() == 0) { try { synchronized (ArrayVisualizer.this) { ArrayVisualizer.this.wait(); @@ -455,14 +560,15 @@ public void run() { e.printStackTrace(); } } + long startTime = System.currentTimeMillis(); try { - if(ArrayVisualizer.this.updateVisualsForced > 0) { - ArrayVisualizer.this.updateVisualsForced--; - ArrayVisualizer.this.Renderer.updateVisualsStart(ArrayVisualizer.this); + if (ArrayVisualizer.this.updateVisualsForced.get() > 0) { + ArrayVisualizer.this.updateVisualsForced.decrementAndGet(); + ArrayVisualizer.this.renderer.updateVisualsStart(ArrayVisualizer.this); int[][] arrays = ArrayVisualizer.this.arrays.toArray(new int[][] { }); - ArrayVisualizer.this.Renderer.drawVisual(ArrayVisualizer.this.VisualStyles, arrays, ArrayVisualizer.this, ArrayVisualizer.this.Highlights); + ArrayVisualizer.this.renderer.drawVisual(ArrayVisualizer.this.visualStyle, arrays, ArrayVisualizer.this, ArrayVisualizer.this.Highlights); - if(ArrayVisualizer.this.TEXTDRAW) { + if (ArrayVisualizer.this.showStatistics) { ArrayVisualizer.this.statSnapshot.updateStats(ArrayVisualizer.this); ArrayVisualizer.this.updateFontSize(); ArrayVisualizer.this.drawStats(Color.BLACK, true); @@ -471,62 +577,103 @@ public void run() { background.drawImage(ArrayVisualizer.this.img, 0, 0, null); Toolkit.getDefaultToolkit().sync(); } - if (ArrayVisualizer.this.updateVisualsForced > 10000) { - ArrayVisualizer.this.updateVisualsForced = 100; + if (ArrayVisualizer.this.updateVisualsForced.get() > 10000) { + ArrayVisualizer.this.updateVisualsForced.set(100); } - } - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); } - // See: https://stackoverflow.com/questions/580419/how-can-i-stop-a-java-while-loop-from-eating-50-of-my-cpu/583537#583537 - try { - Thread.sleep(ArrayVisualizer.this.benchmarking ? 1000 : 0); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - ArrayVisualizer.this.visualsEnabled = false; - } - - }}}; + long endTime = System.currentTimeMillis(); + statSnapshot.setFrameTimeMillis(endTime - startTime); + } + } + }; this.Sounds.startAudioThread(); this.drawWindows(); + + scriptManager.runEventHandlers(ArrayVEventHandler.EventType.ARRAYV_FULLY_LOADED); } - public void refreshSorts() { - this.ComparisonSorts = this.SortAnalyzer.getComparisonSorts(); - this.DistributionSorts = this.SortAnalyzer.getDistributionSorts(); - this.InvalidSorts = this.SortAnalyzer.getInvalidSorts(); - this.sortSuggestions = this.SortAnalyzer.getSuggestions(); + public static ArrayVisualizer getInstance() { + return INSTANCE; + } + + public JFrame getWindow() { + return window; + } - this.AllSorts = new SortPair[this.ComparisonSorts.length + this.DistributionSorts.length]; - System.arraycopy(this.ComparisonSorts, 0, this.AllSorts, 0, this.ComparisonSorts.length); - System.arraycopy(this.DistributionSorts, 0, this.AllSorts, this.ComparisonSorts.length, this.DistributionSorts.length); + public void refreshSorts() { + this.sorts = this.sortAnalyzer.getSorts(); + this.invalidSorts = this.sortAnalyzer.getInvalidSorts(); + this.sortSuggestions = this.sortAnalyzer.getSuggestions(); } - + private void drawStats(Color textColor, boolean dropShadow) { int xOffset = 15; int yOffset = 30; - if(dropShadow) { + if (dropShadow) { xOffset += 3; yOffset += 3; } - + double windowRatio = this.getWindowRatio(); - + int yPos = (int)(fontSelectionScale / 25.0 * 30); + this.mainRender.setColor(textColor); - - this.mainRender.drawString(this.statSnapshot.getSortIdentity(), xOffset, (int) (windowRatio * 30) + yOffset); - this.mainRender.drawString(this.statSnapshot.getArrayLength(), xOffset, (int) (windowRatio * 55) + yOffset); - this.mainRender.drawString(this.statSnapshot.getSortDelay(), xOffset, (int) (windowRatio * 95) + yOffset); - this.mainRender.drawString(this.statSnapshot.getVisualTime(), xOffset, (int) (windowRatio * 120) + yOffset); - this.mainRender.drawString(this.statSnapshot.getEstSortTime(), xOffset, (int) (windowRatio * 145) + yOffset); - this.mainRender.drawString(this.statSnapshot.getComparisonCount(), xOffset, (int) (windowRatio * 185) + yOffset); - this.mainRender.drawString(this.statSnapshot.getSwapCount(), xOffset, (int) (windowRatio * 210) + yOffset); - this.mainRender.drawString(this.statSnapshot.getReversalCount(), xOffset, (int) (windowRatio * 235) + yOffset); - this.mainRender.drawString(this.statSnapshot.getMainWriteCount(), xOffset, (int) (windowRatio * 275) + yOffset); - this.mainRender.drawString(this.statSnapshot.getAuxWriteCount(), xOffset, (int) (windowRatio * 300) + yOffset); - this.mainRender.drawString(this.statSnapshot.getAuxAllocAmount(), xOffset, (int) (windowRatio * 325) + yOffset); - this.mainRender.drawString(this.statSnapshot.getSegments(), xOffset, (int) (windowRatio * 355) + yOffset); + + for (StatisticType statType : statsConfig) { + // System.out.println(yPos); + String stat; + switch (statType) { + case LINE_BREAK: + yPos += (int)(fontSelectionScale / 25.0 * 15); + continue; + case SORT_IDENTITY: + stat = statSnapshot.getSortIdentity(); + break; + case ARRAY_LENGTH: + stat = statSnapshot.getArrayLength(); + break; + case FRAMERATE: + stat = statSnapshot.getFramerate(); + break; + case SORT_DELAY: + stat = statSnapshot.getSortDelay(); + break; + case VISUAL_TIME: + stat = statSnapshot.getVisualTime(); + break; + case EST_SORT_TIME: + stat = statSnapshot.getEstSortTime(); + break; + case COMPARISONS: + stat = statSnapshot.getComparisonCount(); + break; + case SWAPS: + stat = statSnapshot.getSwapCount(); + break; + case REVERSALS: + stat = statSnapshot.getReversalCount(); + break; + case MAIN_WRITE: + stat = statSnapshot.getMainWriteCount(); + break; + case AUX_WRITE: + stat = statSnapshot.getAuxWriteCount(); + break; + case AUX_ALLOC: + stat = statSnapshot.getAuxAllocAmount(); + break; + case SEGMENTS: + stat = statSnapshot.getSegments(); + break; + default: + stat = null; // Unreachable + } + mainRender.drawString(stat, xOffset, (int)(windowRatio * yPos) + yOffset); + yPos += fontSelectionScale; + } } public void updateNow() { @@ -537,83 +684,87 @@ public void updateNow(int fallback) { frameSkipped = true; return; } - this.updateVisualsForced += fallback; + this.updateVisualsForced.addAndGet(fallback); synchronized (this) { this.notify(); } } + /** + * @deprecated This method no longer does anything! + */ + @Deprecated public void toggleVisualUpdates(boolean bool) { - this.updateVisuals = bool; } + public void forceVisualUpdate(int count) { - this.updateVisualsForced += count; + this.updateVisualsForced.addAndGet(count); } + public boolean enableBenchmarking(boolean enabled) { - if (enabled) { - - } - else if (this.benchmarking) { + if (!enabled && this.benchmarking) { if (this.getCurrentLength() >= Math.pow(2, 23)) { - int warning = JOptionPane.showOptionDialog(this.getMainWindow(), "Warning! " - + "Your computer's GPU probably can't handle more than 2^23 elements at any " - + "framrate not significantly less than 1. Would you still like " - + "to re-enable graphics?", "Warning!", 2, JOptionPane.WARNING_MESSAGE, - null, new String[] { "Yes", "Please save my GPU!" }, "Please save my GPU!"); + int warning = JOptionPane.showOptionDialog( + this.getMainWindow(), + "Warning! " + + "Your computer's CPU probably can't handle more than 2^23 elements at any " + + "framrate not significantly less than 1. Would you still like " + + "to re-enable graphics?", + "Warning!", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, + null, new String[] { "Yes", "Please save my GPU!" }, "Please save my GPU!"); if (warning != 0) { enabled = true; } } } this.benchmarking = enabled; - this.updateVisuals = !benchmarking; return this.benchmarking; } public int[] getValidationArray() { return this.validateArray; } - + public int getStabilityValue(int n) { n = Math.max(0, Math.min(n, this.sortLength-1)); - + return this.stabilityTable[n]; } - + public int[] getStabilityTable() { return this.stabilityTable; } - + public void resetStabilityTable() { - for(int i = 0; i < this.sortLength; i++) { + for (int i = 0; i < this.sortLength; i++) { this.stabilityTable[i] = i; } } - + public int getIndexValue(int n) { n = Math.max(0, Math.min(n, this.sortLength-1)); - + return this.indexTable[n]; } - + public int[] getIndexTable() { return this.indexTable; } - + public void setIndexTable() { - for(int i = 0; i < this.sortLength; i++) { + for (int i = 0; i < this.sortLength; i++) { this.indexTable[array[i]] = i; } } - + public void resetIndexTable() { - for(int i = 0; i < this.sortLength; i++) { + for (int i = 0; i < this.sortLength; i++) { this.indexTable[i] = i; } } - + public boolean isSorted() { - return this.statSnapshot.findSegments(this.array, this.sortLength, this.REVERSED)[0] == 1; + return this.statSnapshot.findSegments(this.array, this.sortLength, this.reversedComparator)[0] == 1; } public int[] getArray() { @@ -623,12 +774,12 @@ public int[] getArray() { public ArrayList getArrays() { return this.arrays; } - + public ArrayManager getArrayManager() { - return this.ArrayManager; + return this.arrayManager; } public SortAnalyzer getSortAnalyzer() { - return this.SortAnalyzer; + return this.sortAnalyzer; } public Delays getDelays() { return this.Delays; @@ -640,7 +791,7 @@ public Reads getReads() { return this.Reads; } public Renderer getRender() { - return this.Renderer; + return this.renderer; } public Sounds getSounds() { return this.Sounds; @@ -649,37 +800,32 @@ public Timer getTimer() { return this.Timer; } public VisualStyles getVisualStyles() { - return this.VisualStyles; + return this.visualStyle; } public Writes getWrites() { return this.Writes; } - public MultipleScript getScriptParser() { - return this.MultipleScript; + + public ScriptManager getScriptManager() { + return scriptManager; } - + public Visual[] getVisuals() { return this.visualClasses; } - + public UtilFrame getUtilFrame() { - return this.UtilFrame; + return this.utilFrame; } - + public ArrayFrame getArrayFrame() { - return this.ArrayFrame; - } - - public SortPair[] getAllSorts() { - return this.AllSorts; + return this.arrayFrame; } - public SortPair[] getComparisonSorts() { - return this.ComparisonSorts; - } - public SortPair[] getDistributionSorts() { - return this.DistributionSorts; + + public SortInfo[] getSorts() { + return this.sorts; } - + public Thread getSortingThread() { return this.sortingThread; } @@ -689,14 +835,14 @@ public void setSortingThread(Thread thread) { public void runSortingThread() { this.sortingThread.start(); } - + public int getMinimumLength() { - return this.MIN_ARRAY_VAL; + return this.minArrayVal; } public int getMaximumLength() { - return this.MAX_ARRAY_VAL; + return this.maxArrayVal; } - + public void resetAllStatistics() { this.Reads.resetStatistics(); this.Writes.resetStatistics(); @@ -710,51 +856,51 @@ public boolean isActive() { public void setComparator(int comparator) { switch (comparator) { case 0: - this.REVERSED = false; - this.ANTIQSORT = false; - this.STABILITY = false; - this.NETWORKS = false; + this.reversedComparator = false; + this.useAntiQSort = false; + this.stabilityChecking = false; + this.visualizingNetworks = false; break; case 1: - this.REVERSED = false; - this.ANTIQSORT = true; - this.STABILITY = false; - this.NETWORKS = false; + this.reversedComparator = false; + this.useAntiQSort = true; + this.stabilityChecking = false; + this.visualizingNetworks = false; break; case 2: - this.REVERSED = false; - this.ANTIQSORT = false; - this.STABILITY = true; - this.NETWORKS = false; + this.reversedComparator = false; + this.useAntiQSort = false; + this.stabilityChecking = true; + this.visualizingNetworks = false; break; case 3: - this.REVERSED = true; - this.ANTIQSORT = false; - this.STABILITY = false; - this.NETWORKS = false; + this.reversedComparator = true; + this.useAntiQSort = false; + this.stabilityChecking = false; + this.visualizingNetworks = false; break; case 4: - this.REVERSED = false; - this.ANTIQSORT = false; - this.STABILITY = false; - this.NETWORKS = true; + this.reversedComparator = false; + this.useAntiQSort = false; + this.stabilityChecking = false; + this.visualizingNetworks = true; break; } } - + public boolean generateSortingNetworks() { - return this.NETWORKS; + return this.visualizingNetworks; } public boolean useAntiQSort() { - return this.ANTIQSORT; + return this.useAntiQSort; } public void initAntiQSort() { - this.AntiQSort.beginSort(this.array, this.sortLength); + this.antiQSort.beginSort(this.array, this.sortLength); } public void finishAntiQSort(String name) { - int[] result = this.AntiQSort.getResult(); - this.AntiQSort.hideResult(); + int[] result = this.antiQSort.getResult(); + this.antiQSort.hideResult(); String outName = "antiqsort_" + name + "_" + this.sortLength; if (!ArrayFileWriter.writeArray(outName, result, sortLength)) { return; @@ -762,20 +908,20 @@ public void finishAntiQSort(String name) { JOptionPane.showMessageDialog(null, "Successfully saved output to file \"" + outName + "\"", "AntiQSort", JOptionPane.INFORMATION_MESSAGE); } public int antiqCompare(int left, int right) { - int cmp = this.AntiQSort.compare(left, right); + int cmp = this.antiQSort.compare(left, right); if (cmp == 0) return 0; return cmp / Math.abs(cmp); } public boolean doingStabilityCheck() { - return this.STABILITY; + return this.stabilityChecking; } public boolean reversedComparator() { - return this.REVERSED; + return this.reversedComparator; } - + // These next five methods should be part of ArrayManager public int getCurrentLength() { return this.sortLength; @@ -796,21 +942,22 @@ public void setUniqueItems(int newCount) { public int getUniqueItems() { return uniqueItems; } - + public int getLogBaseNOfLength(int base) { - return (int) (Math.log(this.sortLength) / Math.log(base)); + return (int) (Math.log(this.sortLength) / Math.log(base)); } public int getLogBaseTwoOfLength() { - return getLogBaseNOfLength(2); + return getLogBaseNOfLength(2); } - + public boolean shuffleEnabled() { - return this.SHUFFLEANIM; + return this.showShuffleAnimation; } - public void toggleShuffleAnimation(boolean Bool) { - this.SHUFFLEANIM = Bool; + + public void toggleShuffleAnimation(boolean showShuffleAnimation) { + this.showShuffleAnimation = showShuffleAnimation; } - + public String getCategory() { return this.category; } @@ -830,25 +977,30 @@ public void setExtraHeading(String text) { this.extraHeading = text; } + /** + * @deprecated No longer does anything (always returns {@code false}) + * @return {@code false} + */ + @Deprecated public boolean pointerActive() { - return this.POINTER; + return false; } - + public JFrame getMainWindow() { return this.window; } - + public void setWindowHeight() { this.ch = this.window.getHeight(); } public void setWindowWidth() { this.cw = this.window.getWidth(); } - + // TODO: // CURRENT HEIGHT/WIDTH/X/Y SHOULD CORRESPOND TO "C" VARIABLES // AND WINDOW HEIGHT/WIDTH/X/Y SHOULD CORRESPOND TO WINDOW FIELD - + public int currentHeight() { return this.window.getHeight(); } @@ -861,7 +1013,7 @@ public int currentX() { public int currentY() { return this.window.getY(); } - + public int windowHeight() { return this.ch; } @@ -880,24 +1032,21 @@ public int windowXCoordinate() { public int windowYCoordinate() { return this.cy; } - + public Color getHighlightColor() { - if(this.colorEnabled()) { - if(this.analysisEnabled()) + if (this.colorEnabled()) { + if (this.analysisEnabled()) return Color.LIGHT_GRAY; - else return Color.WHITE; - } - else { - if(this.analysisEnabled()) + } else { + if (this.analysisEnabled()) return Color.BLUE; - else return Color.RED; } } - + public void createVolatileImage() { this.img = this.window.getGraphicsConfiguration().createCompatibleVolatileImage(this.cw, this.ch); } @@ -926,19 +1075,19 @@ public void setExtraRender() { this.extraRender = (Graphics2D) this.img.getGraphics(); } public void updateVisuals() { - for(Visual visual : this.visualClasses) { + for (Visual visual : this.visualClasses) { visual.updateRender(this); } } public void resetMainStroke() { this.mainRender.setStroke(this.getDefaultStroke()); } - + public void renderBackground() { this.mainRender.setColor(new Color(0, 0, 0)); // Pure black this.mainRender.fillRect(0, 0, this.img.getWidth(null), this.img.getHeight(null)); } - + public void updateCoordinates() { this.cx = this.window.getX(); this.cy = this.window.getY(); @@ -951,81 +1100,82 @@ public double getWindowRatio() { return this.cw / 1280d; } public void updateFontSize() { - this.typeFace = new Font(this.fontSelection, Font.PLAIN, (int) (this.getWindowRatio() * 25)); + this.typeFace = new Font(fontSelection, Font.PLAIN, (int) (this.getWindowRatio() * fontSelectionScale)); this.mainRender.setFont(this.typeFace); } - - public void toggleAnalysis(boolean Bool) { - this.ANALYZE = Bool; + + public void toggleAnalysis(boolean highlightAsAnalysis) { + this.highlightAsAnalysis = highlightAsAnalysis; } + public boolean analysisEnabled() { - return this.ANALYZE; + return this.highlightAsAnalysis; } - + public int halfCircle() { return (this.sortLength / 2); } - + //TODO: This method is *way* too long. Break it apart. public synchronized void verifySortAndSweep() { this.Highlights.toggleFancyFinish(true); this.Highlights.resetFancyFinish(); - + this.Delays.setSleepRatio(1); double sleepRatio = 256d/this.sortLength; long tempComps = this.Reads.getComparisons(); this.Reads.setComparisons(0); - + String temp = this.heading; this.heading = "Verifying sort..."; - int cmpVal = this.REVERSED ? -1 : 1; - + int cmpVal = this.reversedComparator ? -1 : 1; + boolean success = true, stable = true; int unstableIdx = 0; boolean validate = this.validateArray != null; boolean validateFailed = false; int invalidateIdx = 0; - - for(int i = 0; i < this.sortLength + this.getLogBaseTwoOfLength(); i++) { - if(i < this.sortLength) this.Highlights.markArray(1, i); + + for (int i = 0; i < this.sortLength + this.getLogBaseTwoOfLength(); i++) { + if (i < this.sortLength) this.Highlights.markArray(1, i); this.Highlights.incrementFancyFinishPosition(); - - if(i < this.sortLength - 1) { + + if (i < this.sortLength - 1) { if (validate && !validateFailed && this.Reads.compareOriginalValues(this.array[i], this.validateArray[i]) != 0) { validateFailed = true; invalidateIdx = i; } - if(stable && this.Reads.compareOriginalValues(this.array[i], this.array[i + 1]) == cmpVal) { + if (stable && this.Reads.compareOriginalValues(this.array[i], this.array[i + 1]) == cmpVal) { stable = false; unstableIdx = i; } - if(this.Reads.compareValues(this.array[i], this.array[i + 1]) == cmpVal) { + if (this.Reads.compareValues(this.array[i], this.array[i + 1]) == cmpVal) { this.Highlights.clearMark(1); - + boolean tempSound = this.Sounds.isEnabled(); this.Sounds.toggleSound(false); this.Highlights.toggleFancyFinish(false); - - for(int j = i + 1; j < this.sortLength; j++) { + + for (int j = i + 1; j < this.sortLength; j++) { this.Highlights.markArray(j, j); this.Delays.sleep(sleepRatio); } - - JOptionPane.showMessageDialog(this.window, "The sort was unsuccessful;\nIndices " + i + " and " + (i + 1) + " are out of order!", "Error", JOptionPane.OK_OPTION, null); + + JOptionPane.showMessageDialog(this.window, "The sort was unsuccessful;\nIndices " + i + " and " + (i + 1) + " are out of order!", "Error", JOptionPane.ERROR_MESSAGE, null); success = false; - + this.Highlights.clearAllMarks(); - + i = this.sortLength + this.getLogBaseTwoOfLength(); - + this.Sounds.toggleSound(tempSound); } } - - if(this.Highlights.fancyFinishEnabled()) { + + if (this.Highlights.fancyFinishEnabled()) { this.Delays.sleep(sleepRatio); } } @@ -1033,33 +1183,32 @@ public synchronized void verifySortAndSweep() { // if (tempStability && success) // JOptionPane.showMessageDialog(this.window, "This sort is stable!", "Information", JOptionPane.OK_OPTION, null); - if(this.STABILITY && success && !stable) { + if (this.stabilityChecking && success && !stable) { boolean tempSound = this.Sounds.isEnabled(); this.Sounds.toggleSound(false); this.Highlights.toggleFancyFinish(false); - - for(int j = unstableIdx; j < this.sortLength; j++) { + + for (int j = unstableIdx; j < this.sortLength; j++) { this.Highlights.markArray(j, j); this.Delays.sleep(sleepRatio); } - - JOptionPane.showMessageDialog(this.window, "This sort is not stable;\nIndices " + unstableIdx + " and " + (unstableIdx + 1) + " are out of order!", "Error", JOptionPane.OK_OPTION, null); - + + JOptionPane.showMessageDialog(this.window, "This sort is not stable;\nIndices " + unstableIdx + " and " + (unstableIdx + 1) + " are out of order!", "Error", JOptionPane.ERROR_MESSAGE, null); + this.Highlights.clearAllMarks(); this.Sounds.toggleSound(tempSound); - } - else if(success && validateFailed) { + } else if (success && validateFailed) { boolean tempSound = this.Sounds.isEnabled(); this.Sounds.toggleSound(false); this.Highlights.toggleFancyFinish(false); - - for(int j = invalidateIdx + 1; j < this.sortLength; j++) { + + for (int j = invalidateIdx + 1; j < this.sortLength; j++) { this.Highlights.markArray(j, j); this.Delays.sleep(sleepRatio); } - - JOptionPane.showMessageDialog(this.window, "The sort was unsuccessful;\narray[" + invalidateIdx + "] != validateArray[" + invalidateIdx + "]", "Error", JOptionPane.OK_OPTION, null); - + + JOptionPane.showMessageDialog(this.window, "The sort was unsuccessful;\narray[" + invalidateIdx + "] != validateArray[" + invalidateIdx + "]", "Error", JOptionPane.ERROR_MESSAGE, null); + this.Highlights.clearAllMarks(); this.Sounds.toggleSound(tempSound); } @@ -1070,25 +1219,25 @@ else if(success && validateFailed) { if (this.benchmarking) { JOptionPane.showMessageDialog(this.window, "The sort took a total of " + this.Timer.getRealTime()); } - - if(this.Highlights.fancyFinishActive()) { + + if (this.Highlights.fancyFinishActive()) { this.Highlights.toggleFancyFinish(false); } this.Highlights.resetFancyFinish(); } public String formatTimes() { - String result = ""; + StringBuilder result = new StringBuilder(); Hashtable categoricalTimes = this.Timer.getCategoricalTimes(); for (Map.Entry keyValuePair : categoricalTimes.entrySet()) { - result += keyValuePair.getKey() + ":\t" + this.Timer.prettifyTime(keyValuePair.getValue()) + "\n"; + result.append(keyValuePair.getKey()).append(":\t").append(this.Timer.prettifyTime(keyValuePair.getValue())).append("\n"); } String totalTime = this.Timer.getRealTime(); - result += "--------------------\nTotal:\t" + totalTime; + result.append("--------------------\nTotal:\t").append(totalTime); - return result; + return result.toString(); } public void endSort() { @@ -1098,7 +1247,7 @@ public void endSort() { this.isCanceled = false; this.Delays.changeSkipped(false); - double speed = this.Delays.getSleepRatio(); + double speed = this.Delays.getSleepRatio(); this.verifySortAndSweep(); this.Delays.setSleepRatio(speed); @@ -1107,48 +1256,75 @@ public void endSort() { this.Highlights.clearAllMarks(); } - - public void togglePointer(boolean Bool) { - this.POINTER = Bool; + + /** + * @deprecated No longer does anything + */ + @Deprecated + public void togglePointer(boolean showPointer) { } - public void toggleDistance(boolean Bool) { - this.DISPARITYDRAW = Bool; + + /** + * @deprecated No longer does anything + */ + @Deprecated + public void toggleDistance(boolean unused) { } - public void togglePixels(boolean Bool) { - this.PIXELDRAW = Bool; + + /** + * @deprecated No longer does anything + */ + @Deprecated + public void togglePixels(boolean usePixels) { } - public void toggleRainbow(boolean Bool) { - this.RAINBOW = Bool; + + /** + * @deprecated No longer does anything + */ + @Deprecated + public void toggleRainbow(boolean rainbow) { } - public void toggleSpiral(boolean Bool) { - this.SPIRALDRAW = Bool; + + /** + * @deprecated No longer does anything + */ + @Deprecated + public void toggleSpiral(boolean spiral) { } - public void toggleLinkedDots(boolean Bool) { - this.LINEDRAW = Bool; + + public void toggleLinkedDots(boolean showLines) { + this.showLines = showLines; } - public void toggleStatistics(boolean Bool) { - this.TEXTDRAW = Bool; + + public void toggleStatistics(boolean showStatistics) { + this.showStatistics = showStatistics; } - public void toggleColor(boolean Bool) { - this.COLOR = Bool; + + public void toggleColor(boolean showColor) { + this.showColor = showColor; } - public void toggleWave(boolean Bool) { - this.WAVEDRAW = Bool; + + /** + * @deprecated No longer does anything + */ + @Deprecated + public void toggleWave(boolean useWave) { } - public void toggleExternalArrays(boolean Bool) { - this.EXTARRAYS = Bool; + + public void toggleExternalArrays(boolean showExternalArrays) { + this.showExternalArrays = showExternalArrays; } - + public void setVisual(VisualStyles choice) { - if(choice == visuals.VisualStyles.CUSTOM_IMAGE) { + if (choice == io.github.arrayv.visuals.VisualStyles.CUSTOM_IMAGE) { ((CustomImage) this.visualClasses[9]).enableImgMenu(); } - this.VisualStyles = choice; + this.visualStyle = choice; synchronized (this) { this.updateNow(); } } - + public int getCurrentGap() { return this.currentGap; } @@ -1162,99 +1338,158 @@ public boolean sortCanceled() { public void setCanceled(boolean canceled) { this.isCanceled = canceled; } - + public void repositionFrames() { - this.ArrayFrame.reposition(); - this.UtilFrame.reposition(this.ArrayFrame); + this.arrayFrame.reposition(); + this.utilFrame.reposition(this.arrayFrame); } - + + /** + * @deprecated No longer does anything (always returns {@code false}) + * @return {@code false} + */ + @Deprecated public boolean rainbowEnabled() { - return this.RAINBOW; + return false; } + public boolean colorEnabled() { - return this.COLOR; + return this.showColor; } + + /** + * @deprecated No longer does anything (always returns {@code false}) + * @return {@code false} + */ + @Deprecated public boolean spiralEnabled() { - return this.SPIRALDRAW; + return false; } + + /** + * @deprecated No longer does anything (always returns {@code false}) + * @return {@code false} + */ + @Deprecated public boolean distanceEnabled() { - return this.DISPARITYDRAW; + return false; } + + /** + * @deprecated No longer does anything (always returns {@code false}) + * @return {@code false} + */ + @Deprecated public boolean pixelsEnabled() { - return this.PIXELDRAW; + return false; } + public boolean linesEnabled() { - return this.LINEDRAW; + return this.showLines; } + + /** + * @deprecated No longer does anything (always returns {@code false}) + * @return {@code false} + */ + @Deprecated public boolean waveEnabled() { - return this.WAVEDRAW; + return false; } + public boolean externalArraysEnabled() { - return this.EXTARRAYS; + return this.showExternalArrays; } - + public DecimalFormat getNumberFormat() { return this.formatter; } - + private static String parseStringArray(String[] stringArray) { - String parsed = ""; - for(int i = 0; i < stringArray.length; i++) { - parsed += stringArray[i] + "\n"; + StringBuilder parsed = new StringBuilder(); + for (String s : stringArray) { + parsed.append(s).append("\n"); } - return parsed; + return parsed.toString(); } - + private void drawWindows() { - this.VisualStyles = visuals.VisualStyles.BARS; + this.visualStyle = io.github.arrayv.visuals.VisualStyles.BARS; this.category = "Select a Sort"; - + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.window.setSize((int) (screenSize.getWidth() / 2), (int) (screenSize.getHeight() / 2)); - + + StringBuilder title = new StringBuilder("w0rthy's Array Visualizer - "); + title.append(this.sorts.length); + title.append(" Sorts, 15 Visual Styles, and Infinite Inputs to Sort"); + String versionName = buildInfo.getProperty("version"); + String commitSha = buildInfo.getProperty("commitId"); + if (commitSha != null || versionName != null) { + title.append(" ("); + if (versionName != null) { + title.append("version ").append(versionName); + if (commitSha != null) { + title.append(", "); + } + } + if (commitSha != null) { + title.append("commit ").append(commitSha); + } + title.append(')'); + } + this.window.setLocation(0, 0); this.window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - this.window.setTitle("w0rthy's Array Visualizer - " + (this.ComparisonSorts.length + this.DistributionSorts.length) + " Sorts, 15 Visual Styles, and Infinite Inputs to Sort"); + this.window.setTitle(title.toString()); this.window.setBackground(Color.BLACK); this.window.setIgnoreRepaint(true); - + this.window.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(WindowEvent close) { ArrayVisualizer.this.Sounds.closeSynth(); ArrayVisualizer.this.visualsEnabled = false; - if(ArrayVisualizer.this.isActive()) { + if (ArrayVisualizer.this.isActive()) { ArrayVisualizer.this.sortingThread.interrupt(); } } }); - + //TODO: Consider removing insets from window size this.cw = this.window.getWidth(); this.ch = this.window.getHeight(); this.window.setVisible(true); this.visualsThread.start(); - this.UtilFrame.setVisible(true); - this.ArrayFrame.setVisible(true); - + this.utilFrame.setVisible(true); + this.arrayFrame.setVisible(true); + this.window.createBufferStrategy(2); - - if(this.InvalidSorts != null) { - String output = parseStringArray(this.InvalidSorts); + + if (this.invalidSorts != null) { + String output = parseStringArray(this.invalidSorts); JOptionPane.showMessageDialog(this.window, "The following algorithms were not loaded:\n" + output, "Warning", JOptionPane.WARNING_MESSAGE); } - if(this.sortSuggestions != null) { + if (this.sortSuggestions != null) { String output = parseStringArray(this.sortSuggestions); JOptionPane.showMessageDialog(this.window, "Here's a list of suggestions based on your sorts:\n" + output, "Info", JOptionPane.INFORMATION_MESSAGE); } } - public static void main(String[] args) { + public boolean isDisabledStabilityCheck() { + return disabledStabilityCheck; + } + + public static int getMaxLengthPower() { + return maxLengthPower; + } + + public static void main(String[] args) throws IOException { System.setProperty("sun.java2d.d3d", "false"); if (args.length > 0) { - ArrayVisualizer.MAX_LENGTH_POWER = Integer.parseInt(args[0]); + ArrayVisualizer.maxLengthPower = Integer.parseInt(args[0]); } new ArrayVisualizer(); } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/main/RunSort.java b/src/main/java/io/github/arrayv/main/RunSort.java new file mode 100644 index 00000000..3dae9e7b --- /dev/null +++ b/src/main/java/io/github/arrayv/main/RunSort.java @@ -0,0 +1,247 @@ +package io.github.arrayv.main; + +import io.github.arrayv.panes.JEnhancedOptionPane; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.sortdata.SortInfo; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.utils.Timer; +import io.github.arrayv.utils.*; + +import javax.swing.*; +import java.util.ArrayList; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class RunSort { + private final ArrayManager arrayManager; + private final ArrayVisualizer arrayVisualizer; + private final Delays delayOps; + private final Sounds sounds; + private final Timer realTimer; + + private final Object[] inputOptions; + + public RunSort(ArrayVisualizer arrayVisualizer) { + this.arrayVisualizer = arrayVisualizer; + this.arrayManager = arrayVisualizer.getArrayManager(); + this.delayOps = arrayVisualizer.getDelays(); + this.sounds = arrayVisualizer.getSounds(); + this.realTimer = arrayVisualizer.getTimer(); + + this.inputOptions = new Object[]{"Enter", "Use default"}; + } + + private String getTimeSortEstimate(int bucketCount) { + String timeString; + String timeUnit; + + int seconds = Math.max(((arrayVisualizer.getCurrentLength() * bucketCount) / 1000), 1); + int minutes; + int hours; + long days; + + if (seconds >= 60) { + minutes = Math.round(seconds / 60f); + + if (minutes >= 60) { + hours = Math.round(minutes / 60f); + + if (hours >= 24) { + days = Math.round(hours / 24f); + + if (days < 2) timeUnit = "day"; + else timeUnit = "days"; + + timeString = "" + arrayVisualizer.getNumberFormat().format(days) + " " + timeUnit + " "; + } else { + if (hours < 2) timeUnit = "hour"; + else timeUnit = "hours"; + + timeString = "" + hours + " " + timeUnit + " "; + } + } else { + if (minutes < 2) timeUnit = "minute"; + else timeUnit = "minutes"; + + timeString = "" + minutes + " " + timeUnit + " "; + } + } else { + if (seconds < 2) timeUnit = "second"; + else timeUnit = "seconds"; + + timeString = "" + seconds + " " + timeUnit + " "; + } + + return timeString; + } + + private int getCustomInput(String text) { + String input = JEnhancedOptionPane.showInputDialog("Customize Sort", text, this.inputOptions); + //noinspection DataFlowIssue + int integer = Integer.parseInt(input); + return Math.abs(integer); + } + + public void runSort(int[] array, int selection) { + if (arrayVisualizer.isActive()) + return; + + //TODO: This code is bugged! It causes the program to forget the sleep ratio specified by the user! + if (delayOps.skipped()) { + delayOps.setSleepRatio(1); + delayOps.changeSkipped(false); + } + + double storeVol = sounds.getVolume(); + sounds.toggleSound(true); + arrayVisualizer.setSortingThread(new Thread("ComparisonSorting") { + @Override + public void run() { + try { + SortInfo sortInfo = arrayVisualizer.getSorts()[selection]; + int extra; + + if (sortInfo.getQuestion() != null) { + try { + extra = sortInfo.validateAnswer(getCustomInput(sortInfo.getQuestion())); + } catch (Exception e) { + extra = sortInfo.getDefaultAnswer(); + } + } else if (sortInfo.isBucketSort()) { + if (sortInfo.isRadixSort()) { + try { + extra = getCustomInput("Enter the base for this sort:"); + } catch (Exception e) { + extra = 4; + } + } else if (sortInfo.getRunName().contains("Shatter")) { + try { + extra = getCustomInput("Enter the size for each partition:"); + } catch (Exception e) { + extra = arrayVisualizer.getCurrentLength() / 16; + } + } else { + try { + extra = getCustomInput("How many buckets will this sort use?"); + } catch (Exception e) { + extra = 16; + } + } + if (extra < 2) extra = 2; + } else { + extra = 0; + } + + boolean goAhead; + + if (sortInfo.getRunName().equals("Timesort")) { + Object[] options = { "Continue", "Cancel" }; + + int warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Time Sort will take at least " + getTimeSortEstimate(extra) + + "to complete. Once it starts, you cannot skip this sort.", "Warning!", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, + null, options, options[1]); + + goAhead = warning == 0; + } else if (sortInfo.getUnreasonableLimit() > 0 && arrayVisualizer.getCurrentLength() > sortInfo.getUnreasonableLimit()) { + + Object[] options = { "Let's see how bad " + sortInfo.getRunName() + " is!", "Cancel" }; + + int warning; + if (sortInfo.isBogoSort()) { + warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Even at a high speed, " + + sortInfo.getRunName() + "ing " + arrayVisualizer.getCurrentLength() + + " numbers will almost certainly not finish in a reasonable amount of time. " + + "Are you sure you want to continue?", "Warning!", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, + null, options, options[1] + ); + } else { + warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Even at a high speed, " + + sortInfo.getRunName() + "ing " + arrayVisualizer.getCurrentLength() + + " numbers will not finish in a reasonable amount of time. " + + "Are you sure you want to continue?", "Warning!", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, + null, options, options[1] + ); + + } + goAhead = warning == 0; + } else { + goAhead = true; + } + + if (goAhead) { + Sort sortInstance = sortInfo.getFreshInstance(); + + if (sortInfo.getRunName().equals("In-Place LSD Radix")) { + sounds.changeVolume(0.01); // Here to protect your ears :) + } + + arrayManager.toggleMutableLength(false); + arrayManager.refreshArray(array, arrayVisualizer.getCurrentLength(), arrayVisualizer); + + arrayVisualizer.setHeading(sortInfo.getRunName()); + arrayVisualizer.setCategory(sortInfo.getCategory()); + + realTimer.enableRealTimer(); + boolean antiq = arrayVisualizer.useAntiQSort(); + boolean networks = arrayVisualizer.generateSortingNetworks(); + if (antiq) + arrayVisualizer.initAntiQSort(); + try { + sortInstance.runSort(array, arrayVisualizer.getCurrentLength(), extra); + } catch (StopSort ignored) { + } catch (OutOfMemoryError e) { + JErrorPane.invokeCustomErrorMessage(sortInfo.getRunName() + " ran out of memory: " + e.getMessage()); + throw new RuntimeException(e); + } + + if (antiq) + arrayVisualizer.finishAntiQSort(sortInfo.getClass().getSimpleName()); + else if (networks) { + ArrayList indicesList = arrayVisualizer.getReads().getNetworkIndices(); + SortingNetworkGenerator.encodeNetworkAndDisplay( + sortInfo.getClass().getSimpleName(), + indicesList, + arrayVisualizer.getCurrentLength() + ); + } + } else { + arrayManager.initializeArray(array); + } + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + arrayVisualizer.endSort(); + arrayManager.toggleMutableLength(true); + sounds.changeVolume(storeVol); + sounds.toggleSound(false); + System.gc(); // Reduce RAM usage from any high-memory tasks (e.g. visualizing a sorting network) + } + }); + + arrayVisualizer.runSortingThread(); + } +} diff --git a/src/main/java/io/github/arrayv/main/SortAnalyzer.java b/src/main/java/io/github/arrayv/main/SortAnalyzer.java new file mode 100644 index 00000000..801788ed --- /dev/null +++ b/src/main/java/io/github/arrayv/main/SortAnalyzer.java @@ -0,0 +1,764 @@ +package io.github.arrayv.main; + +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.sortdata.SortComparator; +import io.github.arrayv.sortdata.SortInfo; +import io.github.arrayv.sortdata.SortNameType; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.utils.CommonUtils; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ClassInfo; +import io.github.classgraph.ScanResult; + +import javax.swing.*; +import javax.tools.*; +import javax.tools.JavaCompiler.CompilationTask; +import java.awt.*; +import java.io.*; +import java.lang.reflect.Method; +import java.net.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.*; +import java.util.stream.StreamSupport; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/* + * +The MIT License (MIT) + +Copyright (c) 2019 Luke Hutchison +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class SortAnalyzer { + private static final URL EXTRA_SORTS_DOWNLOAD; + private static final String EXTRA_SORTS_JAR_NAME = "ArrayV-Extra-Sorts.jar"; + private static final File EXTRA_SORTS_FILE = new File("cache", EXTRA_SORTS_JAR_NAME); + private static final URLClassLoader EXTRA_SORTS_CLASS_LOADER; + private static final Map.Entry[] IMPORT_REPLACEMENTS = CommonUtils.createPairArray( + "import dialogs.", "import io.github.arrayv.dialogs.", + "import frames.", "import io.github.arrayv.frames.", + "import main.", "import io.github.arrayv.main.", + "import panels.", "import io.github.arrayv.panels.", + "import panes.", "import io.github.arrayv.panes.", + "import prompts.", "import io.github.arrayv.prompts.", + "import sorts.", "import io.github.arrayv.sorts.", + "import threads.", "import io.github.arrayv.threads.", + "import utils.", "import io.github.arrayv.utils.", + "import visuals.", "import io.github.arrayv.visuals.", + "import sorts.templates.SortComparator;", "import io.github.arrayv.sortdata.SortComparator;" + ); + + private final Set> extraSorts = new HashSet<>(); + private final Map> sortsByName = new EnumMap<>(SortNameType.class); + + static { + try { + EXTRA_SORTS_DOWNLOAD = new URL("https://nightly.link/Gaming32/ArrayV-Extra-Sorts/workflows/build/main/extra-sorts-jar.zip"); + EXTRA_SORTS_CLASS_LOADER = new URLClassLoader(new URL[] { + EXTRA_SORTS_FILE.toURI().toURL() + }); + } catch (MalformedURLException e) { + throw new Error(e); + } + } + + private final ArrayList sorts; + private final ArrayList invalidSorts; + private final ArrayList suggestions; + + private String sortErrorMsg; + + private final ArrayVisualizer arrayVisualizer; + + SortAnalyzer(ArrayVisualizer arrayVisualizer) { + this.sorts = new ArrayList<>(); + this.invalidSorts = new ArrayList<>(); + this.suggestions = new ArrayList<>(); + + this.arrayVisualizer = arrayVisualizer; + } + + public boolean didSortComeFromExtra(Sort sort) { + return didSortComeFromExtra(sort.getClass()); + } + + public boolean didSortComeFromExtra(Class sort) { + return extraSorts.contains(sort); + } + + public SortInfo addSort(SortInfo sort) { + sort = sort.withId(sorts.size()); + sorts.add(sort); + addSortByName(sort); + return sort; + } + + /** + * Like {@link #addSort}, but also sorts it. + * This is equivalent to, but more efficient than: + *
+     * addSort(sort);
+     * sortSorts();
+     * 
+ */ + public SortInfo insortSort(SortInfo sort) { + int position = Collections.binarySearch(sorts, sort, new SortComparator()); + if (position < 0) { + // Not found (good) + position = -position - 1; + } + sort = sort.withId(position); + sorts.add(null); + for (int i = sorts.size() - 1; i > position; i--) { + sorts.set(i, sorts.get(i - 1).withId(i)); + } + sorts.set(position, sort); + addSortByName(sort); + return sort; + } + + private void setSortCameFromExtra(Class sort) { + extraSorts.add(sort); + } + + @SuppressWarnings("unchecked") + private boolean compileSingle(String name, ClassLoader loader) { + Class sortClass; + try { + if (loader == null) + sortClass = Class.forName(name); + else + sortClass = Class.forName(name, true, loader); + if (!Sort.class.isAssignableFrom(sortClass)) { + throw new IllegalArgumentException(sortClass + " does not subclass Sort"); + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return true; + } + return compileSingle((Class)sortClass); + } + + private boolean compileSingle(Class sortClass) { + try { + if (sortClass.getClassLoader() == EXTRA_SORTS_CLASS_LOADER) { + setSortCameFromExtra(sortClass); + } + SortInfo sort = new SortInfo(sorts.size(), sortClass); + + try { + if (verifySort(sort)) { + String suggestion = checkForSuggestions(sort); + if (!suggestion.isEmpty()) { + suggestions.add(suggestion); + } + sorts.add(sort); + addSortByName(sort); + } else if (sortErrorMsg != null) { + throw new Exception(sortErrorMsg); + } else { + return false; + } + } catch (Exception e) { + invalidSorts.add(sort.getInternalName() + " (" + e.getMessage() + ")"); + return false; + } + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e, "Could not load " + sortClass.getName()); + invalidSorts.add(sortClass.getName() + " (failed to load)"); + return false; + } + return true; + } + + private Map getSortNameCategory(SortNameType type) { + return sortsByName.computeIfAbsent(type, k -> new HashMap<>()); + } + + private void addSortByName(SortInfo sort) { + if (sort.getInternalName() != null) { + getSortNameCategory(SortNameType.INTERNAL_NAME).put(sort.getInternalName(), sort); + } + getSortNameCategory(SortNameType.LIST_NAME).put(sort.getListName(), sort); + getSortNameCategory(SortNameType.RUN_NAME).put(sort.getRunName(), sort); + getSortNameCategory(SortNameType.SHOWCASE_NAME).put(sort.getRunAllName(), sort); + } + + public SortInfo getSortByName(SortNameType nameType, String name) { + return getSortNameCategory(nameType).get(name); + } + + private ClassGraph classGraph(boolean includeExtras) { + ClassGraph classGraph = new ClassGraph() + .acceptPackages("sorts", "io.github.arrayv.sorts") + .rejectPackages("sorts.templates", "io.github.arrayv.sorts.templates") + .initializeLoadedClasses(); + if (includeExtras && extraSortsInstalled()) { + classGraph.addClassLoader(EXTRA_SORTS_CLASS_LOADER); + } + return classGraph; + } + + public void analyzeSorts() { + analyzeSorts(true); + } + + public void analyzeSorts(boolean includeExtras) { + this.sorts.clear(); + this.invalidSorts.clear(); + this.suggestions.clear(); + this.sortErrorMsg = null; + this.sortsByName.clear(); + analyzeSorts(classGraph(includeExtras)); + } + + public void analyzeSortsExtrasOnly() { + if (!extraSortsInstalled()) return; + // analyzeSorts( + // classGraph(true) + // .whitelistJars(EXTRA_SORTS_FILE.getName()) + // ); + // Custom sort analysis so sorts don't get duplicated + try { + try (ZipFile zf = new ZipFile(EXTRA_SORTS_FILE)) { + for (final Enumeration en = zf.entries(); en.hasMoreElements();) { + ZipEntry entry = en.nextElement(); + if (entry.isDirectory()) continue; + String name = entry.getName(); + if (!name.endsWith(".class")) continue; + String nameNoExt = name.substring(0, name.length() - 6); + if (!nameNoExt.startsWith("sorts") && !nameNoExt.startsWith("io/github/arrayv/sorts")) continue; + if (nameNoExt.contains("$")) continue; + String className = nameNoExt.replace('/', '.'); + this.compileSingle(className, EXTRA_SORTS_CLASS_LOADER); + } + } + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException)e; // rethrow + } + throw new RuntimeException(e); + } + } + + public void analyzeSorts(ClassGraph classGraph) { + try (ScanResult scanResult = classGraph.scan()) { + List sortFiles; + sortFiles = scanResult.getAllClasses(); + + for (ClassInfo sortFile : sortFiles) { + if (sortFile.getName().contains("$")) continue; // Ignore inner classes + this.compileSingle(sortFile.loadClass(Sort.class)); + } + sortSorts(); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + } + + public boolean extraSortsInstalled() { + return EXTRA_SORTS_FILE.isFile(); + } + + public void installOrUpdateExtraSorts() throws IOException { + installOrUpdateExtraSorts(null); + } + + public void unloadAllExtraSorts() { + int j = 0; + for (SortInfo sort : sorts) { + if (!sort.isFromExtra()) { + sorts.set(j++, sort); + } + } + sorts.subList(j, sorts.size()).clear(); + extraSorts.clear(); + } + + public void installOrUpdateExtraSorts(ProgressMonitor monitor) throws IOException { + final File CACHE_DIR = EXTRA_SORTS_FILE.getParentFile(); + CACHE_DIR.mkdirs(); + final File DOWNLOAD_TEMP_FILE = File.createTempFile("avdownload-", ".zip", CACHE_DIR); + DOWNLOAD_TEMP_FILE.deleteOnExit(); // Really just a safeguard in case installOrUpdateExtraSorts fails + URLConnection connection = EXTRA_SORTS_DOWNLOAD.openConnection(); + int totalProgress = 0; + int partProgress = 0; + int partLength = 0; + if (monitor != null) { + monitor.setMinimum(0); + final int contentLength = (int)connection.getContentLengthLong(); + if (contentLength > 0) { // Negative if size unknown or overflow + partLength = contentLength; + monitor.setMaximum(contentLength * 2); + } else if (EXTRA_SORTS_FILE.isFile()) { + // We can estimate the download size from the previous file if this is an update + final int fileLength = (int)EXTRA_SORTS_FILE.length(); + if (fileLength > 0) { + partLength = fileLength; + monitor.setMaximum(fileLength * 2); + } else { + partLength = -1; + } + } else { + partLength = -1; + } + monitor.setNote("Downloading..."); + monitor.setProgress(0); + } + try ( + InputStream is = connection.getInputStream(); + OutputStream os = new FileOutputStream(DOWNLOAD_TEMP_FILE); + ) { + byte[] buffer = new byte[8192]; + int len; + while ((len = is.read(buffer)) != -1) { + if (monitor != null && partLength != -1) { + totalProgress += len; + partProgress += len; + monitor.setProgress(totalProgress); + monitor.setNote("Downloading... (" + partProgress / 1024 + " KB/" + partLength / 1024 + " KB)"); + } + os.write(buffer, 0, len); + } + } + try (ZipFile zf = new ZipFile(DOWNLOAD_TEMP_FILE)) { + final ZipEntry EXTRA_SORTS_JAR_ENTRY = zf.getEntry(EXTRA_SORTS_JAR_NAME); + if (monitor != null) { + final int size = (int)EXTRA_SORTS_JAR_ENTRY.getSize(); + if (size > 0) { // Negative if size unknown or overflow (extremely unlikely) + partLength = size; + monitor.setMaximum(totalProgress + size); + } else { + partLength = -1; + } + partProgress = 0; + monitor.setNote("Extracting..."); + } + try ( + InputStream is = zf.getInputStream(EXTRA_SORTS_JAR_ENTRY); + OutputStream os = new FileOutputStream(EXTRA_SORTS_FILE); + ) { + byte[] buffer = new byte[8192]; + int len; + while ((len = is.read(buffer)) != -1) { + if (monitor != null && partLength != -1) { + totalProgress += len; + partProgress += len; + monitor.setProgress(totalProgress); + monitor.setNote("Extracting... (" + partProgress / 1024 + " KB/" + partLength / 1024 + " KB)"); + } + os.write(buffer, 0, len); + } + } + } + DOWNLOAD_TEMP_FILE.delete(); // Might as well do it now + } + + private static final class JavaPackageNameFinder { + final String source; + int i, c; + + JavaPackageNameFinder(String source) { + this.source = source; + } + + String findPackageName() { + i = 0; + while (true) { + if (skipWhitespace()) break; + + if (c == '/') { + if (advance()) break; + if (c == '/') { + while (true) { + if (advance() || c == '\n') break; + } + } else if (c == '*') { + while (true) { + if (advance()) break; + if (c == '*' && (advance() || c == '/')) break; + } + } else { + throw new IllegalArgumentException("/ by itself (not part of a comment) before class declaration"); + } + continue; + } + + if (c == 'p') { + if (advance() || c == 'u') break; // public + if (c != 'a') throw new IllegalArgumentException("Except u or a after p"); + expectWord("ckage", "package"); + if (skipWhitespace()) throw new IllegalArgumentException("Expect package name"); + return readPackageName(); + } + + if (c == 'i' || c == 'a' || c == 'c' || c == 'r' || c == 'e' || c == 'f') break; + } + return ""; + } + + private String readPackageName() { + StringBuilder result = new StringBuilder(); + boolean isAfterDot = true; + do { + // @checkstyle:off IndentationCheck - It looks nicer how it is + if (isAfterDot) { + if (Character.isJavaIdentifierStart(c)) { + result.appendCodePoint(c); + } else { + throw new IllegalArgumentException("Illegal character in package name: " + new String(Character.toChars(c))); + } + isAfterDot = false; + } else { + if (Character.isJavaIdentifierPart(c)) { + result.appendCodePoint(c); + } else if (c == '.') { + result.append('.'); + isAfterDot = true; + } else { + throw new IllegalArgumentException("Illegal character in package name: " + new String(Character.toChars(c))); + } + } + // @checkstyle:on IndentationCheck + if (advance()) { + throw new IllegalArgumentException("EOF"); + } + } while (c != ';'); + return result.toString(); + } + + private boolean skipWhitespace() { + do { + if (advance()) return true; + } while (Character.isWhitespace(c)); + return false; + } + + private boolean advance() { + // True indicates EOF + if (i >= source.length()) return true; + c = source.codePointAt(i); + i += Character.charCount(c); + return false; + } + + private void expectWord(String word, String fullWord) { + for (int j = 0; j < word.length(); j++) { + if (advance() || c != word.charAt(j)) throw new IllegalArgumentException("EOL or unexpected character in word '" + fullWord + "'"); + } + } + } + + private String findPackageName(String source) { + return new JavaPackageNameFinder(source).findPackageName(); + } + + private static String performImportReplacements(String source) { + for (Map.Entry replacement : IMPORT_REPLACEMENTS) { + source = CommonUtils.replace(source, replacement.getKey(), replacement.getValue()); + } + return source; + } + + public static JavaCompiler tryGetJavaCompiler() { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + if ( + JOptionPane.showConfirmDialog( + null, + "You must install a JDK on your system in order to import sorts.\n" + + "Would you like to download one now?", + "Import Sort", + JOptionPane.YES_NO_OPTION, + JOptionPane.ERROR_MESSAGE + ) == JOptionPane.YES_OPTION + ) { + try { + Desktop.getDesktop().browse(new URI("https://adoptium.net/temurin/releases")); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (URISyntaxException e) { + throw new Error(e); + } + } + } + return compiler; + } + + public boolean importSort(File file, boolean showConfirmation) { + // SLightly modified from https://stackoverflow.com/a/40772073/8840278 + // Pattern packagePattern = Pattern.compile("package (([a-zA-Z]{1}[a-zA-Z\\d_]*\\.)*[a-zA-Z][a-zA-Z\\d_]*);"); + String originalContents; + try { + originalContents = new String(Files.readAllBytes(file.toPath())); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + return false; + } + String packageName; + try { + packageName = findPackageName(originalContents); + } catch (IllegalArgumentException e) { + JErrorPane.invokeCustomErrorMessage("Invalid Java syntax detected: " + e.getMessage()); + return false; + } + if (!packageName.startsWith("sorts") && !packageName.startsWith("io.github.arrayv.sorts")) { + JErrorPane.invokeCustomErrorMessage("Sort package must be either sorts or io.github.arrayv.sorts"); + return false; + } + + final File CACHE_DIR = new File("./cache/"); + CACHE_DIR.mkdirs(); + final Path CACHE_PATH = CACHE_DIR.toPath(); + + String contents = performImportReplacements(originalContents); + File useFile; + if (!contents.equals(originalContents)) { + useFile = new File(CACHE_DIR, file.getName()); + try (Writer writer = new FileWriter(useFile)) { + writer.write(contents); + } catch (IOException e) { + JErrorPane.invokeErrorMessage(e, "Sort Import"); + return false; + } + } else { + useFile = file; + } + + JavaCompiler compiler = tryGetJavaCompiler(); + if (compiler == null) { + return false; + } + StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); + Iterable jFiles = fileManager.getJavaFileObjects(useFile); + final File logFile = new File(CACHE_DIR, "compile-" + System.currentTimeMillis() + ".log").getAbsoluteFile(); + int success; + try (Writer output = new FileWriter(logFile)) { + fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList(CACHE_DIR)); + // @checkstyle:off ParenPadCheck + CompilationTask task = compiler.getTask( + output, // out + fileManager, // fileManager + null, // diagnosticListener + Arrays.asList( // options + "-classpath", System.getProperty("java.class.path") + ), + null, // classes + jFiles // compilationUnits + ); + // @checkstyle:on ParenPadCheck + try { + // Code that would work except that reflection is safer (I think) when using APIs that may be removed + // com.sun.tools.javac.main.Main.Result result = ((com.sun.tools.javac.api.JavacTaskImpl)task).doCall(); + // success = result.exitCode; + Method doCall = task.getClass().getDeclaredMethod("doCall"); + Object result = doCall.invoke(task); + success = (int)result.getClass().getDeclaredField("exitCode").get(result); + } catch (Exception e) { + success = task.call() ? 0 : 1; + } + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e, "Sort Import"); + success = -1; + } + if (success != 0) { + if ( + JOptionPane.showConfirmDialog( + null, + "Failed to compile: " + file + + "\nError code " + success + "\n" + + "Would you like to open the log file?", + "Import Sort", + JOptionPane.YES_NO_OPTION, + JOptionPane.ERROR_MESSAGE + ) == JOptionPane.YES_OPTION + ) { + try { + Desktop.getDesktop().open(logFile); + } catch (IOException e) { + e.printStackTrace(); + } + } + return false; + } + + final String rawClassName; + { + String baseName = file.getName(); + rawClassName = baseName.substring(0, baseName.lastIndexOf('.')); + } + + String[][] maybeNames; + try { + maybeNames = StreamSupport.stream( + fileManager.list(StandardLocation.CLASS_OUTPUT, "", Collections.singleton(JavaFileObject.Kind.CLASS), true).spliterator(), + false + ) + .map(fobj -> { + File jioFile = new File(fobj.getName()); + Path relativePath = CACHE_PATH.relativize(jioFile.getParentFile().toPath()); + String baseName = jioFile.getName(); + return new String[] { + relativePath.toString().replace(File.separatorChar, '.'), + baseName.substring(0, baseName.lastIndexOf('.')) + }; + }) + .filter(fc -> + packageName.equals(fc[0]) && rawClassName.equals(fc[1]) + ) + .toArray(String[][]::new); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e, "Sort Import"); + return false; + } + if (maybeNames.length == 2) { + JErrorPane.invokeCustomErrorMessage( + "Multiple sorts found that match this file (" + + Arrays.deepToString(maybeNames) + + "). Please contact the sort devs of all sorts named " + + file.getName() + ); + return false; + } + if (maybeNames.length == 0) { + JErrorPane.invokeCustomErrorMessage("The resulting sort file could not be located. Please report this on the bug tracker."); + return false; + } + final String name; + if (maybeNames[0][0].isEmpty()) { + name = rawClassName; + } else { + name = maybeNames[0][0] + "." + rawClassName; + } + + try { + if (!compileSingle(name, URLClassLoader.newInstance(new URL[] { CACHE_DIR.toURI().toURL() }))) + return false; + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + return false; + } + + if (showConfirmation) { + sortSorts(); + arrayVisualizer.refreshSorts(); + JOptionPane.showMessageDialog(null, "Successfully imported sort " + name, "Import Sort", JOptionPane.INFORMATION_MESSAGE); + } + return true; + } + + public boolean importSort(File file) { + return importSort(file, true); + } + + public void sortSorts() { + SortComparator sortComparator = new SortComparator(); + sorts.sort(sortComparator); + // This loop fixes all the sort IDs to match up with the indices again + for (int i = 0; i < sorts.size(); i++) { + SortInfo sort = sorts.get(i); + if (sort.getId() != i) { + sorts.set(i, sort.withId(i)); + } + } + } + + private boolean verifySort(SortInfo sort) { + if (sort.isDisabled()) { + this.sortErrorMsg = null; + return false; + } + if (sort.getListName().isEmpty()) { + this.sortErrorMsg = "missing 'Choose Sort' name"; + return false; + } + if (sort.getRunAllName().isEmpty()) { + this.sortErrorMsg = "missing 'Run All' name"; + return false; + } + if (sort.getRunName().isEmpty()) { + this.sortErrorMsg = "missing 'Run Sort' name"; + return false; + } + if (sort.getCategory().isEmpty()) { + this.sortErrorMsg = "missing category"; + return false; + } + + return true; + } + + private static String checkForSuggestions(SortInfo sort) { + StringBuilder suggestions = new StringBuilder(); + boolean warned = false; + + if (sort.isBogoSort() && !sort.hasUnreasonableLimit()) { + suggestions.append("- ").append(sort.getRunName()).append(" is a bogosort. It should have an unreasonabe limit.\n"); + warned = true; + } + if (sort.isRadixSort() && !sort.isBucketSort()) { + suggestions.append("- ").append(sort.getRunName()).append(" is a radix sort and should also be classified as a bucket sort.\n"); + warned = true; + } + + if (warned) { + suggestions.deleteCharAt(suggestions.length() - 1); + } + return suggestions.toString(); + } + + public SortInfo[] getSorts() { + return sorts.toArray(new SortInfo[this.sorts.size()]); + // SortInfo[] sorts = new SortInfo[this.sorts.size()]; + + // for (int i = 0; i < sorts.length; i++) { + // sorts[i] = new SortInfo(i, this.sorts.get(i)); + // } + + // return sorts; + } + + public String[] getInvalidSorts() { + if (invalidSorts.size() < 1) { + return null; + } + + String[] invalidSorts = new String[this.invalidSorts.size()]; + invalidSorts = this.invalidSorts.toArray(invalidSorts); + + return invalidSorts; + } + public String[] getSuggestions() { + if (suggestions.size() < 1) { + return null; + } + + String[] allSuggestions = new String[suggestions.size()]; + allSuggestions = suggestions.toArray(allSuggestions); + + return allSuggestions; + } +} diff --git a/src/panels/ShufflePanel.java b/src/main/java/io/github/arrayv/panels/ShufflePanel.java similarity index 85% rename from src/panels/ShufflePanel.java rename to src/main/java/io/github/arrayv/panels/ShufflePanel.java index bc490c02..355b34d9 100644 --- a/src/panels/ShufflePanel.java +++ b/src/main/java/io/github/arrayv/panels/ShufflePanel.java @@ -1,27 +1,19 @@ -package panels; +package io.github.arrayv.panels; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.Point; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import io.github.arrayv.utils.ShuffleGraph; + +import javax.swing.*; +import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; - -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import utils.ShuffleGraph; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; public class ShufflePanel extends JPanel implements KeyListener { int camX = 0, camY = 0; int prevX = 0, prevY = 0; - public ShuffleGraph graph; - + private ShuffleGraph graph; + public ShufflePanel() { setPreferredSize(new Dimension(700, 450)); MouseHandler handler = new MouseHandler(); @@ -42,7 +34,8 @@ protected void paintComponent(Graphics g) { } @Override - public void keyTyped(KeyEvent e) {} + public void keyTyped(KeyEvent e) { + } @Override public void keyPressed(KeyEvent e) { @@ -53,7 +46,16 @@ public void keyPressed(KeyEvent e) { } @Override - public void keyReleased(KeyEvent e) {} + public void keyReleased(KeyEvent e) { + } + + public ShuffleGraph getShuffle() { + return graph; + } + + public void setShuffle(ShuffleGraph shuffle) { + this.graph = shuffle; + } protected class MouseHandler extends MouseAdapter { @Override diff --git a/src/main/java/io/github/arrayv/panes/JEnhancedOptionPane.java b/src/main/java/io/github/arrayv/panes/JEnhancedOptionPane.java new file mode 100644 index 00000000..e1f58bc6 --- /dev/null +++ b/src/main/java/io/github/arrayv/panes/JEnhancedOptionPane.java @@ -0,0 +1,26 @@ +package io.github.arrayv.panes; + +import javax.swing.*; +import java.awt.*; + +// Many thanks to Freek de Bruijn on StackOverflow for providing a custom JOptionPane. +// https://stackoverflow.com/questions/14407804/how-to-change-the-default-text-of-buttons-in-joptionpane-showinputdialog?noredirect=1&lq=1 +public final class JEnhancedOptionPane extends JOptionPane { + private static final long serialVersionUID = 1L; + + public static String showInputDialog(final String title, final Object message, final Object[] options) + throws HeadlessException { + final JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE, + OK_CANCEL_OPTION, null, + options, null); + pane.setWantsInput(true); + pane.setComponentOrientation((getRootFrame()).getComponentOrientation()); + pane.setMessageType(QUESTION_MESSAGE); + pane.selectInitialValue(); + final JDialog dialog = pane.createDialog(null, title); + dialog.setVisible(true); + dialog.dispose(); + final Object value = pane.getInputValue(); + return (value == UNINITIALIZED_VALUE) ? null : (String) value; + } +} diff --git a/src/panes/JErrorPane.java b/src/main/java/io/github/arrayv/panes/JErrorPane.java similarity index 53% rename from src/panes/JErrorPane.java rename to src/main/java/io/github/arrayv/panes/JErrorPane.java index 3c4d9d2a..eed42615 100644 --- a/src/panes/JErrorPane.java +++ b/src/main/java/io/github/arrayv/panes/JErrorPane.java @@ -1,19 +1,17 @@ -package panes; +package io.github.arrayv.panes; +import javax.swing.*; import java.io.PrintWriter; import java.io.StringWriter; -import javax.swing.JOptionPane; -import javax.swing.JTextArea; - -final public class JErrorPane extends JOptionPane { +public final class JErrorPane extends JOptionPane { /** - * + * */ private static final long serialVersionUID = 1L; - - public volatile static boolean errorMessageActive = false; - + + private static volatile boolean errorMessageActive = false; + private static JTextArea createTextArea(String errorMsg) { JTextArea error = new JTextArea(); error.setText(errorMsg); @@ -21,30 +19,36 @@ private static JTextArea createTextArea(String errorMsg) { error.setEditable(false); return error; } - - public static void invokeErrorMessage(Exception e, String title) { + + public static void invokeMonospaceErrorMessage(String body, String title) { errorMessageActive = true; - - StringWriter exceptionString = new StringWriter(); - e.printStackTrace(new PrintWriter(exceptionString)); - String printException = exceptionString.toString(); - - JTextArea error = createTextArea(printException); - + + JTextArea error = createTextArea(body); + JOptionPane.showMessageDialog(null, error, title, JOptionPane.ERROR_MESSAGE); errorMessageActive = false; } - - public static void invokeErrorMessage(Exception e) { + + public static void invokeErrorMessage(Throwable e, String title) { + errorMessageActive = true; + + StringWriter exceptionString = new StringWriter(); + e.printStackTrace(new PrintWriter(exceptionString)); + invokeMonospaceErrorMessage(exceptionString.toString(), title); + } + + public static void invokeErrorMessage(Throwable e) { JErrorPane.invokeErrorMessage(e, "Error"); } - + public static void invokeCustomErrorMessage(String errorMsg) { errorMessageActive = true; - - JTextArea error = createTextArea(errorMsg); - - JOptionPane.showMessageDialog(null, error, "Error", JOptionPane.ERROR_MESSAGE); + + JOptionPane.showMessageDialog(null, errorMsg, "Error", JOptionPane.ERROR_MESSAGE); errorMessageActive = false; } -} \ No newline at end of file + + public static boolean isErrorMessageActive() { + return errorMessageActive; + } +} diff --git a/src/prompts/ShufflePrompt.java b/src/main/java/io/github/arrayv/prompts/ShufflePrompt.java similarity index 56% rename from src/prompts/ShufflePrompt.java rename to src/main/java/io/github/arrayv/prompts/ShufflePrompt.java index 09a7b0bd..bd4cbb52 100644 --- a/src/prompts/ShufflePrompt.java +++ b/src/main/java/io/github/arrayv/prompts/ShufflePrompt.java @@ -1,28 +1,22 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package prompts; +package io.github.arrayv.prompts; -import java.util.Arrays; +import io.github.arrayv.dialogs.ShuffleDialog; +import io.github.arrayv.frames.AppFrame; +import io.github.arrayv.frames.UtilFrame; +import io.github.arrayv.main.ArrayManager; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.utils.Distributions; +import io.github.arrayv.utils.Shuffles; -import javax.swing.DefaultListModel; -import javax.swing.JFrame; - -import dialogs.ShuffleDialog; -import frames.AppFrame; -import frames.UtilFrame; -import main.ArrayManager; -import panes.JErrorPane; -import utils.Distributions; -import utils.Shuffles; +import javax.swing.*; +import java.util.Arrays; /* - * + * MIT License Copyright (c) 2019 w0rthy -Copyright (c) 2021 ArrayV 4.0 Team +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -44,54 +38,46 @@ of this software and associated documentation files (the "Software"), to deal * */ -/** - * - * @author S630690 - */ -final public class ShufflePrompt extends javax.swing.JFrame implements AppFrame { - - /** - * - */ +public final class ShufflePrompt extends javax.swing.JFrame implements AppFrame { private static final long serialVersionUID = 1L; - - private ArrayManager ArrayManager; - private JFrame Frame; - private UtilFrame UtilFrame; - private DefaultListModel shuffleModel; + private final ArrayManager arrayManager; + private final JFrame frame; + private final UtilFrame utilFrame; + + private final DefaultListModel shuffleModel; private boolean initializing; - + /** * Creates new form SortPrompt */ @SuppressWarnings("unchecked") - public ShufflePrompt(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFrame) { - this.ArrayManager = ArrayManager; - this.Frame = frame; - this.UtilFrame = utilFrame; - + public ShufflePrompt(ArrayManager arrayManager, JFrame frame, UtilFrame utilFrame) { + this.arrayManager = arrayManager; + this.frame = frame; + this.utilFrame = utilFrame; + setAlwaysOnTop(true); setUndecorated(true); initComponents(); initializing = true; - jList1.setListData(ArrayManager.getDistributionIDs()); - for(int i = 0; i < ArrayManager.getDistributions().length; i++) { - if(ArrayManager.getDistribution().equals(ArrayManager.getDistributions()[i])) { + jList1.setListData(arrayManager.getDistributionIDs()); + for (int i = 0; i < arrayManager.getDistributions().length; i++) { + if (arrayManager.getDistribution().equals(arrayManager.getDistributions()[i])) { jList1.setSelectedIndex(i); break; } } shuffleModel = new DefaultListModel<>(); jList2.setModel(shuffleModel); - Arrays.stream(ArrayManager.getShuffleIDs()).forEach(shuffleModel::addElement); - if (ArrayManager.getShuffle().size() > 1) { + Arrays.stream(arrayManager.getShuffleIDs()).forEach(shuffleModel::addElement); + if (arrayManager.getShuffle().size() > 1) { shuffleModel.add(0, "Advanced"); jList2.setSelectedIndex(0); } else { - for(int i = 0; i < ArrayManager.getShuffles().length; i++) { - if(ArrayManager.containsShuffle(ArrayManager.getShuffles()[i])) { + for (int i = 0; i < arrayManager.getShuffles().length; i++) { + if (arrayManager.containsShuffle(arrayManager.getShuffles()[i])) { jList2.setSelectedIndex(i); break; } @@ -104,12 +90,12 @@ public ShufflePrompt(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram initializing = false; reposition(); - setVisible(true); + setVisible(true); } @Override public void reposition() { - setLocation(Frame.getX()+(Frame.getWidth()-getWidth())/2,Frame.getY()+(Frame.getHeight()-getHeight())/2); + setLocation(frame.getX()+(frame.getWidth()-getWidth())/2, frame.getY()+(frame.getHeight()-getHeight())/2); } @@ -122,25 +108,21 @@ public void reposition() { // //GEN-BEGIN:initComponents private void initComponents() { - this.jButton1 = new javax.swing.JButton(); + // Variables declaration - do not modify//GEN-BEGIN:variables + javax.swing.JButton jButton1 = new javax.swing.JButton(); - this.jLabel1 = new javax.swing.JLabel(); - this.jScrollPane1 = new javax.swing.JScrollPane(); + javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); + javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); - this.jLabel2 = new javax.swing.JLabel(); - this.jScrollPane2 = new javax.swing.JScrollPane(); + javax.swing.JLabel jLabel2 = new javax.swing.JLabel(); + javax.swing.JScrollPane jScrollPane2 = new javax.swing.JScrollPane(); this.jList2 = new javax.swing.JList(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); jButton1.setText("Open Advanced Editor"); - jButton1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(); - } - }); + jButton1.addActionListener(evt -> jButton1ActionPerformed()); jLabel1.setText("What shape do you want the array to have?"); jLabel2.setText("How do you want the array to be shuffled?"); @@ -151,96 +133,88 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jScrollPane1.setViewportView(this.jList1); jScrollPane2.setViewportView(this.jList2); - jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - try { - jList1ValueChanged(evt); - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } + jList1.addListSelectionListener(evt -> { + try { + jList1ValueChanged(); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); } }); - jList2.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - try { - jList2ValueChanged(evt); - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } + jList2.addListSelectionListener(evt -> { + try { + jList2ValueChanged(); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() .addGap(20, 20, 20) - .addComponent(this.jLabel1) + .addComponent(jLabel1) .addGap(5, 5, 5)) .addGroup(layout.createSequentialGroup() - .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(20, 20, 20)) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGap(475, 475, 475) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() .addGap(20, 20, 20) - .addComponent(this.jLabel2) + .addComponent(jLabel2) .addGap(5, 5, 5)) .addGroup(layout.createSequentialGroup() - .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(20, 20, 20)) .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() - .addComponent(this.jButton1))) - ); + .addComponent(jButton1))) + ); layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(this.jLabel1)) + .addComponent(jLabel1)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(20, 20, 20)) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(this.jLabel2)) + .addComponent(jLabel2)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(10, 10, 10) - .addComponent(this.jButton1) + .addComponent(jButton1) .addGap(15, 15, 15)) - ); + ); pack(); }// //GEN-END:initComponents private void jButton1ActionPerformed() {//GEN-FIRST:event_jList1ValueChanged - UtilFrame.jButton6ResetText(); + utilFrame.jButton6ResetText(); dispose(); - new ShuffleDialog(ArrayManager, this, UtilFrame); + new ShuffleDialog(arrayManager, this); }//GEN-LAST:event_jList1ValueChanged - private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged - // TODO add your handling code here: + private void jList1ValueChanged() {//GEN-FIRST:event_jList1ValueChanged if (initializing) return; int selection = jList1.getSelectedIndex(); - Distributions[] distributions = ArrayManager.getDistributions(); + Distributions[] distributions = arrayManager.getDistributions(); if (selection >= 0 && selection < distributions.length) - ArrayManager.setDistribution(distributions[selection]); + arrayManager.setDistribution(distributions[selection]); }//GEN-LAST:event_jList1ValueChanged - private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged - // TODO add your handling code here: + private void jList2ValueChanged() {//GEN-FIRST:event_jList1ValueChanged if (initializing) return; int selection = jList2.getSelectedIndex(); @@ -249,22 +223,15 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws shuffleModel.remove(0); selection--; } - Shuffles[] shuffles = ArrayManager.getShuffles(); + Shuffles[] shuffles = arrayManager.getShuffles(); if (selection >= 0 && selection < shuffles.length) - ArrayManager.setShuffleSingle(shuffles[selection]); + arrayManager.setShuffleSingle(shuffles[selection]); }//GEN-LAST:event_jList1ValueChanged - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton jButton1; - - private javax.swing.JLabel jLabel1; @SuppressWarnings("rawtypes") private javax.swing.JList jList1; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JLabel jLabel2; @SuppressWarnings("rawtypes") private javax.swing.JList jList2; - private javax.swing.JScrollPane jScrollPane2; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/prompts/SortPrompt.java b/src/main/java/io/github/arrayv/prompts/SortPrompt.java new file mode 100644 index 00000000..a964e183 --- /dev/null +++ b/src/main/java/io/github/arrayv/prompts/SortPrompt.java @@ -0,0 +1,398 @@ +package io.github.arrayv.prompts; + +import io.github.arrayv.dialogs.ImportSortDialog; +import io.github.arrayv.frames.AppFrame; +import io.github.arrayv.frames.UtilFrame; +import io.github.arrayv.groovyapi.GroovyLocals; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.main.RunSort; +import io.github.arrayv.main.SortAnalyzer; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.sortdata.SortInfo; + +import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.io.File; +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.Map; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy +Copyright (c) 2021-2022 ArrayV Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class SortPrompt extends javax.swing.JFrame implements AppFrame { + public static class PlaceholderTextField extends JTextField { + /** + * Shamelessly copied from https://stackoverflow.com/a/16229082/8840278 + */ + private static final long serialVersionUID = 1L; + private String placeholder; + + public String getPlaceholder() { + return placeholder; + } + + @Override + protected void paintComponent(final Graphics pG) { + super.paintComponent(pG); + + if (placeholder == null || placeholder.length() == 0 || getText().length() > 0) { + return; + } + + final Graphics2D g = (Graphics2D) pG; + g.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g.setColor(getDisabledTextColor()); + g.drawString(placeholder, getInsets().left, pG.getFontMetrics() + .getMaxAscent() + getInsets().top); + } + + public void setPlaceholder(final String s) { + placeholder = s; + } + } + + private static int lastCategory = -1; + private static boolean showExtraSorts = true; + + private static final long serialVersionUID = 1L; + + private static final Map> CATEGORY_SORT_THREADS = new LinkedHashMap<>(); + + private final int[] array; + + private final ArrayVisualizer arrayVisualizer; + private final JFrame frame; + private final UtilFrame utilFrame; + + public SortPrompt(int[] array, ArrayVisualizer arrayVisualizer, JFrame frame, UtilFrame utilFrame) { + this.array = array; + this.arrayVisualizer = arrayVisualizer; + this.frame = frame; + this.utilFrame = utilFrame; + + setAlwaysOnTop(true); + setUndecorated(true); + initComponents(); + if (lastCategory == -1) { + for (lastCategory = 1; ; lastCategory++) { + jComboBox1.setSelectedIndex(lastCategory); + //noinspection DataFlowIssue + if (jComboBox1.getSelectedItem().equals("Hybrid Sorts")) { + break; + } + } + } else { + jComboBox1.setSelectedIndex(lastCategory); + } + jTextField1.requestFocusInWindow(); + loadSorts(); + reposition(); + setVisible(true); + } + + public static void setSortThreadForCategory(String category, int sortCount, Runnable sortThread) { + synchronized (CATEGORY_SORT_THREADS) { + CATEGORY_SORT_THREADS.put(category, new SimpleImmutableEntry<>(sortThread, sortCount)); + } + } + + @Override + public void reposition() { + setLocation(frame.getX()+(frame.getWidth()-getWidth())/2, frame.getY()+(frame.getHeight()-getHeight())/2); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + // //GEN-BEGIN:initComponents + private void initComponents() { + + this.jComboBox1 = new javax.swing.JComboBox(); + JScrollPane jScrollPane1 = new JScrollPane(); + this.jList1 = new javax.swing.JList(); + JButton jButton1 = new JButton(); + JButton jButton2 = new JButton(); + this.jButton3 = new javax.swing.JButton(); + this.jTextField1 = new PlaceholderTextField(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + + jComboBox1.setModel(new DefaultComboBoxModel<>(SortInfo.getCategories(arrayVisualizer.getSorts()))); + jComboBox1.insertItemAt("All Sorts", 0); + + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + jList1.addListSelectionListener(this::jList1ValueChanged); + + jScrollPane1.setViewportView(this.jList1); + + jComboBox1.addActionListener(this::jComboBox1SelectionChanged); + + jTextField1.setPlaceholder("Search"); + jTextField1.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + jTextField1TextChanged(e); + } + @Override + public void removeUpdate(DocumentEvent e) { + jTextField1TextChanged(e); + } + @Override + public void changedUpdate(DocumentEvent e) { + jTextField1TextChanged(e); + } + }); + + jButton1.setText("Showcase Sorts (approx. 30-90 minutes)"); + jButton1.addActionListener(evt -> jButton1ActionPerformed()); + + jButton2.setText("Import Sort"); + jButton2.addActionListener(evt -> jButton2ActionPerformed()); + + jButton3.setText("Run All in Selected Category"); + jButton3.addActionListener(evt -> jButton3ActionPerformed()); + + JPanel extraSortsManagementPanel = new JPanel(); + JButton installExtraSortPackButton = new JButton( + arrayVisualizer.getSortAnalyzer().extraSortsInstalled() ? + "Update Extra Sorts Pack" : + "Install Extra Sorts Pack" + ); + installExtraSortPackButton.addActionListener(e -> { + utilFrame.jButton1ResetText(); + utilFrame.jButton1Disable(); + dispose(); + new Thread(() -> { + ProgressMonitor installProgress = new ProgressMonitor( + arrayVisualizer.getMainWindow(), + "Installing...", + "Installing...", + 0, 1 + ); + installProgress.setMillisToDecideToPopup(500); + installProgress.setMillisToPopup(500); + SortAnalyzer analyzer = arrayVisualizer.getSortAnalyzer(); + boolean success; + try { + analyzer.installOrUpdateExtraSorts(installProgress); + success = true; + } catch (Exception e1) { + e1.printStackTrace(); + JErrorPane.invokeCustomErrorMessage("Failed to install: " + e1.getMessage()); + JErrorPane.invokeErrorMessage(e1, "Install Extra Sorts Pack"); + success = false; + } + installProgress.close(); + if (success) { + analyzer.unloadAllExtraSorts(); + analyzer.analyzeSortsExtrasOnly(); + analyzer.sortSorts(); + arrayVisualizer.refreshSorts(); + utilFrame.jButton1Enable(); + JOptionPane.showMessageDialog( + arrayVisualizer.getMainWindow(), + "Successfully installed and loaded extra sorts pack!", + "Install Extra Sorts Pack", + JOptionPane.INFORMATION_MESSAGE + ); + } else { + utilFrame.jButton1Enable(); + } + }, "ExtraSortsInstall").start(); + }); + extraSortsManagementPanel.add(installExtraSortPackButton); + if (arrayVisualizer.getSortAnalyzer().extraSortsInstalled()) { + JCheckBox showExtraSorts = new JCheckBox("Show Extra Sorts"); + showExtraSorts.setSelected(SortPrompt.showExtraSorts); + showExtraSorts.addActionListener(e -> { + SortPrompt.showExtraSorts = showExtraSorts.isSelected(); + loadSorts(); + }); + extraSortsManagementPanel.add(showExtraSorts); + } + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(25, 25, 25) + .addComponent(this.jComboBox1) + .addGap(25, 25, 25)) + .addGroup(layout.createSequentialGroup() + .addGap(45, 45, 45) + .addComponent(this.jTextField1) + .addGap(45, 45, 45)) + .addGroup(layout.createSequentialGroup() + .addGap(25, 25, 25) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(25, 25, 25)) + .addGroup(Alignment.CENTER, layout.createSequentialGroup() + .addComponent(this.jButton3)) + .addGroup(Alignment.CENTER, layout.createSequentialGroup() + .addComponent(jButton1)) + .addGroup(Alignment.CENTER, layout.createSequentialGroup() + .addComponent(extraSortsManagementPanel)) + .addGroup(Alignment.CENTER, layout.createSequentialGroup() + .addComponent(jButton2)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(this.jComboBox1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(this.jTextField1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING, false) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(this.jButton3) + .addGap(5, 5, 5) + .addComponent(jButton1) + .addComponent(extraSortsManagementPanel) + .addComponent(jButton2) + .addGap(5, 5, 5)) + ); + + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + GroovyLocals.runGroupInThread( + CATEGORY_SORT_THREADS.values().stream().map(Map.Entry::getValue).reduce(Integer::sum).get(), + () -> + CATEGORY_SORT_THREADS.values().stream().map(Map.Entry::getKey).forEach(Runnable::run), + true + ); + utilFrame.jButton1ResetText(); + dispose(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + new Thread("ImportSort") { + @Override + public void run() { + if (SortAnalyzer.tryGetJavaCompiler() == null) { + return; + } + File f = new ImportSortDialog().getFile(); + if (f == null) { + return; + } + arrayVisualizer.getSortAnalyzer().importSort(f); + } + }.start(); + utilFrame.jButton1ResetText(); + dispose(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton3ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed\ + final String category = (String)jComboBox1.getSelectedItem(); + Map.Entry groupInfo = CATEGORY_SORT_THREADS.get(category); + if (groupInfo != null) { + arrayVisualizer.setCategory(category); + GroovyLocals.runGroupInThread(groupInfo.getValue(), groupInfo.getKey()); + } + utilFrame.jButton1ResetText(); + dispose(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_jList1ValueChanged + @SuppressWarnings("rawtypes") + String sortName = (String)((JList)evt.getSource()).getSelectedValue(); + SortInfo sortNotFinal = null; + for (SortInfo sort : arrayVisualizer.getSorts()) { + if (sort.getListName().equals(sortName)) { + sortNotFinal = sort; + break; + } + } + final SortInfo selection = sortNotFinal; + new Thread("SortingThread") { + @Override + public void run() { + RunSort sortThread = new RunSort(arrayVisualizer); + sortThread.runSort(array, selection.getId()); + } + }.start(); + utilFrame.jButton1ResetText(); + dispose(); + }//GEN-LAST:event_jList1ValueChanged + + @SuppressWarnings("unchecked") + private void loadSorts() { + int index = jComboBox1.getSelectedIndex(); + String category = (String)jComboBox1.getSelectedItem(); + assert category != null; + ArrayList sorts = new ArrayList<>(); + String searchTerms = jTextField1.getText().toLowerCase(); + boolean isSearching = !searchTerms.isEmpty(); + for (SortInfo sort : arrayVisualizer.getSorts()) { + if (index == 0 || sort.getCategory().equals(category)) { + if (!showExtraSorts && sort.isFromExtra()) continue; + if (isSearching && !sort.getListName().toLowerCase().contains(searchTerms)) continue; + sorts.add(sort.getListName()); + } + } + jList1.setListData(sorts.toArray()); + if (index == 0) { + jButton3.setEnabled(false); + } else { + jButton3.setText("Run All ".concat(category)); + jButton3.setEnabled(CATEGORY_SORT_THREADS.containsKey(category)); + } + } + + private void jComboBox1SelectionChanged(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jList1ValueChanged + loadSorts(); + SortPrompt.lastCategory = jComboBox1.getSelectedIndex(); + }//GEN-LAST:event_jList1ValueChanged + + private void jTextField1TextChanged(DocumentEvent e) {//GEN-FIRST:event_jList1ValueChanged + if (e.getLength() == jTextField1.getText().length()) + jComboBox1.setSelectedIndex(0); + loadSorts(); + }//GEN-LAST:event_jList1ValueChanged + + // Variables declaration - do not modify//GEN-BEGIN:variables + @SuppressWarnings("rawtypes") + private javax.swing.JComboBox jComboBox1; + private javax.swing.JButton jButton3; + @SuppressWarnings("rawtypes") + private javax.swing.JList jList1; + private PlaceholderTextField jTextField1; + // End of variables declaration//GEN-END:variables +} diff --git a/src/prompts/ViewPrompt.java b/src/main/java/io/github/arrayv/prompts/ViewPrompt.java similarity index 51% rename from src/prompts/ViewPrompt.java rename to src/main/java/io/github/arrayv/prompts/ViewPrompt.java index 71019d39..d72aeea1 100644 --- a/src/prompts/ViewPrompt.java +++ b/src/main/java/io/github/arrayv/prompts/ViewPrompt.java @@ -1,22 +1,16 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package prompts; +package io.github.arrayv.prompts; -import javax.swing.JFrame; +import io.github.arrayv.frames.AppFrame; +import io.github.arrayv.frames.UtilFrame; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.visuals.VisualStyles; -import frames.AppFrame; -import frames.UtilFrame; -import main.ArrayVisualizer; -import visuals.VisualStyles; -import javax.swing.JButton; +import javax.swing.*; import javax.swing.GroupLayout.Alignment; -import javax.swing.GroupLayout; import javax.swing.LayoutStyle.ComponentPlacement; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -42,24 +36,18 @@ of this software and associated documentation files (the "Software"), to deal * */ -/** - * - * @author S630690 - */ - -final public class ViewPrompt extends javax.swing.JFrame implements AppFrame { - +public final class ViewPrompt extends javax.swing.JFrame implements AppFrame { private static final long serialVersionUID = 1L; - private ArrayVisualizer ArrayVisualizer; - private JFrame Frame; - private UtilFrame UtilFrame; - + private final ArrayVisualizer arrayVisualizer; + private final JFrame frame; + private final UtilFrame utilFrame; + public ViewPrompt(ArrayVisualizer arrayVisualizer, JFrame frame, UtilFrame utilFrame) { - this.ArrayVisualizer = arrayVisualizer; - this.Frame = frame; - this.UtilFrame = utilFrame; - + this.arrayVisualizer = arrayVisualizer; + this.frame = frame; + this.utilFrame = utilFrame; + setAlwaysOnTop(true); setUndecorated(true); initComponents(); @@ -69,154 +57,80 @@ public ViewPrompt(ArrayVisualizer arrayVisualizer, JFrame frame, UtilFrame utilF @Override public void reposition(){ - setLocation(Frame.getX() + ((Frame.getWidth() - getWidth()) / 2), Frame.getY() + ((Frame.getHeight() - getHeight()) / 2)); + setLocation(frame.getX() + ((frame.getWidth() - getWidth()) / 2), frame.getY() + ((frame.getHeight() - getHeight()) / 2)); } // //GEN-BEGIN:initComponents private void initComponents() { - this.jLabel1 = new javax.swing.JLabel(); - - this.barGraph = new javax.swing.JButton(); - this.dotGraph = new javax.swing.JButton(); - this.colorCircle = new javax.swing.JButton(); - this.pixelMesh = new javax.swing.JButton(); - this.spiral = new javax.swing.JButton(); - this.disparity = new javax.swing.JButton(); - this.disparityDots = new javax.swing.JButton(); - this.spiralDots = new javax.swing.JButton(); - this.rainbow = new javax.swing.JButton(); - this.customImage = new javax.swing.JButton(); - this.sineWave = new javax.swing.JButton(); - this.waveDots = new javax.swing.JButton(); - this.hoopStack = new javax.swing.JButton(); - this.disparityBarGraph = new javax.swing.JButton(); - this.disparityChords = new javax.swing.JButton(); + javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); + + // Variables declaration - do not modify//GEN-BEGIN:variables + javax.swing.JButton barGraph = new javax.swing.JButton(); + javax.swing.JButton dotGraph = new javax.swing.JButton(); + javax.swing.JButton colorCircle = new javax.swing.JButton(); + javax.swing.JButton pixelMesh = new javax.swing.JButton(); + javax.swing.JButton spiral = new javax.swing.JButton(); + javax.swing.JButton disparity = new javax.swing.JButton(); + javax.swing.JButton disparityDots = new javax.swing.JButton(); + javax.swing.JButton spiralDots = new javax.swing.JButton(); + javax.swing.JButton rainbow = new javax.swing.JButton(); + javax.swing.JButton customImage = new javax.swing.JButton(); + javax.swing.JButton sineWave = new javax.swing.JButton(); + javax.swing.JButton waveDots = new javax.swing.JButton(); + javax.swing.JButton hoopStack = new javax.swing.JButton(); + javax.swing.JButton disparityBarGraph = new javax.swing.JButton(); + javax.swing.JButton disparityChords = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setResizable(false); jLabel1.setText("Select Visual Style"); - + barGraph.setText("Bar Graph"); - barGraph.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - barGraphActionPerformed(evt); - } - }); + barGraph.addActionListener(this::barGraphActionPerformed); dotGraph.setText("Dot Graph"); - dotGraph.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - dotGraphActionPerformed(evt); - } - }); + dotGraph.addActionListener(this::dotGraphActionPerformed); colorCircle.setText("Color Circle"); - colorCircle.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - colorCircleActionPerformed(evt); - } - }); + colorCircle.addActionListener(this::colorCircleActionPerformed); pixelMesh.setText("Pixel Mesh"); - pixelMesh.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - triangleMeshActionPerformed(evt); - } - }); + pixelMesh.addActionListener(this::triangleMeshActionPerformed); spiral.setText("Spiral"); - spiral.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - spiralActionPerformed(evt); - } - }); + spiral.addActionListener(this::spiralActionPerformed); rainbow.setText("Rainbow"); - rainbow.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - rainbowActionPerformed(evt); - } - }); + rainbow.addActionListener(this::rainbowActionPerformed); disparity.setText("Disparity Circle"); - disparity.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - disparityActionPerformed(evt); - } - }); + disparity.addActionListener(this::disparityActionPerformed); customImage.setText("Custom Image"); - customImage.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - customImageActionPerformed(evt); - } - }); + customImage.addActionListener(this::customImageActionPerformed); disparityDots.setText("Disparity Dots"); - disparityDots.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - disparityDotsActionPerformed(evt); - } - }); + disparityDots.addActionListener(this::disparityDotsActionPerformed); spiralDots.setText("Spiral Dots"); - spiralDots.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - spiralDotsActionPerformed(evt); - } - }); - + spiralDots.addActionListener(this::spiralDotsActionPerformed); + sineWave.setText("Sine Wave"); - sineWave.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - sineWaveActionPerformed(evt); - } - }); + sineWave.addActionListener(this::sineWaveActionPerformed); waveDots.setText("Wave Dots"); - waveDots.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - waveDotsActionPerformed(evt); - } - }); + waveDots.addActionListener(this::waveDotsActionPerformed); hoopStack.setText("Hoop Stack"); - hoopStack.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - hoopStackActionPerformed(evt); - } - }); - + hoopStack.addActionListener(this::hoopStackActionPerformed); + disparityBarGraph.setText("Disparity Bar Graph"); - disparityBarGraph.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - disparityBarGraphActionPerformed(evt); - } - }); - + disparityBarGraph.addActionListener(this::disparityBarGraphActionPerformed); + disparityChords.setText("Disparity Chords"); - disparityChords.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - disparityChordsActionPerformed(evt); - } - }); - + disparityChords.addActionListener(this::disparityChordsActionPerformed); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.CENTER) @@ -282,127 +196,104 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { pack(); }// //GEN-END:initComponents - private void setAllFieldsFalse(){ - ArrayVisualizer.togglePointer(false); - ArrayVisualizer.toggleDistance(false); - ArrayVisualizer.togglePixels(false); - ArrayVisualizer.toggleRainbow(false); - ArrayVisualizer.toggleSpiral(false); - ArrayVisualizer.toggleWave(false); + private void setAllFieldsFalse() { } - + private void barGraphActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.BARS); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.BARS); + utilFrame.jButton2ResetText(); dispose(); } private void dotGraphActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.DOTS); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.DOTS); + utilFrame.jButton2ResetText(); dispose(); } private void rainbowActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.RAINBOW); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.RAINBOW); + utilFrame.jButton2ResetText(); dispose(); } private void triangleMeshActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.PIXEL_MESH); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.PIXEL_MESH); + utilFrame.jButton2ResetText(); dispose(); } private void colorCircleActionPerformed(java.awt.event.ActionEvent evt) { //TODO: Pointer as separate option setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.COLOR_CIRCLE); - if(ArrayVisualizer.getCurrentLength() == 2) ArrayVisualizer.setCurrentLength(4); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.COLOR_CIRCLE); + if (arrayVisualizer.getCurrentLength() == 2) arrayVisualizer.setCurrentLength(4); + utilFrame.jButton2ResetText(); dispose(); } private void spiralActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.SPIRAL); - if(ArrayVisualizer.getCurrentLength() == 2) ArrayVisualizer.setCurrentLength(4); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.SPIRAL); + if (arrayVisualizer.getCurrentLength() == 2) arrayVisualizer.setCurrentLength(4); + utilFrame.jButton2ResetText(); dispose(); } private void disparityActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.DISP_CIRCLE); - if(ArrayVisualizer.getCurrentLength() == 2) ArrayVisualizer.setCurrentLength(4); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.DISP_CIRCLE); + if (arrayVisualizer.getCurrentLength() == 2) arrayVisualizer.setCurrentLength(4); + utilFrame.jButton2ResetText(); dispose(); } private void customImageActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.CUSTOM_IMAGE); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.CUSTOM_IMAGE); + utilFrame.jButton2ResetText(); dispose(); } private void disparityDotsActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.DISP_DOTS); - if(ArrayVisualizer.getCurrentLength() == 2) ArrayVisualizer.setCurrentLength(4); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.DISP_DOTS); + if (arrayVisualizer.getCurrentLength() == 2) arrayVisualizer.setCurrentLength(4); + utilFrame.jButton2ResetText(); dispose(); } private void spiralDotsActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.SPIRAL_DOTS); - if(ArrayVisualizer.getCurrentLength() == 2) ArrayVisualizer.setCurrentLength(4); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.SPIRAL_DOTS); + if (arrayVisualizer.getCurrentLength() == 2) arrayVisualizer.setCurrentLength(4); + utilFrame.jButton2ResetText(); dispose(); } private void sineWaveActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.SINE_WAVE); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.SINE_WAVE); + utilFrame.jButton2ResetText(); dispose(); } private void waveDotsActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.WAVE_DOTS); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.WAVE_DOTS); + utilFrame.jButton2ResetText(); dispose(); } private void hoopStackActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.HOOP_STACK); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.HOOP_STACK); + utilFrame.jButton2ResetText(); dispose(); } private void disparityBarGraphActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.DISP_BARS); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.DISP_BARS); + utilFrame.jButton2ResetText(); dispose(); } private void disparityChordsActionPerformed(java.awt.event.ActionEvent evt) { setAllFieldsFalse(); - ArrayVisualizer.setVisual(VisualStyles.DISP_CHORDS); - UtilFrame.jButton2ResetText(); + arrayVisualizer.setVisual(VisualStyles.DISP_CHORDS); + utilFrame.jButton2ResetText(); dispose(); } - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton barGraph; - private javax.swing.JButton dotGraph; - private javax.swing.JButton colorCircle; - private javax.swing.JButton pixelMesh; - private javax.swing.JButton spiral; - private javax.swing.JButton spiralDots; - private javax.swing.JButton disparity; - private javax.swing.JButton disparityDots; - private javax.swing.JButton rainbow; - private javax.swing.JButton customImage; - private javax.swing.JButton sineWave; - private javax.swing.JButton waveDots; - private javax.swing.JButton hoopStack; - private javax.swing.JButton disparityBarGraph; - private javax.swing.JButton disparityChords; - private javax.swing.JLabel jLabel1; -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/sortdata/MethodAnswerValidator.java b/src/main/java/io/github/arrayv/sortdata/MethodAnswerValidator.java new file mode 100644 index 00000000..90656e8f --- /dev/null +++ b/src/main/java/io/github/arrayv/sortdata/MethodAnswerValidator.java @@ -0,0 +1,51 @@ +package io.github.arrayv.sortdata; + +import io.github.arrayv.sorts.templates.Sort; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.util.function.IntUnaryOperator; + +public final class MethodAnswerValidator implements IntUnaryOperator { + private static final MethodHandles.Lookup LOOKUP = MethodHandles.publicLookup(); + private static final MethodType VALIDATOR_TYPE = MethodType.methodType(int.class, int.class); + + private final MethodHandle mh; + + public MethodAnswerValidator(MethodHandle mh) { + this.mh = mh; + } + + public MethodAnswerValidator(Method validator) throws IllegalAccessException { + this(LOOKUP.unreflect(validator)); + } + + public MethodAnswerValidator(Class sortClass) throws NoSuchMethodException, IllegalAccessException { + this(getMh(sortClass)); + } + + public MethodAnswerValidator(Sort sort) throws IllegalAccessException, NoSuchMethodException { + this(sort.getClass()); + } + + private static MethodHandle getMh(Class sortClass) throws NoSuchMethodException, IllegalAccessException { + return LOOKUP.findStatic(sortClass, "validateAnswer", VALIDATOR_TYPE); + } + + public MethodHandle getValidatorHandle() { + return mh; + } + + @Override + public int applyAsInt(int answer) { + try { + return (int)mh.invokeExact(answer); + } catch (RuntimeException | Error e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/io/github/arrayv/sortdata/NewSortInstance.java b/src/main/java/io/github/arrayv/sortdata/NewSortInstance.java new file mode 100644 index 00000000..4c8c0174 --- /dev/null +++ b/src/main/java/io/github/arrayv/sortdata/NewSortInstance.java @@ -0,0 +1,52 @@ +package io.github.arrayv.sortdata; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Constructor; +import java.util.function.Supplier; + +public final class NewSortInstance implements Supplier { + private static final MethodHandles.Lookup LOOKUP = MethodHandles.publicLookup(); + private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class, ArrayVisualizer.class); + + private final MethodHandle mh; + + public NewSortInstance(MethodHandle mh) { + this.mh = mh; + } + + public NewSortInstance(Constructor constructor) throws IllegalAccessException { + this(LOOKUP.unreflectConstructor(constructor)); + } + + public NewSortInstance(Class sortClass) throws NoSuchMethodException, IllegalAccessException { + this(getMh(sortClass)); + } + + public NewSortInstance(Sort sort) throws IllegalAccessException, NoSuchMethodException { + this(sort.getClass()); + } + + private static MethodHandle getMh(Class sortClass) throws NoSuchMethodException, IllegalAccessException { + return LOOKUP.findConstructor(sortClass, CONSTRUCTOR_TYPE); + } + + public MethodHandle getConstructorHandle() { + return mh; + } + + @Override + public Sort get() { + try { + return (Sort)mh.invoke(ArrayVisualizer.getInstance()); + } catch (RuntimeException | Error e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/io/github/arrayv/sortdata/SortComparator.java b/src/main/java/io/github/arrayv/sortdata/SortComparator.java new file mode 100644 index 00000000..4927a857 --- /dev/null +++ b/src/main/java/io/github/arrayv/sortdata/SortComparator.java @@ -0,0 +1,12 @@ +package io.github.arrayv.sortdata; + +import java.util.Comparator; + +public final class SortComparator implements Comparator { + public SortComparator() {} + + @Override + public int compare(SortInfo left, SortInfo right) { + return left.getListName().compareTo(right.getListName()); + } +} diff --git a/src/main/java/io/github/arrayv/sortdata/SortInfo.java b/src/main/java/io/github/arrayv/sortdata/SortInfo.java new file mode 100644 index 00000000..bad5dbef --- /dev/null +++ b/src/main/java/io/github/arrayv/sortdata/SortInfo.java @@ -0,0 +1,540 @@ +package io.github.arrayv.sortdata; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Objects; +import java.util.function.IntUnaryOperator; +import java.util.function.Supplier; + +public final class SortInfo { + private static final String NAME_MUST_BE_SPECIFIED = + "name must be specified unless all three of listName, showcaseName, and runName are specified"; + + private final int id; + private final String internalName; + private final Supplier instanceSupplier; + private final boolean disabled; + private final int unreasonableLimit; + private final String listName; + private final String runName; + private final String runAllName; + private final String category; + private final boolean bogoSort; + private final boolean radixSort; + private final boolean bucketSort; + private final String question; + private final int defaultAnswer; + private final IntUnaryOperator answerValidator; + private final boolean fromExtra; + + private SortInfo(int id, SortInfo sort) { + this.id = id; + this.internalName = sort.internalName; + this.instanceSupplier = sort.instanceSupplier; + this.disabled = sort.disabled; + this.unreasonableLimit = sort.unreasonableLimit; + this.listName = sort.listName; + this.runName = sort.runName; + this.runAllName = sort.runAllName; + this.category = sort.category; + this.bogoSort = sort.bogoSort; + this.radixSort = sort.radixSort; + this.bucketSort = sort.bucketSort; + this.question = sort.question; + this.defaultAnswer = sort.defaultAnswer; + this.answerValidator = sort.answerValidator; + this.fromExtra = sort.fromExtra; + } + + @SuppressWarnings("deprecation") + public SortInfo(int id, Class sortClass) { + this.id = id; + this.internalName = sortClass.getSimpleName(); + try { + this.instanceSupplier = new NewSortInstance(sortClass); + this.answerValidator = new MethodAnswerValidator(sortClass); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new Error(e); + } + SortMeta metaAnnotation = sortClass.getAnnotation(SortMeta.class); + if (metaAnnotation == null) { + Sort sort = getFreshInstance(); + this.disabled = !sort.isSortEnabled(); + this.unreasonableLimit = sort.getUnreasonableLimit(); + this.listName = sort.getSortListName(); + this.runName = sort.getRunSortName(); + this.runAllName = sort.getRunAllSortsName(); + this.category = sort.getCategory(); + this.bogoSort = sort.isBogoSort(); + this.radixSort = sort.isRadixSort(); + this.bucketSort = sort.usesBuckets(); + this.question = sort.getQuestion(); + this.defaultAnswer = sort.getDefaultAnswer(); + } else { + String name = normalizeName(metaAnnotation); + this.disabled = metaAnnotation.disabled(); + this.unreasonableLimit = metaAnnotation.unreasonableLimit(); + this.listName = metaAnnotation.listName().isEmpty() + ? requireName(name) + : metaAnnotation.listName(); + this.runName = metaAnnotation.runName().isEmpty() + ? requireName(name) + "sort" + : metaAnnotation.runName(); + this.runAllName = metaAnnotation.showcaseName().isEmpty() + ? requireName(name) + " Sort" + : metaAnnotation.showcaseName(); + this.category = metaAnnotation.category().isEmpty() ? findSortCategory(sortClass) : metaAnnotation.category(); + this.bogoSort = metaAnnotation.bogoSort(); + this.radixSort = metaAnnotation.radixSort(); + this.bucketSort = metaAnnotation.bucketSort(); + this.question = metaAnnotation.question().isEmpty() ? null : metaAnnotation.question(); + this.defaultAnswer = metaAnnotation.defaultAnswer(); + } + this.fromExtra = ArrayVisualizer.getInstance().getSortAnalyzer().didSortComeFromExtra(sortClass); + } + + @SuppressWarnings("deprecation") + public SortInfo(int id, Sort sort) { + this.id = id; + this.internalName = sort.getClass().getSimpleName(); + try { + this.instanceSupplier = new NewSortInstance(sort.getClass()); + this.answerValidator = new MethodAnswerValidator(sort.getClass()); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new Error(e); + } + SortMeta metaAnnotation = sort.getClass().getAnnotation(SortMeta.class); + if (metaAnnotation == null) { + this.disabled = !sort.isSortEnabled(); + this.unreasonableLimit = sort.getUnreasonableLimit(); + this.listName = sort.getSortListName(); + this.runName = sort.getRunSortName(); + this.runAllName = sort.getRunAllSortsName(); + this.category = sort.getCategory(); + this.bogoSort = sort.isBogoSort(); + this.radixSort = sort.isRadixSort(); + this.bucketSort = sort.usesBuckets(); + this.question = sort.getQuestion(); + this.defaultAnswer = sort.getDefaultAnswer(); + } else { + String name = normalizeName(metaAnnotation); + this.disabled = metaAnnotation.disabled(); + this.unreasonableLimit = metaAnnotation.unreasonableLimit(); + this.listName = metaAnnotation.listName().isEmpty() + ? requireName(name) + : metaAnnotation.listName(); + this.runName = metaAnnotation.runName().isEmpty() + ? requireName(name) + "sort" + : metaAnnotation.runName(); + this.runAllName = metaAnnotation.showcaseName().isEmpty() + ? requireName(name) + " Sort" + : metaAnnotation.showcaseName(); + this.category = metaAnnotation.category().isEmpty() ? findSortCategory(sort.getClass()) : metaAnnotation.category(); + this.bogoSort = metaAnnotation.bogoSort(); + this.radixSort = metaAnnotation.radixSort(); + this.bucketSort = metaAnnotation.bucketSort(); + this.question = metaAnnotation.question().isEmpty() ? null : metaAnnotation.question(); + this.defaultAnswer = metaAnnotation.defaultAnswer(); + } + this.fromExtra = ArrayVisualizer.getInstance().getSortAnalyzer().didSortComeFromExtra(sort.getClass()); + } + + private SortInfo( + int id, + String internalName, + Supplier instanceSupplier, + boolean disabled, + int unreasonableLimit, + String listName, + String runName, + String runAllName, + String category, + boolean slowSort, + boolean bogoSort, + boolean radixSort, + boolean bucketSort, + String question, + int defaultAnswer, + IntUnaryOperator answerValidator + ) { + this.id = id; + this.internalName = internalName; + this.instanceSupplier = instanceSupplier; + this.disabled = disabled; + this.unreasonableLimit = unreasonableLimit; + this.listName = listName; + this.runName = runName; + this.runAllName = runAllName; + this.category = category; + this.bogoSort = bogoSort; + this.radixSort = radixSort; + this.bucketSort = bucketSort; + this.question = question; + this.defaultAnswer = defaultAnswer; + this.answerValidator = answerValidator; + this.fromExtra = false; // Built sorts cannot come from extra + } + + public SortInfo(Class sort) { + this(-1, sort); + } + + public SortInfo(Sort sort) { + this(-1, sort); + } + + private static String findSortCategory(Class sortClass) { + Package checkPackage = sortClass.getPackage(); + if (checkPackage != null) { + SortPackageMeta packageMetaAnnotation = checkPackage.getAnnotation(SortPackageMeta.class); + if (packageMetaAnnotation != null) { + return packageMetaAnnotation.category(); + } + } + throw new NullPointerException( + "Sort " + sortClass.getSimpleName() + " does not declare a category, and neither do any of its packages" + ); + } + + private static String requireName(String name) { + return Objects.requireNonNull(name, NAME_MUST_BE_SPECIFIED); + } + + private static String normalizeName(SortMeta meta) { + String name = meta.name(); + if (name.endsWith(" Sort")) { + return name.substring(0, name.length() - 5); + } + if (name.endsWith("sort")) { + return name.substring(0, name.length() - 4); + } + // Cause an NPE if name isn't specified, and all three required names also aren't + return name.isEmpty() ? null : name; + } + + public int getId() { + return id; + } + + public Supplier getInstanceSupplier() { + return instanceSupplier; + } + + public String getInternalName() { + return internalName; + } + + public boolean isDisabled() { + return disabled; + } + + public int getUnreasonableLimit() { + return unreasonableLimit; + } + + public String getListName() { + return listName; + } + + public String getRunName() { + return runName; + } + + public String getRunAllName() { + return runAllName; + } + + public String getCategory() { + return category; + } + + public boolean hasUnreasonableLimit() { + return unreasonableLimit > 0; + } + + public boolean isBogoSort() { + return bogoSort; + } + + public boolean isRadixSort() { + return radixSort; + } + + public boolean isBucketSort() { + return bucketSort; + } + + public String getQuestion() { + return question; + } + + public int getDefaultAnswer() { + return defaultAnswer; + } + + public IntUnaryOperator getAnswerValidator() { + return answerValidator; + } + + public Sort getFreshInstance() { + return instanceSupplier.get(); + } + + public int validateAnswer(int answer) { + return answerValidator.applyAsInt(answer); + } + + public boolean isFromExtra() { + return fromExtra; + } + + /** + * Creates a copy of this info with a new ID + * @param id The ID for the new instance + * @return Copied info with new ID + */ + public SortInfo withId(int id) { + return new SortInfo(id, this); + } + + public static String[] getListNames(SortInfo[] sorts) { + String[] result = new String[sorts.length]; + for (int i = 0; i < sorts.length; i++) { + result[i] = sorts[i].listName; + } + return result; + } + + public static String[] getCategories(SortInfo[] sorts) { + HashSet result = new HashSet<>(); + for (SortInfo sort : sorts) { + result.add(sort.category); + } + String[] resultArray = result.toArray(new String[0]); + Arrays.sort(resultArray); + return resultArray; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (bogoSort ? 1231 : 1237); + result = prime * result + (bucketSort ? 1231 : 1237); + result = prime * result + ((category == null) ? 0 : category.hashCode()); + result = prime * result + defaultAnswer; + result = prime * result + (disabled ? 1231 : 1237); + result = prime * result + (fromExtra ? 1231 : 1237); + result = prime * result + id; + result = prime * result + ((listName == null) ? 0 : listName.hashCode()); + result = prime * result + ((question == null) ? 0 : question.hashCode()); + result = prime * result + (radixSort ? 1231 : 1237); + result = prime * result + ((runAllName == null) ? 0 : runAllName.hashCode()); + result = prime * result + ((runName == null) ? 0 : runName.hashCode()); + result = prime * result + unreasonableLimit; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof SortInfo)) { + return false; + } + SortInfo other = (SortInfo) obj; + if (bogoSort != other.bogoSort) { + return false; + } + if (bucketSort != other.bucketSort) { + return false; + } + if (category == null) { + if (other.category != null) { + return false; + } + } else if (!category.equals(other.category)) { + return false; + } + if (defaultAnswer != other.defaultAnswer) { + return false; + } + if (disabled != other.disabled) { + return false; + } + if (fromExtra != other.fromExtra) { + return false; + } + if (id != other.id) { + return false; + } + if (listName == null) { + if (other.listName != null) { + return false; + } + } else if (!listName.equals(other.listName)) { + return false; + } + if (question == null) { + if (other.question != null) { + return false; + } + } else if (!question.equals(other.question)) { + return false; + } + if (radixSort != other.radixSort) { + return false; + } + if (runAllName == null) { + if (other.runAllName != null) { + return false; + } + } else if (!runAllName.equals(other.runAllName)) { + return false; + } + if (runName == null) { + if (other.runName != null) { + return false; + } + } else if (!runName.equals(other.runName)) { + return false; + } + return unreasonableLimit == other.unreasonableLimit; + } + + @Override + public String toString() { + return "SortInfo for " + runAllName; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private int id = -1; + private String internalName = null; + private Supplier instanceSupplier; + private boolean disabled = false; + private int unreasonableLimit = 0; + private String listName; // Required + private String runName = null; + private String runAllName = null; + private String category; // Required + private boolean slowSort = false; + private boolean bogoSort = false; + private boolean radixSort = false; + private boolean bucketSort = false; + private String question = null; + private int defaultAnswer = 0; + private IntUnaryOperator answerValidator = IntUnaryOperator.identity(); + + private Builder() { + } + + public SortInfo build() { + return new SortInfo( + id, + internalName, + Objects.requireNonNull(instanceSupplier, "instanceSupplier"), + disabled, + unreasonableLimit, + Objects.requireNonNull(listName, "listName"), + runName != null ? runName : (listName + "sort"), + runAllName != null ? runAllName : (listName + " Sort"), + Objects.requireNonNull(category, "category"), + slowSort, + bogoSort, + radixSort, + bucketSort, + question, + defaultAnswer, + answerValidator + ); + } + + public Builder id(int id) { + this.id = id; + return this; + } + + public Builder internalName(String internalName) { + this.internalName = internalName; + return this; + } + + public Builder instanceSupplier(Supplier instanceSupplier) { + this.instanceSupplier = instanceSupplier; + return this; + } + + public Builder disabled(boolean disabled) { + this.disabled = disabled; + return this; + } + + public Builder unreasonableLimit(int unreasonableLimit) { + this.unreasonableLimit = unreasonableLimit; + return this; + } + + public Builder listName(String listName) { + this.listName = listName; + return this; + } + + public Builder runName(String runName) { + this.runName = runName; + return this; + } + + public Builder runAllName(String runAllName) { + this.runAllName = runAllName; + return this; + } + + public Builder category(String category) { + this.category = category; + return this; + } + + public Builder slowSort(boolean slowSort) { + this.slowSort = slowSort; + return this; + } + + public Builder bogoSort(boolean bogoSort) { + this.bogoSort = bogoSort; + return this; + } + + public Builder radixSort(boolean radixSort) { + this.radixSort = radixSort; + return this; + } + + public Builder bucketSort(boolean bucketSort) { + this.bucketSort = bucketSort; + return this; + } + + public Builder question(String question) { + this.question = question; + return this; + } + + public Builder defaultAnswer(int defaultAnswer) { + this.defaultAnswer = defaultAnswer; + return this; + } + + public Builder answerValidator(IntUnaryOperator answerValidator) { + this.answerValidator = Objects.requireNonNull(answerValidator, "answerValidator"); + return this; + } + } +} diff --git a/src/main/java/io/github/arrayv/sortdata/SortMeta.java b/src/main/java/io/github/arrayv/sortdata/SortMeta.java new file mode 100644 index 00000000..1ff6632e --- /dev/null +++ b/src/main/java/io/github/arrayv/sortdata/SortMeta.java @@ -0,0 +1,94 @@ +package io.github.arrayv.sortdata; + +import java.lang.annotation.*; + +/** + * Annotation to specify the sorting algorithm's metadata. This should only be applied to subclasses of + * {@link io.github.arrayv.sorts.templates.Sort Sort}. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface SortMeta { + /** + * The sort's name. This is generally of the form {@code "Something"} or {@code "Something Sort"}. If not + * specified, all three of {@link #listName()}, {@link #runName()}, and {@link #showcaseName()} must be specified. + * @return The sort's annotated name. + */ + String name() default ""; + + /** + * The sort's category. This may be specified on a package-level in package-info.java. Specifying it here will + * override it for the package. + * @return The sort's category, or {@code ""} if you should look at the package level. + */ + String category() default ""; + + /** + * Explicit sort list name. This is generated from {@link #name()} by default. + * @return The sort's explicit list name, if it has one. {@code ""} otherwise. + */ + String listName() default ""; + + /** + * Explicit Run Sort name. This is generated from {@link #name()} by default. + * @return The sort's explicit Run Sort name, if it has one. {@code ""} otherwise. + */ + String runName() default ""; + + /** + * Explicit Showcase Sorts name (and scripting name). This is generated from {@link #name()} by default. + * @return The sort's explicit Showcase Sorts name, if it has one. {@code ""} otherwise. + */ + String showcaseName() default ""; + + /** + * Whether this sort is disabled. Disabled sorts won't be loaded. + * @return Whether this sort is disabled. + */ + boolean disabled() default false; + + /** + * This sort's unreasonable limit. If the sort is run with lengths higher than this, a warning is displayed. + * @return This sort's unreasonable limit. + */ + int unreasonableLimit() default 0; + + /** + * Whether to treat this sort as slow in Showcase Sorts and in sort scripts. + * @return Whether to treat this sort as slow. + */ + boolean slowSort() default false; + + /** + * Whether this sort is a bogo sort (i.e. it has "bogo" in its name, and it's non-deterministic). + * @return Whether this sort is a bogo sort. + */ + boolean bogoSort() default false; + + /** + * Whether this sort is a Radix Sort. + * @return Whether this sort is a Radix Sort. + */ + boolean radixSort() default false; + + /** + * Whether this sort uses buckets. + * @return Whether this sort uses buckets. + */ + boolean bucketSort() default false; + + /** + * A question to ask the user when they choose this sort. You can perform response validation by creating a method + * that is {@code public static int validateAnswer(int answer)}. + * @return The question to ask the user, or {@code ""} if there isn't one. + */ + String question() default ""; + + /** + * The default response to use for {@link #question()}. This is used when the user pressed "Use default". This + * value is ignored if there is no question. This value is not passed through {@code validatorAnswer}. + * @return The default answer response. + */ + int defaultAnswer() default 0; +} diff --git a/src/main/java/io/github/arrayv/sortdata/SortNameType.java b/src/main/java/io/github/arrayv/sortdata/SortNameType.java new file mode 100644 index 00000000..91fa94f6 --- /dev/null +++ b/src/main/java/io/github/arrayv/sortdata/SortNameType.java @@ -0,0 +1,8 @@ +package io.github.arrayv.sortdata; + +public enum SortNameType { + INTERNAL_NAME, + LIST_NAME, + RUN_NAME, + SHOWCASE_NAME +} diff --git a/src/main/java/io/github/arrayv/sortdata/SortPackageMeta.java b/src/main/java/io/github/arrayv/sortdata/SortPackageMeta.java new file mode 100644 index 00000000..a8e0fe50 --- /dev/null +++ b/src/main/java/io/github/arrayv/sortdata/SortPackageMeta.java @@ -0,0 +1,13 @@ +package io.github.arrayv.sortdata; + +import java.lang.annotation.*; + +/** + * Annotation to specify metadata about a package containing sorting algorithms. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PACKAGE) +public @interface SortPackageMeta { + String category(); +} diff --git a/src/sorts/concurrent/BitonicSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortIterative.java similarity index 67% rename from src/sorts/concurrent/BitonicSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortIterative.java index 10389101..f112a5c9 100644 --- a/src/sorts/concurrent/BitonicSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortIterative.java @@ -1,39 +1,34 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* * This version of Bitonic Sort was taken from here, written by Nikos Pitsianis: * https://www2.cs.duke.edu/courses/fall08/cps196.1/Pthreads/bitonic.c - * + * * Thanks to Piotr Grochowski for rewriting code to allow this implementation to * work for array lengths other than powers of two! */ -final public class BitonicSortIterative extends Sort { +@SortMeta( + name = "Iterative Bitonic", + listName = "Bitonic (Iterative)", + runName = "Iterative Bitonic Sort" +) +public final class BitonicSortIterative extends Sort { public BitonicSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bitonic (Iterative)"); - this.setRunAllSortsName("Iterative Bitonic Sort"); - this.setRunSortName("Iterative Bitonic Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int i, j, k; for(k = 2; k < sortLength*2; k = 2 * k) { boolean m = (((sortLength + (k - 1)) / k) % 2) != 0; - + for(j = k >> 1; j > 0; j = j >> 1) { for(i = 0; i < sortLength; i++) { int ij = i ^ j; @@ -48,4 +43,4 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti } } } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/BitonicSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortParallel.java similarity index 84% rename from src/sorts/concurrent/BitonicSortParallel.java rename to src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortParallel.java index 9a549d47..e623db1e 100644 --- a/src/sorts/concurrent/BitonicSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortParallel.java @@ -1,23 +1,20 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; +@SortMeta( + name = "Parallel Bitonic", + listName = "Bitonic (Parallel)", + runName = "Parallel Bitonic Sort", + unreasonableLimit = 4096 +) public final class BitonicSortParallel extends Sort { private int[] arr; private final double DELAY = 1; public BitonicSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - this.setSortListName("Bitonic (Parallel)"); - this.setRunAllSortsName("Parallel Bitonic Sort"); - this.setRunSortName("Parallel Bitonic Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(4096); - this.setBogoSort(false); } private class SortThread extends Thread { @@ -84,10 +81,10 @@ private void bitonicSort(int start, int stop, boolean ascending) { this.bitonicMerge(start, mid, stop, gap, ascending ? 1 : -1); } } - + @Override public void runSort(int[] arr, int length, int buckets) { this.arr = arr; this.bitonicSort(0, length, true); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/BitonicSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortRecursive.java similarity index 73% rename from src/sorts/concurrent/BitonicSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortRecursive.java index 2b287753..aced713d 100644 --- a/src/sorts/concurrent/BitonicSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortRecursive.java @@ -1,43 +1,38 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* * This version of Bitonic Sort was taken from here, written by H.W. Lang: * http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/oddn.htm */ -final public class BitonicSortRecursive extends Sort { +@SortMeta( + listName = "Bitonic (Recursive)", + showcaseName = "Batcher's Bitonic Sort", + runName = "Recursive Bitonic Sort" +) +public final class BitonicSortRecursive extends Sort { private boolean direction = true; - + public BitonicSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bitonic (Recursive)"); - this.setRunAllSortsName("Batcher's Bitonic Sort"); - this.setRunSortName("Recursive Bitonic Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private static int greatestPowerOfTwoLessThan(int n){ int k = 1; while (k < n) { k = k << 1; } - return k >> 1; + return k >> 1; } - + private void compare(int[] A, int i, int j, boolean dir) { int cmp = Reads.compareIndices(A, i, j, 0.5, true); - + if (dir == (cmp == 1)) Writes.swap(A, i, j, 0.5, true, false); } @@ -72,9 +67,9 @@ public void changeDirection(String choice) throws Exception { else if(choice.equals("backward")) this.direction = false; else throw new Exception("Invalid direction for Bitonic Sort!"); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.bitonicSort(array, 0, sortLength, this.direction); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/BoseNelsonSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortIterative.java similarity index 56% rename from src/sorts/concurrent/BoseNelsonSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortIterative.java index 19b6b6a9..7ad3af00 100644 --- a/src/sorts/concurrent/BoseNelsonSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortIterative.java @@ -1,37 +1,32 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; -final public class BoseNelsonSortIterative extends Sort { +@SortMeta( + listName = "Bose-Nelson (Iterative)", + showcaseName = "Iterative Bose-Nelson Sorting Network", + runName = "Iterative Bose-Nelson Sort" +) +public final class BoseNelsonSortIterative extends Sort { public BoseNelsonSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bose-Nelson (Iterative)"); - this.setRunAllSortsName("Iterative Bose-Nelson Sorting Network"); - this.setRunSortName("Iterative Bose-Nelson Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private int end; - + private void compSwap(int[] array, int a, int b) { if(b >= this.end) return; - + if(Reads.compareIndices(array, a, b, 0.25, true) == 1) Writes.swap(array, a, b, 0.5, false, false); } - + private void rangeComp(int[] array, int a, int b, int offset) { - int half = (b-a)/2, m = a+half; + int half = (b-a)/2, m = a+half; a += offset; - + for(int i = 0; i < half - offset; i++) if((i & ~offset) == i) this.compSwap(array, a+i, m+i); } @@ -40,10 +35,10 @@ private void rangeComp(int[] array, int a, int b, int offset) { public void runSort(int[] array, int currentLength, int bucketCount) { this.end = currentLength; currentLength = 1 << (int)(Math.ceil(Math.log(currentLength)/Math.log(2))); - + for(int k = 2; k <= currentLength; k*=2) for(int j = 0; j < k/2; j++) for(int i = 0; i+j < this.end; i+=k) this.rangeComp(array, i, i+k, j); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/BoseNelsonSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortParallel.java similarity index 82% rename from src/sorts/concurrent/BoseNelsonSortParallel.java rename to src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortParallel.java index a04f8af7..096632d5 100644 --- a/src/sorts/concurrent/BoseNelsonSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortParallel.java @@ -1,27 +1,23 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; + +@SortMeta( + listName = "Bose-Nelson (Parallel)", + showcaseName = "Parallel Bose-Nelson Sorting Network", + runName = "Parallel Bose-Nelson Sort", + unreasonableLimit = 4096 +) +public final class BoseNelsonSortParallel extends Sort { -final public class BoseNelsonSortParallel extends Sort { - public BoseNelsonSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bose-Nelson (Parallel)"); - this.setRunAllSortsName("Parallel Bose-Nelson Sorting Network"); - this.setRunSortName("Parallel Bose-Nelson Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(4096); - this.setBogoSort(false); } - + private int[] array; - + private class BoseNelson extends Thread { private int start, length; private double sleep; @@ -34,7 +30,7 @@ public void run() { BoseNelsonSortParallel.this.boseNelson(start, length, sleep); } } - + private class BoseNelsonMerge extends Thread { private int start1, len1, start2, len2; private double sleep; @@ -49,7 +45,7 @@ public void run() { BoseNelsonSortParallel.this.boseNelsonMerge(start1, len1, start2, len2, sleep); } } - + private void compareSwap(int start, int end, double sleep) { if (Reads.compareIndices(array, start, end, sleep, true) == 1) { Writes.swap(array, start, end, 2*sleep, true, false); @@ -63,7 +59,7 @@ private void boseNelson(int start, int length, double sleep) { BoseNelson right = new BoseNelson(start + mid, length - mid, sleep); left.start(); right.start(); - + try { left.join(); right.join(); @@ -73,7 +69,7 @@ private void boseNelson(int start, int length, double sleep) { boseNelsonMerge(start, mid, start + mid, length - mid, sleep); } } - + private void boseNelsonMerge(int start1, int len1, int start2, int len2, double sleep) { if (len1 == 1 && len2 == 1) { compareSwap(start1, start2, sleep); @@ -86,12 +82,12 @@ private void boseNelsonMerge(int start1, int len1, int start2, int len2, double } else { int mid1 = len1 / 2; int mid2 = len1 % 2 == 1 ? len2 / 2 : (len2 + 1) / 2; - + BoseNelsonMerge left = new BoseNelsonMerge(start1, mid1, start2, mid2, sleep); BoseNelsonMerge right = new BoseNelsonMerge(start1 + mid1, len1 - mid1, start2 + mid2, len2 - mid2, sleep); left.start(); right.start(); - + try { left.join(); right.join(); @@ -101,10 +97,10 @@ private void boseNelsonMerge(int start1, int len1, int start2, int len2, double boseNelsonMerge(start1 + mid1, len1 - mid1, start2, mid2, sleep); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.boseNelson(0, length, 0.25); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/BoseNelsonSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortRecursive.java similarity index 73% rename from src/sorts/concurrent/BoseNelsonSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortRecursive.java index 817bea88..7dd0f7ce 100644 --- a/src/sorts/concurrent/BoseNelsonSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortRecursive.java @@ -1,25 +1,20 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; + +@SortMeta( + listName = "Bose-Nelson (Recursive)", + showcaseName = "Recursive Bose-Nelson Sorting Network", + runName = "Recursive Bose-Nelson Sort" +) +public final class BoseNelsonSortRecursive extends Sort { -final public class BoseNelsonSortRecursive extends Sort { - public BoseNelsonSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bose-Nelson (Recursive)"); - this.setRunAllSortsName("Recursive Bose-Nelson Sorting Network"); - this.setRunSortName("Recursive Bose-Nelson Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private void compareSwap(int[] array, int start, int end, double sleep) { if (Reads.compareIndices(array, start, end, sleep, true) == 1) { Writes.swap(array, start, end, 2*sleep, true, false); @@ -34,7 +29,7 @@ private void boseNelson(int[] array, int start, int length, double sleep) { boseNelsonMerge(array, start, mid, start + mid, length - mid, sleep); } } - + private void boseNelsonMerge(int[] array, int start1, int len1, int start2, int len2, double sleep) { if (len1 == 1 && len2 == 1) { compareSwap(array, start1, start2, sleep); @@ -52,9 +47,9 @@ private void boseNelsonMerge(int[] array, int start1, int len1, int start2, int boseNelsonMerge(array, start1 + mid1, len1 - mid1, start2, mid2, sleep); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.boseNelson(array, 0, length, 0.25); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/CreaseSort.java b/src/main/java/io/github/arrayv/sorts/concurrent/CreaseSort.java similarity index 75% rename from src/sorts/concurrent/CreaseSort.java rename to src/main/java/io/github/arrayv/sorts/concurrent/CreaseSort.java index 08a7e953..1f319319 100644 --- a/src/sorts/concurrent/CreaseSort.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/CreaseSort.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,22 +30,16 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class CreaseSort extends Sort { +@SortMeta( + name = "Crease", + showcaseName = "Crease Sorting Network", + runName = "Crease Sort" +) +public final class CreaseSort extends Sort { public CreaseSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Crease"); - this.setRunAllSortsName("Crease Sorting Network"); - this.setRunSortName("Crease Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private void compSwap(int[] array, int a, int b) { if(Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); @@ -54,17 +49,17 @@ private void compSwap(int[] array, int a, int b) { public void runSort(int[] array, int length, int bucketCount) { int max = 1; for(; max*2 < length; max*=2); - + int next = max; while(next > 0) { for(int i = 0; i+1 < length; i+=2) this.compSwap(array, i, i+1); - + for(int j = max; j >= next && j > 1; j/=2) for(int i = 1; i+j-1 < length; i+=2) this.compSwap(array, i, i+j-1); - + next /= 2; } } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/DiamondSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortIterative.java similarity index 76% rename from src/sorts/concurrent/DiamondSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortIterative.java index 01ef9847..1981c6a0 100644 --- a/src/sorts/concurrent/DiamondSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortIterative.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 _fluffyy, yuji implemented by aphitorite @@ -29,22 +30,15 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class DiamondSortIterative extends Sort { +@SortMeta( + name = "Iterative Diamond", + listName = "Diamond (Iterative)" +) +public final class DiamondSortIterative extends Sort { public DiamondSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Diamond (Iterative)"); - this.setRunAllSortsName("Iterative Diamond Sort"); - this.setRunSortName("Iterative Diamondsort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private void compSwap(int[] array, int a, int b) { if(Reads.compareIndices(array, a, b, 0.05, true) == 1) Writes.swap(array, a, b, 0.05, true, false); @@ -54,7 +48,7 @@ private void compSwap(int[] array, int a, int b) { public void runSort(int[] array, int length, int bucketCount) throws Exception { int n = 1; for(; n < length; n *= 2); - + int m = 4; for(; m <= n; m *= 2) { for(int k = 0; k < m/2; k++) { @@ -70,4 +64,4 @@ public void runSort(int[] array, int length, int bucketCount) throws Exception { for(int i = k; i+1 < Math.min(length, m-k); i += 2) this.compSwap(array, i, i+1); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/DiamondSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortRecursive.java similarity index 68% rename from src/sorts/concurrent/DiamondSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortRecursive.java index 1939633e..34eafcad 100644 --- a/src/sorts/concurrent/DiamondSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortRecursive.java @@ -1,22 +1,17 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; +@SortMeta( + name = "Recursive Diamond", + listName = "Diamond (Recursive)" +) public final class DiamondSortRecursive extends Sort { private final double DELAY = 0.05; public DiamondSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - this.setSortListName("Diamond (Recursive)"); - this.setRunAllSortsName("Recursive Diamond Sort"); - this.setRunSortName("Recursive Diamondsort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void sort(int[] arr, int start, int stop, boolean merge) { @@ -41,4 +36,4 @@ private void sort(int[] arr, int start, int stop, boolean merge) { public void runSort(int[] arr, int length, int buckets) { this.sort(arr, 0, length, true); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/FoldSort.java b/src/main/java/io/github/arrayv/sorts/concurrent/FoldSort.java similarity index 78% rename from src/sorts/concurrent/FoldSort.java rename to src/main/java/io/github/arrayv/sorts/concurrent/FoldSort.java index aa1a2029..51aeff72 100644 --- a/src/sorts/concurrent/FoldSort.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/FoldSort.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 Marcel Pi Nacy @@ -29,29 +30,23 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class FoldSort extends Sort { +@SortMeta( + name = "Fold", + showcaseName = "Fold Sorting Network", + runName = "Fold Sort" +) +public final class FoldSort extends Sort { public FoldSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Fold"); - this.setRunAllSortsName("Fold Sorting Network"); - this.setRunSortName("Fold Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + int end; - + void compSwap(int[] array, int a, int b) { if(b < end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } - + void halver(int[] array, int low, int high) { while (low < high) @@ -64,10 +59,10 @@ void halver(int[] array, int low, int high) public void runSort(int[] array, int size, int bucketCount) { int ceilLog = 1; for (; (1 << ceilLog) < size; ceilLog++); - + end = size; size = 1 << ceilLog; - + for (int k = size >> 1; k > 0; k >>= 1) //log(N) { for (int i = size; i >= k; i >>= 1) //log(N) @@ -79,4 +74,4 @@ public void runSort(int[] array, int size, int bucketCount) { } } } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/MatrixSort.java b/src/main/java/io/github/arrayv/sorts/concurrent/MatrixSort.java similarity index 82% rename from src/sorts/concurrent/MatrixSort.java rename to src/main/java/io/github/arrayv/sorts/concurrent/MatrixSort.java index d354e2a0..89b13a6d 100644 --- a/src/sorts/concurrent/MatrixSort.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/MatrixSort.java @@ -1,20 +1,24 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* Idea made by Control#2866 in The Studio Discord Server (https://discord.com/invite/2xGkKC2) */ -final public class MatrixSort extends Sort { +@SortMeta( + name = "Matrix", + runName = "Matrix Sort" +) +public final class MatrixSort extends Sort { private class MatrixShape { - int width, height; + int width; boolean unbalanced, insertLast; public MatrixShape(int width, int height, boolean insertLast) { this.width = width; - this.height = height; this.unbalanced = (width == 1) ^ (height == 1); this.insertLast = this.unbalanced || insertLast; } @@ -22,27 +26,11 @@ public MatrixShape(int width, int height, boolean insertLast) { public MatrixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Matrix"); - this.setRunAllSortsName("Matrix Sort"); - this.setRunSortName("Matrix Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int dirCompare(int[] array, int left, int right, boolean dir) { - int res = Reads.compareIndices(array, left, right, 0.5, true); - return dir ? res : (res * -1); } private void gapReverse(int[] array, int start, int end, int gap) { Writes.changeReversals(1); - + for (int i = start, j = end; i < j; i += gap, j -= gap) { Writes.swap(array, i, j - gap, 0.5, true, false); } @@ -59,7 +47,7 @@ private boolean insertLast(int[] array, int a, int b, int gap, boolean dir) { boolean did = false; int key = array[b]; int j = b - gap; - + while (j >= a && dirCompareVal(key, array[j], dir) < 0) { Writes.write(array, j + gap, array[j], 0.5, true, false); did = true; @@ -129,4 +117,4 @@ else if (length <= 16) { public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.matrixSort(array, 0, sortLength, 1, true); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/MergeExchangeSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/MergeExchangeSortIterative.java similarity index 57% rename from src/sorts/concurrent/MergeExchangeSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/MergeExchangeSortIterative.java index 15ff2eed..e05fd9b8 100644 --- a/src/sorts/concurrent/MergeExchangeSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/MergeExchangeSortIterative.java @@ -1,25 +1,20 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; + +@SortMeta( + listName = "Merge-Exchange (Iterative)", + showcaseName = "Batcher's Merge-Exchange Sort", + runName = "Iterative Merge-Exchange Sort" +) +public final class MergeExchangeSortIterative extends Sort { -final public class MergeExchangeSortIterative extends Sort { - public MergeExchangeSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Merge-Exchange (Iterative)"); - this.setRunAllSortsName("Batcher's Merge-Exchange Sort"); - this.setRunSortName("Iterative Merge-Exchange Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int t = (int)(Math.log(length-1) / Math.log(2))+1; @@ -41,4 +36,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/OddEvenMergeSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortIterative.java similarity index 63% rename from src/sorts/concurrent/OddEvenMergeSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortIterative.java index d754fa13..49e4b1bb 100644 --- a/src/sorts/concurrent/OddEvenMergeSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortIterative.java @@ -1,30 +1,25 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* * This version of Odd-Even Merge Sort was taken from here, written by wkpark on StackOverflow: * https://stackoverflow.com/questions/34426337/how-to-fix-this-non-recursive-odd-even-merge-sort-algorithm - * + * * Thanks to Piotr Grochowski for rewriting code to allow this implementation to * work for array lengths other than powers of two! */ -final public class OddEvenMergeSortIterative extends Sort { +@SortMeta( + listName = "Odd-Even Merge (Iterative)", + showcaseName = "Iterative Odd-Even Merge Sort", + runName = "Iterative Odd-Even Mergesort" +) +public final class OddEvenMergeSortIterative extends Sort { public OddEvenMergeSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Odd-Even Merge (Iterative)"); - this.setRunAllSortsName("Iterative Odd-Even Merge Sort"); - this.setRunSortName("Iterative Odd-Even Mergesort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -38,4 +33,4 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti if(Reads.compareIndices(array, i + j, i + j + k, 0.5, true) > 0) Writes.swap(array, i + j, i + j + k, 0.5, true, false); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/OddEvenMergeSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortParallel.java similarity index 82% rename from src/sorts/concurrent/OddEvenMergeSortParallel.java rename to src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortParallel.java index 90a95e29..90d78dbc 100644 --- a/src/sorts/concurrent/OddEvenMergeSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortParallel.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 Piotr Grochowski @@ -30,27 +31,21 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class OddEvenMergeSortParallel extends Sort { +@SortMeta( + name = "Parallel Odd-Even Merge", + listName = "Odd-Even Merge (Parallel)", + unreasonableLimit = 4096 +) +public final class OddEvenMergeSortParallel extends Sort { public OddEvenMergeSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Odd-Even Merge (Parallel)"); - this.setRunAllSortsName("Parallel Odd-Even Merge Sort"); - this.setRunSortName("Parallel Odd-Even Mergesort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(4096); - this.setBogoSort(false); } - + private int[] array; - + private class OddEvenMerge extends Thread { private int lo, m2, n, r; - + OddEvenMerge(int lo, int m2, int n, int r) { this.lo = lo; this.m2 = m2; @@ -61,10 +56,10 @@ public void run() { OddEvenMergeSortParallel.this.oddEvenMerge(lo, m2, n, r); } } - + private class OddEvenMergeSort extends Thread { private int lo, n; - + OddEvenMergeSort(int lo, int n) { this.lo = lo; this.n = n; @@ -73,17 +68,17 @@ public void run() { OddEvenMergeSortParallel.this.oddEvenMergeSort(lo, n); } } - + private void compSwap(int a, int b) { if(Reads.compareIndices(array, a, b, 1, true) == 1) Writes.swap(array, a, b, 1, true, false); } - + private void oddEvenMerge(int lo, int m2, int n, int r) { int m = r * 2; if(m < n) { OddEvenMerge left, right; - + if((n/r)%2 != 0) { left = new OddEvenMerge(lo, (m2+1)/2, n+r, m); right = new OddEvenMerge(lo+r, m2/2, n-r, m); @@ -92,22 +87,22 @@ private void oddEvenMerge(int lo, int m2, int n, int r) { left = new OddEvenMerge(lo, (m2+1)/2, n, m); right = new OddEvenMerge(lo+r, m2/2, n, m); } - + left.start(); right.start(); - + try { left.join(); right.join(); - } + } catch(InterruptedException e) { Thread.currentThread().interrupt(); } if(m2%2 != 0) - for(int i = lo; i + r < lo + n; i += m) + for(int i = lo; i + r < lo + n; i += m) this.compSwap(i, i + r); - + else for(int i = lo + r; i + r < lo + n; i += m) this.compSwap(i, i + r); @@ -118,21 +113,21 @@ private void oddEvenMerge(int lo, int m2, int n, int r) { private void oddEvenMergeSort(int lo, int n) { if (n > 1) { int m = n / 2; - + OddEvenMergeSort left = new OddEvenMergeSort(lo, m); OddEvenMergeSort right = new OddEvenMergeSort(lo + m, n-m); - + left.start(); right.start(); - + try { left.join(); right.join(); - } + } catch(InterruptedException e) { Thread.currentThread().interrupt(); } - + this.oddEvenMerge(lo, m, n, 1); } } @@ -142,4 +137,4 @@ public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.oddEvenMergeSort(0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/OddEvenMergeSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortRecursive.java similarity index 78% rename from src/sorts/concurrent/OddEvenMergeSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortRecursive.java index 1dd80e11..43d88055 100644 --- a/src/sorts/concurrent/OddEvenMergeSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortRecursive.java @@ -1,30 +1,25 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* * This version of Odd-Even Merge Sort was taken from here, written by H.W. Lang: * http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/networks/oemen.htm - * + * * Thanks to Piotr Grochowski for rewriting code to allow this implementation to * work for array lengths other than powers of two! */ -final public class OddEvenMergeSortRecursive extends Sort { +@SortMeta( + name = "Recursive Odd-Even Merge", + listName = "Odd-Even Merge (Recursive)", + showcaseName = "Batcher's Odd-Even Merge Sort" +) +public final class OddEvenMergeSortRecursive extends Sort { public OddEvenMergeSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Odd-Even Merge (Recursive)"); - this.setRunAllSortsName("Batcher's Odd-Even Merge Sort"); - this.setRunSortName("Recursive Odd-Even Mergesort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void oddEvenMergeCompare(int[] array, int i, int j) { @@ -80,4 +75,4 @@ void oddEvenMergeSort(int[] array, int lo, int n) { public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.oddEvenMergeSort(array, 0, sortLength); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/PairwiseMergeSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortIterative.java similarity index 76% rename from src/sorts/concurrent/PairwiseMergeSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortIterative.java index 7c98566c..3f7242b7 100644 --- a/src/sorts/concurrent/PairwiseMergeSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortIterative.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,24 +30,17 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class PairwiseMergeSortIterative extends Sort { +@SortMeta( + name = "Iterative Pairwise Merge", + listName = "Pairwise Merge (Iterative)" +) +public final class PairwiseMergeSortIterative extends Sort { public PairwiseMergeSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pairwise Merge (Iterative)"); - this.setRunAllSortsName("Iterative Pairwise Merge Sort"); - this.setRunSortName("Iterative Pairwise Mergesort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private int end; - + private void compSwap(int[] array, int a, int b) { if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); @@ -57,12 +51,12 @@ public void runSort(int[] array, int length, int bucketCount) throws Exception { this.end = length; int n = 1; for(; n < length; n <<= 1); - + for(int k = n >> 1; k > 0; k >>= 1) for(int j = 0; j < length; j += k << 1) for(int i = 0; i < k; i++) this.compSwap(array, j+i, j+k+i); - + for(int k = 2; k < n; k <<= 1) for(int m = k >> 1; m > 0; m >>= 1) for(int j = 0; j < length; j += k<<1) @@ -70,4 +64,4 @@ public void runSort(int[] array, int length, int bucketCount) throws Exception { for(int i = 0; i < m; i++) this.compSwap(array, j+p+i, j+p+m+i); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/PairwiseMergeSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortRecursive.java similarity index 77% rename from src/sorts/concurrent/PairwiseMergeSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortRecursive.java index c7fb43b1..5b83d33b 100644 --- a/src/sorts/concurrent/PairwiseMergeSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortRecursive.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,45 +30,38 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class PairwiseMergeSortRecursive extends Sort { +@SortMeta( + name = "Recursive Pairwise Merge", + listName = "Pairwise Merge (Recursive)" +) +public final class PairwiseMergeSortRecursive extends Sort { public PairwiseMergeSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pairwise Merge (Recursive)"); - this.setRunAllSortsName("Recursive Pairwise Merge Sort"); - this.setRunSortName("Recursive Pairwise Mergesort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private int end; - + private void compSwap(int[] array, int a, int b) { if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } - + private void pairwiseMerge(int[] array, int a, int b) { int m = (a+b)/2, m1 = (a+m)/2, g = m-m1; - + for(int i = 0; m1+i < m; i++) for(int j = m1, k = g; k > 0; k >>= 1, j -= k-(i&k)) this.compSwap(array, j+i, j+i+k); - + if(b-a > 4) this.pairwiseMerge(array, m, b); } - + private void pairwiseMergeSort(int[] array, int a, int b) { int m = (a+b)/2; - + for(int i = a, j = m; i < m; i++, j++) this.compSwap(array, i, j); - + if(b-a > 2) { this.pairwiseMergeSort(array, a, m); this.pairwiseMergeSort(array, m, b); @@ -80,7 +74,7 @@ public void runSort(int[] array, int length, int bucketCount) throws Exception { this.end = length; int n = 1; for(; n < length; n <<= 1); - + this.pairwiseMergeSort(array, 0, n); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/PairwiseSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortIterative.java similarity index 81% rename from src/sorts/concurrent/PairwiseSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortIterative.java index 92319c75..88e3be29 100644 --- a/src/sorts/concurrent/PairwiseSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortIterative.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 PiotrGrochowski Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,20 +26,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class PairwiseSortIterative extends Sort { +@SortMeta( + listName = "Pairwise (Iterative)", + showcaseName = "Iterative Pairwise Sorting Network", + runName = "Iterative Pairwise Sort" +) +public final class PairwiseSortIterative extends Sort { public PairwiseSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pairwise (Iterative)"); - this.setRunAllSortsName("Iterative Pairwise Sorting Network"); - this.setRunSortName("Iterative Pairwise Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void iterativepairwise(int[] array, int length, double sleep) { @@ -85,9 +80,9 @@ private void iterativepairwise(int[] array, int length, double sleep) { e = (e * 2) + 1; } } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.iterativepairwise(array, sortLength, 0.5); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/PairwiseSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortRecursive.java similarity index 81% rename from src/sorts/concurrent/PairwiseSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortRecursive.java index 550ade75..abea1eb3 100644 --- a/src/sorts/concurrent/PairwiseSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortRecursive.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 PiotrGrochowski Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,20 +26,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class PairwiseSortRecursive extends Sort { +@SortMeta( + listName = "Pairwise (Recursive)", + showcaseName = "Recursive Pairwise Sorting Network", + runName = "Recursive Pairwise Sort" +) +public final class PairwiseSortRecursive extends Sort { public PairwiseSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pairwise (Recursive)"); - this.setRunAllSortsName("Recursive Pairwise Sorting Network"); - this.setRunSortName("Recursive Pairwise Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void pairwiserecursive(int[] array, int start, int end, int gap, double sleep) { @@ -83,4 +78,4 @@ private void pairwiserecursive(int[] array, int start, int end, int gap, double public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.pairwiserecursive(array, 0, sortLength, 1, 0.5); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/WeaveSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortIterative.java similarity index 74% rename from src/sorts/concurrent/WeaveSortIterative.java rename to src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortIterative.java index 18dd0c14..bd514602 100644 --- a/src/sorts/concurrent/WeaveSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortIterative.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,24 +30,18 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class WeaveSortIterative extends Sort { +@SortMeta( + listName = "Weave (Iterative)", + showcaseName = "Iterative Weave Sorting Network", + runName = "Iterative Weave Sort" +) +public final class WeaveSortIterative extends Sort { public WeaveSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Weave (Iterative)"); - this.setRunAllSortsName("Iterative Weave Sorting Network"); - this.setRunSortName("Iterative Weave Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private int end; - + private void compSwap(int[] array, int a, int b) { if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); @@ -57,7 +52,7 @@ public void runSort(int[] array, int length, int bucketCount) { this.end = length; int n = 1; for(; n < length; n*=2); - + for(int i = 1; i < n; i*=2) for(int j = 1; j <= i; j*=2) for(int k = 0; k < n; k += n/j) @@ -65,4 +60,4 @@ public void runSort(int[] array, int length, int bucketCount) { for(int p = 0; p < d; p++, m++) this.compSwap(array, k+m, k+l+p); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/WeaveSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortParallel.java similarity index 81% rename from src/sorts/concurrent/WeaveSortParallel.java rename to src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortParallel.java index 8cc455df..1d9b6243 100644 --- a/src/sorts/concurrent/WeaveSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortParallel.java @@ -1,24 +1,21 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; -final public class WeaveSortParallel extends Sort { +@SortMeta( + name = "Parallel Weave", + listName = "Iterative Weave Sort", + runName = "Parallel Weave Sort", + unreasonableLimit = 4096 +) +public final class WeaveSortParallel extends Sort { private int[] arr; private int length; private double DELAY = 1; public WeaveSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - this.setSortListName("Weave (Parallel)"); - this.setRunAllSortsName("Parallel Weave Sort"); - this.setRunSortName("Parallel Weave Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(4096); - this.setBogoSort(false); } private class SortThread extends Thread { @@ -92,4 +89,4 @@ public void runSort(int[] arr, int length, int bucketCount) { this.length = length; this.wrapper(0, 1); } -} \ No newline at end of file +} diff --git a/src/sorts/concurrent/WeaveSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortRecursive.java similarity index 77% rename from src/sorts/concurrent/WeaveSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortRecursive.java index a529f319..5e3083f6 100644 --- a/src/sorts/concurrent/WeaveSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortRecursive.java @@ -1,10 +1,11 @@ -package sorts.concurrent; +package io.github.arrayv.sorts.concurrent; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,45 +30,39 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class WeaveSortRecursive extends Sort { +@SortMeta( + listName = "Weave (Recursive)", + showcaseName = "Recursive Weave Sorting Network", + runName = "Recursive Weave Sort" +) +public final class WeaveSortRecursive extends Sort { public WeaveSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Weave (Recursive)"); - this.setRunAllSortsName("Recursive Weave Sorting Network"); - this.setRunSortName("Recursive Weave Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private int end; - + private void compSwap(int[] array, int a, int b) { if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } - + private void circle(int[] array, int pos, int len, int gap) { if(len < 2) return; - + for(int i = 0; 2*i < (len-1)*gap; i+=gap) this.compSwap(array, pos+i, pos+(len-1)*gap-i); - + this.circle(array, pos, len/2, gap); if(pos+len*gap/2 < this.end) this.circle(array, pos+len*gap/2, len/2, gap); } - + private void weaveCircle(int[] array, int pos, int len, int gap) { if(len < 2) return; - + this.weaveCircle(array, pos, len/2, 2*gap); this.weaveCircle(array, pos+gap, len/2, 2*gap); - + this.circle(array, pos, len, gap); } @@ -76,7 +71,7 @@ public void runSort(int[] array, int length, int bucketCount) { this.end = length; int n = 1; for(; n < length; n*=2); - + this.weaveCircle(array, 0, n, 1); } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/package-info.java b/src/main/java/io/github/arrayv/sorts/concurrent/package-info.java new file mode 100644 index 00000000..953c9ea8 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/concurrent/package-info.java @@ -0,0 +1,4 @@ +@io.github.arrayv.sortdata.SortPackageMeta( + category = "Concurrent Sorts" +) +package io.github.arrayv.sorts.concurrent; diff --git a/src/sorts/distribute/AmericanFlagSort.java b/src/main/java/io/github/arrayv/sorts/distribute/AmericanFlagSort.java similarity index 90% rename from src/sorts/distribute/AmericanFlagSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/AmericanFlagSort.java index 263d0fbf..4d6c347e 100644 --- a/src/sorts/distribute/AmericanFlagSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/AmericanFlagSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * Copyright 2017 Justin Wetherell Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,7 @@ * distributes items into hundreds of buckets. Non-comparative sorting * algorithms such as radix sort and American flag sort are typically used to * sort large objects such as strings, for which comparison is not a unit-time - * operation. + * operation. *

* Family: Bucket.
* Space: In-place.
@@ -43,32 +43,31 @@ * @author Justin Wetherell */ -final public class AmericanFlagSort extends Sort { +public final class AmericanFlagSort extends Sort { private int NUMBER_OF_BUCKETS = 128; // ex. 10 for base 10 numbers - + public AmericanFlagSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("American Flag"); this.setRunAllSortsName("American Flag Sort, " + this.NUMBER_OF_BUCKETS + " Buckets"); this.setRunSortName("American Flag Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(true); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + // Slightly different than Reads.analyzeMaxLog. private int getMaxNumberOfDigits(int[] array, int length) { int max = Integer.MIN_VALUE; int temp = 0; - + for (int i = 0; i < length; i++) { temp = (int) (Math.log(array[i]) / Math.log(this.NUMBER_OF_BUCKETS)) + 1; - + if (temp > max) max = temp; } @@ -78,49 +77,49 @@ private int getMaxNumberOfDigits(int[] array, int length) { private int getDigit(int integer, int divisor) { return (integer / divisor) % this.NUMBER_OF_BUCKETS; } - + private void sort(int[] array, int start, int length, int divisor) { // First pass - find counts int[] count = new int[this.NUMBER_OF_BUCKETS]; int[] offset = new int[this.NUMBER_OF_BUCKETS]; Writes.changeAllocAmount(2 * this.NUMBER_OF_BUCKETS); int digit = 0; - + for (int i = start; i < length; i++) { Highlights.markArray(1, i); Delays.sleep(0.75); - + int d = array[i]; digit = this.getDigit(d, divisor); - + Writes.write(count, digit, count[digit] + 1, 0, false, true); } - + Writes.write(offset, 0, start + 0, 0, false, true); - + for (int i = 1; i < this.NUMBER_OF_BUCKETS; i++) { Writes.write(offset, i, count[i - 1] + offset[i - 1], 0, false, true); } - + // Second pass - move into position for (int b = 0; b < this.NUMBER_OF_BUCKETS; b++) { while (count[b] > 0) { int origin = offset[b]; int from = origin; int num = array[from]; - + Writes.visualClear(array, from, 0.5); - + do { digit = this.getDigit(num, divisor); int to = offset[digit]; - + Writes.write(offset, digit, offset[digit] + 1, 0, false, true); Writes.write(count, digit, count[digit] - 1, 0, false, true); - + int temp = array[to]; Writes.write(array, to, num, 0.75, true, false); - + num = temp; from = to; } while (from != origin); @@ -131,7 +130,7 @@ private void sort(int[] array, int start, int length, int divisor) { for (int i = 0; i < this.NUMBER_OF_BUCKETS; i++) { int begin = (i > 0) ? offset[i - 1] : start; int end = offset[i]; - + if (end - begin > 1) this.sort(array, begin, end, divisor / this.NUMBER_OF_BUCKETS); } @@ -144,13 +143,13 @@ private void sort(int[] array, int start, int length, int divisor) { public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.NUMBER_OF_BUCKETS = bucketCount; this.setRunAllSortsName("American Flag Sort, " + this.NUMBER_OF_BUCKETS + " Buckets"); - + int numberOfDigits = this.getMaxNumberOfDigits(array, sortLength); // Max number of digits int max = 1; - + for (int i = 0; i < numberOfDigits - 1; i++) max *= this.NUMBER_OF_BUCKETS; - + this.sort(array, 0, sortLength, max); } - } \ No newline at end of file + } diff --git a/src/sorts/distribute/BinaryQuickSortIterative.java b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortIterative.java similarity index 86% rename from src/sorts/distribute/BinaryQuickSortIterative.java rename to src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortIterative.java index a800f6c8..d24ffa7d 100644 --- a/src/sorts/distribute/BinaryQuickSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortIterative.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BinaryQuickSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BinaryQuickSorting; /** * Binary MSD Radix Sort / Binary Quicksort. @@ -20,25 +20,24 @@ * @author Skeen */ -final public class BinaryQuickSortIterative extends BinaryQuickSorting { +public final class BinaryQuickSortIterative extends BinaryQuickSorting { public BinaryQuickSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Binary Quick (Iterative with a Queue)"); this.setRunAllSortsName("Iterative Binary Quick Sort"); this.setRunSortName("Iterative Binary Quicksort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int mostSignificantBit = Reads.analyzeBit(array, sortLength); this.binaryQuickSort(array, 0, sortLength - 1, mostSignificantBit); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/BinaryQuickSortRecursive.java b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortRecursive.java similarity index 86% rename from src/sorts/distribute/BinaryQuickSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortRecursive.java index 770cc716..be850059 100644 --- a/src/sorts/distribute/BinaryQuickSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortRecursive.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BinaryQuickSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BinaryQuickSorting; /** * Binary MSD Radix Sort / Binary Quicksort. @@ -20,25 +20,24 @@ * @author Skeen */ -final public class BinaryQuickSortRecursive extends BinaryQuickSorting { +public final class BinaryQuickSortRecursive extends BinaryQuickSorting { public BinaryQuickSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Binary Quick (Recursive)"); this.setRunAllSortsName("Recursive Binary Quick Sort"); this.setRunSortName("Recursive Binary Quicksort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int mostSignificantBit = Reads.analyzeBit(array, sortLength); this.binaryQuickSortRecursive(array, 0, sortLength - 1, mostSignificantBit); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/BogoBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/BogoBogoSort.java similarity index 95% rename from src/sorts/distribute/BogoBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/BogoBogoSort.java index 6e7332ae..8e146067 100644 --- a/src/sorts/distribute/BogoBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/BogoBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* * @@ -50,14 +50,13 @@ public BogoBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Bogo Bogo Sort"); this.setRunSortName("Bogobogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); this.setUnreasonableLimit(5); this.setBogoSort(true); } - + private int[][] tmp; //fix seizure aux using 2d array private boolean bogoBogoIsSorted(int[] array, int length) { @@ -91,12 +90,12 @@ private void bogoBogo(int[] array, int length, boolean aux) { @Override public void runSort(int[] array, int length, int bucketCount) { tmp = new int[length-1][]; - + for(int i = length; i > 1; i--) tmp[i-2] = Writes.createExternalArray(i); - + bogoBogo(array, length, false); - + for(int i = length; i > 1; i--) Writes.deleteExternalArray(tmp[i-2]); } diff --git a/src/sorts/distribute/BogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/BogoSort.java similarity index 92% rename from src/sorts/distribute/BogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/BogoSort.java index d43a9eb8..93d275cb 100644 --- a/src/sorts/distribute/BogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/BogoSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -40,7 +40,6 @@ public BogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Bogo Sort"); this.setRunSortName("Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/BozoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/BozoSort.java similarity index 85% rename from src/sorts/distribute/BozoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/BozoSort.java index 09c72932..9fa6fcb1 100644 --- a/src/sorts/distribute/BozoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/BozoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /** * Bozosort randomly swaps any two elements until the array is sorted. @@ -14,7 +14,6 @@ public BozoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Bozo Sort"); this.setRunSortName("Bozosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/ClassicGravitySort.java b/src/main/java/io/github/arrayv/sorts/distribute/ClassicGravitySort.java similarity index 92% rename from src/sorts/distribute/ClassicGravitySort.java rename to src/main/java/io/github/arrayv/sorts/distribute/ClassicGravitySort.java index a40f99a8..514d63f9 100644 --- a/src/sorts/distribute/ClassicGravitySort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/ClassicGravitySort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,22 +29,21 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ClassicGravitySort extends Sort { +public final class ClassicGravitySort extends Sort { public ClassicGravitySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Classic Gravity"); this.setRunAllSortsName("Classic Gravity (Bead) Sort"); this.setRunSortName("Classic Beadsort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int max = Reads.analyzeMax(array, length, 0.5, true); @@ -75,4 +74,4 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.deleteExternalArray(transpose); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/CocktailBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/CocktailBogoSort.java similarity index 90% rename from src/sorts/distribute/CocktailBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/CocktailBogoSort.java index 52e58fd7..dbc69fd5 100644 --- a/src/sorts/distribute/CocktailBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/CocktailBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /** * Cocktail Bogosort is a bidirectional variation of Less Bogosort. @@ -16,7 +16,6 @@ public CocktailBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Cocktail Bogo Sort"); this.setRunSortName("Cocktail Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/CountingSort.java b/src/main/java/io/github/arrayv/sorts/distribute/CountingSort.java similarity index 88% rename from src/sorts/distribute/CountingSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/CountingSort.java index a2202888..c083a785 100644 --- a/src/sorts/distribute/CountingSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/CountingSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class CountingSort extends Sort { +public final class CountingSort extends Sort { public CountingSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Counting"); this.setRunAllSortsName("Counting Sort"); this.setRunSortName("Counting Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -48,24 +47,24 @@ public CountingSort(ArrayVisualizer arrayVisualizer) { @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int max = Reads.analyzeMax(array, sortLength, 0, false); - + int[] output = Writes.copyOfArray(array, sortLength); int[] counts = Writes.createExternalArray(max + 1); - - for (int i = 0; i < sortLength; i++) { + + for (int i = 0; i < sortLength; i++) { Writes.write(counts, array[i], counts[array[i]] + 1, 1, false, true); Highlights.markArray(1, i); - } + } - for (int i = 1; i < counts.length; i++) { + for (int i = 1; i < counts.length; i++) { Writes.write(counts, i, counts[i] + counts[i - 1], 1, true, true); - } + } for (int i = sortLength - 1; i >= 0; i--) { output[counts[array[i]] - 1] = array[i]; counts[array[i]]--; } - + // Extra loop to simulate the results from the "output" array being written // to the visual array. for (int i = sortLength - 1; i >= 0; i--) { @@ -76,4 +75,4 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Writes.deleteExternalArray(output); Writes.deleteExternalArray(counts); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/DeterministicBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/DeterministicBogoSort.java similarity index 94% rename from src/sorts/distribute/DeterministicBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/DeterministicBogoSort.java index d6ee6255..58ea48d7 100644 --- a/src/sorts/distribute/DeterministicBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/DeterministicBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* MIT License Copyright (c) 2020 Walker Gray @@ -37,7 +37,6 @@ public DeterministicBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Deterministic Bogo Sort"); this.setRunSortName("Deterministic Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/FlashSort.java b/src/main/java/io/github/arrayv/sorts/distribute/FlashSort.java similarity index 95% rename from src/sorts/distribute/FlashSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/FlashSort.java index dcdffdcf..47c1bb5b 100644 --- a/src/sorts/distribute/FlashSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/FlashSort.java @@ -1,27 +1,26 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; import java.util.Arrays; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; -final public class FlashSort extends Sort { +public final class FlashSort extends Sort { public FlashSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Flash"); this.setRunAllSortsName("Flash Sort"); this.setRunSortName("Flashsort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + // The flashsort algorithm is attributed to Karl-Dietrich Neubert // The translation to C++ is provided by Clint Jed Casper // Refactored in Java by MusicTheorist @@ -29,7 +28,7 @@ public FlashSort(ArrayVisualizer arrayVisualizer) { // sorts an array in place in O(n) time using 20% of the // memory used by the array for storing intermediate, // temporary computations - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { if(sortLength == 0) return; @@ -54,7 +53,7 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti int bigIndex; Highlights.markArray(1, i); - + //which is bigger A(i) or A(i+1) if(Reads.compareValues(array[i], array[i + 1]) == -1) { @@ -79,7 +78,7 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti { min = small; } - + Delays.sleep(1); } @@ -97,7 +96,7 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) Delays.sleep(1); Highlights.clearMark(1); - + if(max == min) { //all the elements are the same @@ -108,7 +107,7 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) //note that L is in the range 1...m (hence //the extra 1) int[] L = Writes.createExternalArray(m + 1); - + //O(m) //initialize L to contain all zeros (L[0] is unused) for(int t = 1; t <= m; t++) @@ -131,9 +130,9 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) int K; for(int h = 0; h < sortLength; h++) { - + Highlights.markArray(1, h); - + //classify the A(i) value K = ((int)((array[h] - min) * c)) + 1; @@ -141,7 +140,7 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) Writes.write(L, K, L[K] + 1, 1, false, true); } Highlights.clearMark(1); - + //O(m) //sum over each L(i) such that each L(i) contains //the number of A(i) values that are in the ith @@ -157,13 +156,13 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) Writes.swap(array, maxIndex, 0, 1, true, false); Highlights.clearMark(1); Highlights.clearMark(2); - + //Except when being iterated upwards, //j always points to the first A(i) that starts //a new class boundary && that class hasn't yet //had all of its elements moved inside its borders; - //This is called a cycle leader since you know + //This is called a cycle leader since you know //that you can begin permuting again here. You know //this because it is the lowest index of the class //and as such A(j) must be out of place or else all @@ -171,7 +170,7 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) //within the borders of the this class (which means //j wouldn't be pointing to this A(i) in the first place) int j = 0; - + //K is the class of an A(i) value. It is always in the range 1..m K = m; @@ -223,7 +222,7 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) Writes.write(array, location, evicted, 1, false, false); Highlights.markArray(1, location); evicted = temp; - + //decrease the count for this class //see counting sort for why this is done Writes.write(L, K, L[K] - 1, 0, false, true); @@ -233,7 +232,7 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) } } Highlights.clearMark(1); - + //-------RECURSION or STRAIGHT INSERTION------- //if the classes do not have the A(i) values uniformly distributed @@ -247,7 +246,7 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) //if the class has 25% more elements than it should int threshold = (int)(1.25 * ((sortLength / m) + 1)); int minElements = 30; - + //for each class decide whether to insertion sort its members //or recursively flashsort its members; //skip the K == m class because it is already sorted @@ -263,10 +262,10 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) //of it then... if(classSize > threshold && classSize > minElements) { - //...attempt to flashsort the class. This will work + //...attempt to flashsort the class. This will work //well if the elements inside the class are uniformly - //distributed throughout the class otherwise it will - //perform badly, O(n^2) worst case, since we will have + //distributed throughout the class otherwise it will + //perform badly, O(n^2) worst case, since we will have //performed another classification and permutation step //and not succeeded in making the problem significantly //smaller for the next level of recursion. However, @@ -282,4 +281,4 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) Writes.deleteExternalArray(L); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/GravitySort.java b/src/main/java/io/github/arrayv/sorts/distribute/GravitySort.java similarity index 92% rename from src/sorts/distribute/GravitySort.java rename to src/main/java/io/github/arrayv/sorts/distribute/GravitySort.java index e27d65fd..98fa68b7 100644 --- a/src/sorts/distribute/GravitySort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/GravitySort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,64 +29,63 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class GravitySort extends Sort { +public final class GravitySort extends Sort { public GravitySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Gravity"); this.setRunAllSortsName("Gravity (Bead) Sort"); this.setRunSortName("Beadsort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int min = array[0], max = array[0]; - + for(int i = 1; i < length; i++) { if(array[i] < min) min = array[i]; if(array[i] > max) max = array[i]; } - + int[] x = Writes.createExternalArray(length); int[] y = Writes.createExternalArray(max - min + 1); - + double delay = Math.max(2d / length, 0.001); - + //save a copy of array-min in x //increase count of the array-min value in y for(int i = 0; i < length; i++) { Writes.write(x, i, array[i]-min, 0, true, true); Writes.write(y, array[i]-min, y[array[i]-min]+1, 1, false, true); } - + //do a partial sum backwards to determine how many elements are greater than a value for(int i = y.length-1; i > 0; i--) Writes.write(y, i-1, y[i-1]+=y[i], 1, true, true); - + //iterate for every integer value in the array range for(int j = y.length-1; j >= 0; j--) { Highlights.markArray(2, length-y[j]); - + //iterate for every item in array and x for(int i = 0; i < length; i++) { Highlights.markArray(1, i); Delays.sleep(delay); - + int inc = (i >= length-y[j] ? 1 : 0) - (x[i] >= j ? 1 : 0); - + //update the main array Writes.write(array, i, array[i]+inc, delay, true, false); } } - + Writes.deleteExternalArray(x); Writes.deleteExternalArray(y); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/GuessSort.java b/src/main/java/io/github/arrayv/sorts/distribute/GuessSort.java similarity index 94% rename from src/sorts/distribute/GuessSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/GuessSort.java index b0262299..340c12bf 100644 --- a/src/sorts/distribute/GuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/GuessSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; public final class GuessSort extends BogoSorting { public GuessSort(ArrayVisualizer arrayVisualizer) { @@ -10,7 +10,6 @@ public GuessSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Guess Sort"); this.setRunSortName("Guess Sort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/InPlaceLSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/InPlaceLSDRadixSort.java similarity index 90% rename from src/sorts/distribute/InPlaceLSDRadixSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/InPlaceLSDRadixSort.java index a41dcb62..7dec3c13 100644 --- a/src/sorts/distribute/InPlaceLSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/InPlaceLSDRadixSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,16 +29,15 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class InPlaceLSDRadixSort extends Sort { +public final class InPlaceLSDRadixSort extends Sort { public InPlaceLSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("In-Place LSD Radix"); //this.setRunAllID("In-Place LSD Radix Sort, Base 2"); this.setRunAllSortsName("In-Place LSD Radix Sort, Base 10"); this.setRunSortName("In-Place LSD Radix Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(true); this.setUnreasonablySlow(false); @@ -49,33 +48,33 @@ public InPlaceLSDRadixSort(ArrayVisualizer arrayVisualizer) { @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.setRunAllSortsName("In-Place LSD Radix Sort, Base " + bucketCount); - + int pos = 0; int[] vregs = new int[bucketCount - 1]; Writes.changeAllocAmount(vregs.length); - + int maxpower = Reads.analyzeMaxLog(array, sortLength, bucketCount, 0.5, true); - + for(int p = 0; p <= maxpower; p++){ for(int i = 0; i < vregs.length; i++) { Writes.write(vregs, i, sortLength - 1, 0, false, true); } - + pos = 0; - + for(int i = 0; i < sortLength; i++){ int digit = Reads.getDigit(array[pos], p, bucketCount); - + if(digit == 0) { pos++; Highlights.markArray(0, pos); - } + } else { for(int j = 0; j < vregs.length;j++) Highlights.markArray(j + 1, vregs[j]); - + Writes.multiSwap(array, pos, vregs[digit - 1], bucketCount / 10000d, false, false); - + for(int j = digit - 1; j > 0; j--) { Writes.write(vregs, j - 1, vregs[j - 1] - 1, 0, false, true); } @@ -85,4 +84,4 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Writes.changeAllocAmount(-vregs.length); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/IndexSort.java b/src/main/java/io/github/arrayv/sorts/distribute/IndexSort.java similarity index 92% rename from src/sorts/distribute/IndexSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/IndexSort.java index 81ea6a86..8830852f 100644 --- a/src/sorts/distribute/IndexSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/IndexSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 Gaming32 @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class IndexSort extends Sort { +public final class IndexSort extends Sort { public IndexSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Index"); this.setRunAllSortsName("Simple Static Sort (Index Sort)"); this.setRunSortName("Index Sort (Simple Static Sort)"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -62,4 +61,4 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Delays.sleep(1); } } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/LSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/LSDRadixSort.java similarity index 91% rename from src/sorts/distribute/LSDRadixSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/LSDRadixSort.java index c1c0d4db..d20bbc61 100644 --- a/src/sorts/distribute/LSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/LSDRadixSort.java @@ -1,12 +1,12 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; import java.util.ArrayList; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -31,15 +31,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class LSDRadixSort extends Sort { +public final class LSDRadixSort extends Sort { public LSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("LSD Radix"); this.setRunAllSortsName("Least Significant Digit Radix Sort, Base 4"); this.setRunSortName("Least Significant Digit Radixsort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(true); this.setUnreasonablySlow(false); @@ -50,22 +49,22 @@ public LSDRadixSort(ArrayVisualizer arrayVisualizer) { @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.setRunAllSortsName("Least Significant Digit Radix Sort, Base " + bucketCount); - + int highestpower = Reads.analyzeMaxLog(array, sortLength, bucketCount, 0.5, true); - + @SuppressWarnings("unchecked") ArrayList[] registers = new ArrayList[bucketCount]; - + for(int i = 0; i < bucketCount; i++) registers[i] = new ArrayList<>(); - + for(int p = 0; p <= highestpower; p++){ for(int i = 0; i < sortLength; i++){ Highlights.markArray(1, i); - + int digit = Reads.getDigit(array[i], p, bucketCount); Writes.arrayListAdd(registers[digit], array[i]); - + Writes.mockWrite(sortLength, digit, array[i], 1); } @@ -74,4 +73,4 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Writes.deleteExternalArray(registers); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/LessBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/LessBogoSort.java similarity index 86% rename from src/sorts/distribute/LessBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/LessBogoSort.java index 45b2968e..47b90c35 100644 --- a/src/sorts/distribute/LessBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/LessBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /** * Less Bogosort repeatedly shuffles the array, @@ -15,7 +15,6 @@ public LessBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Less Bogo Sort"); this.setRunSortName("Less Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/MSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/MSDRadixSort.java similarity index 91% rename from src/sorts/distribute/MSDRadixSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/MSDRadixSort.java index 034c9139..1ed627f1 100644 --- a/src/sorts/distribute/MSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/MSDRadixSort.java @@ -1,12 +1,12 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; import java.util.ArrayList; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -31,16 +31,15 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class MSDRadixSort extends Sort { +public final class MSDRadixSort extends Sort { public MSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("MSD Radix"); //this.setRunAllID("Most Significant Digit Radix Sort"); this.setRunAllSortsName("Most Significant Digit Radix Sort, Base 4"); this.setRunSortName("Most Significant Digit Radixsort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(true); this.setUnreasonablySlow(false); @@ -51,34 +50,34 @@ public MSDRadixSort(ArrayVisualizer arrayVisualizer) { private void radixMSD(int[] array, int length, int min, int max, int radix, int pow) { if(min >= max || pow < 0) return; - + Highlights.markArray(2, max - 1); Highlights.markArray(3, min); - + @SuppressWarnings("unchecked") ArrayList[] registers = new ArrayList[radix]; - + for(int i = 0; i < radix; i++) registers[i] = new ArrayList<>(); - + for(int i = min; i < max; i++) { Highlights.markArray(1, i); - + int digit = Reads.getDigit(array[i], pow, radix); Writes.arrayListAdd(registers[digit], array[i]); - + Writes.mockWrite(length, digit, array[i], 1); } - + Highlights.clearMark(2); Highlights.clearMark(3); - + Writes.transcribeMSD(array, registers, 0, min, 0.8, true, false); - + int sum = 0; for(int i = 0; i < registers.length; i++) { this.radixMSD(array, length, sum + min, sum + min + registers[i].size(), radix, pow-1); - + sum += registers[i].size(); Writes.arrayListClear(registers[i]); Writes.changeAuxWrites(registers[i].size()); @@ -86,11 +85,11 @@ private void radixMSD(int[] array, int length, int min, int max, int radix, int Writes.deleteExternalArray(registers); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int highestpower = Reads.analyzeMaxLog(array, sortLength, bucketCount, 0.5, true); - + radixMSD(array, sortLength, 0, sortLength, bucketCount, highestpower); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/MedianQuickBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/MedianQuickBogoSort.java similarity index 94% rename from src/sorts/distribute/MedianQuickBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/MedianQuickBogoSort.java index f1576803..32161e42 100644 --- a/src/sorts/distribute/MedianQuickBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/MedianQuickBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* * @@ -41,7 +41,6 @@ public MedianQuickBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Median Quick Bogo Sort"); this.setRunSortName("Median Quick Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/MergeBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/MergeBogoSort.java similarity index 95% rename from src/sorts/distribute/MergeBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/MergeBogoSort.java index ac891d9a..ba74ac23 100644 --- a/src/sorts/distribute/MergeBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/MergeBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* * @@ -41,7 +41,6 @@ public MergeBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Merge Bogo Sort"); this.setRunSortName("Merge Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/OptimizedGuessSort.java b/src/main/java/io/github/arrayv/sorts/distribute/OptimizedGuessSort.java similarity index 94% rename from src/sorts/distribute/OptimizedGuessSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/OptimizedGuessSort.java index ad1fe640..18247d15 100644 --- a/src/sorts/distribute/OptimizedGuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/OptimizedGuessSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; public final class OptimizedGuessSort extends BogoSorting { public OptimizedGuessSort(ArrayVisualizer arrayVisualizer) { @@ -11,7 +11,6 @@ public OptimizedGuessSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Optimized Guess Sort"); this.setRunSortName("Optimized Guess Sort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/PigeonholeSort.java b/src/main/java/io/github/arrayv/sorts/distribute/PigeonholeSort.java similarity index 89% rename from src/sorts/distribute/PigeonholeSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/PigeonholeSort.java index 675bb56c..ff62afe1 100644 --- a/src/sorts/distribute/PigeonholeSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/PigeonholeSort.java @@ -1,13 +1,13 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS * LICENSE OR COPYRIGHT LAW IS PROHIBITED. - * + * * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. * TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN * CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. @@ -15,27 +15,26 @@ // Code refactored from the Python implementation found here: https://en.wikipedia.org/wiki/Pigeonhole_sort -final public class PigeonholeSort extends Sort { +public final class PigeonholeSort extends Sort { public PigeonholeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Pigeonhole"); this.setRunAllSortsName("Pigeonhole Sort"); this.setRunSortName("Pigeonhole Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; - + for(int i = 0; i < sortLength; i++) { if(array[i] < min) { min = array[i]; @@ -44,23 +43,23 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti max = array[i]; } } - + int mi = min; int size = max - mi + 1; int[] holes = Writes.createExternalArray(size); - + for(int x = 0; x < sortLength; x++) { Writes.write(holes, array[x] - mi, holes[array[x] - mi] + 1, 1, false, true); Highlights.markArray(1, x); } - + int j = 0; - + for(int count = 0; count < size; count++) { while(holes[count] > 0) { Writes.write(holes, count, holes[count] - 1, 0, false, true); Writes.write(array, j, count + mi, 1, false, false); - + Highlights.markArray(1, j); j++; } @@ -68,4 +67,4 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Writes.deleteExternalArray(holes); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/QuickBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/QuickBogoSort.java similarity index 95% rename from src/sorts/distribute/QuickBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/QuickBogoSort.java index 2fbf68e4..2fc580c4 100644 --- a/src/sorts/distribute/QuickBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/QuickBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* * @@ -42,7 +42,6 @@ public QuickBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Quick Bogo Sort"); this.setRunSortName("Quick Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/RandomGuessSort.java b/src/main/java/io/github/arrayv/sorts/distribute/RandomGuessSort.java similarity index 93% rename from src/sorts/distribute/RandomGuessSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/RandomGuessSort.java index bc96e243..d23f8132 100644 --- a/src/sorts/distribute/RandomGuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/RandomGuessSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; public final class RandomGuessSort extends BogoSorting { public RandomGuessSort(ArrayVisualizer arrayVisualizer) { @@ -11,7 +11,6 @@ public RandomGuessSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Random Guess Sort"); this.setRunSortName("Random Guess Sort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/RotateLSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/RotateLSDRadixSort.java similarity index 91% rename from src/sorts/distribute/RotateLSDRadixSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/RotateLSDRadixSort.java index 35430dee..b09ce854 100644 --- a/src/sorts/distribute/RotateLSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/RotateLSDRadixSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -29,32 +29,31 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class RotateLSDRadixSort extends Sort { +public final class RotateLSDRadixSort extends Sort { public RotateLSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Rotate LSD Radix"); this.setRunAllSortsName("Rotate LSD Radix Sort, Base 4"); this.setRunSortName("Rotate LSD Radixsort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(true); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int base; - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 0.5, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -70,50 +69,50 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private int binSearch(int[] array, int a, int b, int d, int p) { while(a < b) { int m = (a+b)/2; - - if(Reads.getDigit(array[m], p, this.base) >= d) + + if(Reads.getDigit(array[m], p, this.base) >= d) b = m; - + else a = m+1; } return a; } - + private void merge(int[] array, int a, int m, int b, int da, int db, int p) { if(b-a < 2 || db-da < 2) return; - + int dm = (da+db)/2; int m1 = this.binSearch(array, a, m, dm, p); int m2 = this.binSearch(array, m, b, dm, p); - + this.rotate(array, m1, m, m2); m = m1+(m2-m); - + this.merge(array, m, m2, b, dm, db, p); this.merge(array, a, m1, m, da, dm, p); } - + private void mergeSort(int[] array, int a, int b, int p) { if(b-a < 2) return; - + int m = (a+b)/2; - + this.mergeSort(array, a, m, p); this.mergeSort(array, m, b, p); - + this.merge(array, a, m, b, 0, this.base, p); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.base = bucketCount; int max = Reads.analyzeMaxLog(array, length, this.base, 0.5, true); - + for(int i = 0; i <= max; i++) this.mergeSort(array, 0, length, i); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/RotateMSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/RotateMSDRadixSort.java similarity index 92% rename from src/sorts/distribute/RotateMSDRadixSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/RotateMSDRadixSort.java index 24d5ba67..82f04b91 100644 --- a/src/sorts/distribute/RotateMSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/RotateMSDRadixSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -29,31 +29,30 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class RotateMSDRadixSort extends Sort { +public final class RotateMSDRadixSort extends Sort { public RotateMSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Rotate MSD Radix"); this.setRunAllSortsName("Rotate MSD Radix Sort, Base 4"); this.setRunSortName("Rotate MSD Radixsort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(true); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int stabVal(int idx) { if(arrayVisualizer.doingStabilityCheck()) return arrayVisualizer.getStabilityValue(idx); else return idx; } - + private int base; - + private int shift(int n, int q) { while(q > 0) { n /= this.base; @@ -61,15 +60,15 @@ private int shift(int n, int q) { } return n; } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 0.5, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -85,59 +84,59 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private int binSearch(int[] array, int a, int b, int d, int p) { while(a < b) { int m = (a+b)/2; - - if(Reads.getDigit(array[m], p, this.base) >= d) + + if(Reads.getDigit(array[m], p, this.base) >= d) b = m; - + else a = m+1; } return a; } - + private void merge(int[] array, int a, int m, int b, int da, int db, int p) { if(b-a < 2 || db-da < 2) return; - + int dm = (da+db)/2; int m1 = this.binSearch(array, a, m, dm, p); int m2 = this.binSearch(array, m, b, dm, p); - + this.rotate(array, m1, m, m2); m = m1+(m2-m); - + this.merge(array, m, m2, b, dm, db, p); this.merge(array, a, m1, m, da, dm, p); } - + private void mergeSort(int[] array, int a, int b, int p) { if(b-a < 2) return; - + int m = (a+b)/2; - + this.mergeSort(array, a, m, p); this.mergeSort(array, m, b, p); - + this.merge(array, a, m, b, 0, this.base, p); } - + private int dist(int[] array, int a, int b, int p) { this.mergeSort(array, a, b, p); - + return this.binSearch(array, a, b, 1, p); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.base = bucketCount; int q = Reads.analyzeMaxLog(array, length, this.base, 0.5, true); int m = 0, i = 0, b = length; - + while(i < length) { int p = b-i < 1 ? i : this.dist(array, i, b, q); - + if(q == 0) { m += this.base; int t = m/this.base; @@ -145,7 +144,7 @@ public void runSort(int[] array, int length, int bucketCount) { t /= this.base; q++; } - + i = b; Highlights.clearMark(2); arrayVisualizer.toggleAnalysis(true); @@ -162,4 +161,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/SelectionBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/SelectionBogoSort.java similarity index 94% rename from src/sorts/distribute/SelectionBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/SelectionBogoSort.java index ec972ab6..5d3f1d2a 100644 --- a/src/sorts/distribute/SelectionBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/SelectionBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* * @@ -50,7 +50,6 @@ public SelectionBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Selection Bogo Sort"); this.setRunSortName("Selection Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/ShatterSort.java b/src/main/java/io/github/arrayv/sorts/distribute/ShatterSort.java similarity index 89% rename from src/sorts/distribute/ShatterSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/ShatterSort.java index 31c131c4..45d11c7f 100644 --- a/src/sorts/distribute/ShatterSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/ShatterSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.ShatterSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.ShatterSorting; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,24 +29,23 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ShatterSort extends ShatterSorting { +public final class ShatterSort extends ShatterSorting { public ShatterSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Shatter"); this.setRunAllSortsName("Shatter Sort"); this.setRunSortName("Shatter Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.shatterSort(array, sortLength, bucketCount); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/SimpleShatterSort.java b/src/main/java/io/github/arrayv/sorts/distribute/SimpleShatterSort.java similarity index 89% rename from src/sorts/distribute/SimpleShatterSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/SimpleShatterSort.java index b988e9c7..4552815b 100644 --- a/src/sorts/distribute/SimpleShatterSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/SimpleShatterSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.ShatterSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.ShatterSorting; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,24 +29,23 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class SimpleShatterSort extends ShatterSorting { +public final class SimpleShatterSort extends ShatterSorting { public SimpleShatterSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Simple Shatter"); this.setRunAllSortsName("Simple Shatter Sort"); this.setRunSortName("Simple Shatter Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.simpleShatterSort(array, sortLength, bucketCount, (int) (Math.log(sortLength) / Math.log(2)) / 2); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/SimplisticGravitySort.java b/src/main/java/io/github/arrayv/sorts/distribute/SimplisticGravitySort.java similarity index 90% rename from src/sorts/distribute/SimplisticGravitySort.java rename to src/main/java/io/github/arrayv/sorts/distribute/SimplisticGravitySort.java index 735e23ac..bc8d2982 100644 --- a/src/sorts/distribute/SimplisticGravitySort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/SimplisticGravitySort.java @@ -1,30 +1,28 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -import main.ArrayVisualizer; +public final class SimplisticGravitySort extends Sort { -final public class SimplisticGravitySort extends Sort { - public SimplisticGravitySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Simplistic Gravity"); this.setRunAllSortsName("Simplistic Gravity Sort (By McDude_73)"); this.setRunSortName("Simplistic Gravity Sort"); this.setCategory("Distributive Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + int[] aux; int min; double sleep; - + private void transferFrom(int[] array, int arrayLength, int index) { for(int pointer = 0;pointer < arrayLength && this.aux[pointer] != 0;pointer++) { Highlights.markArray(2, index); @@ -32,7 +30,7 @@ private void transferFrom(int[] array, int arrayLength, int index) { Writes.write(this.aux, pointer, --this.aux[pointer], this.sleep, true, true); } } - + private void transferTo(int[] array, int arrayLength, int index) { for(int pointer = 0;array[index] > this.min;pointer++) { Highlights.markArray(2, index); @@ -40,7 +38,7 @@ private void transferTo(int[] array, int arrayLength, int index) { Writes.write(this.aux, pointer, ++this.aux[pointer], this.sleep, true, true); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.sleep = 10d/length; @@ -63,4 +61,4 @@ public void runSort(int[] array, int length, int bucketCount) { } Writes.deleteExternalArray(this.aux); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/SmartBogoBogoSort.java b/src/main/java/io/github/arrayv/sorts/distribute/SmartBogoBogoSort.java similarity index 94% rename from src/sorts/distribute/SmartBogoBogoSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/SmartBogoBogoSort.java index 9dd6df9f..96c6e76b 100644 --- a/src/sorts/distribute/SmartBogoBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/SmartBogoBogoSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* * @@ -47,7 +47,6 @@ public SmartBogoBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Smart Bogo Bogo Sort"); this.setRunSortName("Smart Bogobogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/SmartGuessSort.java b/src/main/java/io/github/arrayv/sorts/distribute/SmartGuessSort.java similarity index 94% rename from src/sorts/distribute/SmartGuessSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/SmartGuessSort.java index 5a9533cd..e5a012bd 100644 --- a/src/sorts/distribute/SmartGuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/SmartGuessSort.java @@ -1,7 +1,7 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; public final class SmartGuessSort extends BogoSorting { public SmartGuessSort(ArrayVisualizer arrayVisualizer) { @@ -11,7 +11,6 @@ public SmartGuessSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Smart Guess Sort"); this.setRunSortName("Smart Guess Sort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/distribute/StacklessAmericanFlagSort.java b/src/main/java/io/github/arrayv/sorts/distribute/StacklessAmericanFlagSort.java similarity index 93% rename from src/sorts/distribute/StacklessAmericanFlagSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/StacklessAmericanFlagSort.java index eea6af62..34da93b3 100644 --- a/src/sorts/distribute/StacklessAmericanFlagSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/StacklessAmericanFlagSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -29,29 +29,28 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StacklessAmericanFlagSort extends Sort { +public final class StacklessAmericanFlagSort extends Sort { public StacklessAmericanFlagSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stackless American Flag"); this.setRunAllSortsName("Stackless American Flag Sort"); this.setRunSortName("Stackless American Flag Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(true); this.setRadixSort(true); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int stabVal(int idx) { if(arrayVisualizer.doingStabilityCheck()) return arrayVisualizer.getStabilityValue(idx); else return idx; } - + private static int shift(int n, int q, int r) { while(q > 0) { n /= r; @@ -59,7 +58,7 @@ private static int shift(int n, int q, int r) { } return n; } - + private int dist(int[] array, int[] cnts, int[] offs, int a, int b, int q, int r) { for(int i = 1; i < r; i++) { Writes.write(cnts, i, cnts[i]+cnts[i-1], 0, false, true); @@ -67,60 +66,60 @@ private int dist(int[] array, int[] cnts, int[] offs, int a, int b, int q, int r } for(int i = 0; i < r-1; i++) { int pos = a+offs[i]; - + if(cnts[i] > offs[i]) { Highlights.markArray(2, pos); int t = array[pos]; - + do { int digit = Reads.getDigit(t, q, r); Writes.write(cnts, digit, cnts[digit]-1, 0, false, true); - + int t1 = array[a+cnts[digit]]; Writes.write(array, a+cnts[digit], t, 0.5, true, false); t = t1; } while(cnts[i] > offs[i]); - + Highlights.clearMark(2); } } int p = a+offs[1]; - + for(int i = 0; i < r; i++) { Writes.write(cnts, i, 0, 0, false, true); Writes.write(offs, i, 0, 0, false, true); } return p; } - + @Override public void runSort(int[] array, int length, int bucketCount) { int r = bucketCount, q = Reads.analyzeMaxLog(array, length, r, 0.5, true), m = 0, i = 0, b = length; - + int[] cnts = new int[r], offs = new int[r]; Writes.changeAllocAmount(2 * r); - + for(int j = i; j < b; j++) { Highlights.markArray(1, j); int digit = Reads.getDigit(array[j], q, r); Writes.write(cnts, digit, cnts[digit]+1, 0.5, false, true); } - + while(i < length) { int p = b-i < 1 ? i : this.dist(array, cnts, offs, i, b, q, r); - + if(q == 0) { m += r; int t = m/r; - + while(t%r == 0) { t /= r; q++; } - + i = b; while(b < length && shift(this.stabVal(array[b]), q+1, r) == shift(m, q+1, r)) { Highlights.markArray(1, b); @@ -132,7 +131,7 @@ public void runSort(int[] array, int length, int bucketCount) { else { b = p; q--; - + for(int j = i; j < b; j++) { Highlights.markArray(1, j); int digit = Reads.getDigit(array[j], q, r); @@ -142,4 +141,4 @@ public void runSort(int[] array, int length, int bucketCount) { } Writes.changeAllocAmount(-2 * r); } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/StacklessBinaryQuickSort.java b/src/main/java/io/github/arrayv/sorts/distribute/StacklessBinaryQuickSort.java similarity index 92% rename from src/sorts/distribute/StacklessBinaryQuickSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/StacklessBinaryQuickSort.java index e4342840..5d59b6a3 100644 --- a/src/sorts/distribute/StacklessBinaryQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/StacklessBinaryQuickSort.java @@ -1,10 +1,10 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -29,32 +29,31 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StacklessBinaryQuickSort extends Sort { +public final class StacklessBinaryQuickSort extends Sort { public StacklessBinaryQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stackless Binary Quick"); this.setRunAllSortsName("Stackless Binary Quick Sort"); this.setRunSortName("Stackless Binary Quicksort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int stabVal(int idx) { if(arrayVisualizer.doingStabilityCheck()) return arrayVisualizer.getStabilityValue(idx); else return idx; } - + private int partition(int[] array, int a, int b, int bit) { int i = a-1, j = b; - + while(true) { do { i++; @@ -62,31 +61,31 @@ private int partition(int[] array, int a, int b, int bit) { Delays.sleep(0.5); } while(i < j && !Reads.getBit(array[i], bit)); - + do { j--; Highlights.markArray(2, j); Delays.sleep(0.5); } while(j > i && Reads.getBit(array[j], bit)); - + if(i < j) Writes.swap(array, i, j, 1, true, false); else return i; } } - + @Override public void runSort(int[] array, int length, int bucketCount) { int q = Reads.analyzeBit(array, length), m = 0, i = 0, b = length; - + while(i < length) { int p = b-i < 1 ? i : this.partition(array, i, b, q); - + if(q == 0) { m += 2; while(!Reads.getBit(m, q+1)) q++; - + i = b; Highlights.clearMark(2); arrayVisualizer.toggleAnalysis(true); @@ -103,4 +102,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } } -} \ No newline at end of file +} diff --git a/src/sorts/distribute/StaticSort.java b/src/main/java/io/github/arrayv/sorts/distribute/StaticSort.java similarity index 86% rename from src/sorts/distribute/StaticSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/StaticSort.java index 88f86b5c..42552513 100644 --- a/src/sorts/distribute/StaticSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/StaticSort.java @@ -1,14 +1,12 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.insert.UnstableInsertionSort; -import sorts.select.MaxHeapSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.select.MaxHeapSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 thatsOven @@ -33,18 +31,17 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StaticSort extends Sort { +public final class StaticSort extends Sort { MaxHeapSort heapSorter; - UnstableInsertionSort insertSorter; + InsertionSort insertSorter; public StaticSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Static"); this.setRunAllSortsName("Static Sort"); this.setRunSortName("Static Sort"); this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -73,10 +70,8 @@ public void staticSort(int[] array, int a, int b) { int[] count = Writes.createExternalArray(auxLen + 1), offset = Writes.createExternalArray(auxLen + 1); - float CONST = (float) auxLen / (minMax[1] - minMax[0] + 4); + float CONST = (float) auxLen / (minMax[1] - minMax[0] + 1); - System.out.println(CONST); - int idx; for (int i = a; i < b; i++) { Highlights.markArray(1, i); @@ -84,31 +79,31 @@ public void staticSort(int[] array, int a, int b) { idx = (int)((array[i] - minMax[0]) * CONST); Writes.write(count, idx, count[idx] + 1, 1, false, true); } - + Writes.write(offset, 0, a, 0, false, true); - + for (int i = 1; i < auxLen; i++) { Writes.write(offset, i, count[i - 1] + offset[i - 1], 0, false, true); } - + for (int v = 0; v < auxLen; v++) { while (count[v] > 0) { int origin = offset[v]; int from = origin; int num = array[from]; - + Writes.write(array, from, -1, 0.5, true, false); - + do { idx = (int)((num - minMax[0]) * CONST); int to = offset[idx]; - + Writes.write(offset, idx, offset[idx] + 1, 1, false, true); Writes.write(count, idx, count[idx] - 1, 1, false, true); - + int temp = array[to]; Writes.write(array, to, num, 1, true, false); - + num = temp; from = to; } while (from != origin); @@ -124,17 +119,17 @@ public void staticSort(int[] array, int a, int b) { if (e - s > 16) heapSorter.customHeapSort(array, s, e, 1); else - insertSorter.unstableInsertionSort(array, s, e); + insertSorter.customInsertSort(array, s, e, 1, false); } Writes.deleteExternalArray(count); Writes.deleteExternalArray(offset); } - + @Override public void runSort(int[] mainArray, int size, int bucketCount) throws Exception { heapSorter = new MaxHeapSort(this.arrayVisualizer); - insertSorter = new UnstableInsertionSort(this.arrayVisualizer); + insertSorter = new InsertionSort(this.arrayVisualizer); this.staticSort(mainArray, 0, size); } diff --git a/src/sorts/distribute/TimeSort.java b/src/main/java/io/github/arrayv/sorts/distribute/TimeSort.java similarity index 76% rename from src/sorts/distribute/TimeSort.java rename to src/main/java/io/github/arrayv/sorts/distribute/TimeSort.java index 99dd9308..c6f45cb6 100644 --- a/src/sorts/distribute/TimeSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/TimeSort.java @@ -1,17 +1,17 @@ -package sorts.distribute; +package io.github.arrayv.sorts.distribute; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; -import utils.StopSort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -36,28 +36,22 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class TimeSort extends Sort { +@SortMeta( + name = "Time", + category = "Distribution Sorts", + showcaseName = "Time Sort, Mul 10", + question = "Enter delay per number in milliseconds:", + defaultAnswer = 10 +) +public final class TimeSort extends Sort { private InsertionSort insertSorter; - + private volatile int next = 0; - + public TimeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Time"); - //this.setRunAllID("Time Sort"); - this.setRunAllSortsName("Time Sort, Mul 10"); - this.setRunSortName("Timesort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(false); // *Does not* use buckets! "magnitude" is only a multiplier. - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1); //See threads.RunDistributionSort for details - this.setBogoSort(false); - this.setQuestion("Enter delay per number in milliseconds:", 10); } - + private synchronized void report(int[] array, int a){ Writes.write(array, next, a, 0, true, false); next++; @@ -66,32 +60,32 @@ private synchronized void report(int[] array, int a){ @Override public void runSort(int[] array, int sortLength, int magnitude) throws Exception { insertSorter = new InsertionSort(this.arrayVisualizer); - + final int A = magnitude; next = 0; - + ArrayList threads = new ArrayList<>(); - + final int[] tmp = Writes.createExternalArray(sortLength); - + for(int i = 0; i < sortLength; i++) { Writes.write(tmp, i, array[i], 0.25, true, true); } - + double temp = Delays.getDisplayedDelay(); Delays.updateDelayForTimeSort(magnitude); - + for(int i = 0; i < sortLength; i++){ final int index = i; - threads.add(new Thread(){ + threads.add(new Thread("TimeSort-" + i) { @Override public void run() { int a = tmp[index]; - + try { Thread.sleep(a*A); Writes.addTime(A); - } + } catch (InterruptedException ex) { Logger.getLogger(ArrayVisualizer.class.getName()).log(Level.SEVERE, null, ex); } @@ -102,10 +96,10 @@ public void run() { } }); } - + for(Thread t : threads) t.start(); - + try { Thread.sleep(sortLength * A); } @@ -115,12 +109,12 @@ public void run() { catch (IllegalArgumentException ex) { JErrorPane.invokeErrorMessage(ex); } - + Delays.setCurrentDelay(temp); Writes.setTime(sortLength * A); - + insertSorter.customInsertSort(array, 0, sortLength, 0.2, false); Writes.deleteExternalArray(tmp); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/BinaryGnomeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/BinaryGnomeSort.java similarity index 83% rename from src/sorts/exchange/BinaryGnomeSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/BinaryGnomeSort.java index 3c8ba167..b9bc015a 100644 --- a/src/sorts/exchange/BinaryGnomeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/BinaryGnomeSort.java @@ -1,17 +1,16 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class BinaryGnomeSort extends Sort { +public final class BinaryGnomeSort extends Sort { public BinaryGnomeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Binary Gnome"); this.setRunAllSortsName("Optimized Gnome Sort + Binary Search"); this.setRunSortName("Optimized Gnomesort + Binary Search"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -27,13 +26,13 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti int lo = 0, hi = i; while (lo < hi) { int mid = lo + ((hi - lo) / 2); - + Highlights.markArray(1, lo); Highlights.markArray(3, mid); Highlights.markArray(2, hi); - + Delays.sleep(1); - + if (Reads.compareValues(num, array[mid]) < 0) { // do NOT shift equal elements past each other; this maintains stability! hi = mid; } @@ -46,12 +45,12 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Highlights.clearMark(1); Highlights.clearMark(2); - + int j = i; - while (j > lo) { + while (j > lo) { Writes.swap(array, j, j - 1, 0.05, true, false); j--; } - } + } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/BubbleBogoSort.java b/src/main/java/io/github/arrayv/sorts/exchange/BubbleBogoSort.java similarity index 93% rename from src/sorts/exchange/BubbleBogoSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/BubbleBogoSort.java index d2f3a9d1..21827d54 100644 --- a/src/sorts/exchange/BubbleBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/BubbleBogoSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -40,7 +40,6 @@ public BubbleBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Bubble Bogo Sort"); this.setRunSortName("Bubble Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/exchange/BubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/BubbleSort.java similarity index 91% rename from src/sorts/exchange/BubbleSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/BubbleSort.java index dcedf095..0a7918e0 100644 --- a/src/sorts/exchange/BubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/BubbleSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,22 +29,21 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class BubbleSort extends Sort { +public final class BubbleSort extends Sort { public BubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Bubble"); this.setRunAllSortsName("Bubble Sort"); this.setRunSortName("Bubblesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { for(int i = length - 1; i > 0; i--) { @@ -54,7 +53,7 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.swap(array, j, j + 1, 0.075, true, false); sorted = false; } - + Highlights.markArray(1, j); Highlights.markArray(2, j + 1); Delays.sleep(0.025); @@ -62,4 +61,4 @@ public void runSort(int[] array, int length, int bucketCount) { if(sorted) break; } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/CircleSortIterative.java b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortIterative.java similarity index 84% rename from src/sorts/exchange/CircleSortIterative.java rename to src/main/java/io/github/arrayv/sorts/exchange/CircleSortIterative.java index 480585e7..97806f83 100644 --- a/src/sorts/exchange/CircleSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortIterative.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.IterativeCircleSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.IterativeCircleSorting; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -15,35 +15,34 @@ * */ -final public class CircleSortIterative extends IterativeCircleSorting { +public final class CircleSortIterative extends IterativeCircleSorting { public CircleSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Circle (Iterative)"); this.setRunAllSortsName("Iterative Circle Sort"); this.setRunSortName("Iterative Circlesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + public void singleRoutine(int[] array, int length) { this.circleSortRoutine(array, length, 0.1); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.end = sortLength; int n = 1; for(; n < sortLength; n*=2); - + int numberOfSwaps = 0; do { numberOfSwaps = this.circleSortRoutine(array, n, 1); } while (numberOfSwaps != 0); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/CircleSortRecursive.java b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortRecursive.java similarity index 85% rename from src/sorts/exchange/CircleSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/exchange/CircleSortRecursive.java index 4559cb48..f83c76bf 100644 --- a/src/sorts/exchange/CircleSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortRecursive.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.CircleSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.CircleSorting; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -15,35 +15,34 @@ * */ -final public class CircleSortRecursive extends CircleSorting { +public final class CircleSortRecursive extends CircleSorting { public CircleSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Circle (Recursive)"); this.setRunAllSortsName("Recursive Circle Sort"); this.setRunSortName("Circlesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + public void singleRoutine(int[] array, int length) { this.circleSortRoutine(array, 0, length - 1, 0, 0.1); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.end = sortLength; int n = 1; for(; n < sortLength; n*=2); - + int numberOfSwaps = 0; do { numberOfSwaps = this.circleSortRoutine(array, 0, n - 1, 0, 1); } while (numberOfSwaps != 0); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/CircloidSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CircloidSort.java similarity index 92% rename from src/sorts/exchange/CircloidSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/CircloidSort.java index 83f8bc7c..a6e0fdbf 100644 --- a/src/sorts/exchange/CircloidSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CircloidSort.java @@ -1,11 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import sorts.templates.Sort; - -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 yuji @@ -30,22 +29,21 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class CircloidSort extends Sort { +public final class CircloidSort extends Sort { public CircloidSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Circloid"); this.setRunAllSortsName("Circloid Sort"); this.setRunSortName("Circloid Sort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private boolean circle(int[] array, int left, int right) { int a = left; int b = right; @@ -63,7 +61,7 @@ private boolean circle(int[] array, int left, int right) { } return swapped; } - + private boolean circlePass(int[] array, int left, int right) { if(left >= right) return false; int mid = (left + right) / 2; @@ -71,9 +69,9 @@ private boolean circlePass(int[] array, int left, int right) { boolean r = this.circlePass(array, mid+1, right); return this.circle(array, left, right) || l || r; } - + @Override public void runSort(int[] array, int length, int bucketCount) { while(this.circlePass(array, 0, length-1)); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/ClassicThreeSmoothCombSort.java b/src/main/java/io/github/arrayv/sorts/exchange/ClassicThreeSmoothCombSort.java similarity index 90% rename from src/sorts/exchange/ClassicThreeSmoothCombSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/ClassicThreeSmoothCombSort.java index a6f6717f..b5dfe818 100644 --- a/src/sorts/exchange/ClassicThreeSmoothCombSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ClassicThreeSmoothCombSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 PiotrGrochowski Copyright (c) 2020 aphitorite @@ -26,30 +26,29 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ClassicThreeSmoothCombSort extends Sort { +public final class ClassicThreeSmoothCombSort extends Sort { public ClassicThreeSmoothCombSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Classic 3-Smooth Comb"); this.setRunAllSortsName("Classic 3-Smooth Comb Sort"); this.setRunSortName("Classic 3-Smooth Combsort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private boolean is3Smooth(int n) { while(n%6 == 0) n /= 6; while(n%3 == 0) n /= 3; while(n%2 == 0) n /= 2; - + return n == 1; } - + @Override public void runSort(int[] array, int length, int bucketCount) { for(int g = length-1; g > 0; g--) @@ -58,4 +57,4 @@ public void runSort(int[] array, int length, int bucketCount) { if(Reads.compareIndices(array, i-g, i, 0.5, true) == 1) Writes.swap(array, i-g, i, 0.5, true, false); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/CocktailShakerSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CocktailShakerSort.java similarity index 91% rename from src/sorts/exchange/CocktailShakerSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/CocktailShakerSort.java index d0800293..41ba91b7 100644 --- a/src/sorts/exchange/CocktailShakerSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CocktailShakerSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class CocktailShakerSort extends Sort { +public final class CocktailShakerSort extends Sort { public CocktailShakerSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Cocktail"); this.setRunAllSortsName("Cocktail Shaker Sort"); this.setRunSortName("Cocktail Shaker Sort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -54,10 +53,10 @@ private void smartCocktailShaker(int[] array, int start, int end, double sleep) Writes.swap(array, j, j + 1, sleep, true, false); sorted = false; } - + Highlights.markArray(1, j); Highlights.markArray(2, j + 1); - + Delays.sleep(sleep / 2); } for(int j = end + start - i - 1; j > i; j--){ @@ -65,23 +64,23 @@ private void smartCocktailShaker(int[] array, int start, int end, double sleep) Writes.swap(array, j, j - 1, sleep, true, false); sorted = false; } - + Highlights.markArray(1, j); Highlights.markArray(2, j - 1); - + Delays.sleep(sleep / 2); } if(sorted) break; else i++; } } - + public void customSort(int[] array, int start, int end) { this.smartCocktailShaker(array, start, end, 1); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.smartCocktailShaker(array, 0, length, 0.1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/CombSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CombSort.java similarity index 68% rename from src/sorts/exchange/CombSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/CombSort.java index 85fe9dd1..b45cf030 100644 --- a/src/sorts/exchange/CombSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CombSort.java @@ -1,10 +1,11 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.CombSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.CombSorting; /* - * + * The MIT License (MIT) Copyright (c) 2012 Daniel Imms, http://www.growingwiththeweb.com @@ -28,25 +29,18 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class CombSort extends CombSorting { +@SortMeta( + name = "Comb", + category = "Exchange Sorts", + question = "Enter shrink factor (input/100):", + defaultAnswer = 130 +) +public final class CombSort extends CombSorting { public CombSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Comb"); - this.setRunAllSortsName("Comb Sort"); - this.setRunSortName("Combsort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - this.setQuestion("Enter shrink factor (input/100):", 130); } - @Override - public int validateAnswer(int answer) { + public static int validateAnswer(int answer) { if (answer < 110) return 130; return answer; } @@ -55,4 +49,4 @@ public int validateAnswer(int answer) { public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.combSort(array, sortLength, bucketCount/100d, false); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/CompleteGraphSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CompleteGraphSort.java similarity index 91% rename from src/sorts/exchange/CompleteGraphSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/CompleteGraphSort.java index 5a791e20..f506912e 100644 --- a/src/sorts/exchange/CompleteGraphSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CompleteGraphSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2021 aphitorite @@ -27,52 +27,51 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - -final public class CompleteGraphSort extends Sort { + +public final class CompleteGraphSort extends Sort { public CompleteGraphSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Complete Graph"); this.setRunAllSortsName("Complete Graph Sorting Network"); this.setRunSortName("Complete Graph Sorting Network"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void compSwap(int[] array, int a, int b) { if(Reads.compareIndices(array, a, b, 0.0125, true) > 0) Writes.swap(array, a, b, 0.0875, true, false); } - + private void split(int[] array, int a, int m, int b) { if(b-a < 2) return; - + int c = 0, len1 = (b-a)/2; boolean odd = (b-a)%2 == 1; - + if(odd) { if(m-a > b-m) c = a++; else c = --b; } for(int s = 0; s < len1; s++) { int i = a; - + for(int j = s; j < len1; j++) this.compSwap(array, i++, m+j); - + for(int j = 0; j < s; j++) this.compSwap(array, i++, m+j); } if(odd) { - if(c < m) + if(c < m) for(int j = 0; j < len1; j++) this.compSwap(array, c, m+j); - else + else for(int j = 0; j < len1; j++) this.compSwap(array, a+j, c); } @@ -82,21 +81,21 @@ private void split(int[] array, int a, int m, int b) { public void runSort(int[] array, int currentLength, int bucketCount) { int n = currentLength; int d = 2, end = 1 << (int)(Math.log(n-1)/Math.log(2) + 1); - + while(d <= end) { int i = 0, dec = 0; - + while(i < n) { int j = i; dec += n; - + while(dec >= d) { dec -= d; j++; } int k = j; dec += n; - + while(dec >= d) { dec -= d; k++; @@ -107,4 +106,4 @@ public void runSort(int[] array, int currentLength, int bucketCount) { d *= 2; } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/DualPivotQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/DualPivotQuickSort.java similarity index 90% rename from src/sorts/exchange/DualPivotQuickSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/DualPivotQuickSort.java index 1ab0707e..b5c9e38e 100644 --- a/src/sorts/exchange/DualPivotQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/DualPivotQuickSort.java @@ -1,53 +1,51 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; -final public class DualPivotQuickSort extends Sort { +public final class DualPivotQuickSort extends Sort { private InsertionSort insertSorter; - + public DualPivotQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Dual-Pivot Quick"); this.setRunAllSortsName("Dual-Pivot Quick Sort"); this.setRunSortName("Dual-Pivot Quicksort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + /* * ArrayV's original example of a basic Dual-Pivot Quicksort may be found here, written by Sebastian Wild (Sebastian on StackOverflow): * https://cs.stackexchange.com/questions/24092/dual-pivot-quicksort-reference-implementation - * + * * Unfortunately, its O(n^2) worst-case behavior began to cause stack overflow exceptions with large array sizes. This new unoptimized * version is a stripped-down copy of ArrayV's "Optimized Dual-Pivot Quicksort", written by Vladimir Yaroslavskiy. * https://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf */ - + private void dualPivot(int[] array, int left, int right, int divisor) { int length = right - left; - + // insertion sort for tiny array if(length < 4) { Highlights.clearMark(2); insertSorter.customInsertSort(array, left, right + 1, 1, false); return; } - + int third = length / divisor; - + // "medians" int med1 = left + third; int med2 = right - third; - + if(med1 <= left) { med1 = left + 1; } @@ -62,15 +60,15 @@ private void dualPivot(int[] array, int left, int right, int divisor) { Writes.swap(array, med1, right, 1, true, false); Writes.swap(array, med2, left, 1, true, false); } - + // pivots int pivot1 = array[left]; int pivot2 = array[right]; - + // pointers int less = left + 1; int great = right - 1; - + // sorting for(int k = less; k <= great; k++) { if(Reads.compareValues(array[k], pivot1) == -1) { @@ -84,22 +82,22 @@ else if(Reads.compareValues(array[k], pivot2) == 1) { } Writes.swap(array, k, great--, 1, true, false); Highlights.clearMark(3); - + if(Reads.compareValues(array[k], pivot1) == -1) { Writes.swap(array, k, less++, 1, true, false); } } } - + // swaps int dist = great - less; - + if(dist < 13) { divisor++; } Writes.swap(array, less - 1, left, 1, true, false); Writes.swap(array, great + 1, right, 1, true, false); - + // subarrays this.dualPivot(array, left, less - 2, divisor); if(pivot1 < pivot2) { @@ -107,10 +105,10 @@ else if(Reads.compareValues(array[k], pivot2) == 1) { } this.dualPivot(array, great + 2, right, divisor); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.insertSorter = new InsertionSort(this.arrayVisualizer); this.dualPivot(array, 0, sortLength - 1, 3); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/ExchangeBogoSort.java b/src/main/java/io/github/arrayv/sorts/exchange/ExchangeBogoSort.java similarity index 89% rename from src/sorts/exchange/ExchangeBogoSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/ExchangeBogoSort.java index 4b9efbd2..7fbde59d 100644 --- a/src/sorts/exchange/ExchangeBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ExchangeBogoSort.java @@ -1,7 +1,7 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /** * Exchange Bogosort randomly sorts any two elements until the array is sorted. @@ -14,7 +14,6 @@ public ExchangeBogoSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Exchange Bogo Sort"); this.setRunSortName("Exchange Bogosort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); diff --git a/src/sorts/exchange/ForcedStableQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/ForcedStableQuickSort.java similarity index 92% rename from src/sorts/exchange/ForcedStableQuickSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/ForcedStableQuickSort.java index 65ec2041..7276865d 100644 --- a/src/sorts/exchange/ForcedStableQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ForcedStableQuickSort.java @@ -1,12 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -31,88 +29,87 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ForcedStableQuickSort extends Sort { +public final class ForcedStableQuickSort extends Sort { public ForcedStableQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Forced Stable Quick"); this.setRunAllSortsName("Forced Stable Quick Sort"); this.setRunSortName("Forced Stable Quicksort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void medianOfThree(int[] array, int[] key, int a, int b) { int m = a+(b-1-a)/2; - + if(this.stableComp(array, key, a, m)) this.stableSwap(array, key, a, m); - + if(this.stableComp(array, key, m, b-1)) { this.stableSwap(array, key, m, b-1); - + if(this.stableComp(array, key, a, m)) return; } - + this.stableSwap(array, key, a, m); } - + private boolean stableComp(int[] array, int[] key, int a, int b) { int comp = Reads.compareIndices(array, a, b, 0.5, true); - + return comp > 0 || (comp == 0 && Reads.compareOriginalIndices(key, a, b, 0.5, false) > 0); } - + private void stableSwap(int[] array, int[] key, int a, int b) { Writes.swap(array, a, b, 0, true, false); Writes.swap(key, a, b, 1, false, true); } - + private int partition(int[] array, int[] key, int a, int b, int p) { int i = a - 1, j = b; Highlights.markArray(3, p); - + while(true) { do i++; while(i < j && !this.stableComp(array, key, i, p)); - + do j--; while(j >= i && this.stableComp(array, key, j, p)); - + if(i < j) this.stableSwap(array, key, i, j); else return j; } } - + private void quickSort(int[] array, int[] key, int a, int b) { if(b-a < 3) { if(b-a == 2 && this.stableComp(array, key, a, a+1)) this.stableSwap(array, key, a, a+1); return; } - + this.medianOfThree(array, key, a, b); int p = this.partition(array, key, a+1, b, a); this.stableSwap(array, key, a, p); - + this.quickSort(array, key, a, p); this.quickSort(array, key, p+1, b); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int[] key = Writes.createExternalArray(length); for(int i = 0; i < length; i++) Writes.write(key, i, i, 0.5, true, true); - + this.quickSort(array, key, 0, length); - + Writes.deleteExternalArray(key); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/FunSort.java b/src/main/java/io/github/arrayv/sorts/exchange/FunSort.java similarity index 94% rename from src/sorts/exchange/FunSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/FunSort.java index d5a4f054..cf32cbc4 100644 --- a/src/sorts/exchange/FunSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/FunSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 fungamer2 Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,23 +25,22 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class FunSort extends Sort { - +public final class FunSort extends Sort { + public FunSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Fun"); this.setRunAllSortsName("Fun Sort"); this.setRunSortName("Fun Sort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + /* Fun Sort - or the chaos of unordered binary search https://www.sciencedirect.com/science/article/pii/S0166218X04001131 @@ -67,7 +66,7 @@ public int binarySearch(int[] array, int start, int end, int value) { Highlights.clearMark(3); return start; } - + @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = 1; i < length; i++) { @@ -86,4 +85,4 @@ public void runSort(int[] array, int length, int bucketCount) { } while (!done); } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/GnomeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/GnomeSort.java similarity index 82% rename from src/sorts/exchange/GnomeSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/GnomeSort.java index 2b909fac..8dd32c44 100644 --- a/src/sorts/exchange/GnomeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/GnomeSort.java @@ -1,26 +1,25 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class GnomeSort extends Sort { +public final class GnomeSort extends Sort { public GnomeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Gnome"); this.setRunAllSortsName("Gnome Sort"); this.setRunSortName("Gnomesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + // Code retrieved from http://www.algostructure.com/sorting/gnomesort.php - + @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = 1; i < length;) @@ -32,11 +31,11 @@ public void runSort(int[] array, int length, int bucketCount) { else { Writes.swap(array, i, i - 1, 0.02, true, false); - + if (i > 1) { i--; } } } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/LLQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/LLQuickSort.java similarity index 86% rename from src/sorts/exchange/LLQuickSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/LLQuickSort.java index cc6e4885..fd743197 100644 --- a/src/sorts/exchange/LLQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/LLQuickSort.java @@ -1,28 +1,27 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class LLQuickSort extends Sort { +public final class LLQuickSort extends Sort { public LLQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Left/Left Quick"); this.setRunAllSortsName("Quick Sort, Left/Left Pointers"); this.setRunSortName("Left/Left Quicksort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int partition(int[] array, int lo, int hi) { int pivot = array[hi]; int i = lo; - + for(int j = lo; j < hi; j++) { Highlights.markArray(1, j); if(Reads.compareValues(array[j], pivot) < 0) { @@ -34,7 +33,7 @@ private int partition(int[] array, int lo, int hi) { Writes.swap(array, i, hi, 1, true, false); return i; } - + private void quickSort(int[] array, int lo, int hi) { if(lo < hi) { int p = this.partition(array, lo, hi); @@ -42,9 +41,9 @@ private void quickSort(int[] array, int lo, int hi) { this.quickSort(array, p + 1, hi); } } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.quickSort(array, 0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/LRQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSort.java similarity index 85% rename from src/sorts/exchange/LRQuickSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/LRQuickSort.java index bbd48039..709f9cc3 100644 --- a/src/sorts/exchange/LRQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSort.java @@ -1,17 +1,16 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class LRQuickSort extends Sort { +public final class LRQuickSort extends Sort { public LRQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Left/Right Quick"); this.setRunAllSortsName("Quick Sort, Left/Right Pointers"); this.setRunSortName("Left/Right Quicksort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -20,15 +19,15 @@ public LRQuickSort(ArrayVisualizer arrayVisualizer) { } // Thanks to Timo Bingmann for providing a good reference for Quick Sort w/ LR pointers. - private void quickSort(int[] a, int p, int r) { + private void quickSort(int[] a, int p, int r) { int pivot = p + (r - p + 1) / 2; int x = a[pivot]; - + int i = p; int j = r; Highlights.markArray(3, pivot); - + while (i <= j) { while (Reads.compareValues(a[i], x) == -1){ i++; @@ -49,14 +48,14 @@ private void quickSort(int[] a, int p, int r) { if(j == pivot) { Highlights.markArray(3, i); } - + Writes.swap(a, i, j, 1, true, false); - + i++; j--; } } - + if(p < j) { this.quickSort(a, p, j); } @@ -69,4 +68,4 @@ private void quickSort(int[] a, int p, int r) { public void runSort(int[] array, int currentLength, int bucketCount) { this.quickSort(array, 0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/LRQuickSortParallel.java b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSortParallel.java similarity index 87% rename from src/sorts/exchange/LRQuickSortParallel.java rename to src/main/java/io/github/arrayv/sorts/exchange/LRQuickSortParallel.java index 47f9ce42..7981339c 100644 --- a/src/sorts/exchange/LRQuickSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSortParallel.java @@ -1,26 +1,25 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class LRQuickSortParallel extends Sort { +public final class LRQuickSortParallel extends Sort { public LRQuickSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Left/Right Quick (Parallel)"); this.setRunAllSortsName("Parallel Quick Sort, Left/Right Pointers"); this.setRunSortName("Parallel Left/Right Quicksort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] a; - + private class QuickSort extends Thread { private int p, r; QuickSort(int p, int r) { @@ -33,16 +32,16 @@ public void run() { } // Thanks to Timo Bingmann for providing a good reference for Quick Sort w/ LR pointers. - private void quickSort(int p, int r) { + private void quickSort(int p, int r) { if(p < r) { int pivot = p + (r - p + 1) / 2; int x = this.a[pivot]; - + int i = p; int j = r; Highlights.markArray(3, pivot); - + while (i <= j) { while (Reads.compareValues(this.a[i], x) == -1){ i++; @@ -63,19 +62,19 @@ private void quickSort(int p, int r) { if(j == pivot) { Highlights.markArray(3, i); } - + Writes.swap(this.a, i, j, 1, true, false); - + i++; j--; } } - + QuickSort left = new QuickSort(p, j); QuickSort right = new QuickSort(i, r); left.start(); right.start(); - + try { left.join(); right.join(); @@ -90,4 +89,4 @@ public void runSort(int[] array, int currentLength, int bucketCount) { this.a = array; this.quickSort(0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/OddEvenSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OddEvenSort.java similarity index 86% rename from src/sorts/exchange/OddEvenSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/OddEvenSort.java index b61aaf4b..64b7f1f5 100644 --- a/src/sorts/exchange/OddEvenSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OddEvenSort.java @@ -1,22 +1,21 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * This version of Odd-Even Sort was taken from here, written by Rachit Belwariar: * https://www.geeksforgeeks.org/odd-even-sort-brick-sort/ */ -final public class OddEvenSort extends Sort { +public final class OddEvenSort extends Sort { public OddEvenSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Odd-Even"); this.setRunAllSortsName("Odd-Even Sort"); this.setRunSortName("Odd-Even Sort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -27,29 +26,29 @@ public OddEvenSort(ArrayVisualizer arrayVisualizer) { @Override public void runSort(int[] array, int length, int bucketCount) { boolean sorted = false; - + while (!sorted) { sorted = true; - + for (int i = 1; i < length - 1; i += 2) { if(Reads.compareValues(array[i], array[i + 1]) == 1) { Writes.swap(array, i, i + 1, 0.075, true, false); sorted = false; } - + Highlights.markArray(1, i); Delays.sleep(0.025); } - + for (int i = 0; i < length - 1; i += 2) { if(Reads.compareValues(array[i], array[i + 1]) == 1) { Writes.swap(array, i, i + 1, 0.075, true, false); sorted = false; } - + Highlights.markArray(2, i); Delays.sleep(0.025); } } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/OptimizedBubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedBubbleSort.java similarity index 83% rename from src/sorts/exchange/OptimizedBubbleSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/OptimizedBubbleSort.java index 65fdda28..bc9af77c 100644 --- a/src/sorts/exchange/OptimizedBubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedBubbleSort.java @@ -1,24 +1,23 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class OptimizedBubbleSort extends Sort { +public final class OptimizedBubbleSort extends Sort { public OptimizedBubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Bubble"); this.setRunAllSortsName("Optimized Bubble Sort"); this.setRunSortName("Optimized Bubblesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int consecSorted; @@ -32,4 +31,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/OptimizedCocktailShakerSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedCocktailShakerSort.java similarity index 86% rename from src/sorts/exchange/OptimizedCocktailShakerSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/OptimizedCocktailShakerSort.java index d85b4090..070ae302 100644 --- a/src/sorts/exchange/OptimizedCocktailShakerSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedCocktailShakerSort.java @@ -1,24 +1,23 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class OptimizedCocktailShakerSort extends Sort { +public final class OptimizedCocktailShakerSort extends Sort { public OptimizedCocktailShakerSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Cocktail"); this.setRunAllSortsName("Optimized Cocktail Shaker Sort"); this.setRunSortName("Optimized Cocktailsort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { for(int start = 0, end = length - 1; start < end; ) { @@ -30,7 +29,7 @@ public void runSort(int[] array, int length, int bucketCount) { } else consecSorted++; } end -= consecSorted; - + consecSorted = 1; for(int i = end; i > start; i--) { if(Reads.compareIndices(array, i - 1, i, 0.025, true) > 0){ @@ -41,4 +40,4 @@ public void runSort(int[] array, int length, int bucketCount) { start += consecSorted; } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/OptimizedGnomeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedGnomeSort.java similarity index 84% rename from src/sorts/exchange/OptimizedGnomeSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/OptimizedGnomeSort.java index 2e5e3b84..34de02c3 100644 --- a/src/sorts/exchange/OptimizedGnomeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedGnomeSort.java @@ -1,28 +1,27 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class OptimizedGnomeSort extends Sort { +public final class OptimizedGnomeSort extends Sort { public OptimizedGnomeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Gnome"); this.setRunAllSortsName("Optimized Gnome Sort"); this.setRunSortName("Optimized Gnomesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + // Taken from https://en.wikipedia.org/wiki/Gnome_sort private void smartGnomeSort(int[] array, int lowerBound, int upperBound, double sleep) { int pos = upperBound; - + while(pos > lowerBound && Reads.compareValues(array[pos - 1], array[pos]) == 1) { Writes.swap(array, pos - 1, pos, sleep, true, false); pos--; @@ -34,11 +33,11 @@ public void customSort(int[] array, int low, int high, double sleep) { smartGnomeSort(array, low, i, sleep); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { for(int i = 1; i < length; i++) { smartGnomeSort(array, 0, i, 0.05); - } + } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/OptimizedStoogeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSort.java similarity index 88% rename from src/sorts/exchange/OptimizedStoogeSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSort.java index 734b63d9..1aee7211 100644 --- a/src/sorts/exchange/OptimizedStoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSort.java @@ -1,86 +1,85 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; // Code refactored from: https://www.ijitee.org/wp-content/uploads/papers/v8i12/L31671081219.pdf // Written by Professors Amit Kishor and Pankaj Pratap Singh -final public class OptimizedStoogeSort extends Sort { +public final class OptimizedStoogeSort extends Sort { public OptimizedStoogeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Stooge"); this.setRunAllSortsName("Optimized Stooge Sort"); this.setRunSortName("Optimized Stoogesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void forward(int[] array, int left, int right) { while(left < right) { int index = right; - + while(left < index) { Highlights.markArray(1, left); Highlights.markArray(2, index); Delays.sleep(0.05); - + if(Reads.compareValues(array[left], array[index]) > 0) { Writes.swap(array, left, index, 0.075, true, false); } left++; index--; } - + left = 0; right--; } } - + private void backward(int[] array, int left, int right) { int length = right; - + while(left < right) { int index = left; - + while(index < right) { Highlights.markArray(1, index); Highlights.markArray(2, right); Delays.sleep(0.05); - + if(Reads.compareValues(array[index], array[right]) > 0) { Writes.swap(array, index, right, 0.075, true, false); } index++; right--; } - + left++; right = length; } } - + private void exchange(int[] array, int length) { int left = 0; int right = length - 1; - + while(left < right) { Highlights.markArray(1, left); Highlights.markArray(2, right); Delays.sleep(0.05); - + if(Reads.compareValues(array[left], array[right]) > 0) { Writes.swap(array, left, right, 0.075, true, false); } left++; right--; } - + this.forward(array, 0, length - 2); this.backward(array, 1, length - 1); } @@ -89,4 +88,4 @@ private void exchange(int[] array, int length) { public void runSort(int[] array, int sortLength, int bucketCount) { this.exchange(array, sortLength); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/OptimizedStoogeSortStudio.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSortStudio.java similarity index 90% rename from src/sorts/exchange/OptimizedStoogeSortStudio.java rename to src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSortStudio.java index 1b56484c..6b817228 100644 --- a/src/sorts/exchange/OptimizedStoogeSortStudio.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSortStudio.java @@ -1,7 +1,7 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /** * Optimized Stooge Sort: @@ -14,22 +14,21 @@ * @author EilrahcF - Key ideas / concepts */ -final public class OptimizedStoogeSortStudio extends Sort { +public final class OptimizedStoogeSortStudio extends Sort { public OptimizedStoogeSortStudio(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Stooge (The Studio version)"); this.setRunAllSortsName("Optimized Stooge Sort"); this.setRunSortName("Optistooge Sort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private boolean compSwap(int[] array, int a, int b) { if(Reads.compareIndices(array, a, b, 0.025, true) == 1) { Writes.swap(array, a, b, 0.075, false, false); @@ -37,22 +36,22 @@ private boolean compSwap(int[] array, int a, int b) { } return false; } - + private boolean stoogeSort(int[] array, int a, int m, int b, boolean merge) { if(a >= m) return false; if(b-a == 2) return this.compSwap(array, a, m); - + boolean lChange = false; boolean rChange = false; - + int a2 = (a+a+b)/3; int b2 = (a+b+b+2)/3; - + if(m < b2) { lChange = this.stoogeSort(array, a, m, b2, merge); - + if(merge) { rChange = this.stoogeSort(array, Math.max(a+b2-m, a2), b2, b, true); if(rChange) this.stoogeSort(array, a+b2-m, a2, 2*a2-a, true); @@ -73,4 +72,4 @@ private boolean stoogeSort(int[] array, int a, int m, int b, boolean merge) { public void runSort(int[] array, int currentLength, int bucketCount) { this.stoogeSort(array, 0, 1, currentLength, false); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/QuadStoogeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/QuadStoogeSort.java similarity index 87% rename from src/sorts/exchange/QuadStoogeSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/QuadStoogeSort.java index cadbe19c..4895adb6 100644 --- a/src/sorts/exchange/QuadStoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/QuadStoogeSort.java @@ -1,62 +1,61 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author aphitorite - * @author EilrahcF - * - */ -public final class QuadStoogeSort extends Sort { - - /** - * @param arrayVisualizer - */ - public QuadStoogeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Quad Stooge"); - setRunAllSortsName("Quad Stooge Sort"); - setRunSortName("Quad Stoogesort"); - setCategory("Impractical Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(2048); - setBogoSort(false); - - } - - private void quadStooge(int[] array, int pos, int len) { - if (len >= 2 && this.Reads.compareIndices(array, pos, pos + len - 1, 0.0025D, true) == 1) { - this.Writes.swap(array, pos, pos + len - 1, 0.005D, true, false); - } - if (len <= 2) { - return; - } - - int len1 = len / 2; - int len2 = (len + 1) / 2; - int len3 = (len1 + 1) / 2 + (len2 + 1) / 2; - - quadStooge(array, pos, len1); - quadStooge(array, pos + len1, len2); - quadStooge(array, pos + len1 / 2, len3); - quadStooge(array, pos + len1, len2); - quadStooge(array, pos, len1); - if (len > 3) { - quadStooge(array, pos + len1 / 2, len3); - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - quadStooge(array, 0, sortLength); - - } - -} +/** + * + */ +package io.github.arrayv.sorts.exchange; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * @author aphitorite + * @author EilrahcF + * + */ +public final class QuadStoogeSort extends Sort { + + /** + * @param arrayVisualizer + */ + public QuadStoogeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + setSortListName("Quad Stooge"); + setRunAllSortsName("Quad Stooge Sort"); + setRunSortName("Quad Stoogesort"); + setCategory("Impractical Sorts"); + setBucketSort(false); + setRadixSort(false); + setUnreasonablySlow(true); + setUnreasonableLimit(2048); + setBogoSort(false); + + } + + private void quadStooge(int[] array, int pos, int len) { + if (len >= 2 && this.Reads.compareIndices(array, pos, pos + len - 1, 0.0025D, true) == 1) { + this.Writes.swap(array, pos, pos + len - 1, 0.005D, true, false); + } + if (len <= 2) { + return; + } + + int len1 = len / 2; + int len2 = (len + 1) / 2; + int len3 = (len1 + 1) / 2 + (len2 + 1) / 2; + + quadStooge(array, pos, len1); + quadStooge(array, pos + len1, len2); + quadStooge(array, pos + len1 / 2, len3); + quadStooge(array, pos + len1, len2); + quadStooge(array, pos, len1); + if (len > 3) { + quadStooge(array, pos + len1 / 2, len3); + } + } + + @Override + public void runSort(int[] array, int sortLength, int bucketCount) { + quadStooge(array, 0, sortLength); + + } + +} diff --git a/src/sorts/exchange/ShoveSort.java b/src/main/java/io/github/arrayv/sorts/exchange/ShoveSort.java similarity index 88% rename from src/sorts/exchange/ShoveSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/ShoveSort.java index d43e333d..1865d0b1 100644 --- a/src/sorts/exchange/ShoveSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ShoveSort.java @@ -1,53 +1,52 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author frankblob - * @author PiotrGrochowski - * - */ -public final class ShoveSort extends Sort { - - public ShoveSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Shove"); - setRunAllSortsName("Shove Sort"); - setRunSortName("Shove Sort"); - setCategory("Impractical Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(512); - setBogoSort(false); - - } - - private void shovesort(int[] array, int start, int end, double sleep) { - int i = start; - while (i < end - 1) { - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, i + 1); - this.Delays.sleep(sleep); - if (this.Reads.compareValues(array[i], array[i + 1]) == 1) { - for (int f = i; f < end - 1; f++) { - this.Writes.swap(array, f, f + 1, sleep, true, false); - } - if (i > start) { - i--; - } - continue; - } - i++; - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - shovesort(array, 0, length, 0.125D); - - } - -} +package io.github.arrayv.sorts.exchange; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * @author frankblob + * @author PiotrGrochowski + * + */ +public final class ShoveSort extends Sort { + + public ShoveSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + setSortListName("Shove"); + setRunAllSortsName("Shove Sort"); + setRunSortName("Shove Sort"); + setCategory("Impractical Sorts"); + setBucketSort(false); + setRadixSort(false); + setUnreasonablySlow(true); + setUnreasonableLimit(512); + setBogoSort(false); + + } + + private void shovesort(int[] array, int start, int end, double sleep) { + int i = start; + while (i < end - 1) { + this.Highlights.markArray(1, i); + this.Highlights.markArray(2, i + 1); + this.Delays.sleep(sleep); + if (this.Reads.compareValues(array[i], array[i + 1]) == 1) { + for (int f = i; f < end - 1; f++) { + this.Writes.swap(array, f, f + 1, sleep, true, false); + } + if (i > start) { + i--; + } + continue; + } + i++; + } + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + shovesort(array, 0, length, 0.125D); + + } + +} diff --git a/src/sorts/exchange/SillySort.java b/src/main/java/io/github/arrayv/sorts/exchange/SillySort.java similarity index 82% rename from src/sorts/exchange/SillySort.java rename to src/main/java/io/github/arrayv/sorts/exchange/SillySort.java index c85bde29..f38b1a40 100644 --- a/src/sorts/exchange/SillySort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/SillySort.java @@ -1,52 +1,51 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; // Written by Tom Duff, and found here: http://home.tiac.net/~cri_d/cri/2001/badsort.html // from https://stackoverflow.com/questions/2609857/are-there-any-worse-sorting-algorithms-than-bogosort-a-k-a-monkey-sort/ -final public class SillySort extends Sort { +public final class SillySort extends Sort { public SillySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Silly"); this.setRunAllSortsName("Silly Sort"); this.setRunSortName("Sillysort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); this.setUnreasonableLimit(150); this.setBogoSort(false); } - + private void sillySort(int[] array, int i, int j) { int m; - + if (i < j) { /* find the middle of the array */ m = i + ((j - i) / 2); - - /* - * use this function (recursively) to find put the minimum elements of + + /* + * use this function (recursively) to find put the minimum elements of * each half into the first elements of each half */ this.sillySort(array, i, m); this.sillySort(array, m + 1, j); - - /* + + /* * Choose the smallest element of the two halves, and put that element in * the first position */ - if (Reads.compareValues(array[i], array[m + 1]) >= 0) { + if (Reads.compareValues(array[i], array[m + 1]) >= 0) { Writes.swap(array, i, m + 1, 1, true, false); } - + Highlights.markArray(1, i); Highlights.markArray(2, m + 1); - + this.sillySort(array, i + 1, j); } } @@ -55,4 +54,4 @@ private void sillySort(int[] array, int i, int j) { public void runSort(int[] array, int currentLength, int bucketCount) { this.sillySort(array, 0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/SlopeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/SlopeSort.java similarity index 83% rename from src/sorts/exchange/SlopeSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/SlopeSort.java index 48570fc6..908e3390 100644 --- a/src/sorts/exchange/SlopeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/SlopeSort.java @@ -1,47 +1,46 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author McDude_73 - * @author EilrahcF - * - */ -public final class SlopeSort extends Sort { - - /** - * @param arrayVisualizer - */ - public SlopeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Slope"); - setRunAllSortsName("Slope Sort"); - setRunSortName("Slopesort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(16384); - setBogoSort(false); - - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - for (int i = 1, j = 1; i < length; i++, j++) { - for (int k = i - 1; k >= 0; k--, i--) { - if (this.Reads.compareIndices(array, i, k, 0.04D, true) < 0) { - this.Writes.swap(array, i, k, 0.02D, true, false); - } - } - i = j; - } - - } - -} +/** + * + */ +package io.github.arrayv.sorts.exchange; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * @author McDude_73 + * @author EilrahcF + * + */ +public final class SlopeSort extends Sort { + + /** + * @param arrayVisualizer + */ + public SlopeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + setSortListName("Slope"); + setRunAllSortsName("Slope Sort"); + setRunSortName("Slopesort"); + setCategory("Exchange Sorts"); + setBucketSort(false); + setRadixSort(false); + setUnreasonablySlow(true); + setUnreasonableLimit(16384); + setBogoSort(false); + + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + for (int i = 1, j = 1; i < length; i++, j++) { + for (int k = i - 1; k >= 0; k--, i--) { + if (this.Reads.compareIndices(array, i, k, 0.04D, true) < 0) { + this.Writes.swap(array, i, k, 0.02D, true, false); + } + } + i = j; + } + + } + +} diff --git a/src/sorts/exchange/SlowSort.java b/src/main/java/io/github/arrayv/sorts/exchange/SlowSort.java similarity index 80% rename from src/sorts/exchange/SlowSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/SlowSort.java index 5ed71bb1..6f01a55a 100644 --- a/src/sorts/exchange/SlowSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/SlowSort.java @@ -1,43 +1,42 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; // Code refactored from Python: http://wiki.c2.com/?SlowSort -final public class SlowSort extends Sort { +public final class SlowSort extends Sort { public SlowSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Slow"); this.setRunAllSortsName("Slow Sort"); this.setRunSortName("Slowsort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); this.setUnreasonableLimit(150); this.setBogoSort(false); } - - private void slowSort(int[] A, int i, int j) { + + private void slowSort(int[] A, int i, int j) { if (i >= j) { return; } - + int m = i + ((j - i) / 2); - + this.slowSort(A, i, m); this.slowSort(A, m + 1, j); - + if (Reads.compareValues(A[m], A[j]) == 1) { Writes.swap(A, m, j, 1, true, false); } - + Highlights.markArray(1, j); Highlights.markArray(2, m); - + this.slowSort(A, i, j - 1); } @@ -45,4 +44,4 @@ private void slowSort(int[] A, int i, int j) { public void runSort(int[] array, int currentLength, int bucketCount) { this.slowSort(array, 0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/SnuffleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/SnuffleSort.java similarity index 90% rename from src/sorts/exchange/SnuffleSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/SnuffleSort.java index fdb6e3aa..b09b26f5 100644 --- a/src/sorts/exchange/SnuffleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/SnuffleSort.java @@ -1,27 +1,26 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; +package io.github.arrayv.sorts.exchange; import java.lang.Math; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + public class SnuffleSort extends Sort { private static double DELAY = 1; public SnuffleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Snuffle"); this.setRunAllSortsName("Snuffle Sort"); this.setRunSortName("Snuffle Sort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); this.setUnreasonableLimit(100); this.setBogoSort(false); } - + private void snuffleSort(int[] arr, int start, int stop) { if (stop - start + 1 >= 2) { Highlights.markArray(0, start); @@ -42,4 +41,4 @@ private void snuffleSort(int[] arr, int start, int stop) { public void runSort(int[] array, int length, int buckets) { this.snuffleSort(array, 0, length - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/StablePermutationSort.java b/src/main/java/io/github/arrayv/sorts/exchange/StablePermutationSort.java similarity index 90% rename from src/sorts/exchange/StablePermutationSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/StablePermutationSort.java index fb1738ae..d15d1733 100644 --- a/src/sorts/exchange/StablePermutationSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/StablePermutationSort.java @@ -1,11 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import sorts.templates.Sort; -import sorts.templates.BogoSorting; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BogoSorting; /* - * + * MIT License Copyright (c) 2021 Control, implemented by aphitorite @@ -30,59 +29,58 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StablePermutationSort extends BogoSorting { +public final class StablePermutationSort extends BogoSorting { public StablePermutationSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stable Permutation"); this.setRunAllSortsName("Stable Permutation Sort"); this.setRunSortName("Stable Permutation Sort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); this.setUnreasonableLimit(11); this.setBogoSort(false); } - + private int length; - + private boolean permute(int[] array, int[] idx, int len) { if(len < 2) return this.isArraySorted(array, this.length); - + for(int i = len-2; i >= 0; i--) { if(this.permute(array, idx, len-1)) return true; - + Writes.swap(array, idx[i], idx[len-1], 0, true, false); Writes.swap(idx, i, len-1, this.delay, false, true); } if(this.permute(array, idx, len-1)) return true; - + int t = idx[len-1]; - + for(int i = len-1; i > 0; i--) Writes.write(idx, i, idx[i-1], 0, false, true); Writes.write(idx, 0, t, 0, false, true); - + t = array[idx[0]]; - + for(int i = 1; i < len; i++) Writes.write(array, idx[i-1], array[idx[i]], this.delay, true, false); Writes.write(array, idx[len-1], t, this.delay, true, false); - + return false; } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.length = length; int[] idx = Writes.createExternalArray(length); - + for(int i = 0; i < length; i++) Writes.write(idx, i, i, this.delay, true, true); - + this.permute(array, idx, length); Writes.deleteExternalArray(idx); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/StableQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSort.java similarity index 77% rename from src/sorts/exchange/StableQuickSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/StableQuickSort.java index 374aa8bd..6b35907e 100644 --- a/src/sorts/exchange/StableQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSort.java @@ -1,12 +1,11 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.utils.ArrayVList; /* - * + * MIT License Copyright (c) 2017 Rodney Shaghoulian @@ -31,15 +30,16 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StableQuickSort extends Sort { +public final class StableQuickSort extends Sort { + private int length; + public StableQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stable Quick"); this.setRunAllSortsName("Stable Quick Sort"); this.setRunSortName("Stable Quicksort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -50,42 +50,44 @@ public StableQuickSort(ArrayVisualizer arrayVisualizer) { // Author: Rodney Shaghoulian // Github: github.com/RodneyShag - private void copy(ArrayList list, int [] array, int startIndex) { + private void copy(ArrayVList list, int [] array, int startIndex) { for (int num : list) { Writes.write(array, startIndex++, num, 0.25, false, false); Highlights.markArray(1, startIndex); } } - + /* Partition/Quicksort "Stable Sort" version using O(n) space */ private int stablePartition(int[] array, int start, int end) { int pivotValue = array[start]; //poor pivot choice Highlights.markArray(3, start); - - ArrayList leftList = new ArrayList<>(); - ArrayList rightList = new ArrayList<>(); + + ArrayVList leftList = Writes.createArrayList(this.length); + ArrayVList rightList = Writes.createArrayList(this.length); for (int i = start + 1 ; i <= end; i++) { Highlights.markArray(1, i); - + if (Reads.compareValues(array[i], pivotValue) == -1) { - Writes.mockWrite(end - start, leftList.size(), array[i], 0.25); - Writes.arrayListAdd(leftList, array[i]); - } + // Writes.mockWrite(end - start, leftList.size(), array[i], 0.25); + // Writes.arrayListAdd(leftList, array[i]); + leftList.add(array[i], 0.25, false); + } else { - Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); - Writes.arrayListAdd(rightList, array[i]); + // Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); + // Writes.arrayListAdd(rightList, array[i]); + rightList.add(array[i], 0.25, false); } } /* Recreate array */ this.copy(leftList, array, start); - + int newPivotIndex = start + leftList.size(); - + Writes.write(array, newPivotIndex, pivotValue, 0.25, false, false); Highlights.markArray(1, newPivotIndex); - + this.copy(rightList, array, newPivotIndex + 1); Writes.deleteArrayList(leftList); @@ -101,9 +103,10 @@ private void stableQuickSort(int [] array, int start, int end) { this.stableQuickSort(array, pivotIndex + 1, end); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { + this.length = length; this.stableQuickSort(array, 0, length - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/StableQuickSortParallel.java b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSortParallel.java similarity index 94% rename from src/sorts/exchange/StableQuickSortParallel.java rename to src/main/java/io/github/arrayv/sorts/exchange/StableQuickSortParallel.java index 716906e0..7f9bbd70 100644 --- a/src/sorts/exchange/StableQuickSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSortParallel.java @@ -1,12 +1,12 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; import java.util.Random; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2021 aphitorite @@ -30,25 +30,24 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class StableQuickSortParallel extends Sort { +public final class StableQuickSortParallel extends Sort { public StableQuickSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stable Quick (Parallel)"); this.setRunAllSortsName("Parallel Stable Quick Sort"); this.setRunSortName("Parallel Stable Quicksort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] array; private int[] tmp; - + private class QuickSortInt extends Thread { private int a, b; QuickSortInt(int a, int b) { @@ -69,21 +68,21 @@ public void run() { StableQuickSortParallel.this.quickSortExt(a, b); } } - + private int partitionInt(int a, int b) { Random r = new Random(); int p = a + r.nextInt(b-a); - + int piv = array[p]; int j = a, k = b-1; - + while(j < p && Reads.compareValues(array[j], piv) <= 0) j++; if(j < p) Writes.write(tmp, k--, array[j], 1, false, true); - + for(int i = j+1; i < p; i++) { if(Reads.compareValues(array[i], piv) <= 0) Writes.write(array, j++, array[i], 1, true, false); - + else { Highlights.markArray(2, k); Writes.write(tmp, k--, array[i], 1, false, true); @@ -92,26 +91,26 @@ private int partitionInt(int a, int b) { for(int i = p+1; i < b; i++) { if(Reads.compareValues(array[i], piv) < 0) Writes.write(array, j++, array[i], 1, true, false); - + else { Highlights.markArray(2, k); Writes.write(tmp, k--, array[i], 1, false, true); } } Writes.write(array, j, piv, 1, true, false); - + return j; } private int partitionExt(int a, int b) { Random r = new Random(); int p = a + r.nextInt(b-a); - + int piv = tmp[p]; int j = b-1, k = a; - + while(j > p && Reads.compareValues(tmp[j], piv) > 0) j--; if(j > p) Writes.write(array, k++, tmp[j], 1, true, false); - + for(int i = j-1; i > p; i--) { if(Reads.compareValues(tmp[i], piv) > 0) { Highlights.markArray(2, j); @@ -127,22 +126,22 @@ private int partitionExt(int a, int b) { else Writes.write(array, k++, tmp[i], 1, true, false); } Writes.write(array, k, piv, 1, true, false); - + return k; } - + private void quickSortInt(int a, int b) { int len = b-a; - + if(len < 2) return; - + int p = this.partitionInt(a, b); - + QuickSortInt left = new QuickSortInt(a, p); QuickSortExt right = new QuickSortExt(p+1, b); left.start(); right.start(); - + try { left.join(); right.join(); @@ -152,19 +151,19 @@ private void quickSortInt(int a, int b) { } private void quickSortExt(int a, int b) { int len = b-a; - + if(len < 2) { if(len == 1) Writes.write(array, a, tmp[a], 1, true, false); return; } - + int p = this.partitionExt(a, b); - + QuickSortInt left = new QuickSortInt(a, p); QuickSortExt right = new QuickSortExt(p+1, b); left.start(); right.start(); - + try { left.join(); right.join(); @@ -172,7 +171,7 @@ private void quickSortExt(int a, int b) { Thread.currentThread().interrupt(); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; @@ -180,4 +179,4 @@ public void runSort(int[] array, int length, int bucketCount) { this.quickSortInt(0, length); Writes.deleteExternalArray(tmp); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/StoogeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/StoogeSort.java similarity index 89% rename from src/sorts/exchange/StoogeSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/StoogeSort.java index 6e4edffd..80b930da 100644 --- a/src/sorts/exchange/StoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/StoogeSort.java @@ -1,43 +1,42 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS * LICENSE OR COPYRIGHT LAW IS PROHIBITED. - * + * * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. * TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN * CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. */ // Code refactored from: https://en.wikipedia.org/wiki/Stooge_sort -final public class StoogeSort extends Sort { +public final class StoogeSort extends Sort { public StoogeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stooge"); this.setRunAllSortsName("Stooge Sort"); this.setRunSortName("Stoogesort"); this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); this.setUnreasonableLimit(1024); this.setBogoSort(false); } - + private void stoogeSort(int[] A, int i, int j) { if (Reads.compareIndices(A, i, j, 0.0025, true) == 1) { Writes.swap(A, i, j, 0.005, true, false); } - + if (j - i + 1 >= 3) { int t = (j - i + 1) / 3; - + this.stoogeSort(A, i, j-t); this.stoogeSort(A, i+t, j); this.stoogeSort(A, i, j-t); @@ -48,4 +47,4 @@ private void stoogeSort(int[] A, int i, int j) { public void runSort(int[] array, int currentLength, int bucketCount) { this.stoogeSort(array, 0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/SwaplessBubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/SwaplessBubbleSort.java similarity index 92% rename from src/sorts/exchange/SwaplessBubbleSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/SwaplessBubbleSort.java index 5ebd7e31..2f1902cf 100644 --- a/src/sorts/exchange/SwaplessBubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/SwaplessBubbleSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 Josiah (Gaming32) Glosson @@ -29,22 +29,21 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class SwaplessBubbleSort extends Sort { +public final class SwaplessBubbleSort extends Sort { public SwaplessBubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Swapless Bubble"); this.setRunAllSortsName("Swapless Bubble Sort"); this.setRunSortName("Swapless Bubblesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int last; @@ -70,4 +69,4 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.write(array, i - 1, comp, 0.075, true, false); } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/TableSort.java b/src/main/java/io/github/arrayv/sorts/exchange/TableSort.java similarity index 94% rename from src/sorts/exchange/TableSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/TableSort.java index a97fb3d5..ccab4c1b 100644 --- a/src/sorts/exchange/TableSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/TableSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class TableSort extends Sort { +public final class TableSort extends Sort { public TableSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,97 +37,96 @@ public TableSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Table Sort"); this.setRunSortName("Tablesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private boolean stableComp(int[] array, int[] table, int a, int b) { int comp = Reads.compareIndices(array, table[a], table[b], 0.5, true); - + return comp > 0 || (comp == 0 && Reads.compareOriginalIndices(table, a, b, 0.5, false) > 0); } - + private void medianOfThree(int[] array, int[] table, int a, int b) { int m = a+(b-1-a)/2; - + if(this.stableComp(array, table, a, m)) Writes.swap(table, a, m, 1, true, true); - + if(this.stableComp(array, table, m, b-1)) { Writes.swap(table, m, b-1, 1, true, true); - + if(this.stableComp(array, table, a, m)) return; } - + Writes.swap(table, a, m, 1, true, true); } - + private int partition(int[] array, int[] table, int a, int b, int p) { int i = a-1, j = b; Highlights.markArray(3, p); - + while(true) { do i++; while(i < j && !this.stableComp(array, table, i, p)); - + do j--; while(j >= i && this.stableComp(array, table, j, p)); - + if(i < j) Writes.swap(table, i, j, 1, true, true); else return j; } } - + private void quickSort(int[] array, int[] table, int a, int b) { if(b-a < 3) { if(b-a == 2 && this.stableComp(array, table, a, a+1)) Writes.swap(table, a, a+1, 1, true, true); return; } - + this.medianOfThree(array, table, a, b); int p = this.partition(array, table, a+1, b, a); Writes.swap(table, a, p, 1, true, true); - + this.quickSort(array, table, a, p); this.quickSort(array, table, p+1, b); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { int[] table = Writes.createExternalArray(currentLength); for(int i = 0; i < currentLength; i++) Writes.write(table, i, i, 0.5, true, true); - + this.quickSort(array, table, 0, currentLength); Highlights.clearMark(3); - + for(int i = 0; i < table.length; i++) { Highlights.markArray(2, i); - + if(Reads.compareOriginalValues(i, table[i]) != 0) { int t = array[i]; int j = i, next = table[i]; - + do { Writes.write(array, j, array[next], 1, true, false); Writes.write(table, j, j, 1, true, true); - + j = next; next = table[next]; } while(Reads.compareOriginalValues(next, i) != 0); - + Writes.write(array, j, t, 1, true, false); Writes.write(table, j, j, 1, true, true); } } - + Writes.deleteExternalArray(table); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/ThreeSmoothCombSortIterative.java b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortIterative.java similarity index 91% rename from src/sorts/exchange/ThreeSmoothCombSortIterative.java rename to src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortIterative.java index ae22e23c..6d4a3361 100644 --- a/src/sorts/exchange/ThreeSmoothCombSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortIterative.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2020 aphitorite @@ -28,22 +28,21 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class ThreeSmoothCombSortIterative extends Sort { +public final class ThreeSmoothCombSortIterative extends Sort { public ThreeSmoothCombSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("3-Smooth Comb (Iterative)"); this.setRunAllSortsName("Iterative 3-Smooth Comb Sort"); this.setRunSortName("Iterative 3-Smooth Combsort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void compSwap(int[] array, int a, int b) { if(Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); @@ -52,16 +51,16 @@ private void compSwap(int[] array, int a, int b) { @Override public void runSort(int[] array, int length, int bucketCount) { int pow2 = (int)(Math.log(length-1)/Math.log(2)); - + for(int k = pow2; k >= 0; k--) { int pow3 = (int)((Math.log(length) - k*Math.log(2))/Math.log(3)); - + for(int j = pow3; j >= 0; j--) { int gap = (int)(Math.pow(2, k)*Math.pow(3, j)); - + for(int i = 0; i+gap < length; i++) this.compSwap(array, i, i+gap); } } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/ThreeSmoothCombSortParallel.java b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortParallel.java similarity index 93% rename from src/sorts/exchange/ThreeSmoothCombSortParallel.java rename to src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortParallel.java index e3c2a116..5e6722c2 100644 --- a/src/sorts/exchange/ThreeSmoothCombSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortParallel.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 PiotrGrochowski Copyright (c) 2020 aphitorite @@ -26,24 +26,23 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ThreeSmoothCombSortParallel extends Sort { +public final class ThreeSmoothCombSortParallel extends Sort { public ThreeSmoothCombSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("3-Smooth Comb (Parallel)"); this.setRunAllSortsName("Parallel 3-Smooth Comb Sort"); this.setRunSortName("Parallel 3-Smooth Combsort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] array; - + private class RecursiveComb extends Thread { private int pos, gap, end; RecursiveComb(int pos, int gap, int end) { @@ -55,7 +54,7 @@ public void run() { ThreeSmoothCombSortParallel.this.recursiveComb(pos, gap, end); } } - + private class PowerOfThree extends Thread { private int pos, gap, end; PowerOfThree(int pos, int gap, int end) { @@ -67,15 +66,15 @@ public void run() { ThreeSmoothCombSortParallel.this.powerOfThree(pos, gap, end); } } - + private void recursiveComb(int pos, int gap, int end) { if(pos+gap > end) return; - + RecursiveComb a = new RecursiveComb(pos, gap*2, end); RecursiveComb b = new RecursiveComb(pos+gap, gap*2, end); a.start(); b.start(); - + try { a.join(); b.join(); @@ -87,14 +86,14 @@ private void recursiveComb(int pos, int gap, int end) { private void powerOfThree(int pos, int gap, int end) { if(pos+gap > end) return; - + PowerOfThree a = new PowerOfThree(pos, gap*3, end); PowerOfThree b = new PowerOfThree(pos+gap, gap*3, end); PowerOfThree c = new PowerOfThree(pos+2*gap, gap*3, end); a.start(); b.start(); c.start(); - + try { a.join(); b.join(); @@ -106,10 +105,10 @@ private void powerOfThree(int pos, int gap, int end) { if(Reads.compareIndices(this.array, i, i+gap, 0.5, true) == 1) Writes.swap(this.array, i, i+gap, 0.5, false, false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.recursiveComb(0, 1, length); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/ThreeSmoothCombSortRecursive.java b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortRecursive.java similarity index 91% rename from src/sorts/exchange/ThreeSmoothCombSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortRecursive.java index ef76dda4..3e3bfc01 100644 --- a/src/sorts/exchange/ThreeSmoothCombSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortRecursive.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 PiotrGrochowski Copyright (c) 2020 aphitorite @@ -26,15 +26,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ThreeSmoothCombSortRecursive extends Sort { +public final class ThreeSmoothCombSortRecursive extends Sort { public ThreeSmoothCombSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("3-Smooth Comb (Recursive)"); this.setRunAllSortsName("Recursive 3-Smooth Comb Sort"); this.setRunSortName("Recursive 3-Smooth Combsort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -44,27 +43,27 @@ public ThreeSmoothCombSortRecursive(ArrayVisualizer arrayVisualizer) { private void recursiveComb(int[] array, int pos, int gap, int end) { if(pos+gap > end) return; - + this.recursiveComb(array, pos, gap*2, end); this.recursiveComb(array, pos+gap, gap*2, end); - + this.powerOfThree(array, pos, gap, end); } private void powerOfThree(int[] array, int pos, int gap, int end) { if(pos+gap > end) return; - + this.powerOfThree(array, pos, gap*3, end); this.powerOfThree(array, pos+gap, gap*3, end); this.powerOfThree(array, pos+2*gap, gap*3, end); - + for(int i = pos; i+gap < end; i+=gap) if(Reads.compareIndices(array, i, i+gap, 0.5, true) == 1) Writes.swap(array, i, i+gap, 0.5, false, false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.recursiveComb(array, 0, 1, length); } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/UnoptimizedBubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedBubbleSort.java similarity index 88% rename from src/sorts/exchange/UnoptimizedBubbleSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedBubbleSort.java index 92df1a09..e1ecdfc2 100644 --- a/src/sorts/exchange/UnoptimizedBubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedBubbleSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class UnoptimizedBubbleSort extends Sort { +public final class UnoptimizedBubbleSort extends Sort { public UnoptimizedBubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Unoptimized Bubble"); this.setRunAllSortsName("Unoptimized Bubble Sort"); this.setRunSortName("Unoptimized Bubblesort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -51,7 +50,7 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti while(!sorted) { sorted = true; - for(int i = 0; i < sortLength - 1; i++) { + for(int i = 0; i < sortLength - 1; i++) { if(Reads.compareValues(array[i], array[i + 1]) == 1){ Writes.swap(array, i, i + 1, 0.075, true, false); sorted = false; @@ -61,6 +60,6 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Highlights.markArray(2, i + 1); Delays.sleep(0.05); } - } + } } -} \ No newline at end of file +} diff --git a/src/sorts/exchange/UnoptimizedCocktailShakerSort.java b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedCocktailShakerSort.java similarity index 90% rename from src/sorts/exchange/UnoptimizedCocktailShakerSort.java rename to src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedCocktailShakerSort.java index 3eac9f78..b46d257c 100644 --- a/src/sorts/exchange/UnoptimizedCocktailShakerSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedCocktailShakerSort.java @@ -1,10 +1,10 @@ -package sorts.exchange; +package io.github.arrayv.sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class UnoptimizedCocktailShakerSort extends Sort { +public final class UnoptimizedCocktailShakerSort extends Sort { public UnoptimizedCocktailShakerSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Unoptimized Cocktail Shaker"); this.setRunAllSortsName("Unoptimized Cocktail Shaker Sort"); this.setRunSortName("Unoptimized Cocktailsort"); this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -52,33 +51,33 @@ private void cocktailShaker(int[] array, int start, int end, double sleep) { if(Reads.compareValues(array[j], array[j + 1]) == 1) { Writes.swap(array, j, j + 1, sleep, true, false); } - + Highlights.markArray(1, j); Highlights.markArray(2, j + 1); - + Delays.sleep(sleep / 2); } for(int j = end + start - i - 1; j > i; j--){ if(Reads.compareValues(array[j], array[j - 1]) == -1) { Writes.swap(array, j, j - 1, sleep, true, false); } - + Highlights.markArray(1, j); Highlights.markArray(2, j - 1); - + Delays.sleep(sleep / 2); } - + i++; } } - + public void customSort(int[] array, int start, int end) { this.cocktailShaker(array, start, end, 1); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.cocktailShaker(array, 0, sortLength, 0.1); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/AdaptiveGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/AdaptiveGrailSort.java similarity index 92% rename from src/sorts/hybrid/AdaptiveGrailSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/AdaptiveGrailSort.java index eb48979d..5f934059 100644 --- a/src/sorts/hybrid/AdaptiveGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/AdaptiveGrailSort.java @@ -1,24 +1,24 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * MIT License - * + * * Copyright (c) 2013 Andrey Astrelin * Copyright (c) 2020 The Holy Grail Sort Project - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -48,40 +48,39 @@ /** * Adaptive Grail Sort - * + * * O(1) space stable worst case O(n log n) algorithm * designed to take advantage of partially ordered data with constant memory - * + * * @author aphitorite */ -final public class AdaptiveGrailSort extends Sort { +public final class AdaptiveGrailSort extends Sort { public AdaptiveGrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Adaptive Grail"); this.setRunAllSortsName("Adaptive Grail Sort (Block Merge Sort)"); this.setRunSortName("Adaptive Grailsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + enum Subarray { LEFT, RIGHT; } - + private int minRun; - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + //changes len sized blocks order ABC -> BCA private void multiTriSwap(int[] array, int a, int b, int c, int len) { Highlights.clearMark(2); @@ -92,28 +91,28 @@ private void multiTriSwap(int[] array, int a, int b, int c, int len) { Writes.write(array, c+i, temp, 0.333, true, false); } } - + private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; while(a > b) Writes.write(array, a, array[(a--)-1], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } - + private void insertToBW(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; while(a < b) Writes.write(array, a, array[(a++)+1], 0.5, true, false); Writes.write(array, a, temp, 0.5, true, false); } - + private void shift(int[] array, int a, int m, int b) { while(m < b) Writes.swap(array, a++, m++, 1, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 1 && r > 1) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -133,41 +132,41 @@ private void rotate(int[] array, int a, int m, int b) { if(r == 1) this.insertTo(array, m, a); else if(l == 1) this.insertToBW(array, a, b-1); } - + private int leftBinarySearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; - else + else a = m+1; } - + return a; } - + private int rightBinarySearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; - else + else a = m+1; } - + return a; } - + private int buildUniqueRun(int[] array, int a, int n) { int nKeys = 1, i = a+1; - + //build run at start if(Reads.compareIndices(array, i-1, i, 1, true) == -1){ i++; nKeys++; - + while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == -1) { i++; nKeys++; @@ -176,25 +175,25 @@ private int buildUniqueRun(int[] array, int a, int n) { else if(Reads.compareIndices(array, i-1, i, 1, true) == 1) { i++; nKeys++; - + while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == 1) { i++; nKeys++; } Writes.reversal(array, a, i-1, 1, true, false); } - + return nKeys; } - + private int buildUniqueRunBW(int[] array, int b, int n) { int nKeys = 1, i = b-1; - + //build run at end if(Reads.compareIndices(array, i-1, i, 1, true) == -1){ i--; nKeys++; - + while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == -1) { i--; nKeys++; @@ -203,17 +202,17 @@ private int buildUniqueRunBW(int[] array, int b, int n) { else if(Reads.compareIndices(array, i-1, i, 1, true) == 1) { i--; nKeys++; - + while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == 1) { i--; nKeys++; } Writes.reversal(array, i, b-1, 1, true, false); } - + return nKeys; } - + private int findKeys(int[] array, int a, int b, int nKeys, int n) { int p = a, pEnd = a+nKeys; @@ -222,14 +221,14 @@ private int findKeys(int[] array, int a, int b, int nKeys, int n) { Highlights.markArray(1, i); Delays.sleep(1); int loc = this.leftBinarySearch(array, p, pEnd, array[i]); - + if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, p, pEnd, i); int inc = i-pEnd; loc += inc; p += inc; pEnd += inc; - + this.insertTo(array, pEnd, loc); nKeys++; pEnd++; @@ -248,7 +247,7 @@ private int findKeysBW(int[] array, int a, int b, int nKeys, int n) { Highlights.markArray(1, i); Delays.sleep(1); int loc = this.leftBinarySearch(array, p, pEnd, array[i]); - + if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, i+1, p, pEnd); int inc = p-(i+1); @@ -256,27 +255,27 @@ private int findKeysBW(int[] array, int a, int b, int nKeys, int n) { pEnd -= inc; p -= inc+1; nKeys++; - + this.insertToBW(array, i, loc-1); } } this.rotate(array, p, pEnd, b); return nKeys; } - + //instead of insertion level find & create runs divisible by minRun private void buildRuns(int[] array, int a, int b) { int i = a+1, j = a; - + while(i < b) { if(Reads.compareIndices(array, i-1, i++, 1, true) == 1) { while(i < b && Reads.compareIndices(array, i-1, i, 1, true) == 1) i++; Writes.reversal(array, j, i-1, 1, true, false); } else while(i < b && Reads.compareIndices(array, i-1, i, 1, true) <= 0) i++; - + if(i < b) j = i - (i-j-1)%this.minRun - 1;//a%b, if(a%b == 0) -> a = b - + while(i-j < this.minRun && i < b) { this.insertTo(array, i, this.rightBinarySearch(array, j, i, array[i])); i++; @@ -284,17 +283,17 @@ private void buildRuns(int[] array, int a, int b) { j = i++; } } - + private void binaryInsertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(array, i, this.rightBinarySearch(array, a, i, array[i])); } - + private void mergeWithBufRest(int[] array, int a, int m, int b, int p, int pLen) { int i = 0, j = m, k = a; - + while(i < pLen && j < b) { - if(Reads.compareValues(array[p+i], array[j]) <= 0) + if(Reads.compareValues(array[p+i], array[j]) <= 0) Writes.swap(array, k++, p+(i++), 1, true, false); else Writes.swap(array, k++, j++, 1, true, false); @@ -307,132 +306,132 @@ private void mergeWithBuf(int[] array, int a, int m, int b, int p) { this.multiSwap(array, p, a, l); this.mergeWithBufRest(array, a, m, b, p, l); } - + private void mergeWithBufBW(int[] array, int a, int m, int b, int p) { int pLen = b-m; this.multiSwap(array, m, p, pLen); - + int i = pLen-1, j = m-1, k = b-1; - + while(i >= 0 && j >= a) { - if(Reads.compareValues(array[p+i], array[j]) >= 0) + if(Reads.compareValues(array[p+i], array[j]) >= 0) Writes.swap(array, k--, p+(i--), 1, true, false); else Writes.swap(array, k--, j--, 1, true, false); } while(i >= 0) Writes.swap(array, k--, p+(i--), 1, true, false); } - + private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b) { if(Reads.compareValues(array[i], array[j]) > 0) { k = this.leftBinarySearch(array, j+1, b, array[i]); this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } } - + private void inPlaceMergeBW(int[] array, int a, int m, int b) { int i = m-1, j = b-1, k; - + while(j > i && i >= a){ if(Reads.compareValues(array[i], array[j]) > 0) { k = this.rightBinarySearch(array, a, i, array[j]); this.rotate(array, k, i+1, j+1); - + j -= (i+1)-k; i = k-1; - } + } else j--; } } - + private void mergeWithoutBuf(int[] array, int a, int m, int b) { if(m-a > b-m) this.inPlaceMergeBW(array, a, m, b); else this.inPlaceMerge(array, a, m, b); } - + private boolean checkSorted(int[] array, int a, int m, int b) { return Reads.compareValues(array[m-1], array[m]) > 0; } - + private boolean checkReverseBounds(int[] array, int a, int m, int b) { if(Reads.compareValues(array[a], array[b-1]) == 1) { this.rotate(array, a, m, b); return false; } - + return true; } - + private boolean checkBounds(int[] array, int a, int m, int b) { - return this.checkSorted(array, a, m, b) + return this.checkSorted(array, a, m, b) && this.checkReverseBounds(array, a, m, b); } - + private Subarray grailGetSubarray(int[] array, int t, int mKey) { if(Reads.compareValues(array[t], array[mKey]) < 0) return Subarray.LEFT; - + else return Subarray.RIGHT; } - + //returns mKey final position private int blockSelectSort(int[] array, int p, int t, int r, int d, int lCount, int bCount, int bLen) { int mKey = lCount; - + for(int j = 0, k = lCount+1; j < k-1; j++) { int min = j; - + for(int i = Math.max(lCount-r, j+1); i < k; i++) { int comp = Reads.compareIndices(array, p+d + i*bLen, p+d + min*bLen, 2, true); if(comp < 0 || (comp == 0 && Reads.compareValues(array[t+i], array[t+min]) < 0)) min = i; } - + if(min != j) { this.multiSwap(array, p + j*bLen, p + min*bLen, bLen); Writes.swap(array, t+j, t+min, 1, true, false); - + if(k < bCount && min == k-1) k++; } if(min == mKey) mKey = j; } - + return t+mKey; } - + //special thanks to @Anonymous0726 for this idea private void grailSortKeys(int[] array, int b, int p, int mKey) { Writes.swap(array, p, mKey, 1, true, false); int i = mKey, j = i+1, k = p+1; - + while(j < b) { if(Reads.compareValues(array[j], array[p]) < 0) Writes.swap(array, i++, j, 1, true, false); - + else Writes.swap(array, k++, j, 1, true, false); - + j++; } - + this.multiSwap(array, i, p, b-i); } - + private void grailSortKeysWithoutBuf(int[] array, int b, int mKey) { int i = mKey, j = i+1; - + while(j < b) { if(Reads.compareValues(array[j], array[i]) < 0) this.insertTo(array, j, i++); - + j++; } } @@ -440,29 +439,29 @@ private void grailSortKeysWithoutBuf(int[] array, int b, int mKey) { //special thanks to @Anonymous0726 for this idea private int grailMergeBlocks(int[] array, int a, int m, int b, int p) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareValues(array[i], array[j]) <= 0) Writes.swap(array, p++, i++, 1, true, false); - + else Writes.swap(array, p++, j++, 1, true, false); } - + if(i > p) while(i < m) Writes.swap(array, p++, i++, 1, true, false); return j; } - + //same as grailMergeBlocks() except reverses equal items order private int grailMergeBlocksRev(int[] array, int a, int m, int b, int p) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareValues(array[i], array[j]) < 0) Writes.swap(array, p++, i++, 1, true, false); - + else Writes.swap(array, p++, j++, 1, true, false); } - + if(i > p) while(i < m) Writes.swap(array, p++, i++, 1, true, false); return j; } @@ -473,13 +472,13 @@ private void grailBlockMerge(int[] array, int a, int m, int b, int t, int p, int int b1 = b - (b-m-1)%bLen - 1, i = a+bLen, j = a, key = t-1, lCount = (m-i)/bLen, bCount = (b1-i)/bLen, l = -1, r = lCount-1; - + this.multiTriSwap(array, p, m-bLen, a, bLen); this.insertToBW(array, t, t+lCount-1); - + int mKey = this.blockSelectSort(array, i, t, 1, bLen-1, lCount, bCount, bLen); Subarray frag = Subarray.LEFT; - + while(l < lCount && r < bCount) { if(frag == Subarray.LEFT) { do { @@ -488,13 +487,13 @@ private void grailBlockMerge(int[] array, int a, int m, int b, int t, int p, int key++; } while(l < lCount && this.grailGetSubarray(array, key, mKey) == Subarray.LEFT); - + if(l == lCount) { i = this.grailMergeBlocks(array, i, j, b, i-bLen); this.mergeWithBufRest(array, i-bLen, i, b, p, bLen); } else i = this.grailMergeBlocks(array, i, j, j+bLen-1, i-bLen); - + frag = Subarray.RIGHT; } else { @@ -504,72 +503,72 @@ private void grailBlockMerge(int[] array, int a, int m, int b, int t, int p, int key++; } while(r < bCount && this.grailGetSubarray(array, key, mKey) == Subarray.RIGHT); - + if(r == bCount) { this.shift(array, i-bLen, i, b); this.multiSwap(array, p, b-bLen, bLen); } else i = this.grailMergeBlocksRev(array, i, j, j+bLen-1, i-bLen); - + frag = Subarray.LEFT; } } - + this.grailSortKeys(array, t+bCount, p, mKey); } - + //TODO: rewrite strat 2 merge to be more adaptive - + //1024 items, 8 unique, linear, final merge pass //old: 5812 comps & 5762 writes //new: ??? - + /*private int grailMergeBlocksWithoutBuf(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b) { if(Reads.compareValues(array[i], array[j]) > 0) { k = this.leftBinarySearch(array, j+1, b, array[i]); this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } - + return i; } - + private int grailMergeBlocksWithoutBufRev(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b) { if(Reads.compareValues(array[i], array[j]) >= 0) { k = this.rightBinarySearch(array, j+1, b, array[i]); this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } - + return i; }*/ - + //old private void grailBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, int bLen) { int a1 = a + (m-a)%bLen, b1 = b - (b-m)%bLen, i = a, j = a1, key = t, lCount = (m-j)/bLen + 1, bCount = (b1-j)/bLen + 1, l = 0, r = lCount; - + int mKey = this.blockSelectSort(array, j, t, 0, 0, lCount-1, bCount-1, bLen); Subarray frag = Subarray.LEFT; - + while(l < lCount && r < bCount) { Subarray next = this.grailGetSubarray(array, key++, mKey); - + if(next == frag) { if(frag == Subarray.LEFT) l++; else r++; @@ -577,16 +576,16 @@ private void grailBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, } else {//grailMergeBlocksWithoutBuf() int m2 = j, b2 = j+bLen, k; - + if(frag == Subarray.LEFT) { while(i < m2 && m2 < b2) { if(Reads.compareValues(array[i], array[m2]) > 0) { k = this.leftBinarySearch(array, m2+1, b2, array[i]); this.rotate(array, i, m2, k); - + i += k-m2; m2 = k; - } + } else i++; } } @@ -595,14 +594,14 @@ private void grailBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, if(Reads.compareValues(array[i], array[m2]) >= 0) { k = this.rightBinarySearch(array, m2+1, b2, array[i]); this.rotate(array, i, m2, k); - + i += k-m2; m2 = k; - } + } else i++; } } - + if(i < m2) {//right side is merged first if(next == Subarray.LEFT) l++; else r++; @@ -613,33 +612,33 @@ private void grailBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, frag = next; } } - + j += bLen; } - + if(l < lCount) this.inPlaceMergeBW(array, a, b1, b); this.grailSortKeysWithoutBuf(array, t+bCount-1, mKey); } - + private void smartMerge(int[] array, int a, int m, int b, int p) { if(this.checkBounds(array, a, m, b)) { a = this.rightBinarySearch(array, a, m-1, array[m]); this.mergeWithBuf(array, a, m, b, p); } } - + private void smartMergeBW(int[] array, int a, int m, int b, int p) { if(this.checkBounds(array, a, m, b)) { b = this.leftBinarySearch(array, m+1, b, array[m-1]); this.mergeWithBufBW(array, a, m, b, p); } } - + private void smartBlockMerge(int[] array, int a, int m, int b, int t, int p, int bLen) { if(this.checkBounds(array, a, m, b)) { int n = this.rightBinarySearch(array, a, m-1, array[m]); b = this.leftBinarySearch(array, m+1, b, array[m-1]); - + if(this.checkReverseBounds(array, n, m, b)) { if(m-n <= bLen || b-m <= bLen) { if(b-m < m-n) this.mergeWithBufBW(array, n, m, b, p); @@ -652,61 +651,61 @@ private void smartBlockMerge(int[] array, int a, int m, int b, int t, int p, int } } } - + private void smartBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, int bLen) { if(this.checkBounds(array, a, m, b)) { a = this.rightBinarySearch(array, a, m-1, array[m]); - + if(m-a <= bLen) this.inPlaceMerge(array, a, m, b); else this.grailBlockMergeWithoutBuf(array, a, m, b, t, bLen); } } - + private void smartInPlaceMerge(int[] array, int a, int m, int b) { if(this.checkSorted(array, a, m, b)) this.inPlaceMergeBW(array, a, m, b); } - + private void redistBuffer(int[] array, int a, int m, int b) { int rPos = this.leftBinarySearch(array, m, b, array[a]); this.rotate(array, a, m, rPos); - + int dist = rPos-m; a += dist; m += dist; - + int a1 = a+(m-a)/2; rPos = this.leftBinarySearch(array, m, b, array[a1]); this.rotate(array, a1, m, rPos); - + dist = rPos-m; a1 += dist; m += dist; - + this.mergeWithoutBuf(array, a, a1-dist, a1); this.mergeWithoutBuf(array, a1, m, b); } - + private void redistBufferBW(int[] array, int a, int m, int b) { int rPos = this.rightBinarySearch(array, a, m, array[b-1]); this.rotate(array, rPos, m, b); - + int dist = m-rPos; b -= dist; m -= dist; - + int b1 = m+(b-m)/2; rPos = this.rightBinarySearch(array, a, m, array[b1-1]); this.rotate(array, rPos, m, b1); - + dist = m-rPos; b1 -= dist; m -= dist; - + this.mergeWithoutBuf(array, b1, b1+dist, b); this.mergeWithoutBuf(array, a, m, b1); } - + private void inPlaceMergeSort(int[] array, int a, int b) { this.buildRuns(array, a, b); @@ -714,84 +713,84 @@ private void inPlaceMergeSort(int[] array, int a, int b) { for(int i, j = this.minRun; j < len; j *= 2) { for(i = a; i + 2*j <= b; i += 2*j) this.smartInPlaceMerge(array, i, i+j, i+2*j); - + if(i + j < b) this.smartInPlaceMerge(array, i, i+j, b); } } - + private void grailAdaptiveSortWithoutBuf(int[] array, int a, int b, int keys, int ideal, boolean bwBuf) { int len = b-a, bLen; for(bLen = Math.min(keys, this.minRun); 2*bLen <= keys; bLen *= 2); int tLen = keys-bLen; - + int i, j = this.minRun, t, p, a1, b1; - + if(bwBuf) { p = b-bLen; a1 = a; b1 = p-tLen; t = b1; } else { p = a+tLen; a1 = p+bLen; b1 = b; t = a; } - + //insertion level this.buildRuns(array, a1, b1); - + //merge with buffer level while(j <= bLen && j < len) { for(i = a1; i + 2*j <= b1; i += 2*j) this.smartMerge(array, i, i+j, i+2*j, p); - + if(i + j < b1) this.smartMergeBW(array, i, i+j, b1, p); - + j *= 2; } - + if(bLen/2 >= this.minRun && bLen/2 >= (keys+1)/2) { this.binaryInsertion(array, p, p+bLen); - + bLen /= 2; tLen = keys-bLen; p += bLen; } - + //block merge level while(tLen >= 2*j/bLen - 1 && j < len) { for(i = a1; i + 2*j <= b1; i += 2*j) this.smartBlockMerge(array, i, i+j, i+2*j, t, p, bLen); - + if(i + j < b1) { - if(b1 - (i+j) > bLen) + if(b1 - (i+j) > bLen) this.smartBlockMerge(array, i, i+j, b1, t, p, bLen); - + else this.smartMergeBW(array, i, i+j, b1, p); } - + j *= 2; } - + this.binaryInsertion(array, p, p+bLen); tLen = keys-keys%2; - + //block merge w/o buffer level while(j < len) { bLen = 2*j / tLen; - + for(i = a1; i + 2*j <= b1; i += 2*j) this.smartBlockMergeWithoutBuf(array, i, i+j, i+2*j, t, bLen); - + if(i + j < b1) { - if(b1 - (i+j) > bLen) + if(b1 - (i+j) > bLen) this.smartBlockMergeWithoutBuf(array, i, i+j, b1, t, bLen); - + else this.smartInPlaceMerge(array, i, i+j, b1); } - + j *= 2; } - + //buffer redistribution if(bwBuf) { a = this.rightBinarySearch(array, a, b1, array[b1]); @@ -804,10 +803,10 @@ private void grailAdaptiveSortWithoutBuf(int[] array, int a, int b, int keys, in else this.mergeWithoutBuf(array, a, a1, b); } } - + protected void grailAdaptiveSort(int[] array, int a, int b) { int len = b-a; - + //insertion on small len if(len < 31) { this.binaryInsertion(array, a, b); @@ -817,87 +816,87 @@ protected void grailAdaptiveSort(int[] array, int a, int b) { if(len < 63) { this.minRun = (len+1)/2; this.buildRuns(array, a, b); - + int m = a+this.minRun; if(this.checkBounds(array, a, m, b)) this.redistBufferBW(array, a, m, b); - + return; } //calculate optimal minRun & block len for(this.minRun = len; this.minRun >= 32; this.minRun = (this.minRun+1)/2); - + int bLen; for(bLen = this.minRun; bLen*bLen < len; bLen *= 2); - + int tLen = len/bLen - 2, ideal = tLen + bLen; - + //choose direction to find keys boolean bwBuf; int rRun = this.buildUniqueRunBW(array, b, ideal), lRun = 0; - + if(rRun == ideal) bwBuf = true; else { lRun = this.buildUniqueRun(array, a, ideal); - + if(lRun == ideal) bwBuf = false; else bwBuf = (rRun < 16 && lRun < 16) || rRun >= lRun; } - + //find bLen + tLen unique buffer keys int keys = bwBuf ? this.findKeysBW(array, a, b, rRun, ideal) : this.findKeys(array, a, b, lRun, ideal); - + if(keys < ideal) { if(keys == 1) return; else if(keys <= 4) this.inPlaceMergeSort(array, a, b); else this.grailAdaptiveSortWithoutBuf(array, a, b, keys, ideal, bwBuf); return; } - + int i, j = this.minRun, t, p, a1, b1; - + if(bwBuf) { p = b-bLen; a1 = a; b1 = p-tLen; t = b1; } else { p = a+tLen; a1 = p+bLen; b1 = b; t = a; } - + //insertion level this.buildRuns(array, a1, b1); - + //merge with buffer level while(j <= bLen && j < len) { for(i = a1; i + 2*j <= b1; i += 2*j) this.smartMerge(array, i, i+j, i+2*j, p); - + if(i + j < b1) this.smartMergeBW(array, i, i+j, b1, p); - + j *= 2; } - + //block merge level while(j < len) { for(i = a1; i + 2*j <= b1; i += 2*j) this.smartBlockMerge(array, i, i+j, i+2*j, t, p, bLen); - + if(i + j < b1) { - if(b1 - (i+j) > bLen) + if(b1 - (i+j) > bLen) this.smartBlockMerge(array, i, i+j, b1, t, p, bLen); - + else this.smartMergeBW(array, i, i+j, b1, p); } - + j *= 2; } this.binaryInsertion(array, p, p+bLen); - + //buffer redistribution if(bwBuf) { a = this.rightBinarySearch(array, a, b1, array[b1]); @@ -908,9 +907,9 @@ protected void grailAdaptiveSort(int[] array, int a, int b) { this.redistBuffer(array, a, a1, b); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.grailAdaptiveSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/BinaryMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/BinaryMergeSort.java similarity index 89% rename from src/sorts/hybrid/BinaryMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/BinaryMergeSort.java index face697b..97fd1d42 100644 --- a/src/sorts/hybrid/BinaryMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/BinaryMergeSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.MergeSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.MergeSorting; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,24 +29,23 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class BinaryMergeSort extends MergeSorting { +public final class BinaryMergeSort extends MergeSorting { public BinaryMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Binary Merge"); this.setRunAllSortsName("Binary Merge Sort"); this.setRunSortName("Binary Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.mergeSort(array, length, true); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/BufferPartitionMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/BufferPartitionMergeSort.java similarity index 94% rename from src/sorts/hybrid/BufferPartitionMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/BufferPartitionMergeSort.java index 9fc3cd18..fea96ef3 100644 --- a/src/sorts/hybrid/BufferPartitionMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/BufferPartitionMergeSort.java @@ -1,13 +1,12 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.Sort; -import sorts.insert.InsertionSort; -import sorts.insert.BinaryInsertionSort; - -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 yuji, implemented by aphitorite @@ -32,37 +31,36 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class BufferPartitionMergeSort extends Sort { +public final class BufferPartitionMergeSort extends Sort { public BufferPartitionMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Buffer Partition Merge (BPM)"); this.setRunAllSortsName("Buffer Partition Merge Sort"); this.setRunSortName("BPMSort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private InsertionSort insSort; private BinaryInsertionSort binInsSort; - + private void shiftBW(int[] array, int a, int m, int b) { while(m > a) Writes.swap(array, --b, --m, 1, true, false); } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -78,45 +76,45 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b) { if(Reads.compareValues(array[i], array[j]) > 0) { k = j; while(++k < b && Reads.compareIndices(array, i, k, 0, false) > 0); - + this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } } - + private void medianOfThree(int[] array, int a, int b) { int m = a+(b-1-a)/2; - + if(Reads.compareIndices(array, a, m, 1, true) == 1) Writes.swap(array, a, m, 1, true, false); - + if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { Writes.swap(array, m, b-1, 1, true, false); - + if(Reads.compareIndices(array, a, m, 1, true) == 1) return; } - + Writes.swap(array, a, m, 1, true, false); } - + //lite version private void medianOfMedians(int[] array, int a, int b, int s) { int end = b, start = a, i, j; boolean ad = true; - + while(end - start > 1) { j = start; Highlights.markArray(2, j); @@ -134,11 +132,11 @@ private void medianOfMedians(int[] array, int a, int b, int s) { end = j; } } - + private int partition(int[] array, int a, int b) { int i = a, j = b; Highlights.markArray(3, a); - + while(true) { do { i++; @@ -146,86 +144,86 @@ private int partition(int[] array, int a, int b) { Delays.sleep(0.5); } while(i < j && Reads.compareIndices(array, i, a, 0, false) == 1); - + do { j--; Highlights.markArray(2, j); Delays.sleep(0.5); } while(j >= i && Reads.compareIndices(array, j, a, 0, false) == -1); - + if(i < j) Writes.swap(array, i, j, 1, true, false); else return j; } } - + private int quickSelect(int[] array, int a, int b, int m) { boolean badPartition = false, mom = false; int m1 = (m+b+1)/2; - + while(true) { if(badPartition) { this.medianOfMedians(array, a, b, 5); mom = true; } else this.medianOfThree(array, a, b); - + int p = this.partition(array, a, b); Writes.swap(array, a, p, 1, true, false); - + int l = Math.max(1, p-a); int r = Math.max(1, b-(p+1)); badPartition = !mom && (l/r >= 16 || r/l >= 16); - + if(p >= m && p < m1) return p; else if(p < m) a = p+1; else b = p; } } - + private void merge(int[] array, int a, int m, int b, int p) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); - else + else Writes.swap(array, p++, j++, 1, true, false); } - + while(i < m) Writes.swap(array, p++, i++, 1, true, false); while(j < b) Writes.swap(array, p++, j++, 1, true, false); } - + private int mergeFW(int[] array, int p, int a, int m, int b) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); - else + else Writes.swap(array, p++, j++, 1, true, false); } - + if(i < m) return i; else return j; } - + public static int getMinLevel(int n) { while(n >= 32) n = (n+3)/4; return n; } - + private void mergeSort(int[] array, int a, int b, int p) { int len = b-a; if(len < 2) return; - + int i, pos, j = getMinLevel(len); - + for(i = a; i+j <= b; i+=j) this.binInsSort.customBinaryInsert(array, i, i+j, 0.25); this.binInsSort.customBinaryInsert(array, i, b, 0.25); - + while(j < len) { pos = p; for(i = a; i+2*j <= b; i+=2*j, pos+=2*j) @@ -234,9 +232,9 @@ private void mergeSort(int[] array, int a, int b, int p) { this.merge(array, i, i+j, b, pos); else while(i < b) Writes.swap(array, i++, pos++, 1, true, false); - + j *= 2; - + pos = a; for(i = p; i+2*j <= p+len; i+=2*j, pos+=2*j) this.merge(array, i, i+j, i+2*j, pos); @@ -244,35 +242,35 @@ private void mergeSort(int[] array, int a, int b, int p) { this.merge(array, i, i+j, p+len, pos); else while(i < p+len) Writes.swap(array, i++, pos++, 1, true, false); - + j *= 2; } } - + private void sort(int[] array, int a, int b) { int minLvl = (int)Math.sqrt(b-a); - + int m = (a+b+1)/2; this.mergeSort(array, m, b, a); - + while(m-a > minLvl) { int m1 = (a+m+1)/2; - + m1 = this.quickSelect(array, a, m, m1); this.mergeSort(array, m1, m, a); - + int bSize = m1-a; int m2 = Math.min(m1+bSize, b); m1 = this.mergeFW(array, a, m1, m, m2); - + while(m1 < m) { this.shiftBW(array, m1, m, m2); m1 = m2-(m-m1); a = m1-bSize; m = m2; - + if(m == b) break; - + m2 = Math.min(m2+bSize, b); m1 = this.mergeFW(array, a, m1, m, m2); } @@ -282,11 +280,11 @@ private void sort(int[] array, int a, int b) { this.binInsSort.customBinaryInsert(array, a, m, 0.25); this.inPlaceMerge(array, a, m, b); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.insSort = new InsertionSort(this.arrayVisualizer); this.binInsSort = new BinaryInsertionSort(this.arrayVisualizer); this.sort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/ChaliceSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ChaliceSort.java similarity index 94% rename from src/sorts/hybrid/ChaliceSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/ChaliceSort.java index 3cdc5449..6f8f7d57 100644 --- a/src/sorts/hybrid/ChaliceSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ChaliceSort.java @@ -1,13 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.select.MaxHeapSort; -import sorts.hybrid.FifthMergeSort; -import sorts.templates.BlockMergeSorting; -import utils.IndexedRotations; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.select.MaxHeapSort; +import io.github.arrayv.sorts.templates.BlockMergeSorting; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -32,7 +30,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ChaliceSort extends BlockMergeSorting { +public final class ChaliceSort extends BlockMergeSorting { public ChaliceSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -40,42 +38,41 @@ public ChaliceSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Chalice Sort"); this.setRunSortName("Chalicesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + //stable merge sort using O(cbrt n) dynamic external buffer - + private int ceilCbrt(int n) { int a = 0, b = 11; - + while(a < b) { int m = (a+b)/2; - + if((1 << 3*m) >= n) b = m; else a = m+1; } - + return 1 << a; } - + private int calcKeys(int bLen, int n) { //assumes keys needed is <= n/4 int a = 1, b = n/4; - + while(a < b) { int m = (a+b)/2; - + if((n-4*m-1)/bLen-2 < m) b = m; else a = m+1; } - + return a; } - + private void laziestSortExt(int[] array, int[] tmp, int a, int b) { for(int i = a, s = tmp.length; i < b; i += s) { int j = Math.min(b, i+s); @@ -83,15 +80,15 @@ private void laziestSortExt(int[] array, int[] tmp, int a, int b) { if(i > a) this.mergeBWExt(array, tmp, a, i, j); } } - + private int[] findKeysSm(int[] array, int a, int b, int a1, int b1, boolean full, int n) { int p = a, pEnd = 0; - + if(full) { for(; p < b; p++) { Highlights.markArray(1, p); int loc = this.leftBinSearch(array, a1, b1, array[p]); - + if(loc == b1 || Reads.compareValues(array[p], array[loc]) != 0) { pEnd = p+1; break; @@ -101,18 +98,18 @@ private int[] findKeysSm(int[] array, int a, int b, int a1, int b1, boolean full for(int i = pEnd; i < b && pEnd-p < n; i++) { Highlights.markArray(1, i); int loc = this.leftBinSearch(array, a1, b1, array[i]); - + if(loc == b1 || Reads.compareValues(array[i], array[loc]) != 0) { loc = this.leftBinSearch(array, p, pEnd, array[i]); - + if(loc == pEnd || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, p, pEnd, i); - + int len1 = i-pEnd; p += len1; loc += len1; pEnd = i+1; - + this.insertTo(array, i, loc); } } @@ -122,52 +119,52 @@ private int[] findKeysSm(int[] array, int a, int b, int a1, int b1, boolean full } else { pEnd = p+1; - + for(int i = pEnd; i < b && pEnd-p < n; i++) { Highlights.markArray(1, i); int loc = this.leftBinSearch(array, p, pEnd, array[i]); - + if(loc == pEnd || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, p, pEnd, i); - + int len1 = i-pEnd; p += len1; loc += len1; pEnd = i+1; - + this.insertTo(array, i, loc); } } - } + } int[] t = {p, pEnd}; return t; } private int findKeys(int[] array, int[] tmp, int a, int b, int n, int s) { //searches for n keys s blocks at a time int[] t = this.findKeysSm(array, a, b, 0, 0, false, Math.min(n, s)); int p = t[0], pEnd = t[1]; - + if(s < n && pEnd-p == s) { for(n -= s; ; n -= s) { t = this.findKeysSm(array, pEnd, b, p, pEnd, true, Math.min(s, n)); int keys = t[1]-t[0]; - + if(keys == 0) break; - + if(keys < s || n == s) { this.rotate(array, pEnd, t[0], t[1]); - + t[0] = pEnd; pEnd += keys; - + this.mergeBWExt(array, tmp, p, t[0], pEnd); //merge can be done inplace + stable break; } else { this.rotate(array, p, pEnd, t[0]); - + p += t[0]-pEnd; pEnd = t[1]; - + this.mergeBWExt(array, tmp, p, t[0], pEnd); } } @@ -175,20 +172,20 @@ private int findKeys(int[] array, int[] tmp, int a, int b, int n, int s) { //sea this.rotate(array, a, p, pEnd); return pEnd-p; } - + private int[] findBitsSm(int[] array, int a, int b, int a1, boolean bw, int n) { int p = a, pEnd, cmp = bw ? -1 : 1; - + while(p < b && Reads.compareIndices(array, p, a1, 1, true) != cmp) p++; a1++; - + if(p < b) { pEnd = p+1; - + for(int i = pEnd; i < b && pEnd-p < n; i++) { if(Reads.compareIndices(array, i, a1, 1, true) == cmp) { this.rotate(array, p, pEnd, i); - + p += i-pEnd; pEnd = i+1; a1++; @@ -196,68 +193,68 @@ private int[] findBitsSm(int[] array, int a, int b, int a1, boolean bw, int n) { } } else pEnd = p; - + int[] t = {p, pEnd}; return t; } private int findBits(int[] array, int[] tmp, int a, int b, int n, int s) { this.laziestSortExt(array, tmp, a, a+n); - + int a0 = a, a1 = a+n, c = 0, c0 = 0; - + for(int i = 0; c < n && i < 2; i++) { int p = a1, pEnd = p; - + while(true) { int[] t = this.findBitsSm(array, pEnd, b, a0, i == 1, Math.min(s, n-c)); int bits = t[1]-t[0]; - + if(bits == 0) break; - + a0 += bits; c += bits; - + if(bits < s || c == n) { this.rotate(array, pEnd, t[0], t[1]); - + t[0] = pEnd; pEnd += bits; - + break; } else { this.rotate(array, p, pEnd, t[0]); - + p += t[0]-pEnd; pEnd = t[1]; } } this.rotate(array, a1, p, pEnd); a1 += pEnd-p; - + if(i == 0) c0 = c; } - + //returns the count of ascending pairs of elements NOT how many bits found - + if(c < n) return -1; - + else { this.multiSwap(array, a+c0, a+n+c0, n-c0); return c0; } } - + private void bitReversal(int[] array, int a, int b) { int len = b-a, m = 0; int d1 = len>>1, d2 = d1+(d1>>1); - + for(int i = 1; i < len-1; i++) { int j = d1; - + for( - int k = i, n = d2; - (k&1) == 0; + int k = i, n = d2; + (k&1) == 0; j -= n, k >>= 1, n >>= 1 ); m += j; @@ -266,57 +263,57 @@ private void bitReversal(int[] array, int a, int b) { } private void unshuffle(int[] array, int a, int b) { //b-a is even int len = (b-a)>>1, c = 0; - + for(int n = 2; len > 0; len >>= 1, n *= 2) { if((len&1) == 1) { int a1 = a+c; - + this.bitReversal(array, a1, a1+n); this.bitReversal(array, a1, a1+n/2); this.bitReversal(array, a1+n/2, a1+n); this.rotate(array, a+c/2, a1, a1+n/2); - + c += n; } } } - + private void redistBuffer(int[] array, int[] tmp, int a, int m, int b) { int s = tmp.length; - + while(m-a > s && m < b) { int i = this.leftBinSearch(array, m, b, array[a+s]); this.rotate(array, a+s, m, i); - + int t = i-m; m = i; - + this.mergeFWExt(array, tmp, a, a+s, m); a += t+s; } if(m < b) this.mergeFWExt(array, tmp, a, m, b); } - + private void dualMergeBW(int[] array, int a, int m, int b, int p) { int i = m-1; b--; - + while(p > b+1 && b >= m) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[b], array[i]) >= 0) Writes.swap(array, --p, b--, 1, true, false); else Writes.swap(array, --p, i--, 1, true, false); } - + if(b < m) this.shiftBW(array, a, i+1, p); - + else { i++; b++; p = m-(i-a); - + while(a < i && m < b) { Highlights.markArray(2, m); - + if(Reads.compareValues(array[a], array[m]) <= 0) Writes.swap(array, p++, a++, 1, true, false); else @@ -327,24 +324,24 @@ private void dualMergeBW(int[] array, int a, int m, int b, int p) { } private void dualMergeBWExt(int[] array, int a, int m, int b, int p) { int i = m-1; b--; - + while(p > b+1 && b >= m) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[b], array[i]) >= 0) Writes.write(array, --p, array[b--], 1, true, false); else Writes.write(array, --p, array[i--], 1, true, false); } - + if(b < m) this.shiftBWExt(array, a, i+1, p); - + else { i++; b++; p = m-(i-a); - + while(a < i && m < b) { Highlights.markArray(2, m); - + if(Reads.compareValues(array[a], array[m]) <= 0) Writes.write(array, p++, array[a++], 1, true, false); else @@ -353,27 +350,27 @@ private void dualMergeBWExt(int[] array, int a, int m, int b, int p) { while(a < i) Writes.write(array, p++, array[a++], 1, true, false); } } - + private int smartMerge(int[] array, int p, int a, int m, boolean rev) { int i = m, cmp = rev ? 0 : 1; - + while(a < m) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[a], array[i]) < cmp) Writes.write(array, p++, array[a++], 1, true, false); else Writes.write(array, p++, array[i++], 1, true, false); } - + return i; } private void smartTailMerge(int[] array, int[] tmp, int p, int a, int m, int b) { int i = m, bLen = tmp.length; - + while(a < m && i < b) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[a], array[i]) <= 0) Writes.write(array, p++, array[a++], 1, true, false); else @@ -385,10 +382,10 @@ private void smartTailMerge(int[] array, int[] tmp, int p, int a, int m, int b) } else { a = 0; - + while(a < bLen && i < b) { Highlights.markArray(2, i); - + if(Reads.compareValues(tmp[a], array[i]) <= 0) Writes.write(array, p++, tmp[a++], 1, true, false); else @@ -399,22 +396,22 @@ private void smartTailMerge(int[] array, int[] tmp, int p, int a, int m, int b) } private void blockCycle(int[] array, int a, int t, int tIdx, int tLen, int bLen) { for(int i = 0; i < tLen-1; i++) { - if(Reads.compareValues(array[t+i], array[tIdx+i]) > 0 || + if(Reads.compareValues(array[t+i], array[tIdx+i]) > 0 || (i > 0 && Reads.compareValues(array[t+i], array[tIdx+i-1]) < 0)) { - + Writes.arraycopy(array, a+i*bLen, array, a-bLen, bLen, 1, true, false); - + int val = i, next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; - + do { Writes.arraycopy(array, a+next*bLen, array, a+val*bLen, bLen, 1, true, false); Writes.swap(array, t+i, t+next, 1, true, false); - + val = next; next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; } while(next != i); - + Writes.arraycopy(array, a-bLen, array, a+val*bLen, bLen, 1, true, false); } } @@ -425,11 +422,11 @@ private void blockMerge(int[] array, int[] tmp, int a, int m, int b, int tl, int this.mergeBWExt(array, tmp, a, m, b); return; } - + this.insertTo(array, t+tl-1, t); - + int i = a+bLen-1, j = m+bLen-1, ti = t, tj = t+tl, tp = tIdx; - + while(ti < t+tl && tj < t+tLen) { if(Reads.compareValues(array[i], array[j]) <= 0) { Writes.swap(array, tp++, ti++, 1, true, false); @@ -451,31 +448,31 @@ private void blockMerge(int[] array, int[] tmp, int a, int m, int b, int tl, int Writes.swap(array, bp1++, bp2++, 1, true, false); } t ^= tIdx; tIdx ^= t; t ^= tIdx; - + MaxHeapSort sortHeap = new MaxHeapSort(this.arrayVisualizer); sortHeap.customHeapSort(array, tIdx, tIdx+tLen, 1); - + Writes.arraycopy(array, m-bLen, tmp, 0, bLen, 1, true, true); Writes.arraycopy(array, a, array, m-bLen, bLen, 1, true, false); - + this.blockCycle(array, a+bLen, t, tIdx, tLen, bLen); this.multiSwap(array, t, tIdx, tLen); - + bp1 -= tLen; bp2 -= tLen; - + int f = a+bLen, a1 = f, bp3 = bp2+tLen; - + boolean rev = Reads.compareIndices(array, bp1, bp2, 1, true) > 0; - + while(true) { do { if(rev) Writes.swap(array, bp1, bp2, 1, true, false); - + bp1++; bp2++; a1 += bLen; } while(bp2 < bp3 && Reads.compareIndices(array, bp1, bp2, 1, true) == (rev ? 1 : -1)); - + if(bp2 == bp3) { this.smartTailMerge(array, tmp, f-bLen, f, rev ? f : a1, b); return; @@ -484,18 +481,18 @@ private void blockMerge(int[] array, int[] tmp, int a, int m, int b, int tl, int rev = !rev; } } - + private void blockCycleEasy(int[] array, int a, int t, int tIdx, int tLen, int bLen) { for(int i = 0; i < tLen-1; i++) { - if(Reads.compareValues(array[t+i], array[tIdx+i]) > 0 || + if(Reads.compareValues(array[t+i], array[tIdx+i]) > 0 || (i > 0 && Reads.compareValues(array[t+i], array[tIdx+i-1]) < 0)) { - + int next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; - + do { this.multiSwap(array, a+i*bLen, a+next*bLen, bLen); Writes.swap(array, t+i, t+next, 1, true, false); - + next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; } while(next != i); @@ -506,23 +503,23 @@ private int inPlaceMergeBW(int[] array, int a, int m, int b, boolean rev) { int f = rev ? this.rightBinSearch(array, m, b, array[m-1]) : this.leftBinSearch(array, m, b, array[m-1]); b = f; - + while(b > m && m > a) { int i = rev ? this.leftBinSearch(array, a, m, array[b-1]) : this.rightBinSearch(array, a, m, array[b-1]); - + this.rotate(array, i, m, b); - + int t = m-i; m = i; b -= t+1; - + if(m == a) break; - + b = rev ? this.rightBinSearch(array, m, b, array[m-1]) : this.leftBinSearch(array, m, b, array[m-1]); } - + return f; } private void blockMergeEasy(int[] array, int a, int m, int b, int lenA, int lenB, int tl, int tLen, int t, int tIdx, int bp1, int bp2, int bLen) { @@ -530,11 +527,11 @@ private void blockMergeEasy(int[] array, int a, int m, int b, int lenA, int lenB this.inPlaceMergeBW(array, a, m, b, false); return; } - + int a1 = a+lenA, b1 = b-lenB; - + int i = a1+bLen-1, j = m+bLen-1, ti = tIdx, tj = tIdx+tl, tp = t; - + while(ti < tIdx+tl && tj < tIdx+tLen) { if(Reads.compareValues(array[i], array[j]) <= 0) { Writes.swap(array, ti++, tp++, 1, true, false); @@ -556,215 +553,215 @@ private void blockMergeEasy(int[] array, int a, int m, int b, int lenA, int lenB Writes.swap(array, bp1++, bp2++, 1, true, false); } t ^= tIdx; tIdx ^= t; t ^= tIdx; - + MaxHeapSort sortHeap = new MaxHeapSort(this.arrayVisualizer); sortHeap.customHeapSort(array, tIdx, tIdx+tLen, 1); - + this.blockCycleEasy(array, a1, t, tIdx, tLen, bLen); this.multiSwap(array, t, tIdx, tLen); - + bp1 -= tLen; bp2 -= tLen; - + int f = a1, a2 = f, bp3 = bp2+tLen; - + boolean rev = Reads.compareIndices(array, bp1, bp2, 1, true) > 0; - + while(true) { do { if(rev) Writes.swap(array, bp1, bp2, 1, true, false); - + bp1++; bp2++; a2 += bLen; } while(bp2 < bp3 && Reads.compareIndices(array, bp1, bp2, 1, true) == (rev ? 1 : -1)); - + if(bp2 == bp3) { if(!rev) this.inPlaceMergeBW(array, a1, b1, b, false); this.inPlaceMerge(array, a, a1, b); - + return; } f = this.inPlaceMergeBW(array, f, a2, a2+bLen, rev); rev = !rev; } } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { int a = 0, b = currentLength, n = b-a; - + if(n < 128) { if(n < 32) this.binaryInsertion(array, a, b); - + else { FifthMergeSort smallSort = new FifthMergeSort(this.arrayVisualizer); smallSort.fifthMergeSort(array, n); } - + return; - } - + } + int cbrt = 2*ceilCbrt(n/4), bLen = 2*cbrt; int kLen = this.calcKeys(bLen, n); - + int[] tmp = Writes.createExternalArray(bLen); - + int keys = this.findKeys(array, tmp, a, b, 2*kLen, cbrt); - + if(keys < 8) { //need at least 8 keys to perform a block merge for(int j = 1; j < n; j *= 2) for(int i = a+j; i < b; i += 2*j) this.inPlaceMergeBW(array, i-j, i, Math.min(i+j, b), false); - + return; } else if(keys < 2*kLen) { keys -= keys%4; kLen = keys/2; } - + //bit buffer length always equal to key buffer length int a1 = a+keys, a2 = a1+keys, bSep = this.findBits(array, tmp, a1, b, kLen, cbrt); - + if(bSep == -1) { //if we cant find enough bits we dont have to sort this.laziestSortExt(array, tmp, a, a2); this.inPlaceMerge(array, a, a2, b); - + return; } - + //[a][ keys ][a1][ bits ][a2][extbuf][a3][main sequence][b] int a3 = a2+bLen, i, j = 1; n = b-a3; - + //advanced build blocks this.binaryInsertion(array, a2, a3); Writes.arraycopy(array, a2, tmp, 0, bLen, 1, true, true); - + for(; j < cbrt; j *= 2) { int p = Math.max(2, j); - + for(i = a3; i+2*j < b; i += 2*j) this.mergeWithBufFWExt(array, i, i+j, i+2*j, i-p); - + if(i+j < b) this.mergeWithBufFWExt(array, i, i+j, b, i-p); else this.shiftFWExt(array, i-p, i, b); - + a3 -= p; b -= p; } - + i = b-n%(2*j); - + if(i+j < b) this.mergeWithBufBWExt(array, i, i+j, b, b+j); else this.shiftBWExt(array, i, b, b+j); - + for(i -= 2*j; i >= a3; i -= 2*j) this.mergeWithBufBWExt(array, i, i+j, i+2*j, i+3*j); - + a3 += j; b += j; j *= 2; - + for(i = a3; i+2*j < b; i += 2*j) this.mergeWithBufFWExt(array, i, i+j, i+2*j, i-j); - + if(i+j < b) this.mergeWithBufFWExt(array, i, i+j, b, i-j); else this.shiftFWExt(array, i-j, i, b); - + a3 -= j; b -= j; j *= 2; - + i = b-n%(2*j); - + if(i+j < b) this.dualMergeBWExt(array, i, i+j, b, b+j/2); else this.shiftBWExt(array, i, b, b+j/2); - + for(i -= 2*j; i >= a3; i -= 2*j) this.dualMergeBWExt(array, i, i+j, i+2*j, i+2*j+j/2); - + a3 += j/2; b += j/2; j *= 2; - + //advanced build blocks (in-place using keys) if(keys >= j) { this.rotate(array, a, a1, a3); a2 = a1+bLen; - + if(kLen >= j) { for(int mLvl = 2*j; j < kLen; j *= 2) { int p = Math.max(mLvl, j); - + for(i = a3; i+2*j < b; i += 2*j) this.mergeWithBufFW(array, i, i+j, i+2*j, i-p); - + if(i+j < b) this.mergeWithBufFW(array, i, i+j, b, i-p); else this.shiftFW(array, i-p, i, b); - + a3 -= p; b -= p; } - + i = b-n%(2*j); - + if(i+j < b) this.mergeWithBufBW(array, i, i+j, b, b+j); else this.shiftBW(array, i, b, b+j); - + for(i -= 2*j; i >= a3; i -= 2*j) this.mergeWithBufBW(array, i, i+j, i+2*j, i+3*j); - + a3 += j; b += j; j *= 2; } if(keys >= j) { for(i = a3; i+2*j < b; i += 2*j) this.mergeWithBufFW(array, i, i+j, i+2*j, i-j); - + if(i+j < b) this.mergeWithBufFW(array, i, i+j, b, i-j); else this.shiftFW(array, i-j, i, b); - + a3 -= j; b -= j; j *= 2; - + i = b-n%(2*j); - + if(i+j < b) this.dualMergeBW(array, i, i+j, b, b+j/2); else this.shiftBW(array, i, b, b+j/2); - + for(i -= 2*j; i >= a3; i -= 2*j) this.dualMergeBW(array, i, i+j, i+2*j, i+2*j+j/2); - + a3 += j/2; b += j/2; j *= 2; } - + this.rotate(array, a, a2, a3); a2 = a1+keys; - + MaxHeapSort sortHeap = new MaxHeapSort(this.arrayVisualizer); sortHeap.customHeapSort(array, a, a1, 1); } Writes.arraycopy(tmp, 0, array, a2, bLen, 1, true, false); - + //main block merge this.unshuffle(array, a, a1); int limit = bLen*(kLen+2); - + for(int k = j/bLen-1; j < n && Math.min(2*j, n) <= limit; j *= 2, k = 2*k+1) { for(i = a3; i+2*j <= b; i += 2*j) this.blockMerge(array, tmp, i, i+j, i+2*j, k, 2*k, a, a+kLen, a1, a1+kLen, bLen); - + if(i+j < b) this.blockMerge(array, tmp, i, i+j, b, k, (b-i-1)/bLen-1, a, a+kLen, a1, a1+kLen, bLen); } - + //in-place block merge for(; j < n; j *= 2) { bLen = (2*j)/kLen; int lenA = j%bLen, lenB = lenA; - + for(i = a3; i+2*j <= b; i += 2*j) this.blockMergeEasy(array, i, i+j, i+2*j, lenA, lenB, kLen/2, kLen, a, a+kLen, a1, a1+kLen, bLen); - + if(i+j < b) this.blockMergeEasy(array, i, i+j, b, lenA, (b-i-j)%bLen, kLen/2, kLen/2+(b-i-j)/bLen, a, a+kLen, a1, a1+kLen, bLen); } - + //cleaning up this.multiSwap(array, a1+bSep, a1+kLen+bSep, kLen-bSep); //restore bit buffer initial position this.laziestSortExt(array, tmp, a, a3); this.redistBuffer(array, tmp, a, a3, b); - + Writes.deleteExternalArray(tmp); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/CircularGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/CircularGrailSort.java similarity index 94% rename from src/sorts/hybrid/CircularGrailSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/CircularGrailSort.java index d61d423d..857d3772 100644 --- a/src/sorts/hybrid/CircularGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/CircularGrailSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,52 +29,51 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class CircularGrailSort extends Sort { +public final class CircularGrailSort extends Sort { public CircularGrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Circular Grail"); this.setRunAllSortsName("Circular Grail Sort"); this.setRunSortName("Circular Grailsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int n; - + private void circSwap(int[] array, int a, int b) { Writes.swap(array, a%n, b%n, 1, true, false); } private int circCompareIndices(int[] array, int a, int b) { return Reads.compareValues(array[a%n], array[b%n]); } - + private void shiftFW(int[] array, int a, int m, int b) { while(m < b) this.circSwap(array, a++, m++); } private void shiftBW(int[] array, int a, int m, int b) { while(m > a) this.circSwap(array, --b, --m); } - + private void insertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) while(i > a && this.circCompareIndices(array, i-1, i) > 0) this.circSwap(array, i, --i); } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) this.circSwap(array, a+i, b+i); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -90,31 +89,31 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b) { if(this.circCompareIndices(array, i, j) > 0) { k = j; while(++k < b && this.circCompareIndices(array, i, k) > 0); - + this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } } - + private int merge(int[] array, int p, int a, int m, int b, boolean full) { int i = a, j = m; - + while(i < m && j < b) { if(this.circCompareIndices(array, i, j) <= 0) this.circSwap(array, p++, i++); - + else this.circSwap(array, p++, j++); } @@ -123,37 +122,37 @@ private int merge(int[] array, int p, int a, int m, int b, boolean full) { } else if(full) this.shiftFW(array, p, j, b); - + return i < m ? i : j; } - + private boolean blockLessThan(int[] array, int a, int b, int bLen) { int cmp = this.circCompareIndices(array, a, b); - + return cmp == -1 || (cmp == 0 && this.circCompareIndices(array, a+bLen-1, b+bLen-1) == -1); } - + private void blockMerge(int[] array, int a, int m, int b, int bLen) { int b1 = b-(b-m-1)%bLen-1; - + if(b1 > m) { int b2 = b1; - + for(int i = m-bLen; i > a && this.blockLessThan(array, b1, i, bLen); i -= bLen, b2 -= bLen); - + for(int j = a; j < b1-bLen; j += bLen) { int min = j; - + for(int i = min+bLen; i < b1; i += bLen) if(this.blockLessThan(array, i, min, bLen)) min = i; - + if(min != j) this.multiSwap(array, j, min, bLen); } int f = a; - + for(int i = a+bLen; i < b2; i += bLen) { f = this.merge(array, f-bLen, f, i, i+bLen, false); - + if(f < i) { this.shiftBW(array, f, i, i+bLen); f += bLen; @@ -163,21 +162,21 @@ private void blockMerge(int[] array, int a, int m, int b, int bLen) { } else this.merge(array, a-bLen, a, m, b, true); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.n = length; - + if(length <= 16) { this.insertion(array, 0, length); return; } - + int bLen = 1; for(; bLen*bLen < length; bLen *= 2); - + int i = bLen, j = 1, len = length-i, b = length; - + while(j <= bLen) { for(; i+2*j < b; i += 2*j) this.merge(array, i-j, i, i+j, i+2*j, true); @@ -185,7 +184,7 @@ public void runSort(int[] array, int length, int bucketCount) { this.merge(array, i-j, i, i+j, b, true); else this.shiftFW(array, i-j, i, b); - + i = b+bLen-j; b = i+len; j *= 2; @@ -197,14 +196,14 @@ public void runSort(int[] array, int length, int bucketCount) { this.blockMerge(array, i, i+j, b, bLen); else this.shiftFW(array, i-bLen, i, b); - + i = b; b += len; j *= 2; } this.insertion(array, i-bLen, i); this.inPlaceMerge(array, i-bLen, i, b); - + this.rotate(array, 0, (i-bLen)%n, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/CocktailMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/CocktailMergeSort.java similarity index 90% rename from src/sorts/hybrid/CocktailMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/CocktailMergeSort.java index 27b92d24..9b132cfd 100644 --- a/src/sorts/hybrid/CocktailMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/CocktailMergeSort.java @@ -1,14 +1,14 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.exchange.CocktailShakerSort; -import sorts.templates.Sort; -import sorts.templates.TimSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.exchange.CocktailShakerSort; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.sorts.templates.TimSorting; // Inspired by Sorting Stuff's "Obscure Sorting Algorithms": https://www.youtube.com/watch?v=fWubJgIWyxQ // Basically, "Cocktail Merge Sort" is a hybrid between Cocktail Shaker Sort and TimSort. It starts by building -// runs of TimSort's minimum length using Cocktail Shaker, then merges all these runs using TimSort. This +// runs of TimSort's minimum length using Cocktail Shaker, then merges all these runs using TimSort. This // effectively replaces Binary Insertion Sort, used for building runs in TimSort. Big-O analysis would still say // this is constant time, as the minrun value is not dependent on the number of elements we are sorting, but // Cocktail Shaker has worse constant factors than Insertion Sort. So basically, this is just for fun. @@ -20,27 +20,26 @@ public class CocktailMergeSort extends Sort { // more refactoring, which would be just doing unnecessary busy work. Instead of what we've done for // the rest of the algorithms, we'll favor composition over inheritance here and pass "util" objects // to it. - + public CocktailMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Cocktail Merge"); this.setRunAllSortsName("Cocktail Merge Sort"); this.setRunSortName("Cocktail Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { CocktailShakerSort cocktailShaker = new CocktailShakerSort(this.arrayVisualizer); int minRunLen = TimSorting.minRunLength(sortLength); - + if (sortLength == minRunLen) { cocktailShaker.runSort(array, sortLength, bucketCount); } @@ -52,11 +51,11 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti if (i + minRunLen > sortLength) { cocktailShaker.customSort(array, i, sortLength); } - + Highlights.clearAllMarks(); - + this.timSortInstance = new TimSorting(array, sortLength, this.arrayVisualizer); TimSorting.sort(this.timSortInstance, array, sortLength); } } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/DropMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/DropMergeSort.java similarity index 91% rename from src/sorts/hybrid/DropMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/DropMergeSort.java index 6cd243f0..f87b6fa1 100644 --- a/src/sorts/hybrid/DropMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/DropMergeSort.java @@ -1,14 +1,12 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import java.util.List; -import sorts.hybrid.PDQBranchedSort; - -import java.util.ArrayList; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 fungamer2 and Emil Ernerfeldt Permission is hereby granted, free of charge, to any person obtaining a copy @@ -29,46 +27,44 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class DropMergeSort extends Sort { +public final class DropMergeSort extends Sort { public DropMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Drop Merge"); this.setRunAllSortsName("Drop Merge Sort"); this.setRunSortName("Drop Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private final int RECENCY = 8; private final int EARLY_OUT_TEST_AT = 4; private final double EARLY_OUT_DISORDER_FRACTION = 0.6; - - private void truncateArrayList(ArrayList arrayList, int len) { + + private void truncateArrayList(List arrayList, int len) { int size = arrayList.size(); arrayList.subList(len, size).clear(); - Writes.changeAllocAmount(len - size); } - + @Override public void runSort(int[] array, int length, int bucketCount) { if (length < 2) return; - + PDQBranchedSort pdqSort = new PDQBranchedSort(arrayVisualizer); - ArrayList dropped = new ArrayList<>(length); - + List dropped = Writes.createArrayList(length); + int num_dropped_in_a_row = 0; int read = 0; int write = 0; - + int iteration = 0; int early_out_stop = length / EARLY_OUT_TEST_AT; - + while (read < length) { Highlights.markArray(2, read); iteration += 1; @@ -76,15 +72,16 @@ public void runSort(int[] array, int length, int bucketCount) { // We have seen a lot of the elements and dropped a lot of them. // This doesn't look good. Abort. Highlights.clearMark(2); - + for (int i = 0; i < dropped.size(); i++) { Writes.write(array, write++, dropped.get(i), 1, true, false); } Writes.arrayListClear(dropped); pdqSort.customSort(array, 0, length); + Writes.deleteArrayList(dropped); return; } - + if (write == 0 || Reads.compareIndices(array, read, write - 1, 0, false) >= 0) { // The element is order - keep it: Writes.write(array, write++, array[read++], 1, true, false); @@ -136,24 +133,24 @@ public void runSort(int[] array, int length, int bucketCount) { } } } - + Highlights.clearMark(2); - + for (int i = 0; i < dropped.size(); i++) { Writes.write(array, write + i, dropped.get(i), 1, true, false); } - + pdqSort.customSort(array, write, length); - - + + int[] buffer = Writes.createExternalArray(dropped.size()); - + Writes.arraycopy(array, write, buffer, 0, dropped.size(), 1, true, true); - + int i = buffer.length - 1; int j = write - 1; int k = length - 1; - + while (i >= 0) { if (j < 0 || Reads.compareValues(buffer[i], array[j]) == 1) { Writes.write(array, k--, buffer[i--], 1, true, false); @@ -162,7 +159,7 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.write(array, k--, array[j--], 1, true, false); } } - + Writes.deleteArrayList(dropped); Writes.deleteExternalArray(buffer); } diff --git a/src/sorts/hybrid/EctaSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/EctaSort.java similarity index 94% rename from src/sorts/hybrid/EctaSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/EctaSort.java index b12f110e..ee297349 100644 --- a/src/sorts/hybrid/EctaSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/EctaSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; -import sorts.insert.BinaryDoubleInsertionSort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryDoubleInsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -30,78 +30,77 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class EctaSort extends Sort { +public final class EctaSort extends Sort { public EctaSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Ecta"); this.setRunAllSortsName("Ecta Sort"); this.setRunSortName("Ectasort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int getMinRun(int n) { int mRun = n; for(; mRun >= 32; mRun = (mRun+1)/2); - + return mRun; } - + private void shift(int[] array, int a, int m, int b) { while(m < b) Writes.write(array, a++, array[m++], 1, true, false); } private void shiftBW(int[] array, int a, int m, int b) { while(m > a) Writes.write(array, --b, array[--m], 1, true, false); } - + private void mergeTo(int[] array, int a, int m, int b, int p) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.write(array, p++, array[i++], 1, true, false); - else + else Writes.write(array, p++, array[j++], 1, true, false); } while(i < m) Writes.write(array, p++, array[i++], 1, true, false); while(j < b) Writes.write(array, p++, array[j++], 1, true, false); } - + private void pingPongMerge(int[] array, int a, int m1, int m2, int m3, int b, int p) { int p1 = p + m2-a, pEnd = p + b-a; - + this.mergeTo(array, a, m1, m2, p); this.mergeTo(array, m2, m3, b, p1); this.mergeTo(array, p, p1, pEnd, a); } - + private void merge(int[] array, int a, int m, int b, int p) { int len = b-m, pEnd = p+len-1; Writes.arraycopy(array, m--, array, p, len, 1, true, false); - + while(m >= a && pEnd >= p) { if(Reads.compareValues(array[m], array[pEnd]) > 0) Writes.write(array, --b, array[m--], 1, true, false); - + else Writes.write(array, --b, array[pEnd--], 1, true, false); } while(pEnd >= p) Writes.write(array, --b, array[pEnd--], 1, true, false); } - + private void mergeFromBuf(int[] array, int[] buf, int a, int m, int b, int bufLen) { int i = 0; - + while(i < bufLen && m < b) { Highlights.markArray(2, i); - - if(Reads.compareValues(buf[i], array[m]) <= 0) + + if(Reads.compareValues(buf[i], array[m]) <= 0) Writes.write(array, a++, buf[i++], 1, true, false); else Writes.write(array, a++, array[m++], 1, true, false); @@ -111,78 +110,78 @@ private void mergeFromBuf(int[] array, int[] buf, int a, int m, int b, int bufLe Writes.write(array, a++, buf[i++], 1, true, false); } } - + private void dualMergeFromBufBW(int[] array, int[] buf, int a, int a1, int m, int b, int bufLen) { int i = bufLen-1; bufLen -= b-(m--); - + while(i >= bufLen && m >= a1) { Highlights.markArray(2, i); - - if(Reads.compareValues(buf[i], array[m]) > 0) + + if(Reads.compareValues(buf[i], array[m]) > 0) Writes.write(array, --b, buf[i--], 1, true, false); else Writes.write(array, --b, array[m--], 1, true, false); } if(m < a1) while(i >= 0) Writes.write(array, --b, buf[i--], 1, true, false); - else + else this.mergeFromBuf(array, buf, a, a1, b, bufLen); } - + private int mergeSort(int[] array, int a, int b, int p, int mRun, int bufLen) { BinaryDoubleInsertionSort smallSort = new BinaryDoubleInsertionSort(this.arrayVisualizer); int i = a, j = mRun; - + for(; i+j <= b; i += j) smallSort.customDoubleInsert(array, i, i+j, 0.5); smallSort.customDoubleInsert(array, i, b, 0.5); - + while(4*j <= bufLen) { for(i = a; i+4*j <= b; i += 4*j) this.pingPongMerge(array, i, i+j, i+2*j, i+3*j, i+4*j, p); - + if(i+3*j < b) this.pingPongMerge(array, i, i+j, i+2*j, i+3*j, b, p); else if(i+2*j < b) this.pingPongMerge(array, i, i+j, i+2*j, b, b, p); - else if(i+j < b) + else if(i+j < b) this.merge(array, i, i+j, b, p); - + j *= 4; } while(j <= bufLen) { for(i = a; i+2*j <= b; i += 2*j) this.merge(array, i, i+j, i+2*j, p); - - if(i+j < b) + + if(i+j < b) this.merge(array, i, i+j, b, p); - + j *= 2; } - + return j; } - + private void blockCycle(int[] array, int[] keys, int a, int bLen, int t, int p, boolean excl, boolean fw) { int s = fw ? bLen : -bLen; - + for(int i = 0; i < t; i++) { if(Reads.compareOriginalValues(i, keys[i]) != 0) { Writes.arraycopy(array, a + i*s, array, p, bLen, 1, true, false); int j = i, next = keys[i]; - + do { if(!(excl && j == t-1)) Writes.arraycopy(array, a + next*s, array, a + j*s, bLen, 1, true, false); Highlights.markArray(2, j); Writes.write(keys, j, j, 1, false, true); - + j = next; next = keys[next]; } while(Reads.compareOriginalValues(next, i) != 0); - + Writes.arraycopy(array, p, array, a + j*s, bLen, 1, true, false); Highlights.markArray(2, j); Writes.write(keys, j, j, 1, false, true); @@ -190,15 +189,15 @@ private void blockCycle(int[] array, int[] keys, int a, int bLen, int t, int p, } Highlights.clearMark(2); } - + private void ectaMergeFW(int[] array, int[] tags, int a, int m, int b, int bLen) { int i = a, j = m, t = 0, tc = 0; int[] s = {2*bLen, 0}; int[] p = {a-2*bLen, m}; - + do { int c = s[0] < bLen ? 1 : 0; - + for(int k = 0; k < bLen; k++) { if(i < m && j < b) { if(Reads.compareValues(array[i], array[j]) <= 0) { @@ -221,14 +220,14 @@ else if(i < m) { } p[c] += bLen; s[c] -= bLen; - + Highlights.markArray(2, tc); Writes.write(tags, tc++, c == 0 ? t++ : -1, 1, false, true); } while(i < m || j < b); - + if(s[0] > 0) Writes.write(tags, tc, t++, 1, false, true); - + for(int k = 2; k < tc; k++) { if(tags[k] == -1) { Highlights.markArray(2, k); @@ -241,10 +240,10 @@ private void ectaMergeBW(int[] array, int[] tags, int a, int m, int b, int bLen) int i = b-1, j = m-1, t = 0, tc = 0; int[] s = {2*bLen, 0}; int[] p = {b+2*bLen, m}; - + do { int c = s[0] < bLen ? 1 : 0; - + for(int k = 1; k <= bLen; k++) { if(i >= m && j >= a) { if(Reads.compareValues(array[i], array[j]) >= 0) { @@ -267,14 +266,14 @@ else if(i >= m) { } p[c] -= bLen; s[c] -= bLen; - + Highlights.markArray(2, tc); Writes.write(tags, tc++, c == 0 ? t++ : -1, 1, false, true); } while(i >= m || j >= a); - + if(s[0] > 0) Writes.write(tags, tc, t++, 1, false, true); - + for(int k = 2; k < tc; k++) { if(tags[k] == -1) { Highlights.markArray(2, k); @@ -283,7 +282,7 @@ else if(i >= m) { } this.blockCycle(array, tags, b+bLen, bLen, t, a, s[0] > 0, false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { if(length < 256) { @@ -294,70 +293,70 @@ public void runSort(int[] array, int length, int bucketCount) { else { int mRun = this.getMinRun(length), bufLen = length/2; int[] buf = Writes.createExternalArray(bufLen); - + Writes.arraycopy(array, bufLen, buf, 0, bufLen, 1, true, true); this.mergeSort(array, 0, bufLen, bufLen, mRun, bufLen); - + Writes.arraycopy(buf, 0, array, bufLen, bufLen, 1, true, false); Writes.arraycopy(array, 0, buf, 0, bufLen, 1, true, true); this.mergeSort(array, bufLen, length, 0, mRun, bufLen); - + this.mergeFromBuf(array, buf, 0, bufLen, length, bufLen); Writes.deleteExternalArray(buf); } return; } - + int mRun = this.getMinRun(length), bLen = mRun; for(; bLen*bLen < length/2; bLen *= 2); int bufLen = 2*bLen + length%bLen; - + int a = bufLen, b = length, len = b-a; - + int[] buf = Writes.createExternalArray(bufLen); int[] tags = Writes.createExternalArray(len/bLen+1); - + Writes.arraycopy(array, a, buf, 0, bufLen, 1, true, true); this.mergeSort(array, 0, a, a, this.getMinRun(bufLen), bufLen); - + Writes.arraycopy(buf, 0, array, a, bufLen, 1, true, false); Writes.arraycopy(array, 0, buf, 0, bufLen, 1, true, true); - + int i = a, j = this.mergeSort(array, a, b, 0, mRun, bufLen); boolean bw = false; - + while(j < len) { for(i = a; i+2*j <= b; i += 2*j) this.ectaMergeFW(array, tags, i, i+j, i+2*j, bLen); - + if(i+j < b) this.ectaMergeFW(array, tags, i, i+j, b, bLen); else this.shift(array, i-2*bLen, i, b); - + j *= 2; a -= 2*bLen; b -= 2*bLen; - + if(j >= len) { bw = true; break; } - + for(i = a; i+2*j <= b; i += 2*j); - + if(i+j < b) this.ectaMergeBW(array, tags, i, i+j, b, bLen); else this.shiftBW(array, i, b, b+2*bLen); - + for(i -= 2*j; i >= a; i -= 2*j) this.ectaMergeBW(array, tags, i, i+j, i+2*j, bLen); - + j *= 2; a += 2*bLen; b += 2*bLen; } if(bw) this.dualMergeFromBufBW(array, buf, 0, a, b, length, bufLen); else this.mergeFromBuf(array, buf, 0, a, b, bufLen); - + Writes.deleteExternalArray(buf); Writes.deleteExternalArray(tags); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/FifthMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/FifthMergeSort.java similarity index 94% rename from src/sorts/hybrid/FifthMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/FifthMergeSort.java index 4a1d6262..b0ff1332 100644 --- a/src/sorts/hybrid/FifthMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/FifthMergeSort.java @@ -1,8 +1,8 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.PatternDefeatingInsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* MIT License @@ -28,7 +28,7 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. */ -final public class FifthMergeSort extends Sort { +public final class FifthMergeSort extends Sort { protected final class IndexPair { public int aEnd, bEnd; @@ -38,16 +38,15 @@ public IndexPair(int aEnd, int bEnd) { } } - PatternDefeatingInsertionSort inserter; + BinaryInsertionSort inserter; public FifthMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Fifth Merge"); this.setRunAllSortsName("Fifth Merge Sort"); this.setRunSortName("Fifth Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -108,7 +107,7 @@ protected void mergeForwardsWithBuffer(int[] array, int[] buffer, int dest, int Delays.sleep(0.5); if (Reads.compareValueIndex(array, buffer[left], right, 0, false) <= 0) { Writes.write(array, dest++, buffer[left++], 0.5, true, false); - } else { + } else { Writes.write(array, dest++, array[right++], 0.5, true, false); } } @@ -158,10 +157,10 @@ protected void merge(int[] array, int[] buffer, int chunkOffset, int start, int protected void pingPong(int[] array, int[] buffer, int start, int end) { int i; for (i = start; i + 8 < end; i += 8) { - inserter.insertionSort(array, i, i + 8, 0.5, false); + inserter.customBinaryInsert(array, i, i + 8, 0.5); } if (end - i > 1) { - inserter.insertionSort(array, i, end, 0.5, false); + inserter.customBinaryInsert(array, i, end, 0.5); } int length = end - start; @@ -186,9 +185,9 @@ protected void pingPong(int[] array, int[] buffer, int start, int end) { Writes.arraycopy(buffer, 0, array, start, length, 0.5, true, false); } } - + public void fifthMergeSort(int[] array, int currentLength) { - inserter = new PatternDefeatingInsertionSort(arrayVisualizer); + inserter = new BinaryInsertionSort(arrayVisualizer); int fifthLen = currentLength / 5; int bufferLen = currentLength - fifthLen * 4; @@ -214,7 +213,7 @@ public void fifthMergeSort(int[] array, int currentLength) { Writes.deleteExternalArray(buffer); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { fifthMergeSort(array, currentLength); diff --git a/src/sorts/hybrid/FlanSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/FlanSort.java similarity index 82% rename from src/sorts/hybrid/FlanSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/FlanSort.java index 3d5db1d9..59ce93b3 100644 --- a/src/sorts/hybrid/FlanSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/FlanSort.java @@ -1,12 +1,12 @@ -package sorts.hybrid; - -import sorts.templates.MultiWayMergeSorting; -import main.ArrayVisualizer; +package io.github.arrayv.sorts.hybrid; import java.util.Random; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.MultiWayMergeSorting; + /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -31,235 +31,231 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class FlanSort extends MultiWayMergeSorting { +public final class FlanSort extends MultiWayMergeSorting { public FlanSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Flan"); this.setRunAllSortsName("Flan Sort"); this.setRunSortName("Flansort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - - //unstable sorting algorithm performing an average of + + //unstable sorting algorithm performing an average of //O(n log n) comparisons and O(n) moves in O(1) memory - + private final int G = 14; private final int R = 4; - + private int medianOfThree(int[] array, int a, int m, int b) { if(Reads.compareValues(array[m], array[a]) > 0) { if(Reads.compareValues(array[m], array[b]) < 0) return m; - if(Reads.compareValues(array[a], array[b]) > 0) return a; - else return b; } else { if(Reads.compareValues(array[m], array[b]) > 0) return m; - if(Reads.compareValues(array[a], array[b]) < 0) return a; - else return b; } } + //when shuffled the first 9 and 27 items will be accessed instead respectively private int ninther(int[] array, int a, int b) { int s = (b-a)/9; - - int a1 = this.medianOfThree(array, a, a + s, a + 2*s); - int m1 = this.medianOfThree(array, a + 3*s, a + 4*s, a + 5*s); - int b1 = this.medianOfThree(array, a + 6*s, a + 7*s, a + 8*s); - + + int a1 = this.medianOfThree(array, a, a+ s, a+2*s); + int m1 = this.medianOfThree(array, a+3*s, a+4*s, a+5*s); + int b1 = this.medianOfThree(array, a+6*s, a+7*s, a+8*s); + return this.medianOfThree(array, a1, m1, b1); } private int medianOfThreeNinthers(int[] array, int a, int b) { - int s = (b-a+2)/3; - - int a1 = this.ninther(array, a , a + s); - int m1 = this.ninther(array, a + s, a + 2*s); - int b1 = this.ninther(array, a + 2*s, b); - + int s = (b-a)/3; + + int a1 = this.ninther(array, a, a+s); + int m1 = this.ninther(array, a+s, a+2*s); + int b1 = this.ninther(array, a+2*s, b); + return this.medianOfThree(array, a1, m1, b1); } - + private void shiftBW(int[] array, int a, int m, int b) { while(m > a) Writes.swap(array, --b, --m, 1, true, false); } - + private int leftBlockSearch(int[] array, int a, int b, int val) { int s = G+1; - + while(a < b) { int m = a+(((b-a)/s)/2)*s; Highlights.markArray(3, m); Delays.sleep(0.25); - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; - else + else a = m+s; } - + Highlights.clearMark(3); return a; } private int rightBlockSearch(int[] array, int a, int b, int val) { int s = G+1; - + while(a < b) { int m = a+(((b-a)/s)/2)*s; Highlights.markArray(3, m); Delays.sleep(0.25); - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; - else + else a = m+s; } - + Highlights.clearMark(3); return a; } - + private int rightBinSearch(int[] array, int a, int b, int val, boolean bw) { int cmp = bw ? 1 : -1; - + while(a < b) { int m = a+(b-a)/2; Highlights.markArray(3, m); Delays.sleep(0.25); - - if(Reads.compareValues(val, array[m]) == cmp) + + if(Reads.compareValues(val, array[m]) == cmp) b = m; else a = m+1; } - + Highlights.clearMark(3); return a; } - + private void insertTo(int[] array, int tmp, int a, int b) { Highlights.clearMark(2); while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, tmp, 0.5, true, false); } - + private void binaryInsertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(array, array[i], i, this.rightBinSearch(array, a, i, array[i], false)); } - + private void kWayMerge(int[] array, int[] heap, int[] pa, int s, int b, int p, int size) { if(size < 2) { if(size == 1) while(pa[0] < b) Writes.swap(array, p++, pa[0]++, 1, true, false); return; } int a = pa[0]; - + for(int i = 0; i < size; i++) Writes.write(heap, i, i, 0, false, true); for(int i = (size-1)/2; i >= 0; i--) this.siftDown(array, heap, pa, heap[i], i, size); - + while(size > 0) { int min = heap[0]; - + Writes.swap(array, p++, pa[min], 0, true, false); Writes.write(pa, min, pa[min]+1, 1, false, true); if(pa[min] == Math.min(a+(min+1)*s, b)) this.siftDown(array, heap, pa, heap[--size], 0, size); - else + else this.siftDown(array, heap, pa, heap[0], 0, size); } } - + private void retrieve(int[] array, int i, int p, int pEnd, int bsv, boolean bw) { - int j = i-1, m; - + int j = i-1, m; + for(int k = pEnd-(G+1); k > p+G;) { m = this.rightBinSearch(array, k-G, k, bsv, bw)-1; k -= G+1; - + while(m >= k) Writes.swap(array, j--, m--, 1, true, false); } - + m = this.rightBinSearch(array, p, p+G, bsv, bw)-1; while(m >= p) Writes.swap(array, j--, m--, 1, true, false); } - + //buffer length is at least sortLength*(G+1)-1 private void librarySort(int[] array, int a, int b, int p, int bsv, boolean bw) { int len = b-a; - + if(len < 32) { this.binaryInsertion(array, a, b); return; } - + Random rng = new Random(); - + int s = len; while(s >= 32) s = (s-1)/R + 1; - + int i = a+s, j = a+R*s, pEnd = p + (s+1)*(G+1)+G; this.binaryInsertion(array, a, i); for(int k = 0; k < s; k++) //scatter elements to make G sized gaps b/w them Writes.swap(array, a+k, p + k*(G+1)+G, 1, true, false); - + while(i < b) { if(i == j) { //rebalancing (retrieve from buffer & rescatter) this.retrieve(array, i, p, pEnd, bsv, bw); - + s = i-a; pEnd = p + (s+1)*(G+1)+G; j = a+(j-a)*R; - - for(int k = 0; k < s; k++) + + for(int k = 0; k < s; k++) Writes.swap(array, a+k, p + k*(G+1)+G, 1, true, false); } - + int bLoc = this.leftBlockSearch(array, p+G, pEnd-(G+1), array[i]); //search gap location - + if(Reads.compareValues(array[i], array[bLoc]) == 0) { //handle equal values to prevent worst case O(n^2) int eqEnd = this.rightBlockSearch(array, bLoc+(G+1), pEnd-(G+1), array[i]); //find the endpoint of the gaps with equal head element bLoc += rng.nextInt((eqEnd-bLoc)/(G+1))*(G+1); //choose a random gap from the range of gaps } - + int loc = this.rightBinSearch(array, bLoc-G, bLoc, bsv, bw); //search next empty space in gap - + if(loc == bLoc) { //if there is no empty space filled elements in gap are split - do bLoc += G+1; + do bLoc += G+1; while(bLoc < pEnd && this.rightBinSearch(array, bLoc-G, bLoc, bsv, bw) == bLoc); - - if(bLoc == pEnd) { //rebalancing + + if(bLoc == pEnd) { //rebalancing this.retrieve(array, i, p, pEnd, bsv, bw); - + s = i-a; pEnd = p + (s+1)*(G+1)+G; j = a+(j-a)*R; - - for(int k = 0; k < s; k++) + + for(int k = 0; k < s; k++) Writes.swap(array, a+k, p + k*(G+1)+G, 1, true, false); } else { //if a gap is full find next non full gap to the right & shift the space down int rotP = this.rightBinSearch(array, bLoc-G, bLoc, bsv, bw); int rotS = bLoc - Math.max(rotP, bLoc - G/2); //for odd G whether its floor or ceil(G/2) doesnt matter - this.shiftBW(array, loc-rotS, bLoc-rotS, bLoc); + this.shiftBW(array, loc-rotS, bLoc-rotS, bLoc); } } else { @@ -270,57 +266,68 @@ private void librarySort(int[] array, int a, int b, int p, int bsv, boolean bw) } this.retrieve(array, b, p, pEnd, bsv, bw); } - + @Override public void runSort(int[] array, int length, int bucketCount) { //to benefit from worst case O(n log n) comparisons & O(n) moves //we would normally shuffle the array before sorting //but for the sake of demonstration this step is omitted - int[] pa = new int[G+2]; + int[] pa = new int[G+2]; int[] heap = new int[G+2]; - + int alloc = pa.length + heap.length; Writes.changeAllocAmount(alloc); - + int a = 0, b = length; - + while(b-a >= 32) { int piv = array[this.medianOfThreeNinthers(array, a, b)]; - + //partition -> [a][E > piv][i][E == piv][j][E < piv][b] - int i = a, j = b; - for(int k = i; k < j; k++) { - if(Reads.compareValues(array[k], piv) == 1) - Writes.swap(array, k, i++, 1, true, false); - - else if(Reads.compareValues(array[k], piv) == -1) { - do { - j--; - Highlights.markArray(3, j); - Delays.sleep(1); - } - while(j > k && Reads.compareValues(array[j], piv) == -1); - - Writes.swap(array, k, j, 1, true, false); - Highlights.clearMark(3); - - if(Reads.compareValues(array[k], piv) == 1) - Writes.swap(array, k, i++, 1, true, false); + int i1 = a, i = a-1, j = b, j1 = b; + + for(;;) { + while(++i < j) { + int cmp = Reads.compareIndexValue(array, i, piv, 0.5, true); + if(cmp == 0) Writes.swap(array, i1++, i, 1, true, false); + else if(cmp < 0) break; + } + Highlights.clearMark(2); + + while(--j > i) { + int cmp = Reads.compareIndexValue(array, j, piv, 0.5, true); + if(cmp == 0) Writes.swap(array, --j1, j, 1, true, false); + else if(cmp > 0) break; + } + Highlights.clearMark(2); + + if(i < j) { + Writes.swap(array, i, j, 1, true, false); + Highlights.clearMark(2); + } + else { + if(i1 == b) return; + else if(j < i) j++; + + while(i1 > a) Writes.swap(array, --i, --i1, 1, true, false); + while(j1 < b) Writes.swap(array, j++, j1++, 1, true, false); + + break; } } - + int left = i-a, right = b-j, m, kCnt = 0; - + if(left <= right) { //sort the smaller partition using larger partition as space m = b-left; left = Math.max((right+1)/(G+1), 16); - + for(int k = a; k < i; k += left) { this.librarySort(array, k, Math.min(k+left, i), j, piv, true); Writes.write(pa, kCnt++, k, 0, false, true); } - + this.kWayMerge(array, heap, pa, left, i, m, kCnt); - + //swap items eq to pivot next to sorted area //eq items zone: [i][E == piv][j][E < piv][m][sorted area] if(j-i < m-j) { @@ -335,14 +342,14 @@ else if(Reads.compareValues(array[k], piv) == -1) { else { m = a+right; right = Math.max((left+1)/(G+1), 16); - + for(int k = j; k < b; k += right) { this.librarySort(array, k, Math.min(k+right, b), a, piv, false); Writes.write(pa, kCnt++, k, 0, false, true); } - + this.kWayMerge(array, heap, pa, right, b, a, kCnt); - + //eq items zone: [sorted area][m][E > piv][i][E == piv][j] if(i-m < j-i) { while(m < i) Writes.swap(array, m++, --j, 1, true, false); @@ -357,4 +364,4 @@ else if(Reads.compareValues(array[k], piv) == -1) { this.binaryInsertion(array, a, b); Writes.changeAllocAmount(-alloc); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/FluxSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/FluxSort.java similarity index 95% rename from src/sorts/hybrid/FluxSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/FluxSort.java index 0c058294..8d4ec864 100644 --- a/src/sorts/hybrid/FluxSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/FluxSort.java @@ -1,7 +1,7 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.QuadSorting; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.QuadSorting; /* Copyright (C) 2014-2021 Igor van den Hoven ivdhoven@gmail.com @@ -26,7 +26,7 @@ a copy of this software and associated documentation files (the CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - + Ported to arrayV by mg-2018 and aphitorite, 2021 */ @@ -34,53 +34,52 @@ a copy of this software and associated documentation files (the fluxsort 1.1.3.3 */ -final public class FluxSort extends QuadSorting { +public final class FluxSort extends QuadSorting { public FluxSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Flux"); this.setRunAllSortsName("Flux Sort"); this.setRunSortName("Fluxsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private final int FLUX_OUT = 24; - + private boolean fluxAnalyze(int[] array, int nmemb) { int cnt, balance = 0; int pta; - + pta = 0; cnt = nmemb; - + while(--cnt > 0) if(Reads.compareIndices(array, pta, ++pta, 0.5, true) > 0) balance++; - + if(balance == 0) return false; - + if(balance == nmemb-1) { Writes.reversal(array, 0, nmemb-1, 1, true, false); return false; } - + if(balance <= nmemb / 6 || balance >= nmemb / 6 * 5) { this.quadSort(array, 0, nmemb); return false; } - + return true; } - + private int medianOfFive(int[] array, int v0, int v1, int v2, int v3, int v4) { int[] t = new int[4]; int val; - + val = (Reads.compareIndices(array, v0, v1, 1, true)+1)/2; t[0] = val; t[1] = val^1; val = (Reads.compareIndices(array, v0, v2, 1, true)+1)/2; t[0] += val; t[2] = val^1; val = (Reads.compareIndices(array, v0, v3, 1, true)+1)/2; t[0] += val; t[3] = val^1; @@ -103,7 +102,7 @@ private int medianOfFive(int[] array, int v0, int v1, int v2, int v3, int v4) { return t[3] == 2 ? v3 : v4; } - + private int medianOfThree(int[] array, int v0, int v1, int v2) { int[] t = new int[2]; int val; @@ -117,48 +116,48 @@ private int medianOfThree(int[] array, int v0, int v1, int v2) { return t[1] == 1 ? v1 : v2; } - + private int medianOfFifteen(int[] array, int ptx, int nmemb) { int v0, v1, v2, v3, v4, div = nmemb/16; - + v0 = this.medianOfThree(array, ptx+div*2, ptx+div*1, ptx+div*3); v1 = this.medianOfThree(array, ptx+div*5, ptx+div*4, ptx+div*6); v2 = this.medianOfThree(array, ptx+div*8, ptx+div*7, ptx+div*9); v3 = this.medianOfThree(array, ptx+div*11, ptx+div*10, ptx+div*12); v4 = this.medianOfThree(array, ptx+div*14, ptx+div*13, ptx+div*15); - + return this.medianOfFive(array, v2, v0, v1, v3, v4); } - + private int medianOfNine(int[] array, int ptx, int nmemb) { int v0, v1, v2, div = nmemb/16; - + v0 = this.medianOfThree(array, ptx+div*2, ptx+div*1, ptx+div*4); v1 = this.medianOfThree(array, ptx+div*8, ptx+div*6, ptx+div*10); v2 = this.medianOfThree(array, ptx+div*14, ptx+div*12, ptx+div*15); - + return this.medianOfThree(array, v0, v1, v2); } - + private void fluxPartition(int[] array, int[] swap, int[] main, int start, int nmemb) { int val; int aSize, sSize; int pta, pts, ptx, pte, piv; - + ptx = main == array ? start : 0; - + piv = main[nmemb > 1024 ? this.medianOfFifteen(main, ptx, nmemb) : this.medianOfNine(main, ptx, nmemb)]; - + pte = ptx+nmemb; - + pta = start; pts = 0; - + while(ptx < pte) { Highlights.markArray(3, ptx); val = (Reads.compareValues(main[ptx], piv)+1)/2; Delays.sleep(0.25); - + Writes.write(array, pta, main[ptx], 0.25, true, false); pta += val^1; Highlights.markArray(2, pts); Writes.write(swap, pts, main[ptx], 0.25, false, true); pts += val; @@ -166,10 +165,10 @@ private void fluxPartition(int[] array, int[] swap, int[] main, int start, int n ptx++; } Highlights.clearMark(3); - + sSize = pts; aSize = nmemb-sSize; - + if(aSize <= sSize/16 || sSize <= FLUX_OUT) { Writes.arraycopy(swap, 0, array, pta, sSize, 0.5, true, false); this.quadSortSwap(array, swap, pta, sSize); @@ -182,11 +181,11 @@ private void fluxPartition(int[] array, int[] swap, int[] main, int start, int n else this.fluxPartition(array, swap, array, start, aSize); } - + public void fluxsort(int[] array, int nmemb) { if(nmemb < 32) this.quadSort(array, 0, nmemb); - + else if(this.fluxAnalyze(array, nmemb)) { int[] swap = Writes.createExternalArray(nmemb); @@ -195,9 +194,9 @@ else if(this.fluxAnalyze(array, nmemb)) { Writes.deleteExternalArray(swap); } } - + @Override public void runSort(int[] array, int nmemb, int bucketCount) { this.fluxsort(array, nmemb); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/GrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/GrailSort.java similarity index 80% rename from src/sorts/hybrid/GrailSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/GrailSort.java index 96b6c473..aa59b07f 100644 --- a/src/sorts/hybrid/GrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/GrailSort.java @@ -1,10 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.GrailSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.GrailSorting; /* - * + * The MIT License (MIT) Copyright (c) 2013 Andrey Astrelin @@ -47,33 +48,25 @@ this software and associated documentation files (the "Software"), to deal in /* */ /*********************************************************/ -final public class GrailSort extends GrailSorting { +@SortMeta( + name = "Grail", + category = "Hybrid Sorts", + question = "Enter external buffer type (0 = in-place, 1 = static, 2 = dynamic):", + defaultAnswer = 0 +) +public final class GrailSort extends GrailSorting { public GrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Grail"); - //this.setRunAllID("Grail Sort (Block Merge Sort)"); - //this.setRunAllSortsName("Grail Sort [Block Merge Sort]"); - this.setRunAllSortsName("Grailsort"); - this.setRunSortName("Grailsort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - this.setQuestion("Enter external buffer type (0 = in-place, 1 = static, 2 = dynamic):", 0); } - + public void rotateLength(int[] array, int leftLength, int rightLength) { this.grailRotate(array, 0, leftLength, rightLength); } - + public void customSort(int[] array, int start, int end) { this.grailCommonSort(array, start, end, null, 0, 0); } - + @Override public void runSort(int[] array, int length, int bucketCount) { switch(bucketCount) { @@ -82,7 +75,7 @@ public void runSort(int[] array, int length, int bucketCount) { this.grailCommonSort(array, 0, length, ExtBuf, 0, this.getStaticBuffer()); Writes.deleteExternalArray(ExtBuf); break; - + case 2: int tempLen = 1; while(tempLen * tempLen < length) tempLen *= 2; @@ -90,9 +83,9 @@ public void runSort(int[] array, int length, int bucketCount) { this.grailCommonSort(array, 0, length, DynExtBuf, 0, tempLen); Writes.deleteExternalArray(DynExtBuf); break; - + default: this.grailCommonSort(array, 0, length, null, 0, 0); } } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/HybridCombSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/HybridCombSort.java similarity index 89% rename from src/sorts/hybrid/HybridCombSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/HybridCombSort.java index a5876268..ad61f878 100644 --- a/src/sorts/hybrid/HybridCombSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/HybridCombSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.CombSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.CombSorting; /* - * + * The MIT License (MIT) Copyright (c) 2012 Daniel Imms, http://www.growingwiththeweb.com @@ -28,15 +28,14 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class HybridCombSort extends CombSorting { +public final class HybridCombSort extends CombSorting { public HybridCombSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Hybrid Comb"); this.setRunAllSortsName("Hybrid Comb Sort"); this.setRunSortName("Hybrid Combsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -48,4 +47,4 @@ public HybridCombSort(ArrayVisualizer arrayVisualizer) { public void runSort(int[] array, int currentLength, int bucketCount) { this.combSort(array, currentLength, 1.3, true); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/ImprovedBlockSelectionSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ImprovedBlockSelectionSort.java similarity index 93% rename from src/sorts/hybrid/ImprovedBlockSelectionSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/ImprovedBlockSelectionSort.java index 37d40b3c..4ec1c4fd 100644 --- a/src/sorts/hybrid/ImprovedBlockSelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ImprovedBlockSelectionSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ImprovedBlockSelectionSort extends Sort { +public final class ImprovedBlockSelectionSort extends Sort { public ImprovedBlockSelectionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,28 +37,27 @@ public ImprovedBlockSelectionSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Improved Block Selection Merge Sort"); this.setRunSortName("Improved Block Selection Merge Sort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + public static int sqrt(int n) { int i = 1; for(; i*i < n; i*=2); return i; } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -74,71 +73,71 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private int inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b) { if(Reads.compareValues(array[i], array[j]) > 0) { k = j; do k++; while(k < b && Reads.compareIndices(array, i, k, 0, false) > 0); - + this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } - + return i; } - + private void inPlaceMergeBW(int[] array, int a, int m, int b) { int i = m-1, j = b-1, k; - + while(j > i && i >= a){ if(Reads.compareValues(array[i], array[j]) > 0) { k = i; do k--; while(k >= a && Reads.compareIndices(array, k, j, 0, false) > 0); - + this.rotate(array, k+1, i+1, j+1); - + j -= i-k; i = k; - } + } else j--; } } - + private int selectRange(int[] array, int a, int b, int bLen) { int min = a; a += bLen; - + while(a < b) { int comp = Reads.compareIndices(array, a, min, 0, false); - + if(comp == -1 || (comp == 0 && Reads.compareIndices(array, a+bLen-1, min+bLen-1, 0, false) == -1)) min = a; - + a += bLen; } return min; } - + private void blockSelect(int[] array, int a, int m, int b, int bLen) { int k = a, j = m; - + while(k < m && Reads.compareIndices(array, k, m, 0.5, true) <= 0) k += bLen; if(k == m) return; - + int i = m; this.multiSwap(array, k, j, bLen); k += bLen; j += bLen; - + while(k < j && j < b) { if(Reads.compareIndices(array, i, j, 0.5, true) <= 0) { if(k != i) this.multiSwap(array, k, i, bLen); @@ -159,27 +158,27 @@ private void blockSelect(int[] array, int a, int m, int b, int bLen) { k += bLen; } } - + @Override public void runSort(int[] array, int length, int bucketCount) { for(int i, j = 1; j < length; j *= 2) { int bLen = sqrt(j), n = j, b = length-length%bLen; - + while(n > 16) { for(i = 0; i+j < b; i += 2*j) for(int k = i; k+n < Math.min(i+2*j, b); k += n) this.blockSelect(array, k, k+n, Math.min(k+2*n, b), bLen); - + n = bLen; bLen = sqrt(bLen); } - + for(i = 0; i+j < b; i += 2*j) for(int k = i, f = i; k+n < Math.min(i+2*j, b); k += n) f = this.inPlaceMerge(array, f, k+n, Math.min(k+2*n, b)); - + this.inPlaceMergeBW(array, length-length%(2*j), b, length); } } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/IntroCircleSortIterative.java b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortIterative.java similarity index 84% rename from src/sorts/hybrid/IntroCircleSortIterative.java rename to src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortIterative.java index d1e71287..d179d484 100644 --- a/src/sorts/hybrid/IntroCircleSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortIterative.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.templates.IterativeCircleSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.templates.IterativeCircleSorting; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -16,15 +16,14 @@ * */ -final public class IntroCircleSortIterative extends IterativeCircleSorting { +public final class IntroCircleSortIterative extends IterativeCircleSorting { public IntroCircleSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Intro Circle (Iterative)"); this.setRunAllSortsName("Iterative Introspective Circle Sort"); this.setRunSortName("Iterative Introspective Circlesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -37,13 +36,13 @@ public void runSort(int[] array, int length, int bucketCount) { this.end = length; int threshold = 0, n = 1; for(; n < length; n*=2, threshold++); - + threshold /= 2; int iterations = 0; - + do { iterations++; - + if(iterations >= threshold) { BinaryInsertionSort binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); binaryInserter.customBinaryInsert(array, 0, length, 0.1); @@ -51,4 +50,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } while (this.circleSortRoutine(array, n, 1) != 0); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/IntroCircleSortRecursive.java b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortRecursive.java similarity index 84% rename from src/sorts/hybrid/IntroCircleSortRecursive.java rename to src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortRecursive.java index 09edbefe..1bbfe44c 100644 --- a/src/sorts/hybrid/IntroCircleSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortRecursive.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.templates.CircleSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.templates.CircleSorting; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -16,15 +16,14 @@ * */ -final public class IntroCircleSortRecursive extends CircleSorting { +public final class IntroCircleSortRecursive extends CircleSorting { public IntroCircleSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Intro Circle (Recursive)"); this.setRunAllSortsName("Recursive Introspective Circle Sort"); this.setRunSortName("Introspective Circlesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -37,13 +36,13 @@ public void runSort(int[] array, int length, int bucketCount) { this.end = length; int threshold = 0, n = 1; for(; n < length; n*=2, threshold++); - + threshold /= 2; int iterations = 0; - + do { iterations++; - + if(iterations >= threshold) { BinaryInsertionSort binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); binaryInserter.customBinaryInsert(array, 0, length, 0.1); @@ -51,4 +50,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } while (this.circleSortRoutine(array, 0, n - 1, 0, 1) != 0); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/IntroSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/IntroSort.java similarity index 90% rename from src/sorts/hybrid/IntroSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/IntroSort.java index 885bfaa5..8e808b09 100644 --- a/src/sorts/hybrid/IntroSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/IntroSort.java @@ -1,30 +1,29 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.select.MaxHeapSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.select.MaxHeapSort; +import io.github.arrayv.sorts.templates.Sort; -// original Copyright Ralph Unden, +// original Copyright Ralph Unden, // http://ralphunden.net/content/tutorials/a-guide-to-introsort/?q=a-guide-to-introsort -// Modifications: Bernhard Pfahringer +// Modifications: Bernhard Pfahringer // changes include: local insertion sort, no global array -final public class IntroSort extends Sort { +public final class IntroSort extends Sort { private MaxHeapSort heapSorter; private int middle; private int sizeThreshold = 16; - + public IntroSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Intro"); //this.setRunAllID("Introspective Sort (std::sort)"); this.setRunAllSortsName("Introspective Sort"); this.setRunSortName("Introsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -35,9 +34,10 @@ public IntroSort(ArrayVisualizer arrayVisualizer) { private static int floorLogBaseTwo(int a) { return (int) (Math.floor(Math.log(a) / Math.log(2))); } - + // Swaps the median of arr[left], arr[mid], and arr[right] to index left. // taken from gcc source code found here: https://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/api/a01462_source.html + @SuppressWarnings("unused") private int gccmedianof3(int[] arr, int left, int mid, int right) { if (Reads.compareValues(arr[left], arr[mid]) < 0) { if (Reads.compareValues(arr[mid], arr[right]) < 0) { @@ -62,10 +62,10 @@ else if (Reads.compareValues(arr[mid], arr[right]) < 0) { Highlights.markArray(3, left); return arr[left]; } - + private int medianof3(int[] arr, int left, int mid, int right) { if(Reads.compareValues(arr[right], arr[left]) == -1) { - Writes.swap(arr, left, right, 1, true, false); + Writes.swap(arr, left, right, 1, true, false); } if(Reads.compareValues(arr[mid], arr[left]) == -1) { Writes.swap(arr, mid, left, 1, true, false); @@ -77,7 +77,7 @@ private int medianof3(int[] arr, int left, int mid, int right) { Highlights.markArray(3, mid); return arr[mid]; } - + private int partition(int[] a, int lo, int hi, int x) { int i = lo, j = hi; while (true) { @@ -113,7 +113,7 @@ private int partition(int[] a, int lo, int hi, int x) { i++; } } - + private void introsortLoop (int[] a, int lo, int hi, int depthLimit) { while (hi - lo > sizeThreshold) { if (depthLimit == 0) { @@ -128,7 +128,7 @@ private void introsortLoop (int[] a, int lo, int hi, int depthLimit) { } return; } - + @Override public void runSort(int[] array, int length, int bucketCount) { heapSorter = new MaxHeapSort(this.arrayVisualizer); @@ -139,4 +139,4 @@ public void runSort(int[] array, int length, int bucketCount) { InsertionSort sort = new InsertionSort(this.arrayVisualizer); sort.customInsertSort(array, 0, length, 0.5, false); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/KotaSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/KotaSort.java similarity index 82% rename from src/sorts/hybrid/KotaSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/KotaSort.java index be82b1e0..eaa53c58 100644 --- a/src/sorts/hybrid/KotaSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/KotaSort.java @@ -1,26 +1,25 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.KotaSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.KotaSorting; -final public class KotaSort extends KotaSorting { +public final class KotaSort extends KotaSorting { public KotaSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Kota"); //this.setRunAllID("Grail Sort (Block Merge Sort)"); //this.setRunAllSortsName("Grail Sort [Block Merge Sort]"); this.setRunAllSortsName("Kotasort"); this.setRunSortName("Kotasort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { if(Delays.getSleepRatio() == 55.1) { @@ -31,4 +30,4 @@ public void runSort(int[] array, int length, int bucketCount) { this.kotaSort(array, 0, length); } } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/LazierestSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/LazierestSort.java similarity index 92% rename from src/sorts/hybrid/LazierestSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/LazierestSort.java index 0bf84750..b884680a 100644 --- a/src/sorts/hybrid/LazierestSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/LazierestSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; -import utils.IndexedRotations; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.utils.IndexedRotations; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -30,49 +30,48 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class LazierestSort extends Sort { +public final class LazierestSort extends Sort { public LazierestSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); this.setSortListName("Lazierest Stable"); this.setRunAllSortsName("Lazierest Stable Sort"); this.setRunSortName("Lazierest Sort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int ceilCbrt(int n) { int a = 0, b = Math.min(1291, n); - + while(a < b) { int m = (a+b)/2; - + if(m*m*m >= n) b = m; else a = m+1; } - + return a; } - + private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -88,75 +87,75 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private int leftBinSearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; - else + else a = m+1; } - + return a; } private int rightBinSearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; - else + else a = m+1; } - + return a; } - + private int leftExpSearch(int[] array, int a, int b, int val) { int i = 1; while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) > 0) i *= 2; - + return this.leftBinSearch(array, a+i/2, Math.min(b, a-1+i), val); } private int rightExpSearch(int[] array, int a, int b, int val) { int i = 1; while(b-i >= a && Reads.compareValues(val, array[b-i]) < 0) i *= 2; - + return this.rightBinSearch(array, Math.max(a, b-i+1), b-i/2, val); } - + private void binaryInsertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); } - + private void inPlaceMergeFW(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b){ if(Reads.compareValues(array[i], array[j]) == 1) { k = this.leftExpSearch(array, j+1, b, array[i]); IndexedRotations.cycleReverse(array, i, j, k, 0.75, true, false); - + i += k-j; j = k; - } + } else i++; } } private void inPlaceMergeBW(int[] array, int a, int m, int b) { int i = m-1, j = b-1, k; - + while(j > i && i >= a){ if(Reads.compareValues(array[i], array[j]) > 0) { k = this.rightExpSearch(array, a, i, array[j]); this.rotate(array, k, i+1, j+1); - + j -= (i+1)-k; i = k-1; - } + } else j--; } } @@ -164,32 +163,32 @@ private void inPlaceMerge(int[] array, int a, int m, int b) { if(b-m < m-a) this.inPlaceMergeBW(array, a, m, b); else this.inPlaceMergeFW(array, a, m, b); } - + private void fragmentedMerge(int[] array, int a, int m, int b, int s) { int i = a+(m-a)%s; - + while(i < m) { int j = this.leftExpSearch(array, m, b, array[i]); IndexedRotations.cycleReverse(array, i, m, j, 0.75, true, false); - + int rLen = j-m; j = i; i += rLen; m += rLen; - + this.inPlaceMerge(array, a, j, i); a = i; i += s; } this.inPlaceMerge(array, Math.max(a, i-s), i, b); } - + public void lazierestStableSort(int[] array, int a, int b) { int len = b-a, s = this.ceilCbrt(len), s1 = s*s; - + for(int i = len%s; i <= b; i += s) this.binaryInsertion(array, Math.max(a, i-s), i); - + for(int i = b-s, j = b; i > a; i -= s) { if(j-i == s1) { j -= s1; @@ -197,14 +196,14 @@ public void lazierestStableSort(int[] array, int a, int b) { } this.inPlaceMergeFW(array, Math.max(a, i-s), i, j); } - + for(int i = b-s1; i > a; i -= s1) this.fragmentedMerge(array, Math.max(a, i-s1), i, b, s); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { if(currentLength <= 16) this.binaryInsertion(array, 0, currentLength); else this.lazierestStableSort(array, 0, currentLength); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/LaziestSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/LaziestSort.java similarity index 90% rename from src/sorts/hybrid/LaziestSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/LaziestSort.java index 6468fc4a..bcfb5da3 100644 --- a/src/sorts/hybrid/LaziestSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/LaziestSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,36 +29,35 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class LaziestSort extends Sort { +public final class LaziestSort extends Sort { public LaziestSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); this.setSortListName("Laziest Stable"); this.setRunAllSortsName("Laziest Stable Sort"); this.setRunSortName("Laziest Sort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -74,81 +73,81 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private int leftBinSearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; - else + else a = m+1; } - + return a; } - + private int rightBinSearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; - else + else a = m+1; } - + return a; } - + private int leftExpSearch(int[] array, int a, int b, int val) { int i = 1; while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) > 0) i *= 2; - + return this.leftBinSearch(array, a+i/2, Math.min(b, a-1+i), val); } - + private void binaryInsertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); } - + private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b){ if(Reads.compareValues(array[i], array[j]) == 1) { k = this.leftExpSearch(array, j+1, b, array[i]); this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } } - + protected void laziestStableSort(int[] array, int start, int end) { int len = end - start; if(len <= 16) { this.binaryInsertion(array, start, end); return; } - + int i, blockLen = Math.max(16, (int)Math.sqrt(len)); for(i = start; i+2*blockLen < end; i+=blockLen) { this.binaryInsertion(array, i, i+blockLen); } this.binaryInsertion(array, i, end); - - while(i-blockLen >= start) { + + while(i-blockLen >= start) { this.inPlaceMerge(array, i-blockLen, i, end); i-=blockLen; } } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.laziestStableSort(array, 0, currentLength); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/MedianMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/MedianMergeSort.java similarity index 94% rename from src/sorts/hybrid/MedianMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/MedianMergeSort.java index f197d118..7bc22ad3 100644 --- a/src/sorts/hybrid/MedianMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/MedianMergeSort.java @@ -1,13 +1,12 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.Sort; -import sorts.insert.BinaryInsertionSort; -import sorts.insert.InsertionSort; - -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 yuji, implemented by aphitorite @@ -32,46 +31,45 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class MedianMergeSort extends Sort { +public final class MedianMergeSort extends Sort { public MedianMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Median Merge"); this.setRunAllSortsName("Median Mergesort"); this.setRunSortName("Median Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private InsertionSort insSort; private BinaryInsertionSort binInsSort; - + private void medianOfThree(int[] array, int a, int b) { int m = a+(b-1-a)/2; - + if(Reads.compareIndices(array, a, m, 1, true) == 1) Writes.swap(array, a, m, 1, true, false); - + if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { Writes.swap(array, m, b-1, 1, true, false); - + if(Reads.compareIndices(array, a, m, 1, true) == 1) return; } - + Writes.swap(array, a, m, 1, true, false); } - + //lite version private void medianOfMedians(int[] array, int a, int b, int s) { int end = b, start = a, i, j; boolean ad = true; - + while(end - start > 1) { j = start; Highlights.markArray(2, j); @@ -89,12 +87,12 @@ private void medianOfMedians(int[] array, int a, int b, int s) { end = j; } } - + public int partition(int[] array, int a, int b, int p) { int i = a - 1; int j = b; Highlights.markArray(3, p); - + while(true) { do { i++; @@ -102,48 +100,48 @@ public int partition(int[] array, int a, int b, int p) { Delays.sleep(0.5); } while(i < j && Reads.compareIndices(array, i, p, 0, false) == -1); - + do { j--; Highlights.markArray(2, j); Delays.sleep(0.5); } while(j >= i && Reads.compareIndices(array, j, p, 0, false) == 1); - + if(i < j) Writes.swap(array, i, j, 1, true, false); else return j; } } - + private void merge(int[] array, int a, int m, int b, int p) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); - else + else Writes.swap(array, p++, j++, 1, true, false); } - + while(i < m) Writes.swap(array, p++, i++, 1, true, false); while(j < b) Writes.swap(array, p++, j++, 1, true, false); } - + public static int getMinLevel(int n) { while(n >= 32) n = (n+3)/4; return n; } - + private void mergeSort(int[] array, int a, int b, int p) { int length = b-a; if(length < 2) return; - + int i, pos, j = getMinLevel(length); - + for(i = a; i+j <= b; i+=j) this.binInsSort.customBinaryInsert(array, i, i+j, 0.25); this.binInsSort.customBinaryInsert(array, i, b, 0.25); - + while(j < length) { pos = p; for(i = a; i+2*j <= b; i+=2*j, pos+=2*j) @@ -152,9 +150,9 @@ private void mergeSort(int[] array, int a, int b, int p) { this.merge(array, i, i+j, b, pos); else while(i < b) Writes.swap(array, i++, pos++, 1, true, false); - + j *= 2; - + pos = a; for(i = p; i+2*j <= p+length; i+=2*j, pos+=2*j) this.merge(array, i, i+j, i+2*j, pos); @@ -162,29 +160,29 @@ private void mergeSort(int[] array, int a, int b, int p) { this.merge(array, i, i+j, p+length, pos); else while(i < p+length) Writes.swap(array, i++, pos++, 1, true, false); - + j *= 2; } } - + private void medianMergeSort(int[] array, int a, int b) { int start = a, end = b; boolean badPartition = false, mom = false; - + while(end - start > 16) { if(badPartition) { this.medianOfMedians(array, start, end, 5); mom = true; } else this.medianOfThree(array, start, end); - + int p = this.partition(array, start+1, end, start); Writes.swap(array, start, p, 1, true, false); - + int left = p-start; int right = end-(p+1); badPartition = !mom && ((left == 0 || right == 0) || (left/right >= 16 || right/left >= 16)); - + if(left <= right) { this.mergeSort(array, start, p, p+1); start = p+1; @@ -196,11 +194,11 @@ private void medianMergeSort(int[] array, int a, int b) { } this.binInsSort.customBinaryInsert(array, start, end, 0.25); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.insSort = new InsertionSort(this.arrayVisualizer); this.binInsSort = new BinaryInsertionSort(this.arrayVisualizer); this.medianMergeSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/MergeInsertionSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/MergeInsertionSort.java similarity index 92% rename from src/sorts/hybrid/MergeInsertionSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/MergeInsertionSort.java index c90b4407..67e72368 100644 --- a/src/sorts/hybrid/MergeInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/MergeInsertionSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class MergeInsertionSort extends Sort { +public final class MergeInsertionSort extends Sort { public MergeInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,25 +37,24 @@ public MergeInsertionSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Merge-Insertion Sort"); this.setRunSortName("Merge-Insertsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void blockSwap(int[] array, int a, int b, int s, double sleep) { while(s-- > 0) Writes.swap(array, a--, b--, sleep, true, false); } - + private void blockInsert(int[] array, int a, int b, int s, double sleep) { while(a-s >= b) { this.blockSwap(array, a-s, a, s, sleep); a -= s; } } - + private void blockReversal(int[] array, int a, int b, int s, double sleep) { b -= s; while(b > a) { @@ -64,28 +63,28 @@ private void blockReversal(int[] array, int a, int b, int s, double sleep) { b -= s; } } - + private int blockSearch(int[] array, int a, int b, int s, int val) { while(a < b) { int m = a+(((b-a)/s)/2)*s; - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; else a = m+s; } - + return a; } - + private void order(int[] array, int a, int b, int s, double sleep) { for(int i = a, j = i+s; j < b; i+=s, j+=2*s) this.blockInsert(array, j, i, s, sleep); - + int m = a+(((b-a)/s)/2)*s; this.blockReversal(array, m, b, s, 1); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int k = 1; @@ -93,23 +92,23 @@ public void runSort(int[] array, int length, int bucketCount) { for(int i = 2*k-1; i < length; i+=2*k) if(Reads.compareValues(array[i-k], array[i]) > 0) this.blockSwap(array, i-k, i, k, 1); - + k *= 2; } - + double delay = 12; while(k > 0) { int a = k-1, i = a+2*k, g = 2, p = 4; double sleep = Math.min(1, delay); - + while(i+2*k*g-k <= length) { this.order(array, i, i+2*k*g-k, k, sleep); int b = a+k*(p-1); - + i += k*g-k; for(int j = i; j < i+k*g; j+=k) this.blockInsert(array, j, this.blockSearch(array, a, b, k, array[j]), k, sleep); - + i += k*g+k; g = p-g; p *= 2; @@ -118,9 +117,9 @@ public void runSort(int[] array, int length, int bucketCount) { this.blockInsert(array, i, this.blockSearch(array, a, i, k, array[i]), k, sleep); i += 2*k; } - + k /= 2; delay /= 2; } } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/OptimizedBottomUpMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedBottomUpMergeSort.java similarity index 94% rename from src/sorts/hybrid/OptimizedBottomUpMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/OptimizedBottomUpMergeSort.java index f04871c5..5bfcd73f 100644 --- a/src/sorts/hybrid/OptimizedBottomUpMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedBottomUpMergeSort.java @@ -1,26 +1,25 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.templates.Sort; -final public class OptimizedBottomUpMergeSort extends Sort { +public final class OptimizedBottomUpMergeSort extends Sort { public OptimizedBottomUpMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Bottom-Up Merge"); //this.setRunAllID("Bottom-Up Merge Sort w/ Binary Insert (std::stable_sort)"); this.setRunAllSortsName("Optimized Bottom-Up Merge Sort [std::stable_sort]"); this.setRunSortName("Bottom-Up Mergesort w/ Binary Insert"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + /** * Iterative merge sort algorithm --- as a static method @@ -99,7 +98,7 @@ private void mergePass (int[] x, int[] y, int s, int n, boolean activeSound) Writes.write(y, j, x[j], 1, false, activeSound); // copy last segment to y Highlights.markArray(1, j); Highlights.clearMark(2); - } + } }// end mergePass() @@ -109,12 +108,12 @@ private void mergePass (int[] x, int[] y, int s, int n, boolean activeSound) */ private void stableSort (int[] a, int n) { BinaryInsertionSort binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); - + if(n < 16) { binaryInserter.customBinaryInsert(a, 0, 16, 0.35); return; } - + // Sort a[0:n-1] using merge sort. int s = 16; // segment size int[] b = Writes.createExternalArray(n); @@ -137,9 +136,9 @@ private void stableSort (int[] a, int n) { Writes.deleteExternalArray(b); }// end MergeArray class - + @Override public void runSort(int[] array, int length, int bucketCount) { this.stableSort(array, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/OptimizedDualPivotQuickSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedDualPivotQuickSort.java similarity index 60% rename from src/sorts/hybrid/OptimizedDualPivotQuickSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/OptimizedDualPivotQuickSort.java index 01cf887f..b3ada1e1 100644 --- a/src/sorts/hybrid/OptimizedDualPivotQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedDualPivotQuickSort.java @@ -1,54 +1,53 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; // code retrieved from https://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf // written by Vladimir Yaroslavskiy -final public class OptimizedDualPivotQuickSort extends Sort { +public final class OptimizedDualPivotQuickSort extends Sort { private InsertionSort insertSorter; - + public OptimizedDualPivotQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Dual-Pivot Quick"); //this.setRunAllID("Optimized Dual-Pivot Quick Sort"); this.setRunAllSortsName("Optimized Dual-Pivot Quick Sort [Arrays.sort]"); this.setRunSortName("Optimized Dual-Pivot Quicksort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void dualPivot(int[] array, int left, int right, int divisor) { int length = right - left; - + // insertion sort for tiny array if(length < 27) { Highlights.clearMark(2); insertSorter.customInsertSort(array, left, right + 1, 0.333, false); return; } - + int third = length / divisor; - + // "medians" int med1 = left + third; int med2 = right - third; - + if(med1 <= left) { med1 = left + 1; } if(med2 >= right) { med2 = right - 1; } - if(Reads.compareValues(array[med1], array[med2]) == -1) { + if(Reads.compareIndices(array, med1, med2, 1, true) == -1) { Writes.swap(array, med1, left, 1, true, false); Writes.swap(array, med2, right, 1, true, false); } @@ -56,64 +55,77 @@ private void dualPivot(int[] array, int left, int right, int divisor) { Writes.swap(array, med1, right, 1, true, false); Writes.swap(array, med2, left, 1, true, false); } - + // pivots int pivot1 = array[left]; int pivot2 = array[right]; - + // pointers int less = left + 1; int great = right - 1; - + + Highlights.markArray(2, less); + Highlights.markArray(3, great); + // sorting for(int k = less; k <= great; k++) { - if(Reads.compareValues(array[k], pivot1) == -1) { - Writes.swap(array, k, less++, 1, true, false); + if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == -1) { + Writes.swap(array, k, less++, 0.5, false, false); + Highlights.markArray(2, less); } - else if(Reads.compareValues(array[k], pivot2) == 1) { - while(k < great && Reads.compareValues(array[great], pivot2) == 1) { + else if(Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 1) { + while(k < great && Reads.compareIndexValue(array, great, pivot2, 0.5, false) == 1) { great--; Highlights.markArray(3, great); - Delays.sleep(1); + Delays.sleep(0.5); } - Writes.swap(array, k, great--, 1, true, false); - Highlights.clearMark(3); - - if(Reads.compareValues(array[k], pivot1) == -1) { - Writes.swap(array, k, less++, 1, true, false); + Writes.swap(array, k, great--, 0.5, false, false); + Highlights.markArray(3, great); + + if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == -1) { + Writes.swap(array, k, less++, 0.5, false, false); + Highlights.markArray(2, less); } } } - + Highlights.clearAllMarks(); + // swaps int dist = great - less; - + if(dist < 13) { divisor++; } Writes.swap(array, less - 1, left, 1, true, false); Writes.swap(array, great + 1, right, 1, true, false); - + // subarrays this.dualPivot(array, left, less - 2, divisor); this.dualPivot(array, great + 2, right, divisor); - + + Highlights.markArray(2, less); + Highlights.markArray(3, great); + // equal elements if(dist > length - 13 && pivot1 != pivot2) { for(int k = less; k <= great; k++) { - if(Reads.compareValues(array[k], pivot1) == 0) { - Writes.swap(array, k, less++, 1, true, false); + if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == 0) { + Writes.swap(array, k, less++, 0.5, false, false); + Highlights.markArray(2, less); } - else if(Reads.compareValues(array[k], pivot2) == 0) { - Writes.swap(array, k, great--, 1, true, false); - - if(Reads.compareValues(array[k], pivot1) == 0) { - Writes.swap(array, k, less++, 1, true, false); + else if(Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 0) { + Writes.swap(array, k, great--, 0.5, false, false); + Highlights.markArray(3, great); + + if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == 0) { + Writes.swap(array, k, less++, 0.5, false, false); + Highlights.markArray(2, less); } } } } - + Highlights.clearAllMarks(); + // subarray if(pivot1 < pivot2) { this.dualPivot(array, less, great, divisor); @@ -125,4 +137,4 @@ public void runSort(int[] array, int currentLength, int bucketCount) { this.insertSorter = new InsertionSort(this.arrayVisualizer); this.dualPivot(array, 0, currentLength - 1, 3); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/OptimizedLazyStableSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedLazyStableSort.java similarity index 69% rename from src/sorts/hybrid/OptimizedLazyStableSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/OptimizedLazyStableSort.java index a4bde038..686b0585 100644 --- a/src/sorts/hybrid/OptimizedLazyStableSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedLazyStableSort.java @@ -1,11 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.PatternDefeatingInsertionSort; -import sorts.templates.GrailSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.GrailSorting; /* - * + * The MIT License (MIT) Copyright (c) 2013 Andrey Astrelin @@ -39,15 +38,14 @@ this software and associated documentation files (the "Software"), to deal in /* */ /*****************************************/ -final public class OptimizedLazyStableSort extends GrailSorting { +public final class OptimizedLazyStableSort extends GrailSorting { public OptimizedLazyStableSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Lazy Stable"); this.setRunAllSortsName("Optimized Lazy Stable Sort"); this.setRunSortName("Optimized Lazy Stable Sort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -55,13 +53,35 @@ public OptimizedLazyStableSort(ArrayVisualizer arrayVisualizer) { this.setBogoSort(false); } + public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { + int i = a + 1; + if(Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { + while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; + Writes.reversal(array, a, i - 1, sleep, true, auxwrite); + } + else while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; + + Highlights.clearMark(2); + + while(i < b) { + int current = array[i]; + int pos = i - 1; + while(pos >= a && Reads.compareValues(array[pos], current) > 0){ + Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); + pos--; + } + Writes.write(array, pos + 1, current, sleep, true, auxwrite); + + i++; + } + } + protected void grailLazyStableSort(int[] arr, int pos, int len) { - PatternDefeatingInsertionSort inserter = new PatternDefeatingInsertionSort(arrayVisualizer); int dist; for (dist = 0; dist + 16 < len; dist += 16) - inserter.insertionSort(arr, pos + dist, pos + dist + 16, 1, false); + insertionSort(arr, pos + dist, pos + dist + 16, 1, false); if (dist < len) - inserter.insertionSort(arr, pos + dist, pos + len, 1, false); + insertionSort(arr, pos + dist, pos + len, 1, false); for(int part = 16; part < len; part *= 2) { int left = 0; @@ -78,9 +98,9 @@ protected void grailLazyStableSort(int[] arr, int pos, int len) { } } } - + @Override - public void runSort(int[] array, int length, int bucketCount) { + public void runSort(int[] array, int length, int bucketCount) { this.grailLazyStableSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/OptimizedRotateMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedRotateMergeSort.java similarity index 81% rename from src/sorts/hybrid/OptimizedRotateMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/OptimizedRotateMergeSort.java index 4acbd08d..b747c5ac 100644 --- a/src/sorts/hybrid/OptimizedRotateMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedRotateMergeSort.java @@ -1,34 +1,27 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.PatternDefeatingInsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; -final public class OptimizedRotateMergeSort extends Sort { - final int MIN_RUN = 8; +@SortMeta( + name = "Optimized Rotate Merge", + category = "Hybrid Sorts", + question = "How many items should the temp array contain? (must be a power of two) (default: 64)", + defaultAnswer = 64 +) +public final class OptimizedRotateMergeSort extends Sort { + final int MIN_RUN = 32; - PatternDefeatingInsertionSort inserter; int[] tmp; public OptimizedRotateMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Rotate Merge"); - this.setRunAllSortsName("Optimized Rotate Merge Sort"); - this.setRunSortName("Optimized Rotate Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - this.setQuestion("How many items should the temp array contain? (must be a power of two) (default: 64)", 64); } protected void rotateInPlace(int[] array, int pos, int lenA, int lenB) { - if(lenA < 1 || lenB < 1) return; - + if (lenA < 1 || lenB < 1) return; + int a = pos, b = pos + lenA - 1, c = pos + lenA, @@ -61,16 +54,16 @@ protected void rotateInPlace(int[] array, int pos, int lenA, int lenB) { } protected void rotate(int[] array, int pos, int left, int right) { - if(left < 1 || right < 1) return; - + if (left < 1 || right < 1) return; + int pta = pos, ptb = pos + left, ptc = pos + right, ptd = ptb + right; - if(left < right) { + if (left < right) { int bridge = right - left; - if(bridge < left) { + if (bridge < left) { int loop = left; - + if (bridge > tmp.length) { rotateInPlace(array, pos, left, right); return; @@ -78,56 +71,53 @@ protected void rotate(int[] array, int pos, int left, int right) { Writes.arraycopy(array, ptb, tmp, 0, bridge, 1, true, true); - while(loop-- > 0) { + while (loop-- > 0) { Writes.write(array, --ptc, array[--ptd], 0.5, true, false); Writes.write(array, ptd, array[--ptb], 0.5, true, false); } Writes.arraycopy(tmp, 0, array, pta, bridge, 1, true, false); - } - else { + } else { if (left > tmp.length) { rotateInPlace(array, pos, left, right); return; } - + Writes.arraycopy(array, pta, tmp, 0, left, 1, true, true); Writes.arraycopy(array, ptb, array, pta, right, 1, true, false); Writes.arraycopy(tmp, 0, array, ptc, left, 1, true, false); } - } - else if(right < left) { + } else if(right < left) { int bridge = left - right; - if(bridge < right) { + if (bridge < right) { if (bridge > tmp.length) { rotateInPlace(array, pos, left, right); return; } int loop = right; - + Writes.arraycopy(array, ptc, tmp, 0, bridge, 1, true, true); - + while(loop-- > 0) { - Writes.write(array, ptc++, array[pta], 0.5, true, false); + Writes.write(array, ptc++, array[pta], 0.5, true, false); Writes.write(array, pta++, array[ptb++], 0.5, true, false); } Writes.arraycopy(tmp, 0, array, ptd - bridge, bridge, 1, true, false); - } - else { + } else { if (right > tmp.length) { rotateInPlace(array, pos, left, right); return; } - + Writes.arraycopy(array, ptb, tmp, 0, right, 1, true, true); - while(left-- > 0) + while (left-- > 0) Writes.write(array, --ptd, array[--ptb], 1, true, false); Writes.arraycopy(tmp, 0, array, pta, right, 1, true, false); } } else { - while(left-- > 0) + while (left-- > 0) Writes.swap(array, pta++, ptb++, 1, true, false); Highlights.clearMark(2); } @@ -151,7 +141,7 @@ protected void mergeUp(int[] array, int start, int mid, int end) { Writes.write(array, left++, array[right++], 1, true, false); } Highlights.clearMark(2); - + while (left < right) Writes.write(array, left++, tmp[bufferPointer++], 0.5, true, false); Highlights.clearAllMarks(); @@ -188,7 +178,7 @@ private int monoboundLeft(int[] array, int start, int end, int value) { while (top > 1) { mid = top / 2; - + if (Reads.compareValueIndex(array, value, end - mid, 0.5, true) <= 0) { end -= mid; } @@ -223,27 +213,27 @@ private int monoboundRight(int[] array, int start, int end, int value) { private int leftExpSearch(int[] array, int a, int b, int val) { int i = 1; - while(a - 1 + i < b && Reads.compareValueIndex(array, val, a - 1 + i, 0.5, true) >= 0) i *= 2; - + while (a - 1 + i < b && Reads.compareValueIndex(array, val, a - 1 + i, 0.5, true) >= 0) i *= 2; + return this.monoboundRight(array, a + i / 2, Math.min(b, a - 1 + i), val); } - + private int rightExpSearch(int[] array, int a, int b, int val) { int i = 1; - while(b - i >= a && Reads.compareValueIndex(array, val, b - i, 0.5, true) <= 0) i *= 2; - + while (b - i >= a && Reads.compareValueIndex(array, val, b - i, 0.5, true) <= 0) i *= 2; + return this.monoboundLeft(array, Math.max(a, b - i + 1), b - i / 2, val); } protected void merge(int[] array, int start, int mid, int end) { if (start >= mid) return; + end = rightExpSearch(array, mid, end, array[mid - 1]); + if (end < mid) return; + start = leftExpSearch(array, start, mid, array[mid]); if (Reads.compareIndices(array, start, end - 1, 1, true) > 0) { rotate(array, start, mid - start, end - mid); return; } - end = rightExpSearch(array, mid, end, array[mid - 1]); - if (end < mid) return; - start = leftExpSearch(array, start, mid, array[mid]); int llen = mid - start, rlen = end - mid; if (((llen < rlen) ? llen : rlen) > tmp.length) { int m1, m2, m3; @@ -267,18 +257,36 @@ protected void merge(int[] array, int start, int mid, int end) { } } } - + + public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { + int i = a + 1; + if (Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { + while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; + Writes.reversal(array, a, i - 1, sleep, true, auxwrite); + } + else while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; + + Highlights.clearMark(2); + + while (i < b) { + int dest = monoboundRight(array, a, i, array[i]); + int tmp = array[i]; + Writes.arraycopy(array, dest, array, dest + 1, i - dest, 0.5, true, false); + Writes.write(array, dest, tmp, 0.5, true, false); + i++; + } + } + @Override public void runSort(int[] array, int currentLength, int tempLen) { this.tmp = Writes.createExternalArray(tempLen); - inserter = new PatternDefeatingInsertionSort(arrayVisualizer); int i; for (i = 0; i + MIN_RUN < currentLength; i += MIN_RUN) { - inserter.insertionSort(array, i, i + MIN_RUN, 0.5, false); + insertionSort(array, i, i + MIN_RUN, 0.5, false); } if (i + 1 < currentLength) { - inserter.insertionSort(array, i, currentLength, 0.5, false); + insertionSort(array, i, currentLength, 0.5, false); } int gap, fullMerge; diff --git a/src/sorts/hybrid/OptimizedWeaveMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedWeaveMergeSort.java similarity index 93% rename from src/sorts/hybrid/OptimizedWeaveMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/OptimizedWeaveMergeSort.java index 0616fc01..d9aeadd2 100644 --- a/src/sorts/hybrid/OptimizedWeaveMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedWeaveMergeSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -29,36 +29,35 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class OptimizedWeaveMergeSort extends Sort { +public final class OptimizedWeaveMergeSort extends Sort { public OptimizedWeaveMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized Weave Merge"); this.setRunAllSortsName("Optimized Weave Merge Sort"); this.setRunSortName("Optimized Weave Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void insertTo(int[] array, int a, int b) { int temp = array[a]; while(a > b) Writes.write(array, a, array[--a], 0.25, true, false); Writes.write(array, b, temp, 0.25, true, false); } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -74,31 +73,31 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + //pow of 2 only (O(n)) private void bitReversal(int[] array, int a, int b) { int len = b-a, m = 0; int d1 = len>>1, d2 = d1+(d1>>1); - + for(int i = 1; i < len-1; i++) { int j = d1; - + for( - int k = i, n = d2; - (k&1) == 0; + int k = i, n = d2; + (k&1) == 0; j -= n, k >>= 1, n >>= 1 ); m += j; if(m > i) Writes.swap(array, a+i, a+m, 1, true, false); } } - + private void weaveInsert(int[] array, int a, int b, boolean right) { int i = a, j = i+1; - + while(j < b) { while(i < j && Reads.compareIndices(array, i, j, 0, true) < (right ? 1 : 0)) i++; - + if(i == j) { right = !right; j++; @@ -110,16 +109,16 @@ private void weaveInsert(int[] array, int a, int b, boolean right) { } Highlights.clearMark(3); } - + //000111 -> 010101 T //00011 -> 01010 T //00111 -> 10101 F private void weaveMerge(int[] array, int a, int m, int b) { if(b-a < 2) return; - + int a1 = a, b1 = b; boolean right = true; - + if((b-a)%2 == 1) { if(m-a < b-m) { a1--; @@ -127,15 +126,15 @@ private void weaveMerge(int[] array, int a, int m, int b) { } else b1++; } - + for(int e = b1, f; e-a1 > 2; e = f) { m = (a1+e)/2; int p = 1 << (int)(Math.log(m-a1)/Math.log(2)); - + this.rotate(array, m-p, m, e-p); m = e-p; f = m-p; - + this.bitReversal(array, f, m); this.bitReversal(array, m, e); this.bitReversal(array, f, e); @@ -147,10 +146,10 @@ private void weaveMerge(int[] array, int a, int m, int b) { @Override public void runSort(int[] array, int currentLength, int bucketCount) { int n = currentLength, d = 1 << (int)(Math.log(n-1)/Math.log(2) + 1); - + while(d > 1) { int i = 0, dec = 0; - + while(i < n) { int j = i; dec += n; @@ -170,4 +169,4 @@ public void runSort(int[] array, int currentLength, int bucketCount) { d /= 2; } } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/PDQBranchedSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchedSort.java similarity index 87% rename from src/sorts/hybrid/PDQBranchedSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchedSort.java index 505a883e..45c507b6 100644 --- a/src/sorts/hybrid/PDQBranchedSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchedSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.select.MaxHeapSort; -import sorts.templates.PDQSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.select.MaxHeapSort; +import io.github.arrayv.sorts.templates.PDQSorting; /* - * + * pdqsort.h - Pattern-defeating quicksort. Copyright (c) 2015 Orson Peters This software is provided 'as-is', without any express or implied warranty. In no event will the @@ -21,30 +21,29 @@ * */ -final public class PDQBranchedSort extends PDQSorting { +public final class PDQBranchedSort extends PDQSorting { public PDQBranchedSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Pattern-Defeating Quick (PDQ)"); this.setRunAllSortsName("Pattern-Defeating Quick Sort"); this.setRunSortName("Pattern-Defeating Quicksort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + public void customSort(int[] array, int low, int high) { this.newHeapSorter(new MaxHeapSort(this.arrayVisualizer)); pdqLoop(array, low, high, false, pdqLog(high - low)); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.newHeapSorter(new MaxHeapSort(this.arrayVisualizer)); pdqLoop(array, 0, currentLength, false, pdqLog(currentLength)); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/PDQBranchlessSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchlessSort.java similarity index 87% rename from src/sorts/hybrid/PDQBranchlessSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchlessSort.java index cb2e3d76..cdb9c739 100644 --- a/src/sorts/hybrid/PDQBranchlessSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchlessSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.select.MaxHeapSort; -import sorts.templates.PDQSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.select.MaxHeapSort; +import io.github.arrayv.sorts.templates.PDQSorting; /* - * + * pdqsort.h - Pattern-defeating quicksort. Copyright (c) 2015 Orson Peters This software is provided 'as-is', without any express or implied warranty. In no event will the @@ -21,22 +21,21 @@ * */ -final public class PDQBranchlessSort extends PDQSorting { +public final class PDQBranchlessSort extends PDQSorting { public PDQBranchlessSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Pattern-Defeating Quick (Branchless PDQ)"); this.setRunAllSortsName("Branchless Pattern-Defeating Quick Sort"); this.setRunSortName("Branchless Pattern-Defeating Quicksort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { visualizeAux(); @@ -44,4 +43,4 @@ public void runSort(int[] array, int currentLength, int bucketCount) { pdqLoop(array, 0, currentLength, true, pdqLog(currentLength)); deleteAux(); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/ParallelBlockMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelBlockMergeSort.java similarity index 94% rename from src/sorts/hybrid/ParallelBlockMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/ParallelBlockMergeSort.java index 3570431d..14936f8e 100644 --- a/src/sorts/hybrid/ParallelBlockMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelBlockMergeSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.Sort; -import sorts.insert.BinaryInsertionSort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -30,27 +30,26 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ParallelBlockMergeSort extends Sort { +public final class ParallelBlockMergeSort extends Sort { public ParallelBlockMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Parallel Block Merge"); this.setRunAllSortsName("Parallel Block Merge Sort"); this.setRunSortName("Parallel Block Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] array; - + private class BlockMergeSort extends Thread { private int a, b; - + BlockMergeSort(int a, int b) { this.a = a; this.b = b; @@ -59,28 +58,28 @@ public void run() { ParallelBlockMergeSort.this.blockMergeSort(a, b); } } - + private int sqrt(int n) { int a = 0, b = Math.min(46341, n); - + while(a < b) { int m = (a+b)/2; - + if(m*m >= n) b = m; else a = m+1; } - + return a; } - + private void multiSwap(int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(m-r, m, r); @@ -96,49 +95,49 @@ private void rotate(int a, int m, int b) { } } } - + private void inPlaceMergeFW(int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b) { if(Reads.compareValues(array[i], array[j]) > 0) { k = j; while(++k < b && Reads.compareIndices(array, i, k, 0, false) > 0); - + this.rotate(i, j, k); - + i += k-j; j = k; - } + } else i++; } } private void inPlaceMergeBW(int a, int m, int b) { int i = m-1, j = b-1, k; - + while(j > i && i >= a){ if(Reads.compareValues(array[i], array[j]) > 0) { k = i; while(--k >= a && Reads.compareIndices(array, k, j, 0, false) > 0); - + this.rotate(k+1, i+1, j+1); - + j -= i-k; i = k; - } + } else j--; } } - + private void mergeFW(int p, int a, int m, int b) { int len2 = m-a, pEnd = p+len2; - + this.multiSwap(p, a, len2); - + while(p < pEnd && m < b) { if(Reads.compareValues(array[p], array[m]) <= 0) Writes.swap(array, a++, p++, 1, true, false); - + else Writes.swap(array, a++, m++, 1, true, false); } while(p < pEnd) @@ -146,87 +145,87 @@ private void mergeFW(int p, int a, int m, int b) { } private void mergeBW(int p, int a, int m, int b) { int len2 = b-m, pEnd = p+len2-1; - + this.multiSwap(p, m, len2); - + m--; while(pEnd >= p && m >= a) { if(Reads.compareValues(array[pEnd], array[m]) >= 0) Writes.swap(array, --b, pEnd--, 1, true, false); - + else Writes.swap(array, --b, m--, 1, true, false); } while(pEnd >= p) Writes.swap(array, --b, pEnd--, 1, true, false); } - + private int findKeys(int a, int b, int n) { int p = a, found = 1, pEnd = p+found, i = pEnd; - + while(found < n) { while(i < b && Reads.compareIndices(array, pEnd-1, i, 1, true) == 0) i++; if(i == b) break; - + this.rotate(p, pEnd, i); - + p += i-pEnd; pEnd = ++i; - + found++; } this.rotate(a, p, pEnd); - + return found; } - + private int selectMin(int a, int b, int bLen) { int min = a; for(int i = min+bLen; i < b; i += bLen) if(Reads.compareValues(array[i], array[min]) < 0) min = i; - + return min; } - + private void blockMerge(int a, int m, int b) { if(Reads.compareValues(array[m-1], array[m]) <= 0) return; - + else if(Reads.compareValues(array[a], array[b-1]) > 0) { this.rotate(a, m, b); return; } - + int len1 = m-a; - + int bLen = this.sqrt(len1); int tLen = len1/bLen; int idl = bLen+tLen; - + int keys = this.findKeys(a, m, idl); int a1 = a+keys; len1 -= keys; - + if(keys == idl) { int b1 = b-(b-m)%bLen; - + int t = a; int p = a+tLen; - + int i = a1+(len1-1)%bLen+1; - + for(int j = i, k = t; j < m; j += bLen, k++) Writes.swap(array, j, k, 10, true, false); - + while(i < m && m < b1) { if(Reads.compareValues(array[i-1], array[m+bLen-1]) > 0) { this.multiSwap(i, m, bLen); this.mergeBW(p, a1, i, i+bLen); - + m += bLen; } else { int min = this.selectMin(i, m, bLen); - + if(min != i) this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); } @@ -235,13 +234,13 @@ else if(Reads.compareValues(array[a], array[b-1]) > 0) { if(i < m) { do { int min = this.selectMin(i, m, bLen); - + this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); i += bLen; } while(i < m); - + this.mergeBW(p, a1, b1, b); } else { @@ -252,7 +251,7 @@ else if(Reads.compareValues(array[a], array[b-1]) > 0) { if(m == b1) this.mergeBW(p, a1, b1, b); else this.mergeFW(p, m-bLen+1, m, b); } - + BinaryInsertionSort insertion = new BinaryInsertionSort(this.arrayVisualizer); insertion.customBinaryInsert(array, p, a1, 0.5); this.inPlaceMergeFW(a, a+keys, b); @@ -260,23 +259,23 @@ else if(Reads.compareValues(array[a], array[b-1]) > 0) { else if(keys > 1) { bLen = (len1-1)/keys+1; int b1 = b-(b-m)%bLen; - + int t = a; int i = a1+(len1-1)%bLen+1; - + for(int j = i, k = t; j < m; j += bLen, k++) Writes.swap(array, j, k, 10, true, false); - + while(i < m && m < b1) { if(Reads.compareValues(array[i-1], array[m+bLen-1]) > 0) { this.multiSwap(i, m, bLen); this.inPlaceMergeBW(a1, i, i+bLen); - + m += bLen; } else { int min = this.selectMin(i, m, bLen); - + if(min != i) this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); } @@ -285,13 +284,13 @@ else if(keys > 1) { if(i < m) { do { int min = this.selectMin(i, m, bLen); - + this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); i += bLen; } while(i < m); - + this.inPlaceMergeBW(a1, b1, b); } else { @@ -306,36 +305,36 @@ else if(keys > 1) { } else this.inPlaceMergeFW(a, m, b); } - + private void blockMergeSort(int a, int b) { if(b-a < 32) { BinaryInsertionSort insertion = new BinaryInsertionSort(this.arrayVisualizer); insertion.customBinaryInsert(array, a, b, 0.5); - + return; } - + int m = a+(b-a)/2; - + BlockMergeSort left = new BlockMergeSort(a, m); BlockMergeSort right = new BlockMergeSort(m, b); left.start(); right.start(); - + try { left.join(); right.join(); - } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - + this.blockMerge(a, m, b); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.blockMergeSort(0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/ParallelGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelGrailSort.java similarity index 93% rename from src/sorts/hybrid/ParallelGrailSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/ParallelGrailSort.java index 2c3d8c2f..c7524f83 100644 --- a/src/sorts/hybrid/ParallelGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelGrailSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,27 +29,26 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ParallelGrailSort extends Sort { +public final class ParallelGrailSort extends Sort { public ParallelGrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Parallel Grail"); this.setRunAllSortsName("Parallel Grail Sort"); this.setRunSortName("Parallel Grailsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] array; - + private class GrailCommonSort extends Thread { private int a, b, nKeys; - + GrailCommonSort(int a, int b, int nKeys) { this.a = a; this.b = b; @@ -59,10 +58,10 @@ public void run() { ParallelGrailSort.this.grailCommonSort(a, b, nKeys); } } - + private class LazyStableSort extends Thread { private int a, b; - + LazyStableSort(int a, int b) { this.a = a; this.b = b; @@ -71,10 +70,10 @@ public void run() { ParallelGrailSort.this.lazyStableSort(a, b); } } - + private class RedistFW extends Thread { private int a, m, b; - + RedistFW(int a, int m, int b) { this.a = a; this.m = m; @@ -86,7 +85,7 @@ public void run() { } private class RedistBW extends Thread { private int a, m, b; - + RedistBW(int a, int m, int b) { this.a = a; this.m = m; @@ -96,35 +95,35 @@ public void run() { ParallelGrailSort.this.redistBW(a, m, b); } } - + private int sqrt(int n) { int a = 0, b = Math.min(46341, n); - + while(a < b) { int m = (a+b)/2; - + if(m*m >= n) b = m; else a = m+1; } - + return a; } - + private void shiftFW(int a, int m, int b) { while(m < b) Writes.swap(array, a++, m++, 1, true, false); } private void shiftBW(int a, int m, int b) { while(m > a) Writes.swap(array, --b, --m, 1, true, false); } - + private void multiSwap(int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(m-r, m, r); @@ -140,95 +139,95 @@ private void rotate(int a, int m, int b) { } } } - + private void insertTo(int a, int b) { Highlights.clearMark(2); int temp = array[a]; while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } - + private int leftBinSearch(int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; - else + else a = m+1; } - + return a; } private int rightBinSearch(int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; - else + else a = m+1; } - + return a; } - + private void binaryInsertion(int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(i, this.rightBinSearch(a, i, array[i])); } - + private int mergeFW(int p, int a, int m, int b, boolean fwEq) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareValues(array[i], array[j]) < (fwEq ? 1 : 0)) Writes.swap(array, p++, i++, 1, true, false); - + else Writes.swap(array, p++, j++, 1, true, false); } - + int f = i < m ? i : j; if(i < m && p < i) this.shiftFW(p, i, m); - + return f; } - + private int inPlaceMergeFW(int a, int m, int b, boolean fwEq) { int i = a, j = m, k; - + while(i < j && j < b) { if(Reads.compareValues(array[i], array[j]) > (fwEq ? 0 : -1)) { k = fwEq ? this.leftBinSearch(j+1, b, array[i]) : this.rightBinSearch(j+1, b, array[i]); - + this.rotate(i, j, k); - + i += k-j; j = k; - } + } else i++; } - + return i; } private void inPlaceMergeBW(int a, int m, int b, boolean fwEq) { int i = m-1, j = b-1, k; - + while(j > i && i >= a){ if(Reads.compareValues(array[i], array[j]) > (fwEq ? 0 : -1)) { k = fwEq ? this.rightBinSearch(a, i, array[j]) : this.leftBinSearch(a, i, array[j]); - + this.rotate(k, i+1, j+1); - + j -= (i+1)-k; i = k-1; - } + } else j--; } } - + private int findKeys(int a, int b, int n) { int p = a, nKeys = 1, pEnd = a+nKeys; @@ -237,14 +236,14 @@ private int findKeys(int a, int b, int n) { Highlights.markArray(1, i); Delays.sleep(1); int loc = this.leftBinSearch(p, pEnd, array[i]); - + if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(p, pEnd, i); int inc = i-pEnd; loc += inc; p += inc; pEnd += inc; - + this.insertTo(pEnd, loc); nKeys++; pEnd++; @@ -253,61 +252,61 @@ private int findKeys(int a, int b, int n) { this.rotate(a, p, pEnd); return nKeys; } - + private void blockSelect(int a, int b, int t, int bLen) { for(int j = a; j < b; j += bLen) { int min = j; - + for(int i = min+bLen; i < b; i += bLen) { int cmp = Reads.compareValues(array[i], array[min]); - + if(cmp < 0 || (cmp == 0 && Reads.compareValues(array[t+(i-a)/bLen], array[t+(min-a)/bLen]) < 0)) min = i; } - + if(min != j) { this.multiSwap(j, min, bLen); Writes.swap(array, t+(j-a)/bLen, t+(min-a)/bLen, 1, true, false); } } } - + private void blockMerge(int t, int a, int m, int b, int bLen) { int a1 = a+(m-a)%bLen; int b1 = b-(b-m)%bLen; int i = a1, l = i-bLen, r = m; - + int mKey = array[t+(m-i)/bLen]; int f = a; boolean frag = true; - + this.blockSelect(a1, b1, t, bLen); - + while(l < m && r < b1) { boolean curr = Reads.compareValues(array[t++], mKey) < 0; - + if(frag != curr) { f = this.mergeFW(f-bLen, f, i, i+bLen, frag); - + if(f < i) { this.shiftBW(f, i, i+bLen); f += bLen; } else frag = curr; - + if(frag) r += bLen; else l += bLen; } else { this.shiftFW(f-bLen, f, i); f = i; - + if(frag) l += bLen; else r += bLen; } i += bLen; } - + if(l < m) { f = this.mergeFW(f-bLen, f, b1, b, true); if(f >= b1) this.shiftFW(f-bLen, f, b); @@ -318,39 +317,39 @@ private void blockMergeFewKeys(int t, int a, int m, int b, int bLen) { int a1 = a+(m-a)%bLen; int b1 = b-(b-m)%bLen; int i = a1, l = i-bLen, r = m; - + int mKey = array[t+(m-i)/bLen]; int f = a; boolean frag = true; - + this.blockSelect(a1, b1, t, bLen); - + while(l < m && r < b1) { boolean curr = Reads.compareValues(array[t++], mKey) < 0; - + if(frag != curr) { boolean tmp = frag; - - if(f == i || Reads.compareValues(array[i-1], array[i+bLen-1]) < (frag ? 1 : 0)) + + if(f == i || Reads.compareValues(array[i-1], array[i+bLen-1]) < (frag ? 1 : 0)) frag = curr; - + f = this.inPlaceMergeFW(f, i, i+bLen, tmp); - + if(frag) r += bLen; else l += bLen; } else { f = i; - + if(frag) l += bLen; else r += bLen; } i += bLen; } - + if(l < m) this.inPlaceMergeBW(f, b1, b, true); } - + private void redistFW(int a, int m, int b) { this.binaryInsertion(a, m); this.inPlaceMergeFW(a, m, b, true); @@ -359,106 +358,106 @@ private void redistBW(int a, int m, int b) { this.binaryInsertion(m, b); this.inPlaceMergeBW(a, m, b, false); } - + private void lazyStableSort(int a, int b) { if(b-a <= 16) { this.binaryInsertion(a, b); return; } - + int m = (a+b)/2; - + LazyStableSort left = new LazyStableSort(a, m); LazyStableSort right = new LazyStableSort(m, b); left.start(); right.start(); - + try { left.join(); right.join(); - } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - + this.inPlaceMergeFW(a, m, b, true); } - + private void grailCommonSort(int a, int b, int nKeys) { int len = b-a; - + if(len <= 16) { this.binaryInsertion(a, b); return; } - + int bLen = sqrt(len); int tLen = len/bLen; - + int idl = bLen+tLen; boolean strat1 = nKeys >= idl; if(!strat1) idl = nKeys; - + int keys = this.findKeys(a, b, idl); int a1 = a+keys; int m = (a1+b)/2; - + if(strat1 && keys == idl) { GrailCommonSort left = new GrailCommonSort(a1, m, keys); GrailCommonSort right = new GrailCommonSort(m, b, keys); left.start(); right.start(); - + try { left.join(); right.join(); - } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - + this.blockMerge(a, a1, m, b, bLen); - + m = this.leftBinSearch(a+tLen, b-bLen, array[a+tLen-1]); - + RedistFW kBuf = new RedistFW(a, a+tLen, m); RedistBW mBuf = new RedistBW(m, b-bLen, b); kBuf.start(); mBuf.start(); - + try { kBuf.join(); mBuf.join(); - } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else if(keys > 4) { bLen = (b-a1-1)/(keys-keys%2)+1; - + GrailCommonSort left = new GrailCommonSort(a1, m, keys); GrailCommonSort right = new GrailCommonSort(m, b, keys); left.start(); right.start(); - + try { left.join(); right.join(); - } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - + this.blockMergeFewKeys(a, a1, m, b, bLen); this.redistFW(a, a1, b); } else if(keys > 1) this.lazyStableSort(a, b); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.grailCommonSort(0, length, 46341); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/RemiSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/RemiSort.java similarity index 87% rename from src/sorts/hybrid/RemiSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/RemiSort.java index 36a75707..e135528f 100644 --- a/src/sorts/hybrid/RemiSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/RemiSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.MultiWayMergeSorting; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.MultiWayMergeSorting; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,57 +29,56 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class RemiSort extends MultiWayMergeSorting { - public RemiSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Remi"); - this.setRunAllSortsName("Remi Sort"); - this.setRunSortName("Remisort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - +public final class RemiSort extends MultiWayMergeSorting { + public RemiSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + + this.setSortListName("Remi"); + this.setRunAllSortsName("Remi Sort"); + this.setRunSortName("Remisort"); + this.setCategory("Hybrid Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.setBogoSort(false); + } + //stable sorting algorithm that guarantees worst case performance of //O(n log n) comparisons and O(n) moves in O(n^2/3) memory - + private int ceilCbrt(int n) { int a = 0, b = Math.min(1291, n); - + while(a < b) { int m = (a+b)/2; - + if(m*m*m >= n) b = m; else a = m+1; } - + return a; } - + private void siftDown(int[] array, int[] keys, int r, int len, int a, int t) { int j = r; - + while(2*j + 1 < len) { j = 2*j + 1; - + if(j+1 < len) { int cmp = Reads.compareIndices(array, a+keys[j+1], a+keys[j], 0.2, true); - + if(cmp > 0 || (cmp == 0 && Reads.compareOriginalValues(keys[j+1], keys[j]) > 0)) j++; } } for(int cmp = Reads.compareIndices(array, a+t, a+keys[j], 0.2, true); - + cmp > 0 || (cmp == 0 && Reads.compareOriginalValues(t, keys[j]) > 0); - + j = (j-1)/2, cmp = Reads.compareIndices(array, a+t, a+keys[j], 0.2, true)); - + for(int t2; j > r; j = (j-1)/2) { t2 = keys[j]; Highlights.markArray(3, j); @@ -89,13 +88,13 @@ private void siftDown(int[] array, int[] keys, int r, int len, int a, int t) { Highlights.markArray(3, r); Writes.write(keys, r, t, 0.2, false, true); } - + private void tableSort(int[] array, int[] keys, int a, int b) { int len = b-a; - + for(int i = (len-1)/2; i >= 0; i--) this.siftDown(array, keys, i, len, a, keys[i]); - + for(int i = len-1; i > 0; i--) { int t = keys[i]; Highlights.markArray(3, i); @@ -103,44 +102,44 @@ private void tableSort(int[] array, int[] keys, int a, int b) { this.siftDown(array, keys, 0, i, a, t); } Highlights.clearMark(3); - + for(int i = 0; i < len; i++) { Highlights.markArray(2, i); if(Reads.compareOriginalValues(i, keys[i]) != 0) { int t = array[a+i]; int j = i, next = keys[i]; - + do { Writes.write(array, a+j, array[a+next], 1, true, false); Writes.write(keys, j, j, 1, true, true); - + j = next; next = keys[next]; } while(Reads.compareOriginalValues(next, i) != 0); - + Writes.write(array, a+j, t, 1, true, false); Writes.write(keys, j, j, 1, true, true); } } Highlights.clearMark(2); } - + private void blockCycle(int[] array, int[] buf, int[] keys, int a, int bLen, int bCnt) { for(int i = 0; i < bCnt; i++) { if(Reads.compareOriginalValues(i, keys[i]) != 0) { Writes.arraycopy(array, a + i*bLen, buf, 0, bLen, 1, true, true); int j = i, next = keys[i]; - + do { Writes.arraycopy(array, a + next*bLen, array, a + j*bLen, bLen, 1, true, false); Writes.write(keys, j, j, 1, true, true); - + j = next; next = keys[next]; } while(Reads.compareOriginalValues(next, i) != 0); - + Writes.arraycopy(buf, 0, array, a + j*bLen, bLen, 1, true, false); Writes.write(keys, j, j, 1, true, true); } @@ -148,126 +147,124 @@ private void blockCycle(int[] array, int[] buf, int[] keys, int a, int bLen, int } private void kWayMerge(int[] array, int[] buf, int[] keys, int[] heap, int b, int[] pa, int[] p, int bLen, int rLen) { int k = p.length, size = k, a = pa[0], a1 = pa[1]; - + for(int i = 0; i < k; i++) Writes.write(heap, i, i, 0, false, true); for(int i = (k-1)/2; i >= 0; i--) this.siftDown(array, heap, pa, heap[i], i, k); - + for(int i = 0; i < rLen; i++) { int min = heap[0]; - + Highlights.markArray(2, pa[min]); - + Writes.write(buf, i, array[pa[min]], 0, false, true); Writes.write(pa, min, pa[min]+1, 1, false, true); if(pa[min] == Math.min(a + (min+1)*rLen, b)) this.siftDown(array, heap, pa, heap[--size], 0, size); - else + else this.siftDown(array, heap, pa, heap[0], 0, size); } int t = 0, cnt = 0, c = 0; while(pa[c]-p[c] < bLen) c++; - + do { int min = heap[0]; - + Highlights.markArray(2, pa[min]); Highlights.markArray(3, p[c]); - + Writes.write(array, p[c], array[pa[min]], 0, false, false); Writes.write(pa, min, pa[min]+1, 0, false, true); Writes.write(p, c, p[c]+1, 1, false, true); if(pa[min] == Math.min(a + (min+1)*rLen, b)) this.siftDown(array, heap, pa, heap[--size], 0, size); - else + else this.siftDown(array, heap, pa, heap[0], 0, size); - + if(++cnt == bLen) { Writes.write(keys, t++, (c > 0) ? p[c]/bLen-bLen-1 : -1, 0, false, true); - + c = cnt = 0; while(pa[c]-p[c] < bLen) c++; } } while(size > 0); - + Highlights.clearAllMarks(); - + while(cnt-- > 0) { Writes.write(p, c, p[c]-1, 0, false, true); Writes.write(array, --b, array[p[c]], 1, true, false); } Writes.write(pa, k-1, b, 0, false, true); Writes.write(keys, keys.length-1, -1, 0, false, true); - + t = 0; while(keys[t] != -1) t++; - + for(int i = 1, j = a; j < p[0]; i++) { while(p[i] < pa[i]) { Writes.write(keys, t++, p[i]/bLen-bLen, 0, false, true); while(keys[t] != -1) t++; - + Writes.arraycopy(array, j, array, p[i], bLen, 1, true, false); Writes.write(p, i, p[i]+bLen, 0, false, true); - + j += bLen; } } Writes.arraycopy(buf, 0, array, a, rLen, 1, true, false); - + this.blockCycle(array, buf, keys, a1, bLen, (b-a1)/bLen); } - - @Override - public void runSort(int[] array, int length, int bucketCount) { + + @Override + public void runSort(int[] array, int length, int bucketCount) { int a = 0, b = length; - + int bLen = this.ceilCbrt(length); int rLen = bLen*bLen; int rCnt = (length-1)/rLen + 1; - + if(rCnt < 2) { int[] keys = Writes.createExternalArray(length); - + for(int i = 0; i < keys.length; i++) Writes.write(keys, i, i, 1, true, true); - + this.tableSort(array, keys, a, b); - + Writes.deleteExternalArray(keys); return; } - - int bCnt = (length-rLen)/bLen; - + int[] keys = Writes.createExternalArray(rLen); int[] buf = Writes.createExternalArray(rLen); - + int[] heap = new int[rCnt]; int[] p = new int[rCnt]; int[] pa = new int[rCnt]; - + int alloc = 3*rCnt; Writes.changeAllocAmount(alloc); - + for(int i = 0; i < keys.length; i++) Writes.write(keys, i, i, 1, true, true); - + for(int i = a, j = 0; i < b; i += rLen, j++) { this.tableSort(array, keys, i, Math.min(i+rLen, b)); Writes.write(pa, j, i, 0, false, true); } Writes.arraycopy(pa, 0, p, 0, rCnt, 0, false, true); - + this.kWayMerge(array, buf, keys, heap, b, pa, p, bLen, rLen); - + Writes.deleteExternalArray(keys); Writes.deleteExternalArray(buf); Writes.changeAllocAmount(-alloc); - } -} \ No newline at end of file + } +} diff --git a/src/sorts/hybrid/SqrtSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/SqrtSort.java similarity index 94% rename from src/sorts/hybrid/SqrtSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/SqrtSort.java index 7cbb3333..bc443103 100644 --- a/src/sorts/hybrid/SqrtSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/SqrtSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2014 Andrey Astrelin @@ -45,48 +45,47 @@ this software and associated documentation files (the "Software"), to deal in final class SqrtState { private int leftOverLen; private int leftOverFrag; - + protected SqrtState(int len, int frag) { this.leftOverLen = len; this.leftOverFrag = frag; } - + protected int getLeftOverLen() { return leftOverLen; } - + protected int getLeftOverFrag() { return leftOverFrag; } } -final public class SqrtSort extends Sort { +public final class SqrtSort extends Sort { private InsertionSort insertSorter; - + public SqrtSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Sqrt"); //this.setRunAllID("Square Root Sort (Block Merge Sort)"); //this.setRunAllSortsName("Square Root Sort [Block Merge Sort]"); this.setRunAllSortsName("Sqrtsort"); this.setRunSortName("Sqrtsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void sqrtSwap(int[] arr, int a, int b, boolean auxwrite) { Writes.swap(arr, a, b, 1, true, auxwrite); Highlights.clearMark(2); } - private void sqrtMultiSwap(int[] arr, int a, int b, int swapsLeft, boolean auxwrite) { - while(swapsLeft != 0) { + private void sqrtMultiSwap(int[] arr, int a, int b, int swapsLeft, boolean auxwrite) { + while(swapsLeft != 0) { this.sqrtSwap(arr, a++, b++, auxwrite); swapsLeft--; } @@ -95,7 +94,7 @@ private void sqrtMultiSwap(int[] arr, int a, int b, int swapsLeft, boolean auxwr private void sqrtInsertSort(int[] arr, int pos, int len, boolean auxwrite) { insertSorter.customInsertSort(arr, pos, len, 0.25, auxwrite); } - + private void sqrtMergeRight(int[] arr, int pos, int leftLen, int rightLen, int dist, boolean auxwrite) { int mergedPos = leftLen + rightLen + dist - 1; int right = leftLen + rightLen - 1; @@ -104,22 +103,22 @@ private void sqrtMergeRight(int[] arr, int pos, int leftLen, int rightLen, int d while(left >= 0) { Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); - + if(right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { Writes.write(arr, pos + (mergedPos--), arr[pos + (left--)], 1, true, auxwrite); - } + } else Writes.write(arr, pos + (mergedPos--), arr[pos + (right--)], 1, true, auxwrite); } - + Highlights.clearMark(3); - + if(right != mergedPos) { while(right >= leftLen) { Writes.write(arr, pos + (mergedPos--), arr[pos + (right--)], 1, true, auxwrite); Highlights.markArray(2, pos + right); } } - + Highlights.clearMark(2); } @@ -135,20 +134,20 @@ private void sqrtMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEnd Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, auxwrite); } else Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, auxwrite); - + Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); } - + Highlights.clearMark(3); - + if(dist != left) { while(left < leftEnd) { Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, auxwrite); Highlights.markArray(2, pos + left); } } - + Highlights.clearMark(2); } @@ -156,29 +155,29 @@ private void sqrtMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEnd private void sqrtMergeDown(int[] arr, int arrPos, int[] buffer, int bufPos, int leftLen, int rightLen, boolean auxwrite) { int arrMerge = 0, bufMerge = 0; int dist = 0 - rightLen; - + while(bufMerge < rightLen) { if(arrMerge == leftLen || Reads.compareValues(arr[arrPos + arrMerge], buffer[bufPos + bufMerge]) >= 0) { Writes.write(arr, arrPos + dist++, buffer[bufPos + bufMerge++], 1, true, auxwrite); } else Writes.write(arr, arrPos + dist++, arr[arrPos + arrMerge++], 1, true, auxwrite); - + Highlights.markArray(2, arrPos + arrMerge); Highlights.markArray(3, bufPos + bufMerge); } - + Highlights.clearMark(3); - + if(dist != arrMerge) { while(arrMerge < leftLen) { Writes.write(arr, arrPos + dist++, arr[arrPos + arrMerge++], 1, true, auxwrite); Highlights.markArray(2, arrPos + arrMerge); } } - + Highlights.clearMark(2); } - + //returns the leftover length, then the leftover fragment private SqrtState sqrtSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, int leftOverFrag, int blockLen, boolean auxwrite) { int dist = 0 - blockLen, left = 0, right = leftOverLen, leftEnd = right, rightEnd = right + blockLen; @@ -189,30 +188,30 @@ private SqrtState sqrtSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, in Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, auxwrite); } else Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, auxwrite); - + Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); } - + Highlights.clearMark(3); - + int length, fragment = leftOverFrag; - + if(left < leftEnd) { length = leftEnd - left; - + while(left < leftEnd) { Writes.write(arr, pos + --rightEnd, arr[pos + --leftEnd], 1, true, auxwrite); Highlights.markArray(2, pos + leftEnd); } - } + } else { length = rightEnd - right; fragment = typeFrag; } - + Highlights.clearMark(2); - + return new SqrtState(length, fragment); } @@ -236,90 +235,90 @@ private void sqrtMergeBuffersLeftWithXBuf(int[] keys, int midkey, int[] arr, int int processIndex = regBlockLen; int restToProcess; - + for(int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += regBlockLen) { restToProcess = processIndex - leftOverLen; int nextFrag = Reads.compareOriginalValues(keys[keyIndex], midkey) < 0 ? 0 : 1; if(nextFrag == leftOverFrag) { Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, auxwrite); - + restToProcess = processIndex; leftOverLen = regBlockLen; } else { SqrtState results = this.sqrtSmartMergeWithXBuf(arr, pos + restToProcess, leftOverLen, leftOverFrag, regBlockLen, auxwrite); - + leftOverLen = results.getLeftOverLen(); leftOverFrag = results.getLeftOverFrag(); } } - + restToProcess = processIndex - leftOverLen; if(lastLen != 0) { if(leftOverFrag != 0) { Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, auxwrite); - + restToProcess = processIndex; leftOverLen = regBlockLen * aBlockCount; leftOverFrag = 0; - } + } else { leftOverLen += regBlockLen * aBlockCount; } this.sqrtMergeLeftWithXBuf(arr, pos + restToProcess, leftOverLen, lastLen, 0 - regBlockLen, auxwrite); - } + } else { Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, auxwrite); } } - + // build blocks of length buildLen // input: [-buildLen,-1] elements are buffer // output: first buildLen elements are buffer, blocks 2 * buildLen and last subblock sorted private void sqrtBuildBlocks(int[] arr, int pos, int len, int buildLen, boolean auxwrite) { int extraDist, part; - + for(int dist = 1; dist < len; dist += 2) { extraDist = 0; if(Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) extraDist = 1; - + Writes.write(arr, pos + dist - 3, arr[pos + dist - 1 + extraDist], 1, true, auxwrite); Writes.write(arr, pos + dist - 2, arr[pos + dist - extraDist], 1, true, auxwrite); } if(len % 2 != 0) Writes.write(arr, pos + len - 3, arr[pos + len - 1], 1, true, auxwrite); - + pos -= 2; - + for(part = 2; part < buildLen; part *= 2) { int left = 0; int right = len - 2 * part; - + while(left <= right) { this.sqrtMergeLeftWithXBuf(arr, pos + left, part, part, 0 - part, auxwrite); left += 2 * part; } - + int rest = len - left; if(rest > part) { this.sqrtMergeLeftWithXBuf(arr, pos + left, part, rest - part, 0 - part, auxwrite); - } + } else { while(left < len) Writes.write(arr, pos + left - part, arr[pos + left++], 1, true, auxwrite); } - + pos -= part; } int restToBuild = len % (2 * buildLen); int leftOverPos = len - restToBuild; - + if(restToBuild <= buildLen) { Writes.arraycopy(arr, pos + leftOverPos, arr, pos + leftOverPos + buildLen, restToBuild, 1, true, auxwrite); } else this.sqrtMergeRight(arr, pos + leftOverPos, buildLen, restToBuild - buildLen, buildLen, auxwrite); - + while(leftOverPos > 0) { leftOverPos -= 2 * buildLen; this.sqrtMergeRight(arr, pos + leftOverPos, buildLen, buildLen, buildLen, auxwrite); @@ -336,29 +335,29 @@ private void sqrtCombineBlocks(int[] arr, int pos, int len, int buildLen, int re len -= leftOver; leftOver = 0; } - + int leftIndex = 0; - + for(int i = 0; i <= combineLen; i++) { if(i == combineLen && leftOver == 0) break; - + int blockPos = pos + i * 2 * buildLen; int blockCount = (i == combineLen ? leftOver : 2 * buildLen) / regBlockLen; - + int tagIndex = blockCount + (i == combineLen ? 1 : 0); for(int j = 0; j <= tagIndex; j++) Writes.write(tags, j, j, 1, true, true); - + int midkey = buildLen / regBlockLen; - + for(tagIndex = 1; tagIndex < blockCount; tagIndex++) { leftIndex = tagIndex - 1; - + for(int rightIndex = tagIndex; rightIndex < blockCount; rightIndex++) { int rightComp = Reads.compareValues(arr[blockPos + leftIndex * regBlockLen], arr[blockPos + rightIndex * regBlockLen]); if(rightComp > 0 || (rightComp == 0 && tags[leftIndex] > tags[rightIndex])) leftIndex = rightIndex; } - + if(leftIndex != tagIndex - 1) { this.sqrtMultiSwap(arr, blockPos + (tagIndex - 1) * regBlockLen, blockPos + leftIndex * regBlockLen, regBlockLen, auxwrite); this.sqrtSwap(tags, tagIndex - 1, leftIndex, true); @@ -366,9 +365,9 @@ private void sqrtCombineBlocks(int[] arr, int pos, int len, int buildLen, int re } int aBlockCount = 0; int lastLen = 0; - + if(i == combineLen) lastLen = leftOver % regBlockLen; - + if(lastLen != 0) { while(aBlockCount < blockCount && Reads.compareValues(arr[blockPos + blockCount * regBlockLen], arr[blockPos + (blockCount - aBlockCount - 1) * regBlockLen]) < 0) { @@ -382,29 +381,29 @@ private void sqrtCombineBlocks(int[] arr, int pos, int len, int buildLen, int re private void sqrtCommonSort(int[] arr, int pos, int len, int[] extBuf, int extBufPos, int[] tags, boolean auxwrite) { insertSorter = new InsertionSort(this.arrayVisualizer); - + if(len <= 16) { this.sqrtInsertSort(arr, pos, len, auxwrite); Highlights.clearAllMarks(); return; } - + int blockLen = 1; while((blockLen * blockLen) < len) blockLen *= 2; - + Writes.arraycopy(arr, pos, extBuf, extBufPos, blockLen, 1, true, auxwrite); - + this.sqrtCommonSort(extBuf, extBufPos, blockLen, arr, pos, tags, !auxwrite); - + this.sqrtBuildBlocks(arr, pos + blockLen, len - blockLen, blockLen, auxwrite); - + int buildLen = blockLen; - + while(len > (buildLen *= 2)) { this.sqrtCombineBlocks(arr, pos + blockLen, len - blockLen, buildLen, blockLen, tags, auxwrite); } this.sqrtMergeDown(arr, pos + blockLen, extBuf, extBufPos, len - blockLen, blockLen, auxwrite); - + Highlights.clearAllMarks(); } @@ -414,7 +413,7 @@ public void runSort(int[] array, int len, int bucketCount) { while(bufferLen * bufferLen < len) bufferLen *= 2; int numKeys = (len - 1) / bufferLen + 2; - + int[] extBuf = Writes.createExternalArray(bufferLen); int[] tags = Writes.createExternalArray(numKeys); @@ -423,4 +422,4 @@ public void runSort(int[] array, int len, int bucketCount) { Writes.deleteExternalArray(extBuf); Writes.deleteExternalArray(tags); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/StacklessDualPivotQuickSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessDualPivotQuickSort.java similarity index 91% rename from src/sorts/hybrid/StacklessDualPivotQuickSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/StacklessDualPivotQuickSort.java index 4a814326..862f3e53 100644 --- a/src/sorts/hybrid/StacklessDualPivotQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessDualPivotQuickSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.insert.BinaryInsertionSort; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -30,25 +30,24 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StacklessDualPivotQuickSort extends Sort { +public final class StacklessDualPivotQuickSort extends Sort { public StacklessDualPivotQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stackless Dual-Pivot Quick"); this.setRunAllSortsName("Stackless Dual-Pivot Quicksort"); this.setRunSortName("Stackless Dual-Pivot Quicksort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int partition(int[] array, int a, int b, int p) { int m1 = (a+a+b)/3, m2 = (a+b+b)/3; - + if(Reads.compareIndices(array, m1, m2, 1, true) > 0) { Writes.swap(array, m1, a, 1, true, false); Writes.swap(array, m2, --b, 1, true, false); @@ -57,13 +56,13 @@ private int partition(int[] array, int a, int b, int p) { Writes.swap(array, m2, a, 1, true, false); Writes.swap(array, m1, --b, 1, true, false); } - + int i = a, j = b; - + for(int k = i+1; k < j; k++) { if(Reads.compareValues(array[k], array[b]) < 0) Writes.swap(array, k, ++i, 1, true, false); - + else if(Reads.compareValues(array[k], array[a]) >= 0) { do { j--; @@ -71,75 +70,75 @@ else if(Reads.compareValues(array[k], array[a]) >= 0) { Delays.sleep(1); } while(j > k && Reads.compareValues(array[j], array[a]) >= 0); - + Writes.swap(array, k, j, 1, true, false); Highlights.clearMark(3); - + if(Reads.compareValues(array[k], array[b]) < 0) Writes.swap(array, k, ++i, 1, true, false); } } - + Writes.swap(array, a, i, 1, true, false); int t = array[b]; Writes.write(array, b, array[j], 1, true, false); Writes.write(array, j, array[p], 1, true, false); Writes.write(array, p, t, 1, true, false); - + return i; } - + private int leftBinSearch(int[] array, int a, int b, int p) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareIndices(array, p, m, 1, true) <= 0) + + if(Reads.compareIndices(array, p, m, 1, true) <= 0) b = m; else a = m+1; } - + return a; } - + private void quickSort(int[] array, int a, int b) { int max = array[a]; - + for(int i = a+1; i < b; i++) { Highlights.markArray(1, i); Delays.sleep(0.5); - + if(Reads.compareValues(array[i], max) > 0) max = array[i]; } for(int i = b-1; i >= 0; i--) { Highlights.markArray(1, i); Delays.sleep(0.5); - + if(Reads.compareValues(array[i], max) == 0) Writes.swap(array, i, --b, 1, true, false); } - + int b1 = b; boolean med = true; //flag to improve pivot selection in the case of many similar elements BinaryInsertionSort smallSort = new BinaryInsertionSort(this.arrayVisualizer); - + do { while(b1-a > 24) { if(!med) Writes.swap(array, a, (a+a+b1)/3, 1, true, false); - + b1 = this.partition(array, a, b1, b); } smallSort.customBinaryInsert(array, a, b1, 0.25); - + a = b1+1; if(a >= b) { if(a-1 < b) Writes.swap(array, a-1, b, 1, true, false); return; } - + b1 = this.leftBinSearch(array, a, b, a-1); Writes.swap(array, a-1, b, 1, true, false); - + med = true; while(a < b1 && Reads.compareIndices(array, a-1, a, 0.5, true) == 0) { med = false; @@ -149,9 +148,9 @@ private void quickSort(int[] array, int a, int b) { } while(true); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.quickSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/StacklessHybridQuickSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessHybridQuickSort.java similarity index 91% rename from src/sorts/hybrid/StacklessHybridQuickSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/StacklessHybridQuickSort.java index 3d93ab37..f301aee9 100644 --- a/src/sorts/hybrid/StacklessHybridQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessHybridQuickSort.java @@ -1,11 +1,11 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.insert.BinaryInsertionSort; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -30,44 +30,43 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StacklessHybridQuickSort extends Sort { +public final class StacklessHybridQuickSort extends Sort { public StacklessHybridQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stackless Hybrid Quick"); this.setRunAllSortsName("Stackless Hybrid Quicksort"); this.setRunSortName("Stackless Hybrid Quicksort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void medianOfThree(int[] array, int a, int b) { int m = a+(b-1-a)/2; - + if(Reads.compareIndices(array, a, m, 1, true) == 1) Writes.swap(array, a, m, 1, true, false); - + if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { Writes.swap(array, m, b-1, 1, true, false); - + if(Reads.compareIndices(array, a, m, 1, true) == 1) return; } - + Writes.swap(array, a, m, 1, true, false); } - + private int partition(int[] array, int a, int b) { int i = a, j = b; - + this.medianOfThree(array, a, b); Highlights.markArray(3, a); - + do { do { i++; @@ -75,14 +74,14 @@ private int partition(int[] array, int a, int b) { Delays.sleep(0.5); } while(i < j && Reads.compareIndices(array, i, a, 0, false) < 0); - + do { j--; Highlights.markArray(2, j); Delays.sleep(0.5); } while(j >= i && Reads.compareIndices(array, j, a, 0, false) >= 0); - + if(i < j) Writes.swap(array, i, j, 1, true, false); else { Writes.swap(array, a, j, 1, true, false); @@ -92,61 +91,61 @@ private int partition(int[] array, int a, int b) { } while(true); } - + private int leftBinSearch(int[] array, int a, int b, int p) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareIndices(array, p, m, 1, true) <= 0) + + if(Reads.compareIndices(array, p, m, 1, true) <= 0) b = m; - else + else a = m+1; } - + return a; } - + private void quickSort(int[] array, int a, int b) { int max = array[a]; - + for(int i = a+1; i < b; i++) { Highlights.markArray(1, i); Delays.sleep(0.5); - + if(Reads.compareValues(array[i], max) > 0) max = array[i]; } for(int i = b-1; i >= 0; i--) { Highlights.markArray(1, i); Delays.sleep(0.5); - + if(Reads.compareValues(array[i], max) == 0) Writes.swap(array, i, --b, 1, true, false); } - + int b1 = b; boolean med = true; //flag to improve pivot selection in the case of many similar elements BinaryInsertionSort smallSort = new BinaryInsertionSort(this.arrayVisualizer); - + do { while(b1-a > 16) { if(med) this.medianOfThree(array, a, b1); - + int p = this.partition(array, a, b1); Writes.swap(array, p, b, 1, true, false); - + b1 = p; } smallSort.customBinaryInsert(array, a, b1, 0.25); - + a = b1+1; if(a >= b) { if(a-1 < b) Writes.swap(array, a-1, b, 1, true, false); return; } - + b1 = this.leftBinSearch(array, a, b, a-1); Writes.swap(array, a-1, b, 1, true, false); - + med = true; while(a < b1 && Reads.compareIndices(array, a-1, a, 0.5, true) == 0) { med = false; @@ -156,9 +155,9 @@ private void quickSort(int[] array, int a, int b) { } while(true); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.quickSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/SynchronousSqrtSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/SynchronousSqrtSort.java similarity index 94% rename from src/sorts/hybrid/SynchronousSqrtSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/SynchronousSqrtSort.java index 6e030a0d..fc8b1a18 100644 --- a/src/sorts/hybrid/SynchronousSqrtSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/SynchronousSqrtSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import sorts.templates.BlockMergeSorting; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BlockMergeSorting; /* - * + * MIT License Copyright (c) 2021 The Holy Grail Sort Project, implemented by aphitorite @@ -29,29 +29,28 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class SynchronousSqrtSort extends BlockMergeSorting { +public final class SynchronousSqrtSort extends BlockMergeSorting { public SynchronousSqrtSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Synchronous Sqrt"); this.setRunAllSortsName("Synchronous Sqrt Sort"); this.setRunSortName("Synchronous Sqrtsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int smartMergeBW(int[] array, int a, int m, int b, int p, boolean rev) { int i = m-1, j = b-1; int cmp = rev ? -1 : 0; - + while(i >= a && j >= m) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[i], array[j]) > cmp) Writes.write(array, --p, array[i--], 1, true, false); else @@ -59,18 +58,18 @@ private int smartMergeBW(int[] array, int a, int m, int b, int p, boolean rev) { } return i+1; } - + private void blockSelection(int[] array, int[] tags, int a, int b, int bLen, int t, int tj) { for(int i = 0; i < Math.min(tj+1, tags.length-t); i++) Writes.write(tags, t+i, i + (i <= tj/2 ? 0 : tags.length), 1, true, true); - + for(int j = a, p = a; j < b-bLen; j+=bLen) { int min = p == j ? j+bLen : j; - + for(int i = min+bLen; i < b; i+=bLen) { if(i != p) { int cmp = Reads.compareValues(array[i], array[min]); - + if(cmp == -1 || (cmp == 0 && Reads.compareOriginalValues(tags[t + (i-a)/bLen], tags[t + (min-a)/bLen]) == -1)) min = i; } @@ -79,7 +78,7 @@ private void blockSelection(int[] array, int[] tags, int a, int b, int bLen, int if(p == j) { Writes.arraycopy(array, min, array, j, bLen, 1, true, false); Writes.write(tags, t + (j-a)/bLen, tags[t + (min-a)/bLen], 1, true, false); - + p = min; } else { @@ -93,7 +92,7 @@ private void mergeBlocksBW(int[] array, int[] tags, int a, int b, int ti, int tb int tj = tb-1, mkv = tags.length; int f = b, a1 = f-bLen; boolean rev = Reads.compareOriginalValues(tags[tj], mkv) < 0; - + while(true) { do { tj--; @@ -109,73 +108,73 @@ private void mergeBlocksBW(int[] array, int[] tags, int a, int b, int ti, int tb rev = !rev; } } - + @Override public void runSort(int[] array, int length, int bucketCount) { if(length <= 16) { this.binaryInsertion(array, 0, length); return; } - + int bLen = 1; while(bLen*bLen < length) bLen *= 2; int mod = length%bLen; - + int a = bLen+mod, b = length, len = b-a; int i, j = 1; - + int[] temp = Writes.createExternalArray(bLen+mod); int[] tags = Writes.createExternalArray((length-1)/bLen+1); - + this.binaryInsertion(array, 0, a); Writes.arraycopy(array, 0, temp, 0, a, 1, true, true); - + for(; j < bLen; j *= 2) { int p = Math.max(2, j); - + for(i = a; i+2*j < b; i += 2*j) this.mergeWithBufFWExt(array, i, i+j, i+2*j, i-p); - + if(i+j < b) this.mergeWithBufFWExt(array, i, i+j, b, i-p); else this.shiftFWExt(array, i-p, i, b); - + a -= p; b -= p; } - + int p = len%(2*j); i = b-p; - + if(i+j < b) this.mergeWithBufBWExt(array, i, i+j, b, b+j); else this.shiftBWExt(array, i, b, b+j); - + for(i -= 2*j; i >= a; i -= 2*j) this.mergeWithBufBWExt(array, i, i+j, i+2*j, i+3*j); - + a += j; b += j; j *= 2; - + for(int ti, tj = 4; j < len; j *= 2, tj *= 2) { for(i = a, ti = 0; i+2*j < b; i += 2*j, ti += tj) this.blockSelection(array, tags, i-bLen, i+2*j, bLen, ti, tj); - + boolean noFrag = i+j < b; p = (b-i)/bLen; - + if(noFrag) this.blockSelection(array, tags, i-bLen, b, bLen, ti, tj); - + a -= bLen; b -= bLen; i -= bLen; - + if(noFrag) this.mergeBlocksBW(array, tags, i, b, ti, ti+p, bLen); - + for(i -= 2*j, ti -= tj; i >= a; i -= 2*j, ti -= tj) this.mergeBlocksBW(array, tags, i, i+2*j, ti, ti+tj, bLen); - + a += bLen; b += bLen; } p = 0; i = 0; j = a; - + while(i < a && j < b) { Highlights.markArray(2, i); - + if(Reads.compareValues(temp[i], array[j]) <= 0) Writes.write(array, p++, temp[i++], 1, true, false); else @@ -188,4 +187,4 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.deleteExternalArray(temp); Writes.deleteExternalArray(tags); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/TimSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/TimSort.java similarity index 75% rename from src/sorts/hybrid/TimSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/TimSort.java index 9206f2a4..12e3b60a 100644 --- a/src/sorts/hybrid/TimSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/TimSort.java @@ -1,8 +1,9 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; -import sorts.templates.TimSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.sorts.templates.TimSorting; /* * Copyright (C) 2008 The Android Open Source Project @@ -20,32 +21,25 @@ * limitations under the License. */ +@SortMeta( + name = "Tim", + category = "Hybrid Sorts" +) public class TimSort extends Sort { private TimSorting timSortInstance; // TimSort cannot be simply written off as an abstract class, as it creates an instance of itself // in order to track its state. Plus, it contains both instance and static methods, requiring even // more refactoring, which would be just doing unnecessary busy work. Instead of what we've done for // the rest of the algorithms, we'll favor composition over inheritance here and pass "util" objects // to it. - + public TimSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Tim"); - this.setRunAllSortsName("Tim Sort"); - this.setRunSortName("Timsort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.timSortInstance = new TimSorting(array, currentLength, this.arrayVisualizer); - + TimSorting.sort(this.timSortInstance, array, currentLength); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/UnstableGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/UnstableGrailSort.java similarity index 93% rename from src/sorts/hybrid/UnstableGrailSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/UnstableGrailSort.java index b0c6f9c8..336c94e0 100644 --- a/src/sorts/hybrid/UnstableGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/UnstableGrailSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.UnstableGrailSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.UnstableGrailSorting; /* - * + * The MIT License (MIT) Copyright (c) 2013 Andrey Astrelin @@ -47,26 +47,25 @@ this software and associated documentation files (the "Software"), to deal in /* */ /*********************************************************/ -final public class UnstableGrailSort extends UnstableGrailSorting { +public final class UnstableGrailSort extends UnstableGrailSorting { public UnstableGrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Unstable Grail"); //this.setRunAllID("Grail Sort (Block Merge Sort)"); //this.setRunAllSortsName("Grail Sort [Block Merge Sort]"); this.setRunAllSortsName("Unstable Grailsort"); this.setRunSortName("Unstable Grailsort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.grailCommonSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/WeaveMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/WeaveMergeSort.java similarity index 92% rename from src/sorts/hybrid/WeaveMergeSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/WeaveMergeSort.java index efbc61c9..56b7a3bf 100644 --- a/src/sorts/hybrid/WeaveMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/WeaveMergeSort.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class WeaveMergeSort extends Sort { +public final class WeaveMergeSort extends Sort { public WeaveMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Weave Merge"); this.setRunAllSortsName("Weave Merge Sort"); this.setRunSortName("Weave Mergesort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -47,29 +46,29 @@ public WeaveMergeSort(ArrayVisualizer arrayVisualizer) { private void weaveInsert(int[] arr, int start, int end) { int pos; - + for(int j = start; j < end; j++){ pos = j; - + Highlights.markArray(1, j); Highlights.clearMark(2); - + while(pos > start && Reads.compareValues(arr[pos], arr[pos - 1]) < 1) { Writes.swap(arr, pos, pos - 1, 0.2, true, false); pos--; } } } - + private void weaveMerge(int[] arr, int min, int max, int mid) { int i = 1; int target = (mid - min); - + while(i <= target) { Writes.multiSwap(arr, mid + i, min + (i * 2) - 1, 0.05, true, false); i++; } - + this.weaveInsert(arr, min, max + 1); } @@ -95,4 +94,4 @@ else if(max - min == 1) { //only two elements and swaps them public void runSort(int[] array, int currentLength, int bucketCount) { this.weaveMergeSort(array, 0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/WikiSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/WikiSort.java similarity index 76% rename from src/sorts/hybrid/WikiSort.java rename to src/main/java/io/github/arrayv/sorts/hybrid/WikiSort.java index 8d761ac7..454aa6f4 100644 --- a/src/sorts/hybrid/WikiSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/WikiSort.java @@ -1,12 +1,13 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; -import sorts.templates.WikiSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.sorts.templates.WikiSorting; /* - * + * This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or @@ -34,49 +35,41 @@ * */ +@SortMeta( + name = "Wiki", + category = "Hybrid Sorts", + question = "Enter external buffer size (0 for in-place):", + defaultAnswer = 0 +) public class WikiSort extends Sort { - private WikiSorting wikiSortInstance; // Just like TimSort, WikiSort cannot be simply written off as an abstract class, as it creates an - // instance of itself in order to track its state. Plus, it contains both instance and static methods, + private WikiSorting wikiSortInstance; // Just like TimSort, WikiSort cannot be simply written off as an abstract class, as it creates an + // instance of itself in order to track its state. Plus, it contains both instance and static methods, // requiring even more refactoring, which would be just doing unnecessary busy work. Instead of what // we've done for the rest of the algorithms, we'll favor composition over inheritance here and pass // "util" objects to it. - + private InsertionSort insertionSort; - + // Cache sizes for WikiSort - + // final private static int halfSize = (currentLen + 1) / 2; // final private static int squareRoot = (int) (Math.sqrt((currentLen + 1) / 2) + 1); // final private static int staticBuffer = 32; // final private static int noBuffer = 0; - + private int cache; - + public WikiSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Wiki"); - //this.setRunAllID("Wiki Sort (Block Merge Sort)"); - //this.setRunAllSortsName("Wiki Sort [Block Merge Sort]"); - this.setRunAllSortsName("Wikisort"); - this.setRunSortName("Wikisort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - this.setQuestion("Enter external buffer size (0 for in-place):", 0); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.cache = bucketCount; - + this.insertionSort = new InsertionSort(this.arrayVisualizer); this.wikiSortInstance = new WikiSorting(this.insertionSort, this.arrayVisualizer, this.cache); - + WikiSorting.sort(this.wikiSortInstance, array, currentLength); } -} \ No newline at end of file +} diff --git a/src/sorts/hybrid/YujisBufferedMergeSort2.java b/src/main/java/io/github/arrayv/sorts/hybrid/YujisBufferedMergeSort2.java similarity index 95% rename from src/sorts/hybrid/YujisBufferedMergeSort2.java rename to src/main/java/io/github/arrayv/sorts/hybrid/YujisBufferedMergeSort2.java index da966369..2a942aba 100644 --- a/src/sorts/hybrid/YujisBufferedMergeSort2.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/YujisBufferedMergeSort2.java @@ -1,10 +1,10 @@ -package sorts.hybrid; +package io.github.arrayv.sorts.hybrid; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 yuji, implemented by aphitorite, edited by dani_dlg @@ -30,17 +30,16 @@ of this software and associated documentation files (the "Software"), to deal */ -final public class YujisBufferedMergeSort2 extends Sort { - - +public final class YujisBufferedMergeSort2 extends Sort { + + public YujisBufferedMergeSort2(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Optimized A/Y Sort"); this.setRunAllSortsName("Optimized Andrey/Yuji Sort"); this.setRunSortName("Optimized Andrey/Yuji Sort"); this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -53,45 +52,45 @@ public static int ceilLog(int n) { for(i = 0; (1 << i) < n; i++); return i; } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; while(a > b) Writes.write(array, a, array[(a--)-1], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } - + private int binarySearch(int[] array, int start, int end, int value, boolean left) { int a = start, b = end; - + while(a < b) { int m = a+(b-a)/2; boolean comp; - + if(left) comp = Reads.compareValues(value, array[m]) <= 0; else comp = Reads.compareValues(value, array[m]) < 0; - + if(comp) b = m; else a = m+1; } - + return a; } - + private void binaryInsertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(array, i, this.binarySearch(array, a, i, array[i], false)); } - - + + private void mergeWithBufStatic(int[] array, int a, int m, int b, int p, boolean useBinarySearch) { int i = 0, j = m, k = a; - + if(useBinarySearch) { while(i < m-a && j < b) { if(Reads.compareValues(array[j], array[p+i]) == -1) { @@ -118,19 +117,19 @@ private void mergeWithBufStatic(int[] array, int a, int m, int b, int p, boolean } } } - + private int merge(int[] array, int a, int m, int b, int p) { int i = a, j = m; while(i < m && j < b) { if(Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); - else + else Writes.swap(array, p++, j++, 1, true, false); } int leftover = 0; while(i < m) { Writes.swap(array, p++, i++, 1, true, false); - + } while(j < b) { Writes.swap(array, p++, j++, 1, true, false); @@ -138,45 +137,45 @@ private int merge(int[] array, int a, int m, int b, int p) { } return leftover; } - + private void mergeSort(int[] array, int a, int p, int length) { int i, j = 16, pos, ceilLog = ceilLog(length); - + if(length > 16 && (ceilLog & 1) == 1) pos = p; else pos = a; - + for(i = pos; i+16 <= pos+length; i+=16) this.binaryInsertion(array, i, i+16); this.binaryInsertion(array, i, pos+length); - + int next = pos, posNext; while(j < length) { pos = next; next ^= a ^ p; posNext = next; - + for(i = pos; i+2*j <= pos+length; i+=2*j, posNext+=2*j) this.merge(array, i, i+j, i+2*j, posNext); if(i + j < pos+length) this.merge(array, i, i+j, pos+length, posNext); else while(i < pos+length) Writes.swap(array, i++, posNext++, 1, true, false); - + j *= 2; } } - + private void bufferedMerge(int[] array, int a, int b) { if(b-a <= 16) { this.binaryInsertion(array, a, b); return; } - + int m = (a+b+1)/2; this.mergeSort(array, m, 2*m-b, b-m); - + int n = (a+m+1)/2; //The 16 means that it will recursively sort 1/16 of the array. It's interesting to change that number and see how it affects performance int limit = (b-a)/16; @@ -186,18 +185,18 @@ private void bufferedMerge(int[] array, int a, int b) { m = n; n = (a+m+1)/2; } - + // the same as Andreysort's buffer redistribution this.bufferedMerge(array, a, m); this.multiSwap(array, a, b-(m-a), m-a); int s = this.merge(array, m, b-(m-a), b, a); this.bufferedMerge(array, b-(m-a)-s, b); - + } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.bufferedMerge(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/AATreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/AATreeSort.java similarity index 92% rename from src/sorts/insert/AATreeSort.java rename to src/main/java/io/github/arrayv/sorts/insert/AATreeSort.java index 936c513b..91aa6095 100644 --- a/src/sorts/insert/AATreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/AATreeSort.java @@ -1,249 +1,248 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * An implementation of a tree sort using an AA tree. - * - * @author Sam Walko (Anonymous0726) - */ -final public class AATreeSort extends Sort { - public AATreeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("AA Tree"); - this.setRunAllSortsName("Tree Sort (AA Balanced)"); - this.setRunSortName("Tree sort (AA Balanced)"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private Node NULL_NODE = new Node(); // (sub)tree of size 0 - - /** - * The fundamental building block of any programming tree. Each node is the - * root of its own subtree. In general, a node has the data being stored at - * that point, up to two children nodes, and (optionally) data for keeping - * the tree balanced. In the case of an AA tree, the data for balancing is - * an integer telling it's "level": how far above a leaf the node is. - */ - private class Node { - // main array (poor encapsulation since it's all the same but w/e) - private int[] array; - - private int pointer; // index in main array of the element contained here - private Node left, right; // left and right subtrees - - private int level; - - // Default constructor, and constructor for NULL_NODE - private Node() { - // Shouldn't point to anything by default - this.pointer = -1; - this.left = NULL_NODE; - this.right = NULL_NODE; - this.level = -1; // A NULL_NODE is level -1 - } - - // Constructor for a node with a pointer - private Node(int[] array, int pointer) { - this(); - this.array = array; - this.pointer = pointer; - this.level = 0; // A new element is always initially placed at level 0 - } - - /** - * Recursively adds an element to the subtree whose root is this node - * - * @param addPointer A pointer to the array telling what element is to be inserted - * @return the Node at to be located at this point - */ - private Node add(int addPointer) { - // Case 1: If this is where to add the new element, create a node for it - if(this == NULL_NODE) { - Highlights.clearMark(2); // No longer comparing to previous leaves - return new Node(array, addPointer); // Create the node and return it - } - - // If there's an element already here, we need to compare them to - // determine whether it should be placed in the left or the right subtree. - // Thus, mark the element at the pointer for comparison. - Highlights.markArray(2, pointer); - - // Case 2: The element is smaller and thus belongs in the left subtree - if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { - Delays.sleep(0.25); - - // Recursively get the root of the new left subtree - Node newLeft = left.add(addPointer); - - Highlights.markArray(2, pointer); - - // Set the root of the new left subtree as such - Writes.changeAuxWrites(1); - Writes.startLap(); - left = newLeft; - Writes.stopLap(); - Delays.sleep(0.05); - - // This handles the case where left subtree increased in height - if(left.level == level) { - if(level != right.level) // Often, a skew is all that's needed to - return skew(); // keep AA tree properties - - // Other times, we can skip the case where a skew is immediately - // followed by a split (i.e., a right rotation immediately - // followed by a left rotation) on the same subtree. - // My own independently discovered optimization. - level++; - return this; - } - - // Else, just return this node - return this; - } - - // Case 3: The element is equal or larger and thus belongs in the right subtree - // Note: As equality also results in right subtree, this sort is stable - Delays.sleep(0.25); - - // Recursively get the root of the new right subtree - Node newRight = right.add(addPointer); - - Highlights.markArray(2, pointer); - - // Set the root of the new right subtree as such - Writes.changeAuxWrites(1); - Writes.startLap(); - right = newRight; - Writes.stopLap(); - Delays.sleep(0.05); - - // This handles the case where right subtree's right subtree increased - // in height, requiring a split to keep AA tree properties - if(right.right.level == level) - return split(); - - // Else, just return this node - return this; - } - - /** - * Since the level of every left child is exactly one less than that of - * its parent, performs a skew to maintain this AA tree property. Helper - * method for add. Analogous to a single right rotation. - * - * @return the new root of this subtree - */ - private Node skew() { - Node l = left; - - Highlights.markArray(3, pointer); - Highlights.markArray(4, l.pointer); - - Writes.changeAuxWrites(2); - Writes.startLap(); - left = l.right; - l.right = this; - Writes.stopLap(); - Delays.sleep(0.25); - - Highlights.clearMark(3); - Highlights.clearMark(4); - - return l; - } - - /** - * Since only one consecutive right children may be on the same level, - * performs a skew to maintain this AA tree property. Helper method for - * add and skew. Analogous to a single left rotation. - * - * @return the new root of this subtree - */ - private Node split() { - Node r = right; - - Highlights.markArray(3, pointer); - Highlights.markArray(4, r.pointer); - - Writes.changeAuxWrites(2); - Writes.startLap(); - right = r.left; - r.left = this; - Writes.stopLap(); - Delays.sleep(0.25); - - r.level++; - - Highlights.clearMark(3); - Highlights.clearMark(4); - - return r; - } - - /** - * Performs an in-order traversal of the array and writes - * the values of the original array to a sorted temporary array - * - * @param tempArray the temporary array to write the contents of the subtree to - * @param location a pointer to the location in the temporary array to which the - * contents of the current subtree should be written to - * @return The size of subtree, used to determine where the next value should be - * written to. - */ - private int writeToArray(int[] tempArray, int location) { - if(this == NULL_NODE) return 0; - - int leftTreeSize = left.writeToArray(tempArray, location); - int newLocation = location + leftTreeSize; - - Highlights.markArray(1, pointer); - Writes.write(tempArray, newLocation, array[pointer], 0.1, false, true); - - int rightTreeSize = right.writeToArray(tempArray, newLocation + 1); - return leftTreeSize + rightTreeSize + 1; - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - // Tells the tree what array is to be sorted - NULL_NODE.array = array; - // Creates a tree of size 0, to which all elements will be added - Node root = NULL_NODE; - - // This loop adds every element of the array to be sorted into the tree - for(int i = 0; i < length; i++) { - Highlights.markArray(1, i); // Highlights the element being added - Node newRoot = root.add(i); - - Highlights.clearMark(2); - - Writes.changeAuxWrites(1); - Writes.startLap(); - root = newRoot; - Writes.stopLap(); - Delays.sleep(0.25); - - Highlights.clearAllMarks(); // Clearing all just in case - } - - // Write the contents of the tree to a temporary array - int[] tempArray = new int[length]; - root.writeToArray(tempArray, 0); - Highlights.clearMark(1); // No more elements being transferred to temporary array - - // Write the contents of the temporary array back to the main array - for(int i = 0; i < length; i++) { - Writes.write(array, i, tempArray[i], 1, true, false); - } - } -} +package io.github.arrayv.sorts.insert; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * An implementation of a tree sort using an AA tree. + * + * @author Sam Walko (Anonymous0726) + */ +public final class AATreeSort extends Sort { + public AATreeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + + this.setSortListName("AA Tree"); + this.setRunAllSortsName("Tree Sort (AA Balanced)"); + this.setRunSortName("Tree sort (AA Balanced)"); + this.setCategory("Insertion Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.setBogoSort(false); + } + + private Node NULL_NODE = new Node(); // (sub)tree of size 0 + + /** + * The fundamental building block of any programming tree. Each node is the + * root of its own subtree. In general, a node has the data being stored at + * that point, up to two children nodes, and (optionally) data for keeping + * the tree balanced. In the case of an AA tree, the data for balancing is + * an integer telling it's "level": how far above a leaf the node is. + */ + private class Node { + // main array (poor encapsulation since it's all the same but w/e) + private int[] array; + + private int pointer; // index in main array of the element contained here + private Node left, right; // left and right subtrees + + private int level; + + // Default constructor, and constructor for NULL_NODE + private Node() { + // Shouldn't point to anything by default + this.pointer = -1; + this.left = NULL_NODE; + this.right = NULL_NODE; + this.level = -1; // A NULL_NODE is level -1 + } + + // Constructor for a node with a pointer + private Node(int[] array, int pointer) { + this(); + this.array = array; + this.pointer = pointer; + this.level = 0; // A new element is always initially placed at level 0 + } + + /** + * Recursively adds an element to the subtree whose root is this node + * + * @param addPointer A pointer to the array telling what element is to be inserted + * @return the Node at to be located at this point + */ + private Node add(int addPointer) { + // Case 1: If this is where to add the new element, create a node for it + if(this == NULL_NODE) { + Highlights.clearMark(2); // No longer comparing to previous leaves + return new Node(array, addPointer); // Create the node and return it + } + + // If there's an element already here, we need to compare them to + // determine whether it should be placed in the left or the right subtree. + // Thus, mark the element at the pointer for comparison. + Highlights.markArray(2, pointer); + + // Case 2: The element is smaller and thus belongs in the left subtree + if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { + Delays.sleep(0.25); + + // Recursively get the root of the new left subtree + Node newLeft = left.add(addPointer); + + Highlights.markArray(2, pointer); + + // Set the root of the new left subtree as such + Writes.changeAuxWrites(1); + Writes.startLap(); + left = newLeft; + Writes.stopLap(); + Delays.sleep(0.05); + + // This handles the case where left subtree increased in height + if(left.level == level) { + if(level != right.level) // Often, a skew is all that's needed to + return skew(); // keep AA tree properties + + // Other times, we can skip the case where a skew is immediately + // followed by a split (i.e., a right rotation immediately + // followed by a left rotation) on the same subtree. + // My own independently discovered optimization. + level++; + return this; + } + + // Else, just return this node + return this; + } + + // Case 3: The element is equal or larger and thus belongs in the right subtree + // Note: As equality also results in right subtree, this sort is stable + Delays.sleep(0.25); + + // Recursively get the root of the new right subtree + Node newRight = right.add(addPointer); + + Highlights.markArray(2, pointer); + + // Set the root of the new right subtree as such + Writes.changeAuxWrites(1); + Writes.startLap(); + right = newRight; + Writes.stopLap(); + Delays.sleep(0.05); + + // This handles the case where right subtree's right subtree increased + // in height, requiring a split to keep AA tree properties + if(right.right.level == level) + return split(); + + // Else, just return this node + return this; + } + + /** + * Since the level of every left child is exactly one less than that of + * its parent, performs a skew to maintain this AA tree property. Helper + * method for add. Analogous to a single right rotation. + * + * @return the new root of this subtree + */ + private Node skew() { + Node l = left; + + Highlights.markArray(3, pointer); + Highlights.markArray(4, l.pointer); + + Writes.changeAuxWrites(2); + Writes.startLap(); + left = l.right; + l.right = this; + Writes.stopLap(); + Delays.sleep(0.25); + + Highlights.clearMark(3); + Highlights.clearMark(4); + + return l; + } + + /** + * Since only one consecutive right children may be on the same level, + * performs a skew to maintain this AA tree property. Helper method for + * add and skew. Analogous to a single left rotation. + * + * @return the new root of this subtree + */ + private Node split() { + Node r = right; + + Highlights.markArray(3, pointer); + Highlights.markArray(4, r.pointer); + + Writes.changeAuxWrites(2); + Writes.startLap(); + right = r.left; + r.left = this; + Writes.stopLap(); + Delays.sleep(0.25); + + r.level++; + + Highlights.clearMark(3); + Highlights.clearMark(4); + + return r; + } + + /** + * Performs an in-order traversal of the array and writes + * the values of the original array to a sorted temporary array + * + * @param tempArray the temporary array to write the contents of the subtree to + * @param location a pointer to the location in the temporary array to which the + * contents of the current subtree should be written to + * @return The size of subtree, used to determine where the next value should be + * written to. + */ + private int writeToArray(int[] tempArray, int location) { + if(this == NULL_NODE) return 0; + + int leftTreeSize = left.writeToArray(tempArray, location); + int newLocation = location + leftTreeSize; + + Highlights.markArray(1, pointer); + Writes.write(tempArray, newLocation, array[pointer], 0.1, false, true); + + int rightTreeSize = right.writeToArray(tempArray, newLocation + 1); + return leftTreeSize + rightTreeSize + 1; + } + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + // Tells the tree what array is to be sorted + NULL_NODE.array = array; + // Creates a tree of size 0, to which all elements will be added + Node root = NULL_NODE; + + // This loop adds every element of the array to be sorted into the tree + for(int i = 0; i < length; i++) { + Highlights.markArray(1, i); // Highlights the element being added + Node newRoot = root.add(i); + + Highlights.clearMark(2); + + Writes.changeAuxWrites(1); + Writes.startLap(); + root = newRoot; + Writes.stopLap(); + Delays.sleep(0.25); + + Highlights.clearAllMarks(); // Clearing all just in case + } + + // Write the contents of the tree to a temporary array + int[] tempArray = new int[length]; + root.writeToArray(tempArray, 0); + Highlights.clearMark(1); // No more elements being transferred to temporary array + + // Write the contents of the temporary array back to the main array + for(int i = 0; i < length; i++) { + Writes.write(array, i, tempArray[i], 1, true, false); + } + } +} diff --git a/src/sorts/insert/AVLTreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/AVLTreeSort.java similarity index 91% rename from src/sorts/insert/AVLTreeSort.java rename to src/main/java/io/github/arrayv/sorts/insert/AVLTreeSort.java index a1924ffd..c501fae9 100644 --- a/src/sorts/insert/AVLTreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/AVLTreeSort.java @@ -1,374 +1,373 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * An implementation of a tree sort using an AVL tree, - * based on what I learned in my CSSE230 class - * - * @author Sam Walko (Anonymous0726) - */ -final public class AVLTreeSort extends Sort { - public AVLTreeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("AVL Tree"); - this.setRunAllSortsName("Tree Sort (AVL Balanced)"); - this.setRunSortName("Tree sort (AVL Balanced)"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private Node NULL_NODE = new Node(); // (sub)tree of size 0 - - /** - * The fundamental building block of any programming tree. Each node is the - * root of its own subtree. In general, a node has the data being stored at - * that point, up to two children nodes, and (optionally) data for keeping - * the tree balanced. In the case of an AVL tree, the data for balancing is - * an integer telling it's "balance": the height of the right subtree minus - * the height of the left subtree. - */ - private class Node { - // main array (poor encapsulation since it's all the same but w/e) - private int[] array; - - private int pointer; // index in main array of the element contained here - private Node left, right; // left and right subtrees - - // height of right subtree minus height of left subtree - // by definition of an AVL tree, must be -1, 0, or 1 - private int balance; - - // Default constructor, and constructor for NULL_NODE - private Node() { - // Shouldn't point to anything by default - this.pointer = -1; - this.left = NULL_NODE; - this.right = NULL_NODE; - this.balance = 0; // A tree of size 0 is balanced - } - - // Constructor for a node with a pointer - private Node(int[] array, int pointer) { - this(); - this.array = array; - this.pointer = pointer; - } - - /** - * A return container for the recursive add method containing a Node - * and a boolean telling whether or not the subtree changed height - */ - private class AddContainer { - private Node node; - private boolean heightChange; - - private AddContainer(Node node, boolean heightChange) { - this.node = node; - this.heightChange = heightChange; - } - } - - /** - * Recursively adds an element to the subtree whose root is this node - * - * @param addPointer A pointer to the array telling what element is to be inserted - * @return an AddContainer containing the node that is now the root of this - * subtree, and the boolean telling whether or not this subtree increased in height - */ - private AddContainer add(int addPointer) { - // Case 1: If this is where to add the new element, create a node for it - if(this == NULL_NODE) { - Highlights.clearMark(2); // No longer comparing to previous leaves - Node newNode = new Node(array, addPointer); // Create the node - // Return the node, and the fact that the height obviously changed - // as there was no subtree here previously - return new AddContainer(newNode, true); - } - - // If there's an element already here, we need to compare them to - // determine whether it should be placed in the left or the right subtree. - // Thus, mark the element at the pointer for comparison. - Highlights.markArray(2, pointer); - - // Case 2: The element is smaller and thus belongs in the left subtree - if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { - Delays.sleep(0.25); - - // Recursively get the root of the new left subtree - AddContainer container = left.add(addPointer); - - Highlights.markArray(2, pointer); - - // Set the root of the new left subtree as such - Writes.changeAuxWrites(1); - Writes.startLap(); - left = container.node; - Writes.stopLap(); - Delays.sleep(0.05); - - // This handles the case where left subtree increased in - // height, possibly requiring rotations to keep balance - if(container.heightChange) - return heightChangeLeft(); - - // In the case where left subtree did not increase in height, - // return this node, and the fact that the height obviously - // did not change as neither of it subtrees changed in height - return new AddContainer(this, false); - // This is the boolean that took me about a day to fix, btw. - } - - // Case 3: The element is equal or larger and thus belongs in the right subtree - // Note: As equality also results in right subtree, this sort is stable - Delays.sleep(0.25); - - // Recursively get the root of the new right subtree - AddContainer container = right.add(addPointer); - - Highlights.markArray(2, pointer); - - // Set the root of the new right subtree as such - Writes.changeAuxWrites(1); - Writes.startLap(); - right = container.node; - Writes.stopLap(); - Delays.sleep(0.05); - - // This handles the case where right subtree increased in - // height, possibly requiring rotations to keep balance - if(container.heightChange) - return heightChangeRight(); - - // In the case where right subtree did not increase in height, - // return this node, and the fact that the height obviously - // did not change as neither of it subtrees changed in height - return new AddContainer(this, false); - // This is also the boolean that took me about a day to fix. - } - - /** - * Updates balance codes and rotates if necessary when the left subtree's - * height has increased. Helper method for add. - * - * @return an AddContainer including the node to be placed at the position - * and whether or not the left subtree's height has been changed - */ - private AddContainer heightChangeLeft() { - if(balance != -1) { // No rotation necessary - balance--; - // Trust me, this boolean works - return new AddContainer(this, balance == -1); - } - // Determine which type of rotation necessary. Note that after - // a rotation, the subtree height must not have changed. - if(left.balance == -1) - // Left-most subtree must be too large, so fix with single rotation - return new AddContainer(singleRotateRight(), false); - // Middle-left subtree must be too large, so fix with double rotation - return new AddContainer(doubleRotateRight(), false); - } - - /** - * Updates balance codes and rotates if necessary when the right subtree's - * height has increased. Helper method for add. - * - * @return an AddContainer including the node to be placed at the position - * and whether or not the right subtree's height has been changed - */ - private AddContainer heightChangeRight() { - if(balance != 1) { // No rotation necessary - balance++; - // Trust me, this boolean works - return new AddContainer(this, balance == 1); - } - // Determine which type of rotation necessary. Note that after - // a rotation, the subtree height must not have changed. - if(right.balance == 1) - // Right-most subtree must be too large, so fix with single rotation - return new AddContainer(singleRotateLeft(), false); - // Middle-right subtree must be too large, so fix with double rotation - return new AddContainer(doubleRotateLeft(), false); - } - - // These rotations are kinda magic (read: too difficult to explain without - // diagrams), so feel free to ask me (Anonymous0726#2452 on Discord) about it. - // Alternatively, the animations on Wikipedia are pretty good. - - /** - * Singly rotates the subtree right about the current node, - * updating balance codes along the way. Helper method for - * heightChangeLeft and heightChangeRight. - * - * @return the subtree's new root - */ - private Node singleRotateRight() { - Node b = left; - - Highlights.markArray(3, pointer); - Highlights.markArray(4, b.pointer); - - Writes.changeAuxWrites(2); - Writes.startLap(); - left = b.right; - b.right = this; - Writes.stopLap(); - Delays.sleep(0.25); - - balance = 0; - b.balance = 0; - - Highlights.clearMark(3); - Highlights.clearMark(4); - - return b; - } - - /** - * Singly rotates the subtree left about the current node, - * updating balance codes along the way. Helper method for - * heightChangeLeft and heightChangeRight. - * - * @return the subtree's new root - */ - private Node singleRotateLeft() { - Node b = right; - - Highlights.markArray(3, pointer); - Highlights.markArray(4, b.pointer); - - Writes.changeAuxWrites(2); - Writes.startLap(); - right = b.left; - b.left = this; - Writes.stopLap(); - Delays.sleep(0.25); - - balance = 0; - b.balance = 0; - - Highlights.clearMark(3); - Highlights.clearMark(4); - - return b; - } - - /** - * Singly rotates the subtree right about the current node, updating balance - * codes along the way. Also known as a left-right rotation. Helper method for - * heightChangeLeft. - * - * @return the subtree's new root - */ - private Node doubleRotateRight() { - int oldBBalance = left.right.balance; - - Node newLeft = left.singleRotateLeft(); - Writes.changeAuxWrites(1); - Writes.startLap(); - left = newLeft; - Writes.stopLap(); - Delays.sleep(0.25); - - Node b = singleRotateRight(); - - if(oldBBalance == -1) - b.right.balance = 1; - if(oldBBalance == 1) - b.left.balance = -1; - - return b; - } - - /** - * Singly rotates the subtree left about the current node, updating balance - * codes along the way. Also known as a right-left rotation. Helper method for - * heightChangeRight. - * - * @return the subtree's new root - */ - private Node doubleRotateLeft() { - int oldBBalance = right.left.balance; - - Node newRight = right.singleRotateRight(); - Writes.changeAuxWrites(1); - Writes.startLap(); - right = newRight; - Writes.stopLap(); - Delays.sleep(0.25); - - Node b = singleRotateLeft(); - - if(oldBBalance == -1) - b.right.balance = 1; - if(oldBBalance == 1) - b.left.balance = -1; - - return b; - } - - /** - * Performs an in-order traversal of the array and writes - * the values of the original array to a sorted temporary array - * - * @param tempArray the temporary array to write the contents of the subtree to - * @param location a pointer to the location in the temporary array to which the - * contents of the current subtree should be written to - * @return The size of subtree, used to determine where the next value should be - * written to. - */ - private int writeToArray(int[] tempArray, int location) { - if(this == NULL_NODE) return 0; - - int leftTreeSize = left.writeToArray(tempArray, location); - int newLocation = location + leftTreeSize; - - Highlights.markArray(1, pointer); - Writes.write(tempArray, newLocation, array[pointer], 0.1, false, true); - - int rightTreeSize = right.writeToArray(tempArray, newLocation + 1); - return leftTreeSize + rightTreeSize + 1; - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - // Tells the tree what array is to be sorted - NULL_NODE.array = array; - // Creates a tree of size 0, to which all elements will be added - Node root = NULL_NODE; - - // This loop adds every element of the array to be sorted into the tree - for(int i = 0; i < length; i++) { - Highlights.markArray(1, i); // Highlights the element being added - Node.AddContainer container = root.add(i); - - Highlights.clearMark(2); - - Writes.changeAuxWrites(1); - Writes.startLap(); - root = container.node; - Writes.stopLap(); - Delays.sleep(0.25); - - Highlights.clearAllMarks(); // Clearing all just in case - } - - // Write the contents of the tree to a temporary array - int[] tempArray = new int[length]; - root.writeToArray(tempArray, 0); - Highlights.clearMark(1); // No more elements being transferred to temporary array - - // Write the contents of the temporary array back to the main array - for(int i = 0; i < length; i++) { - Writes.write(array, i, tempArray[i], 1, true, false); - } - } -} +package io.github.arrayv.sorts.insert; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * An implementation of a tree sort using an AVL tree, + * based on what I learned in my CSSE230 class + * + * @author Sam Walko (Anonymous0726) + */ +public final class AVLTreeSort extends Sort { + public AVLTreeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + + this.setSortListName("AVL Tree"); + this.setRunAllSortsName("Tree Sort (AVL Balanced)"); + this.setRunSortName("Tree sort (AVL Balanced)"); + this.setCategory("Insertion Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.setBogoSort(false); + } + + private Node NULL_NODE = new Node(); // (sub)tree of size 0 + + /** + * The fundamental building block of any programming tree. Each node is the + * root of its own subtree. In general, a node has the data being stored at + * that point, up to two children nodes, and (optionally) data for keeping + * the tree balanced. In the case of an AVL tree, the data for balancing is + * an integer telling it's "balance": the height of the right subtree minus + * the height of the left subtree. + */ + private class Node { + // main array (poor encapsulation since it's all the same but w/e) + private int[] array; + + private int pointer; // index in main array of the element contained here + private Node left, right; // left and right subtrees + + // height of right subtree minus height of left subtree + // by definition of an AVL tree, must be -1, 0, or 1 + private int balance; + + // Default constructor, and constructor for NULL_NODE + private Node() { + // Shouldn't point to anything by default + this.pointer = -1; + this.left = NULL_NODE; + this.right = NULL_NODE; + this.balance = 0; // A tree of size 0 is balanced + } + + // Constructor for a node with a pointer + private Node(int[] array, int pointer) { + this(); + this.array = array; + this.pointer = pointer; + } + + /** + * A return container for the recursive add method containing a Node + * and a boolean telling whether or not the subtree changed height + */ + private class AddContainer { + private Node node; + private boolean heightChange; + + private AddContainer(Node node, boolean heightChange) { + this.node = node; + this.heightChange = heightChange; + } + } + + /** + * Recursively adds an element to the subtree whose root is this node + * + * @param addPointer A pointer to the array telling what element is to be inserted + * @return an AddContainer containing the node that is now the root of this + * subtree, and the boolean telling whether or not this subtree increased in height + */ + private AddContainer add(int addPointer) { + // Case 1: If this is where to add the new element, create a node for it + if(this == NULL_NODE) { + Highlights.clearMark(2); // No longer comparing to previous leaves + Node newNode = new Node(array, addPointer); // Create the node + // Return the node, and the fact that the height obviously changed + // as there was no subtree here previously + return new AddContainer(newNode, true); + } + + // If there's an element already here, we need to compare them to + // determine whether it should be placed in the left or the right subtree. + // Thus, mark the element at the pointer for comparison. + Highlights.markArray(2, pointer); + + // Case 2: The element is smaller and thus belongs in the left subtree + if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { + Delays.sleep(0.25); + + // Recursively get the root of the new left subtree + AddContainer container = left.add(addPointer); + + Highlights.markArray(2, pointer); + + // Set the root of the new left subtree as such + Writes.changeAuxWrites(1); + Writes.startLap(); + left = container.node; + Writes.stopLap(); + Delays.sleep(0.05); + + // This handles the case where left subtree increased in + // height, possibly requiring rotations to keep balance + if(container.heightChange) + return heightChangeLeft(); + + // In the case where left subtree did not increase in height, + // return this node, and the fact that the height obviously + // did not change as neither of it subtrees changed in height + return new AddContainer(this, false); + // This is the boolean that took me about a day to fix, btw. + } + + // Case 3: The element is equal or larger and thus belongs in the right subtree + // Note: As equality also results in right subtree, this sort is stable + Delays.sleep(0.25); + + // Recursively get the root of the new right subtree + AddContainer container = right.add(addPointer); + + Highlights.markArray(2, pointer); + + // Set the root of the new right subtree as such + Writes.changeAuxWrites(1); + Writes.startLap(); + right = container.node; + Writes.stopLap(); + Delays.sleep(0.05); + + // This handles the case where right subtree increased in + // height, possibly requiring rotations to keep balance + if(container.heightChange) + return heightChangeRight(); + + // In the case where right subtree did not increase in height, + // return this node, and the fact that the height obviously + // did not change as neither of it subtrees changed in height + return new AddContainer(this, false); + // This is also the boolean that took me about a day to fix. + } + + /** + * Updates balance codes and rotates if necessary when the left subtree's + * height has increased. Helper method for add. + * + * @return an AddContainer including the node to be placed at the position + * and whether or not the left subtree's height has been changed + */ + private AddContainer heightChangeLeft() { + if(balance != -1) { // No rotation necessary + balance--; + // Trust me, this boolean works + return new AddContainer(this, balance == -1); + } + // Determine which type of rotation necessary. Note that after + // a rotation, the subtree height must not have changed. + if(left.balance == -1) + // Left-most subtree must be too large, so fix with single rotation + return new AddContainer(singleRotateRight(), false); + // Middle-left subtree must be too large, so fix with double rotation + return new AddContainer(doubleRotateRight(), false); + } + + /** + * Updates balance codes and rotates if necessary when the right subtree's + * height has increased. Helper method for add. + * + * @return an AddContainer including the node to be placed at the position + * and whether or not the right subtree's height has been changed + */ + private AddContainer heightChangeRight() { + if(balance != 1) { // No rotation necessary + balance++; + // Trust me, this boolean works + return new AddContainer(this, balance == 1); + } + // Determine which type of rotation necessary. Note that after + // a rotation, the subtree height must not have changed. + if(right.balance == 1) + // Right-most subtree must be too large, so fix with single rotation + return new AddContainer(singleRotateLeft(), false); + // Middle-right subtree must be too large, so fix with double rotation + return new AddContainer(doubleRotateLeft(), false); + } + + // These rotations are kinda magic (read: too difficult to explain without + // diagrams), so feel free to ask me (Anonymous0726#2452 on Discord) about it. + // Alternatively, the animations on Wikipedia are pretty good. + + /** + * Singly rotates the subtree right about the current node, + * updating balance codes along the way. Helper method for + * heightChangeLeft and heightChangeRight. + * + * @return the subtree's new root + */ + private Node singleRotateRight() { + Node b = left; + + Highlights.markArray(3, pointer); + Highlights.markArray(4, b.pointer); + + Writes.changeAuxWrites(2); + Writes.startLap(); + left = b.right; + b.right = this; + Writes.stopLap(); + Delays.sleep(0.25); + + balance = 0; + b.balance = 0; + + Highlights.clearMark(3); + Highlights.clearMark(4); + + return b; + } + + /** + * Singly rotates the subtree left about the current node, + * updating balance codes along the way. Helper method for + * heightChangeLeft and heightChangeRight. + * + * @return the subtree's new root + */ + private Node singleRotateLeft() { + Node b = right; + + Highlights.markArray(3, pointer); + Highlights.markArray(4, b.pointer); + + Writes.changeAuxWrites(2); + Writes.startLap(); + right = b.left; + b.left = this; + Writes.stopLap(); + Delays.sleep(0.25); + + balance = 0; + b.balance = 0; + + Highlights.clearMark(3); + Highlights.clearMark(4); + + return b; + } + + /** + * Singly rotates the subtree right about the current node, updating balance + * codes along the way. Also known as a left-right rotation. Helper method for + * heightChangeLeft. + * + * @return the subtree's new root + */ + private Node doubleRotateRight() { + int oldBBalance = left.right.balance; + + Node newLeft = left.singleRotateLeft(); + Writes.changeAuxWrites(1); + Writes.startLap(); + left = newLeft; + Writes.stopLap(); + Delays.sleep(0.25); + + Node b = singleRotateRight(); + + if(oldBBalance == -1) + b.right.balance = 1; + if(oldBBalance == 1) + b.left.balance = -1; + + return b; + } + + /** + * Singly rotates the subtree left about the current node, updating balance + * codes along the way. Also known as a right-left rotation. Helper method for + * heightChangeRight. + * + * @return the subtree's new root + */ + private Node doubleRotateLeft() { + int oldBBalance = right.left.balance; + + Node newRight = right.singleRotateRight(); + Writes.changeAuxWrites(1); + Writes.startLap(); + right = newRight; + Writes.stopLap(); + Delays.sleep(0.25); + + Node b = singleRotateLeft(); + + if(oldBBalance == -1) + b.right.balance = 1; + if(oldBBalance == 1) + b.left.balance = -1; + + return b; + } + + /** + * Performs an in-order traversal of the array and writes + * the values of the original array to a sorted temporary array + * + * @param tempArray the temporary array to write the contents of the subtree to + * @param location a pointer to the location in the temporary array to which the + * contents of the current subtree should be written to + * @return The size of subtree, used to determine where the next value should be + * written to. + */ + private int writeToArray(int[] tempArray, int location) { + if(this == NULL_NODE) return 0; + + int leftTreeSize = left.writeToArray(tempArray, location); + int newLocation = location + leftTreeSize; + + Highlights.markArray(1, pointer); + Writes.write(tempArray, newLocation, array[pointer], 0.1, false, true); + + int rightTreeSize = right.writeToArray(tempArray, newLocation + 1); + return leftTreeSize + rightTreeSize + 1; + } + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + // Tells the tree what array is to be sorted + NULL_NODE.array = array; + // Creates a tree of size 0, to which all elements will be added + Node root = NULL_NODE; + + // This loop adds every element of the array to be sorted into the tree + for(int i = 0; i < length; i++) { + Highlights.markArray(1, i); // Highlights the element being added + Node.AddContainer container = root.add(i); + + Highlights.clearMark(2); + + Writes.changeAuxWrites(1); + Writes.startLap(); + root = container.node; + Writes.stopLap(); + Delays.sleep(0.25); + + Highlights.clearAllMarks(); // Clearing all just in case + } + + // Write the contents of the tree to a temporary array + int[] tempArray = new int[length]; + root.writeToArray(tempArray, 0); + Highlights.clearMark(1); // No more elements being transferred to temporary array + + // Write the contents of the temporary array back to the main array + for(int i = 0; i < length; i++) { + Writes.write(array, i, tempArray[i], 1, true, false); + } + } +} diff --git a/src/sorts/insert/BinaryDoubleInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/BinaryDoubleInsertionSort.java similarity index 91% rename from src/sorts/insert/BinaryDoubleInsertionSort.java rename to src/main/java/io/github/arrayv/sorts/insert/BinaryDoubleInsertionSort.java index 0126fa60..aaf295f1 100644 --- a/src/sorts/insert/BinaryDoubleInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/BinaryDoubleInsertionSort.java @@ -1,10 +1,10 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 Gaming32 Morewenn and aphitorite @@ -29,86 +29,85 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class BinaryDoubleInsertionSort extends Sort { +public final class BinaryDoubleInsertionSort extends Sort { public BinaryDoubleInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Binary Double Insertion"); this.setRunAllSortsName("Binary Double Insertion Sort"); this.setRunSortName("Binary Double Insertsort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int leftBinarySearch(int[] array, int a, int b, int val, double sleep) { while(a < b) { int m = a+(b-a)/2; - + Highlights.markArray(1, a); Highlights.markArray(2, m); Highlights.markArray(3, b); Delays.sleep(sleep); - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; else a = m+1; } - + return a; } private int rightBinarySearch(int[] array, int a, int b, int val, double sleep) { while(a < b) { int m = a+(b-a)/2; - + Highlights.markArray(1, a); Highlights.markArray(2, m); Highlights.markArray(3, b); Delays.sleep(sleep); - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; else a = m+1; } - + return a; } - + private void insertToLeft(int[] array, int a, int b, int temp, double sleep) { Highlights.clearMark(2); - + while(a > b) Writes.write(array, a, array[--a], sleep, true, false); Writes.write(array, b, temp, sleep, true, false); } private void insertToRight(int[] array, int a, int b, int temp, double sleep) { Highlights.clearMark(2); - + while(a < b) Writes.write(array, a, array[++a], sleep, true, false); Writes.write(array, a, temp, sleep, true, false); } - + public void doubleInsertion(int[] array, int a, int b, double compSleep, double sleep) { if(b-a < 2) return; - + int j = a+(b-a-2)/2+1, i = a+(b-a-1)/2; - + if(j > i && Reads.compareIndices(array, i, j, compSleep, true) == 1) Writes.swap(array, i, j, compSleep, true, false); - + i--; j++; - + while(j < b) { if(Reads.compareIndices(array, i, j, compSleep, true) == 1) { int l = array[j]; int r = array[i]; - + int m = this.rightBinarySearch(array, i+1, j, l, compSleep); this.insertToRight(array, i, m-1, l, sleep); this.insertToLeft(array, j, this.leftBinarySearch(array, m, j, r, compSleep), r, sleep); @@ -116,7 +115,7 @@ public void doubleInsertion(int[] array, int a, int b, double compSleep, double else { int l = array[i]; int r = array[j]; - + int m = this.leftBinarySearch(array, i+1, j, l, compSleep); this.insertToRight(array, i, m-1, l, sleep); this.insertToLeft(array, j, this.rightBinarySearch(array, m, j, r, compSleep), r, sleep); @@ -126,13 +125,13 @@ public void doubleInsertion(int[] array, int a, int b, double compSleep, double } Highlights.clearAllMarks(); } - + public void customDoubleInsert(int[] array, int a, int b, double sleep) { this.doubleInsertion(array, a, b, sleep, sleep); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.doubleInsertion(array, 0, currentLength, 1, 0.05); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/BinaryInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/BinaryInsertionSort.java similarity index 89% rename from src/sorts/insert/BinaryInsertionSort.java rename to src/main/java/io/github/arrayv/sorts/insert/BinaryInsertionSort.java index 00487230..40ea0f08 100644 --- a/src/sorts/insert/BinaryInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/BinaryInsertionSort.java @@ -1,10 +1,10 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.BinaryInsertionSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.BinaryInsertionSorting; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class BinaryInsertionSort extends BinaryInsertionSorting { +public final class BinaryInsertionSort extends BinaryInsertionSorting { public BinaryInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,7 +37,6 @@ public BinaryInsertionSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Binary Insertion Sort"); this.setRunSortName("Binary Insertsort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -48,9 +47,9 @@ public BinaryInsertionSort(ArrayVisualizer arrayVisualizer) { public void customBinaryInsert(int[] array, int start, int end, double sleep) { this.binaryInsertSort(array, start, end, sleep, sleep); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.binaryInsertSort(array, 0, currentLength, 1, 0.05); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/BlockInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/BlockInsertionSort.java similarity index 91% rename from src/sorts/insert/BlockInsertionSort.java rename to src/main/java/io/github/arrayv/sorts/insert/BlockInsertionSort.java index 739603cd..e12a6fa2 100644 --- a/src/sorts/insert/BlockInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/BlockInsertionSort.java @@ -1,18 +1,17 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.GrailSorting; -import utils.Rotations; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.GrailSorting; +import io.github.arrayv.utils.Rotations; -final public class BlockInsertionSort extends GrailSorting { +public final class BlockInsertionSort extends GrailSorting { public BlockInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Block Insertion"); this.setRunAllSortsName("Block Insertion Sort"); this.setRunSortName("Block Insertsort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -79,9 +78,9 @@ public void insertionSort(int[] array, int a, int b) { i = j; } } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { insertionSort(array, 0, currentLength); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/ClassicTreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/ClassicTreeSort.java similarity index 93% rename from src/sorts/insert/ClassicTreeSort.java rename to src/main/java/io/github/arrayv/sorts/insert/ClassicTreeSort.java index 9e1a7c23..1b588636 100644 --- a/src/sorts/insert/ClassicTreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/ClassicTreeSort.java @@ -1,10 +1,10 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -28,35 +28,34 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - -final public class ClassicTreeSort extends Sort { + +public final class ClassicTreeSort extends Sort { public ClassicTreeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Classic Tree"); this.setRunAllSortsName("Classic Unbalanced Tree Sort"); this.setRunSortName("Classic Unbalanced Treesort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int idx; - + private void traverse(int[] array, int[] temp, int[] lower, int[] upper, int r) { Highlights.markArray(1, r); Delays.sleep(1); - + if(lower[r] != 0) this.traverse(array, temp, lower, upper, lower[r]); - + Writes.write(temp, this.idx++, array[r], 0, false, true); Highlights.markArray(1, r); Delays.sleep(1); - + if(upper[r] != 0) this.traverse(array, temp, lower, upper, upper[r]); } @@ -65,17 +64,17 @@ public void runSort(int[] array, int currentLength, int bucketCount) { int[] lower = Writes.createExternalArray(currentLength); int[] upper = Writes.createExternalArray(currentLength); int[] next; - + for(int i = 1; i < currentLength; i++) { Highlights.markArray(2, i); int c = 0; - + while(true) { Highlights.markArray(1, c); Delays.sleep(0.5); - + next = Reads.compareValues(array[i], array[c]) < 0 ? lower : upper; - + if(next[c] == 0) { Writes.write(next, c, i, 0, false, true); break; @@ -84,14 +83,14 @@ public void runSort(int[] array, int currentLength, int bucketCount) { } } Highlights.clearMark(2); - + int[] temp = Writes.createExternalArray(currentLength); this.idx = 0; this.traverse(array, temp, lower, upper, 0); Writes.arraycopy(temp, 0, array, 0, currentLength, 1, true, false); - + Writes.deleteExternalArray(lower); Writes.deleteExternalArray(upper); Writes.deleteExternalArray(temp); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/DoubleInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/DoubleInsertionSort.java similarity index 95% rename from src/sorts/insert/DoubleInsertionSort.java rename to src/main/java/io/github/arrayv/sorts/insert/DoubleInsertionSort.java index 29a3e793..74dfac4e 100644 --- a/src/sorts/insert/DoubleInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/DoubleInsertionSort.java @@ -1,7 +1,7 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class DoubleInsertionSort extends Sort { +public final class DoubleInsertionSort extends Sort { public DoubleInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,7 +37,6 @@ public DoubleInsertionSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Double Insertion Sort"); this.setRunSortName("Double Insertsort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -115,4 +114,4 @@ public void customInsertSort(int[] array, int start, int end, double sleep, bool public void runSort(int[] array, int currentLength, int bucketCount) { this.insertionSort(array, 0, currentLength, 0.015, false); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/HanoiSort.java b/src/main/java/io/github/arrayv/sorts/insert/HanoiSort.java similarity index 94% rename from src/sorts/insert/HanoiSort.java rename to src/main/java/io/github/arrayv/sorts/insert/HanoiSort.java index 174a016c..849eddaa 100644 --- a/src/sorts/insert/HanoiSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/HanoiSort.java @@ -1,327 +1,326 @@ -package sorts.insert; - -import java.util.Stack; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * Hanoi Sort, a sort inspired by the classic Tower of Hanoi puzzle.

- * - * This sort started as a random idea I had, with a vague idea of how I could approach - * the problem. And this is, in fact, the first complete implementation that I know of. - * However, I was greatly helped by two people before me. The first was Andrei "Mrrl" - * Astrelin (rip), who wrote some pseudocode for this sort that helped solidify the - * ideas that I'd been having. However, this pseudocode failed to explain how to shift - * more than one element from one stack to another without violating the traditional - * rules of the Tower of Hanoi puzzle. Since the sort didn't know the recursion depth - * that would be required, an iterative shift would be necessary; I found a simple - * algorithm for this at Stack Overflow. There were still loose ends I had to wrap up; - * in particular, for the aforementioned iterative hanoi function to work, I had to - * ensure all consecutive identical items were moved together. But I made it work, and - * thus here I present the first implementation of this sort that I am aware of. - * - * @author Sam Walko (Anonymous0726) - * @see - * Mrrl's Hanoi Sort pseudocode - * @see - * Iterative algorithm for Tower of Hanoi problem - */ -final public class HanoiSort extends Sort { - // main array - private int[] array; - // Length of the array - private int length; - // Auxiliary stacks from the classic Tower of Hanoi problem - private Stack stack2, stack3; - // sp is a "stack pointer" for the main array (which isn't actually a stack) - private int sp; - // Where the unsorted portion of the main array begins - private int unsorted; - // These are used in determining end conditions for the hanoi function - private int target; - private int targetMoves; - - public HanoiSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Hanoi"); - this.setRunAllSortsName("Hanoi Sort"); - this.setRunSortName("Hanoi sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(32); - this.setBogoSort(false); - } - - /** - * Moves an element (or group of identical elements) from the unsorted - * portion of the main array into stack2 using the hanoi function. - */ - private void removeFromMainStack() { - Highlights.markArray(2, sp); - target = array[sp]; - - int moves = hanoi(2, true, 1); - int height = getHeight(moves + 1); - targetMoves = moves; - boolean evenHeight = height % 2 == 0; - - Highlights.clearAllMarks(); - Highlights.markArray(1, sp); - - if(evenHeight) // Move smaller elements to stack3, if necessary - hanoi(1, true, 2); - unsorted += moveFromMain(stack2, false); // Move next element(s) to stack2 - hanoi(3, evenHeight, 2); // Move smaller elements back to stack2 - - } - - /** - * Moves all of the elements, currently in order on stack2, - * back to the main array using the hanoi function - */ - private void returnToMainStack() { - int moves = hanoi(2, true, 3); - int height = getHeight(moves + 1); - if(height % 2 == 1) { // Odd height case: moved to stack3 - targetMoves = moves; - hanoi(3, true, 2); - } // In even case, it's already on main stack, and we need not do anything - } - - /** - * Iteratively moves elements around the stacks according to the - * Tower of Hanoi problem. Recursion cannot be used because in many - * cases we do not know the initial recursion depth. - * - * @param startStack Which stack we wish to move a tower from - * @param goRight Whether the smallest disk should go right on the pegs - * (1->2, 2->3, 3->1) or left (1->3, 2->1, 3->2) - * @param endCon Used to determine when to end this function - * @return The number of moves performed - */ - private int hanoi(int startStack, boolean goRight, int endCon) { - int moves = 0; - int minPoleLoc = startStack; - - if(!endConMet(endCon, moves)) { - moves++; - switch(minPoleLoc) { - case 1: - if(goRight) { - moveFromMain(stack2, true); - minPoleLoc = 2; - } else { - moveFromMain(stack3, true); - minPoleLoc = 3; - } break; - case 2: - if(goRight) { - moveBetweenStacks(stack2, stack3); - minPoleLoc = 3; - } else { - moveToMain(stack2); - minPoleLoc = 1; - } break; - case 3: - if(goRight) { - moveToMain(stack3); - minPoleLoc = 1; - } else { - moveBetweenStacks(stack3, stack2); - minPoleLoc = 2; - } break; - } - } - - while(!endConMet(endCon, moves)) { - moves += 2; - switch(minPoleLoc) { - case 1: - if(!stack2.isEmpty() && - (stack3.isEmpty() || Reads.compareValues(stack2.peek(), stack3.peek()) < 0)) - moveBetweenStacks(stack2, stack3); - else - moveBetweenStacks(stack3, stack2); - if(goRight) { - moveFromMain(stack2, true); - minPoleLoc = 2; - } else { - moveFromMain(stack3, true); - minPoleLoc = 3; - } break; - case 2: - if(stack3.isEmpty() || - (sp < unsorted && Reads.compareValues(array[sp], stack3.peek()) < 0)) - moveFromMain(stack3, true); - else - moveToMain(stack3); - if(goRight) { - moveBetweenStacks(stack2, stack3); - minPoleLoc = 3; - } else { - moveToMain(stack2); - minPoleLoc = 1; - } break; - case 3: - if(stack2.isEmpty() || - (sp < unsorted && Reads.compareValues(array[sp], stack2.peek()) < 0)) - moveFromMain(stack2, true); - else - moveToMain(stack2); - if(goRight) { - moveToMain(stack3); - minPoleLoc = 1; - } else { - moveBetweenStacks(stack3, stack2); - minPoleLoc = 2; - } break; - } - } - - return moves; - } - - /** - * Determines whether or not the hanoi function should end now - * - * @param endCon Which ending condition is required for the hanoi function to end - * @param moves the moves completed by the hanoi function so far - * @return Whether or not the end condition has been met - */ - private boolean endConMet(int endCon, int moves) { - if(!validNumberMoves(moves)) - return false; - switch (endCon) { - case 1: return (stack2.isEmpty() || Reads.compareValues(target, stack2.peek()) <= 0); - case 2: return moves == targetMoves; - case 3: return stack2.isEmpty(); - default: throw new IllegalArgumentException(); - } - } - - /** - * @param moves The number of moves completed so far - * @return If the moves is of the form (2^n)-1 - */ - private boolean validNumberMoves(int moves) { - if(moves == 0) - return true; - if(moves % 2 == 0) - return false; - return validNumberMoves(moves/2); - } - - /** - * Figures out the height of the pyramid moved based on number of moves - * - * @param movesPlus1 The number of moves performed, plus one - * @return The height of the pyramid moved (equal to log_2(moves + 1)) - */ - private int getHeight(int movesPlus1) { - if(movesPlus1 == 1) - return 0; - return getHeight(movesPlus1 / 2) + 1; - } - - /** - * Moves an element from the main array to another stack, - * then moves any consecutive duplicates of that element with it - * - * @param stack The stack to move the element(s) from the main array to - * @param checkUnsorted Whether or not it is safe to remove elements in - * the unsorted portion of the main array - * @return duplicates The number of consecutive identical elements - * that were popped off the main array in the current "move" - */ - private int moveFromMain(Stack stack, boolean checkUnsorted) { - int duplicates = 1; - // Move element - Writes.changeAuxWrites(1); - Writes.startLap(); - stack.push(array[sp]); - Writes.stopLap(); - sp++; - Highlights.markArray(1, sp); - Delays.sleep(0.25); - // Move any duplicates (endOnLength indicates the relevant portion of - // the main stack is "empty") - boolean endOnLength = (sp >= length) || (checkUnsorted && sp >= unsorted); - while(!endOnLength && Reads.compareValues(array[sp], stack.peek()) == 0) { - duplicates++; - Writes.changeAuxWrites(1); - Writes.startLap(); - stack.push(array[sp]); - Writes.stopLap(); - sp++; - Highlights.markArray(1, sp); - Delays.sleep(0.25); - endOnLength = (sp >= length) || (checkUnsorted && sp >= unsorted); - } - return duplicates; - } - - /** - * Moves an element to the main array from another stack, - * then moves any consecutive duplicates of that element with it - * - * @param stack The stack to move the element(s) to the main array from - */ - private void moveToMain(Stack stack) { - // Move element - sp--; - Highlights.markArray(1, sp); - Writes.write(array, sp, stack.pop(), 0.25, false, false); - // Move any duplicates - while(!stack.isEmpty() && Reads.compareValues(stack.peek(), array[sp]) == 0) { - sp--; - Highlights.markArray(1, sp); - Writes.write(array, sp, stack.pop(), 0.25, false, false); - } - } - - /** - * Moves an element from one stack to another stack, - * then moves any consecutive duplicates of that element with it - * - * @param from the stack to move the element(s) from - * @param to the stack to move the element(s) to - */ - private void moveBetweenStacks(Stack from, Stack to) { - // Move element - Writes.changeAuxWrites(1); - Writes.startLap(); - to.push(from.pop()); - Writes.stopLap(); - Delays.sleep(0.25); - // Move any duplicates - while(!from.isEmpty() && Reads.compareValues(from.peek(), to.peek()) == 0) { - Writes.changeAuxWrites(1); - Writes.startLap(); - to.push(from.pop()); - Writes.stopLap(); - Delays.sleep(0.25); - } - } - - - @Override - public void runSort(int[] array, int length, int bucketCount) { - // Initialize local variables - this.array = array; - this.length = length; - stack2 = new Stack(); - stack3 = new Stack(); - sp = 0; - unsorted = 0; - - while(unsorted < length) - removeFromMainStack(); - - returnToMainStack(); - } -} +package io.github.arrayv.sorts.insert; + +import java.util.Stack; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * Hanoi Sort, a sort inspired by the classic Tower of Hanoi puzzle.

+ * + * This sort started as a random idea I had, with a vague idea of how I could approach + * the problem. And this is, in fact, the first complete implementation that I know of. + * However, I was greatly helped by two people before me. The first was Andrei "Mrrl" + * Astrelin (rip), who wrote some pseudocode for this sort that helped solidify the + * ideas that I'd been having. However, this pseudocode failed to explain how to shift + * more than one element from one stack to another without violating the traditional + * rules of the Tower of Hanoi puzzle. Since the sort didn't know the recursion depth + * that would be required, an iterative shift would be necessary; I found a simple + * algorithm for this at Stack Overflow. There were still loose ends I had to wrap up; + * in particular, for the aforementioned iterative hanoi function to work, I had to + * ensure all consecutive identical items were moved together. But I made it work, and + * thus here I present the first implementation of this sort that I am aware of. + * + * @author Sam Walko (Anonymous0726) + * @see + * Mrrl's Hanoi Sort pseudocode + * @see + * Iterative algorithm for Tower of Hanoi problem + */ +public final class HanoiSort extends Sort { + // main array + private int[] array; + // Length of the array + private int length; + // Auxiliary stacks from the classic Tower of Hanoi problem + private Stack stack2, stack3; + // sp is a "stack pointer" for the main array (which isn't actually a stack) + private int sp; + // Where the unsorted portion of the main array begins + private int unsorted; + // These are used in determining end conditions for the hanoi function + private int target; + private int targetMoves; + + public HanoiSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + + this.setSortListName("Hanoi"); + this.setRunAllSortsName("Hanoi Sort"); + this.setRunSortName("Hanoi sort"); + this.setCategory("Impractical Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(true); + this.setUnreasonableLimit(32); + this.setBogoSort(false); + } + + /** + * Moves an element (or group of identical elements) from the unsorted + * portion of the main array into stack2 using the hanoi function. + */ + private void removeFromMainStack() { + Highlights.markArray(2, sp); + target = array[sp]; + + int moves = hanoi(2, true, 1); + int height = getHeight(moves + 1); + targetMoves = moves; + boolean evenHeight = height % 2 == 0; + + Highlights.clearAllMarks(); + Highlights.markArray(1, sp); + + if(evenHeight) // Move smaller elements to stack3, if necessary + hanoi(1, true, 2); + unsorted += moveFromMain(stack2, false); // Move next element(s) to stack2 + hanoi(3, evenHeight, 2); // Move smaller elements back to stack2 + + } + + /** + * Moves all of the elements, currently in order on stack2, + * back to the main array using the hanoi function + */ + private void returnToMainStack() { + int moves = hanoi(2, true, 3); + int height = getHeight(moves + 1); + if(height % 2 == 1) { // Odd height case: moved to stack3 + targetMoves = moves; + hanoi(3, true, 2); + } // In even case, it's already on main stack, and we need not do anything + } + + /** + * Iteratively moves elements around the stacks according to the + * Tower of Hanoi problem. Recursion cannot be used because in many + * cases we do not know the initial recursion depth. + * + * @param startStack Which stack we wish to move a tower from + * @param goRight Whether the smallest disk should go right on the pegs + * (1->2, 2->3, 3->1) or left (1->3, 2->1, 3->2) + * @param endCon Used to determine when to end this function + * @return The number of moves performed + */ + private int hanoi(int startStack, boolean goRight, int endCon) { + int moves = 0; + int minPoleLoc = startStack; + + if(!endConMet(endCon, moves)) { + moves++; + switch(minPoleLoc) { + case 1: + if(goRight) { + moveFromMain(stack2, true); + minPoleLoc = 2; + } else { + moveFromMain(stack3, true); + minPoleLoc = 3; + } break; + case 2: + if(goRight) { + moveBetweenStacks(stack2, stack3); + minPoleLoc = 3; + } else { + moveToMain(stack2); + minPoleLoc = 1; + } break; + case 3: + if(goRight) { + moveToMain(stack3); + minPoleLoc = 1; + } else { + moveBetweenStacks(stack3, stack2); + minPoleLoc = 2; + } break; + } + } + + while(!endConMet(endCon, moves)) { + moves += 2; + switch(minPoleLoc) { + case 1: + if(!stack2.isEmpty() && + (stack3.isEmpty() || Reads.compareValues(stack2.peek(), stack3.peek()) < 0)) + moveBetweenStacks(stack2, stack3); + else + moveBetweenStacks(stack3, stack2); + if(goRight) { + moveFromMain(stack2, true); + minPoleLoc = 2; + } else { + moveFromMain(stack3, true); + minPoleLoc = 3; + } break; + case 2: + if(stack3.isEmpty() || + (sp < unsorted && Reads.compareValues(array[sp], stack3.peek()) < 0)) + moveFromMain(stack3, true); + else + moveToMain(stack3); + if(goRight) { + moveBetweenStacks(stack2, stack3); + minPoleLoc = 3; + } else { + moveToMain(stack2); + minPoleLoc = 1; + } break; + case 3: + if(stack2.isEmpty() || + (sp < unsorted && Reads.compareValues(array[sp], stack2.peek()) < 0)) + moveFromMain(stack2, true); + else + moveToMain(stack2); + if(goRight) { + moveToMain(stack3); + minPoleLoc = 1; + } else { + moveBetweenStacks(stack3, stack2); + minPoleLoc = 2; + } break; + } + } + + return moves; + } + + /** + * Determines whether or not the hanoi function should end now + * + * @param endCon Which ending condition is required for the hanoi function to end + * @param moves the moves completed by the hanoi function so far + * @return Whether or not the end condition has been met + */ + private boolean endConMet(int endCon, int moves) { + if(!validNumberMoves(moves)) + return false; + switch (endCon) { + case 1: return (stack2.isEmpty() || Reads.compareValues(target, stack2.peek()) <= 0); + case 2: return moves == targetMoves; + case 3: return stack2.isEmpty(); + default: throw new IllegalArgumentException(); + } + } + + /** + * @param moves The number of moves completed so far + * @return If the moves is of the form (2^n)-1 + */ + private boolean validNumberMoves(int moves) { + if(moves == 0) + return true; + if(moves % 2 == 0) + return false; + return validNumberMoves(moves/2); + } + + /** + * Figures out the height of the pyramid moved based on number of moves + * + * @param movesPlus1 The number of moves performed, plus one + * @return The height of the pyramid moved (equal to log_2(moves + 1)) + */ + private int getHeight(int movesPlus1) { + if(movesPlus1 == 1) + return 0; + return getHeight(movesPlus1 / 2) + 1; + } + + /** + * Moves an element from the main array to another stack, + * then moves any consecutive duplicates of that element with it + * + * @param stack The stack to move the element(s) from the main array to + * @param checkUnsorted Whether or not it is safe to remove elements in + * the unsorted portion of the main array + * @return duplicates The number of consecutive identical elements + * that were popped off the main array in the current "move" + */ + private int moveFromMain(Stack stack, boolean checkUnsorted) { + int duplicates = 1; + // Move element + Writes.changeAuxWrites(1); + Writes.startLap(); + stack.push(array[sp]); + Writes.stopLap(); + sp++; + Highlights.markArray(1, sp); + Delays.sleep(0.25); + // Move any duplicates (endOnLength indicates the relevant portion of + // the main stack is "empty") + boolean endOnLength = (sp >= length) || (checkUnsorted && sp >= unsorted); + while(!endOnLength && Reads.compareValues(array[sp], stack.peek()) == 0) { + duplicates++; + Writes.changeAuxWrites(1); + Writes.startLap(); + stack.push(array[sp]); + Writes.stopLap(); + sp++; + Highlights.markArray(1, sp); + Delays.sleep(0.25); + endOnLength = (sp >= length) || (checkUnsorted && sp >= unsorted); + } + return duplicates; + } + + /** + * Moves an element to the main array from another stack, + * then moves any consecutive duplicates of that element with it + * + * @param stack The stack to move the element(s) to the main array from + */ + private void moveToMain(Stack stack) { + // Move element + sp--; + Highlights.markArray(1, sp); + Writes.write(array, sp, stack.pop(), 0.25, false, false); + // Move any duplicates + while(!stack.isEmpty() && Reads.compareValues(stack.peek(), array[sp]) == 0) { + sp--; + Highlights.markArray(1, sp); + Writes.write(array, sp, stack.pop(), 0.25, false, false); + } + } + + /** + * Moves an element from one stack to another stack, + * then moves any consecutive duplicates of that element with it + * + * @param from the stack to move the element(s) from + * @param to the stack to move the element(s) to + */ + private void moveBetweenStacks(Stack from, Stack to) { + // Move element + Writes.changeAuxWrites(1); + Writes.startLap(); + to.push(from.pop()); + Writes.stopLap(); + Delays.sleep(0.25); + // Move any duplicates + while(!from.isEmpty() && Reads.compareValues(from.peek(), to.peek()) == 0) { + Writes.changeAuxWrites(1); + Writes.startLap(); + to.push(from.pop()); + Writes.stopLap(); + Delays.sleep(0.25); + } + } + + + @Override + public void runSort(int[] array, int length, int bucketCount) { + // Initialize local variables + this.array = array; + this.length = length; + stack2 = new Stack(); + stack3 = new Stack(); + sp = 0; + unsorted = 0; + + while(unsorted < length) + removeFromMainStack(); + + returnToMainStack(); + } +} diff --git a/src/sorts/insert/InsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/InsertionSort.java similarity index 89% rename from src/sorts/insert/InsertionSort.java rename to src/main/java/io/github/arrayv/sorts/insert/InsertionSort.java index db0463ca..5fd6cb9a 100644 --- a/src/sorts/insert/InsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/InsertionSort.java @@ -1,10 +1,10 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.InsertionSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.InsertionSorting; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class InsertionSort extends InsertionSorting { +public final class InsertionSort extends InsertionSorting { public InsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Insertion"); this.setRunAllSortsName("Insertion Sort"); this.setRunSortName("Insertsort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -48,9 +47,9 @@ public InsertionSort(ArrayVisualizer arrayVisualizer) { public void customInsertSort(int[] array, int start, int end, double sleep, boolean auxwrite) { this.insertionSort(array, start, end, sleep, auxwrite); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.insertionSort(array, 0, currentLength, 0.015, false); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/LibrarySort.java b/src/main/java/io/github/arrayv/sorts/insert/LibrarySort.java similarity index 90% rename from src/sorts/insert/LibrarySort.java rename to src/main/java/io/github/arrayv/sorts/insert/LibrarySort.java index 6bafbb18..8e6216ff 100644 --- a/src/sorts/insert/LibrarySort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/LibrarySort.java @@ -1,13 +1,13 @@ -package sorts.insert; - -import sorts.templates.Sort; -import main.ArrayVisualizer; +package io.github.arrayv.sorts.insert; import java.util.Arrays; import java.util.Random; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -32,185 +32,184 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class LibrarySort extends Sort { +public final class LibrarySort extends Sort { public LibrarySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Library"); this.setRunAllSortsName("Library Sort"); this.setRunSortName("Library Sort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + //possible implementation of the library sort here https://en.wikipedia.org/wiki/Library_sort //makes O(1) insertions into gaps of constant size on random data using an extra (1+G)*n space - + private final int G = 15; private final int R = 4; - + private int max; - + private void shiftExt(int[] array, int a, int m, int b) { int m1 = a + Math.min(m-a, b-m); while(m > a) Writes.write(array, --b, array[--m], 0.5, false, true); while(a < m1) Writes.write(array, a++, this.max, 0.5, false, true); } - + private int leftBlockSearch(int[] array, int a, int b, int val) { int s = G+1; - + while(a < b) { int m = a+(((b-a)/s)/2)*s; Highlights.markArray(2, m/s); Delays.sleep(0.25); - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; else a = m+s; } - + Highlights.clearMark(2); return a; } private int rightBlockSearch(int[] array, int a, int b, int val) { int s = G+1; - + while(a < b) { int m = a+(((b-a)/s)/2)*s; Highlights.markArray(2, m/s); Delays.sleep(0.25); - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; else a = m+s; } - + Highlights.clearMark(2); return a; } - + private int locSearch(int[] array, int a, int b) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareOriginalValues(this.max, array[m]) <= 0) + + if(Reads.compareOriginalValues(this.max, array[m]) <= 0) b = m; - else + else a = m+1; } - + return a; } private int rightBinSearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; else a = m+1; } - + return a; } - + private void insertTo(int[] array, int a, int b, boolean aux) { Highlights.clearMark(2); int temp = array[a]; while(a > b) Writes.write(array, a, array[--a], 0.5, !aux, aux); Writes.write(array, b, temp, 0.5, !aux, aux); } - + private void binaryInsertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i]), false); } - + private void retrieve(int[] array, int[] tmp, int i, int pEnd) { - int loc = i-1; - + int loc = i-1; + for(int k = pEnd-(G+1); k > G;) { int m = this.locSearch(tmp, k-G, k)-1; k -= G+1; - + while(m >= k) { Writes.write(array, loc--, tmp[m], 0, true, false); Writes.write(tmp, m--, max, 1, false, true); } } - + int m = this.locSearch(tmp, 0, G)-1; while(m >= 0) { Writes.write(array, loc--, tmp[m], 0, true, false); Writes.write(tmp, m--, max, 1, false, true); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.max = length; - + //there is supposed to be a shuffle here between [0, length) //but for the sake of demonstrating O(n^2) worst case it has been removed - + int[] tmp = Writes.createExternalArray(length*(G+1)-1); Arrays.fill(tmp, this.max); //(o_o;) - + Random rng = new Random(); - + int s = length; while(s >= 32) s = (s-1)/R + 1; - + int i = s, j = R*i, pEnd = (s+1)*(G+1)+G; this.binaryInsertion(array, 0, s); - + for(int k = 0; k < s; k++) { Highlights.markArray(1, k); Writes.write(tmp, k*(G+1)+G, array[k], 1, false, true); } - + for(; i < length; i++) { if(i == j) { this.retrieve(array, tmp, i, pEnd); - + s = i; pEnd = (s+1)*(G+1)+G; j *= R; - + for(int k = 0; k < s; k++) { Highlights.markArray(1, k); Writes.write(tmp, k*(G+1)+G, array[k], 1, false, true); } } - + Highlights.markArray(1, i); int bLoc = this.leftBlockSearch(tmp, G, pEnd-(G+1), array[i]); - + if(Reads.compareValues(array[i], tmp[bLoc]) == 0) { int eqEnd = this.rightBlockSearch(tmp, bLoc+(G+1), pEnd-(G+1), array[i]); bLoc += rng.nextInt((eqEnd-bLoc)/(G+1))*(G+1); } int loc = this.locSearch(tmp, bLoc-G, bLoc); - + if(loc == bLoc) { do bLoc += G+1; while(bLoc < pEnd && this.locSearch(tmp, bLoc-G, bLoc) == bLoc); - + if(bLoc == pEnd) { this.retrieve(array, tmp, i, pEnd); - + s = i; pEnd = (s+1)*(G+1)+G; j = R*i; - + for(int k = 0; k < s; k++) { Highlights.markArray(1, k); Writes.write(tmp, k*(G+1)+G, array[k], 1, false, true); @@ -219,7 +218,7 @@ public void runSort(int[] array, int length, int bucketCount) { else { int rotP = this.locSearch(tmp, bLoc-G, bLoc); int rotS = bLoc - Math.max(rotP, bLoc - G/2); - this.shiftExt(tmp, loc-rotS, bLoc-rotS, bLoc); + this.shiftExt(tmp, loc-rotS, bLoc-rotS, bLoc); } i--; } @@ -231,4 +230,4 @@ public void runSort(int[] array, int length, int bucketCount) { this.retrieve(array, tmp, length, pEnd); Writes.deleteExternalArray(tmp); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/PatienceSort.java b/src/main/java/io/github/arrayv/sorts/insert/PatienceSort.java similarity index 93% rename from src/sorts/insert/PatienceSort.java rename to src/main/java/io/github/arrayv/sorts/insert/PatienceSort.java index 88b80bdc..e6f8211b 100644 --- a/src/sorts/insert/PatienceSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/PatienceSort.java @@ -1,12 +1,12 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; import java.util.ArrayList; import java.util.Collections; import java.util.PriorityQueue; import java.util.Stack; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * @@ -20,22 +20,21 @@ * */ -final public class PatienceSort extends Sort { +public final class PatienceSort extends Sort { public PatienceSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Patience"); this.setRunAllSortsName("Patience Sort"); this.setRunSortName("Patience Sort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + final private class Pile extends Stack implements Comparable { private static final long serialVersionUID = 1L; @@ -48,26 +47,26 @@ public int compareTo(Pile y) { return Reads.compareValues(peek(), y.peek()); } } - + private void binarySearch(ArrayList list, Pile find) { int at = list.size() / 2; int change = list.size() / 4; - + long compsBefore = Reads.getComparisons(); while(list.get(at).compare(find) != 0 && change > 0){ Reads.setComparisons(compsBefore); Highlights.markArray(1, at); Delays.sleep(0.5); - + if(list.get(at).compare(find) < 0) at += change; else at -= change; - + change /= 2; } Reads.setComparisons(compsBefore); - + Highlights.markArray(1, at); Delays.sleep(0.5); } @@ -75,17 +74,17 @@ private void binarySearch(ArrayList list, Pile find) { @Override public void runSort(int[] array, int length, int bucketCount) { ArrayList piles = new ArrayList<>(); - + // sort into piles for (int x = 0; x < length; x++) { Pile newPile = new Pile(); - + Highlights.markArray(2, x); Writes.mockWrite(length, Math.min(newPile.size(), length - 1), array[x], 1); - + newPile.push(array[x]); Writes.changeAllocAmount(1); - + int i = Collections.binarySearch(piles, newPile); if(!piles.isEmpty()) { this.binarySearch(piles, newPile); @@ -97,7 +96,7 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.changeAllocAmount(1); } else { - Writes.mockWrite(length, Math.min(piles.size(), length - 1), newPile.get(0), 0); + Writes.mockWrite(length, Math.min(piles.size(), length - 1), newPile.get(0), 0); piles.add(newPile); Writes.changeAllocAmount(1); } @@ -107,15 +106,15 @@ public void runSort(int[] array, int length, int bucketCount) { // priority queue allows us to retrieve least pile efficiently PriorityQueue heap = new PriorityQueue<>(piles); - + for (int c = 0; c < length; c++) { Writes.mockWrite(length, Math.min(heap.size(), length - 1), 0, 0); Pile smallPile = heap.poll(); - + Writes.mockWrite(length, Math.min(smallPile.size(), length - 1), 0, 0); Writes.write(array, c, smallPile.pop(), 1, true, false); Writes.changeAllocAmount(-1); - + if (!smallPile.isEmpty()) { Writes.mockWrite(length, Math.min(heap.size(), length - 1), smallPile.get(0), 0); heap.offer(smallPile); @@ -125,4 +124,4 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.clearAllocAmount(); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/RecursiveShellSort.java b/src/main/java/io/github/arrayv/sorts/insert/RecursiveShellSort.java similarity index 88% rename from src/sorts/insert/RecursiveShellSort.java rename to src/main/java/io/github/arrayv/sorts/insert/RecursiveShellSort.java index 0d0a87f5..f3f09f2a 100644 --- a/src/sorts/insert/RecursiveShellSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/RecursiveShellSort.java @@ -1,17 +1,16 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class RecursiveShellSort extends Sort { +public final class RecursiveShellSort extends Sort { public RecursiveShellSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Recursive Shell"); this.setRunAllSortsName("yuji's Recursive Shell Sort"); this.setRunSortName("yuji's Recursive Shell Sort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -23,7 +22,7 @@ public void gappedInsertionSort(int[] arr, int a, int b, int gap) { for (int i = a+gap; i < b; i+=gap) { int key = arr[i]; int j = i-gap; - + while (j >= a && Reads.compareValues(key, arr[j]) < 0) { Writes.write(arr, j+gap, arr[j], 0.5, true, false); j-=gap; @@ -46,4 +45,4 @@ public void recursiveShellSort(int[] array, int start, int end, int g) { public void runSort(int[] array, int length, int bucketCount) { this.recursiveShellSort(array, 0, length, 1); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/RedBlackTreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/RedBlackTreeSort.java similarity index 93% rename from src/sorts/insert/RedBlackTreeSort.java rename to src/main/java/io/github/arrayv/sorts/insert/RedBlackTreeSort.java index 5a751e58..848b635a 100644 --- a/src/sorts/insert/RedBlackTreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/RedBlackTreeSort.java @@ -1,337 +1,336 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * An implementation of a tree sort using an red-black tree, - * based on what I learned in my CSSE230 class - * - * @author Sam Walko (Anonymous0726) - */ -final public class RedBlackTreeSort extends Sort { - public RedBlackTreeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Red-Black Tree"); - this.setRunAllSortsName("Tree Sort (Red-Black Balanced)"); - this.setRunSortName("Tree sort (Red-Black Balanced)"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private Node NULL_NODE = new Node(); // (sub)tree of size 0 - - /** - * The fundamental building block of any programming tree. Each node is the - * root of its own subtree. In general, a node has the data being stored at - * that point, up to two children nodes, and (optionally) data for keeping - * the tree balanced. In the case of a red-black tree, the data for balancing - * is a boolean telling the node's "color": red or black. - */ - private class Node { - // main array (poor encapsulation since it's all the same but w/e) - private int[] array; - - private int pointer; // index in main array of the element contained here - private Node left, right; // left and right subtrees - private boolean isRed; // whether this node is red or black - - // Default constructor, and constructor for NULL_NODE - private Node() { - // Shouldn't point to anything by default - this.pointer = -1; - this.left = NULL_NODE; - this.right = NULL_NODE; - this.isRed = false; // All NULL_NODEs being black will not violate black balance - } - - // Constructor for a node with a pointer - private Node(int[] array, int pointer) { - this(); - this.array = array; - this.pointer = pointer; - this.isRed = true; // A node with data, when first created, is red - } - - /** - * A return container for the recursive add method containing a Node - * and a boolean telling whether or not the subtree needs rebalancing - */ - private class AddContainer { - private Node node; - private boolean needsFix; - - private AddContainer(Node node, boolean needsFix) { - this.node = node; - this.needsFix = needsFix; - } - } - - /** - * Recursively adds an element to the subtree whose root is this node - * - * @param addPointer A pointer to the array telling what element is to be inserted - * @return an AddContainer containing the node that is now the root of this - * subtree, and the boolean telling whether or not this subtree increased in height - */ - private AddContainer add(int addPointer) { - // Case 1: If this is where to add the new element, create a node for it - if(this == NULL_NODE) { - Highlights.clearMark(1); // No longer comparing to previous leaves - Node newNode = new Node(array, addPointer); // Create the node - // Return the node, and the fact that a subtree of size 1 - // obviously does not require rebalancing - return new AddContainer(newNode, false); - } - - // If there's an element already here, we need to compare them to - // determine whether it should be placed in the left or the right subtree. - // Thus, mark the element at the pointer for comparison. - Highlights.markArray(2, pointer); - - // This type of restructuring allows us to prevent future - // cascading rotations, without losing black balance. - // (Note that this only occurs when there's actually a node here - // already, hence this check is performed after the check for case 1.) - if(!isRed && left.isRed && right.isRed) { - Highlights.markArray(3, left.pointer); - Highlights.markArray(4, right.pointer); - - isRed = true; - left.isRed = false; - right.isRed = false; - - Delays.sleep(0.25); - Highlights.clearMark(3); - Highlights.clearMark(4); - } - - // Case 2: The element is smaller and thus belongs in the left subtree - if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { - Delays.sleep(0.25); - - // Recursively get the root of the new left subtree - AddContainer container = left.add(addPointer); - - Highlights.markArray(2, pointer); - - // Set the root of the new left subtree as such - Writes.changeAuxWrites(1); - Writes.startLap(); - left = container.node; - Writes.stopLap(); - Delays.sleep(0.05); - - // If the tree is determined to need rebalancing, then first - // determine which type of rotation is necessary, then perform it. - if(container.needsFix) { - if(left.left.isRed) - return new AddContainer(singleRotateRight(), false); - return new AddContainer(doubleRotateRight(), false); - } - - // If no rebalancing is necessary here, return this node, and determine - // whether or not the subtree at the parent will require rebalancing - return new AddContainer(this, isRed && left.isRed); - } - - // Case 3: The element is equal or larger and thus belongs in the right subtree - // Note: As equality also results in right subtree, this sort is stable - Delays.sleep(0.25); - - // Recursively get the root of the new right subtree - AddContainer container = right.add(addPointer); - - Highlights.markArray(2, pointer); - - // Set the root of the new right subtree as such - Writes.changeAuxWrites(1); - Writes.startLap(); - right = container.node; - Writes.stopLap(); - Delays.sleep(0.05); - - // If the tree is determined to need rebalancing, then first - // determine which type of rotation is necessary, then perform it. - if(container.needsFix) { - if(right.right.isRed) - return new AddContainer(singleRotateLeft(), false); - return new AddContainer(doubleRotateLeft(), false); - } - - // If no rebalancing is necessary here, return this node, and determine - // whether or not the subtree at the parent will require rebalancing - return new AddContainer(this, isRed && right.isRed); - } - - // These rotations are kinda magic (read: too difficult to explain without - // diagrams), so feel free to ask me (Anonymous0726#2452 on Discord) about it. - // Alternatively, the animations on Wikipedia for AVL trees are fairly decent - // at showing what happens during any given type of rotation, but don't really - // show what triggers a rotation here in a red-black tree, nor do they explain - // the recoloring. - - /** - * Singly rotates the subtree right about the current node, - * recoloring along the way. Helper method for add. - * - * @return the subtree's new root - */ - private Node singleRotateRight() { - Node b = left; - - Highlights.markArray(3, pointer); - Highlights.markArray(4, b.pointer); - - Writes.changeAuxWrites(2); - Writes.startLap(); - left = b.right; - b.right = this; - Writes.stopLap(); - Delays.sleep(0.25); - - b.isRed = false; - isRed = true; - - Highlights.clearMark(3); - Highlights.clearMark(4); - - return b; - } - - /** - * Singly rotates the subtree left about the current node, - * recoloring along the way. Helper method for add. - * - * @return the subtree's new root - */ - private Node singleRotateLeft() { - Node b = right; - - Highlights.markArray(3, pointer); - Highlights.markArray(4, b.pointer); - - Writes.changeAuxWrites(2); - Writes.startLap(); - right = b.left; - b.left = this; - Writes.stopLap(); - Delays.sleep(0.25); - - b.isRed = false; - isRed = true; - - Highlights.clearMark(3); - Highlights.clearMark(4); - - return b; - } - - /** - * Doubly rotates the subtree right about the current node, recoloring along - * the way. Also known as a left-right rotation. Helper method for add. - * - * @return the subtree's new root - */ - private Node doubleRotateRight() { - - Node newLeft = left.singleRotateLeft(); - Writes.changeAuxWrites(1); - Writes.startLap(); - left = newLeft; - Writes.stopLap(); - Delays.sleep(0.25); - - Node b = singleRotateRight(); - - return b; - } - - /** - * Double rotates the subtree left about the current node, recoloring along - * the way. Also known as a right-left rotation. Helper method for add. - * - * @return the subtree's new root - */ - private Node doubleRotateLeft() { - - Node newRight = right.singleRotateRight(); - Writes.changeAuxWrites(1); - Writes.startLap(); - right = newRight; - Writes.stopLap(); - Delays.sleep(0.25); - - Node b = singleRotateLeft(); - - return b; - } - - /** - * Performs an in-order traversal of the array and writes - * the values of the original array to a sorted temporary array - * - * @param tempArray the temporary array to write the contents of the subtree to - * @param location a pointer to the location in the temporary array to which the - * contents of the current subtree should be written to - * @return The size of subtree, used to determine where the next value should be - * written to. - */ - private int writeToArray(int[] tempArray, int location) { - if(this == NULL_NODE) return 0; - - int leftTreeSize = left.writeToArray(tempArray, location); - int newLocation = location + leftTreeSize; - - Highlights.markArray(1, pointer); - Writes.write(tempArray, newLocation, array[pointer], 0.1, false, true); - - int rightTreeSize = right.writeToArray(tempArray, newLocation + 1); - return leftTreeSize + rightTreeSize + 1; - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - // Tells the tree what array is to be sorted - NULL_NODE.array = array; - // Creates a tree of size 0, to which all elements will be added - Node root = NULL_NODE; - - // This loop adds every element of the array to be sorted into the tree - for(int i = 0; i < length; i++) { - Highlights.markArray(1, i); // Highlights the element being added - Node.AddContainer container = root.add(i); - - Highlights.clearMark(2); - - Writes.changeAuxWrites(1); - Writes.startLap(); - root = container.node; - Writes.stopLap(); - Delays.sleep(0.25); - - Highlights.markArray(2, root.pointer); - root.isRed = false; // Root of a red-black tree must always be black - Delays.sleep(0.25); - - Highlights.clearAllMarks(); // Clearing all just in case - } - - // Write the contents of the tree to a temporary array - int[] tempArray = new int[length]; - root.writeToArray(tempArray, 0); - Highlights.clearMark(1); // No more elements being transferred to temporary array - - // Write the contents of the temporary array back to the main array - for(int i = 0; i < length; i++) { - Writes.write(array, i, tempArray[i], 1, true, false); - } - } -} +package io.github.arrayv.sorts.insert; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * An implementation of a tree sort using an red-black tree, + * based on what I learned in my CSSE230 class + * + * @author Sam Walko (Anonymous0726) + */ +public final class RedBlackTreeSort extends Sort { + public RedBlackTreeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + + this.setSortListName("Red-Black Tree"); + this.setRunAllSortsName("Tree Sort (Red-Black Balanced)"); + this.setRunSortName("Tree sort (Red-Black Balanced)"); + this.setCategory("Insertion Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.setBogoSort(false); + } + + private Node NULL_NODE = new Node(); // (sub)tree of size 0 + + /** + * The fundamental building block of any programming tree. Each node is the + * root of its own subtree. In general, a node has the data being stored at + * that point, up to two children nodes, and (optionally) data for keeping + * the tree balanced. In the case of a red-black tree, the data for balancing + * is a boolean telling the node's "color": red or black. + */ + private class Node { + // main array (poor encapsulation since it's all the same but w/e) + private int[] array; + + private int pointer; // index in main array of the element contained here + private Node left, right; // left and right subtrees + private boolean isRed; // whether this node is red or black + + // Default constructor, and constructor for NULL_NODE + private Node() { + // Shouldn't point to anything by default + this.pointer = -1; + this.left = NULL_NODE; + this.right = NULL_NODE; + this.isRed = false; // All NULL_NODEs being black will not violate black balance + } + + // Constructor for a node with a pointer + private Node(int[] array, int pointer) { + this(); + this.array = array; + this.pointer = pointer; + this.isRed = true; // A node with data, when first created, is red + } + + /** + * A return container for the recursive add method containing a Node + * and a boolean telling whether or not the subtree needs rebalancing + */ + private class AddContainer { + private Node node; + private boolean needsFix; + + private AddContainer(Node node, boolean needsFix) { + this.node = node; + this.needsFix = needsFix; + } + } + + /** + * Recursively adds an element to the subtree whose root is this node + * + * @param addPointer A pointer to the array telling what element is to be inserted + * @return an AddContainer containing the node that is now the root of this + * subtree, and the boolean telling whether or not this subtree increased in height + */ + private AddContainer add(int addPointer) { + // Case 1: If this is where to add the new element, create a node for it + if(this == NULL_NODE) { + Highlights.clearMark(1); // No longer comparing to previous leaves + Node newNode = new Node(array, addPointer); // Create the node + // Return the node, and the fact that a subtree of size 1 + // obviously does not require rebalancing + return new AddContainer(newNode, false); + } + + // If there's an element already here, we need to compare them to + // determine whether it should be placed in the left or the right subtree. + // Thus, mark the element at the pointer for comparison. + Highlights.markArray(2, pointer); + + // This type of restructuring allows us to prevent future + // cascading rotations, without losing black balance. + // (Note that this only occurs when there's actually a node here + // already, hence this check is performed after the check for case 1.) + if(!isRed && left.isRed && right.isRed) { + Highlights.markArray(3, left.pointer); + Highlights.markArray(4, right.pointer); + + isRed = true; + left.isRed = false; + right.isRed = false; + + Delays.sleep(0.25); + Highlights.clearMark(3); + Highlights.clearMark(4); + } + + // Case 2: The element is smaller and thus belongs in the left subtree + if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { + Delays.sleep(0.25); + + // Recursively get the root of the new left subtree + AddContainer container = left.add(addPointer); + + Highlights.markArray(2, pointer); + + // Set the root of the new left subtree as such + Writes.changeAuxWrites(1); + Writes.startLap(); + left = container.node; + Writes.stopLap(); + Delays.sleep(0.05); + + // If the tree is determined to need rebalancing, then first + // determine which type of rotation is necessary, then perform it. + if(container.needsFix) { + if(left.left.isRed) + return new AddContainer(singleRotateRight(), false); + return new AddContainer(doubleRotateRight(), false); + } + + // If no rebalancing is necessary here, return this node, and determine + // whether or not the subtree at the parent will require rebalancing + return new AddContainer(this, isRed && left.isRed); + } + + // Case 3: The element is equal or larger and thus belongs in the right subtree + // Note: As equality also results in right subtree, this sort is stable + Delays.sleep(0.25); + + // Recursively get the root of the new right subtree + AddContainer container = right.add(addPointer); + + Highlights.markArray(2, pointer); + + // Set the root of the new right subtree as such + Writes.changeAuxWrites(1); + Writes.startLap(); + right = container.node; + Writes.stopLap(); + Delays.sleep(0.05); + + // If the tree is determined to need rebalancing, then first + // determine which type of rotation is necessary, then perform it. + if(container.needsFix) { + if(right.right.isRed) + return new AddContainer(singleRotateLeft(), false); + return new AddContainer(doubleRotateLeft(), false); + } + + // If no rebalancing is necessary here, return this node, and determine + // whether or not the subtree at the parent will require rebalancing + return new AddContainer(this, isRed && right.isRed); + } + + // These rotations are kinda magic (read: too difficult to explain without + // diagrams), so feel free to ask me (Anonymous0726#2452 on Discord) about it. + // Alternatively, the animations on Wikipedia for AVL trees are fairly decent + // at showing what happens during any given type of rotation, but don't really + // show what triggers a rotation here in a red-black tree, nor do they explain + // the recoloring. + + /** + * Singly rotates the subtree right about the current node, + * recoloring along the way. Helper method for add. + * + * @return the subtree's new root + */ + private Node singleRotateRight() { + Node b = left; + + Highlights.markArray(3, pointer); + Highlights.markArray(4, b.pointer); + + Writes.changeAuxWrites(2); + Writes.startLap(); + left = b.right; + b.right = this; + Writes.stopLap(); + Delays.sleep(0.25); + + b.isRed = false; + isRed = true; + + Highlights.clearMark(3); + Highlights.clearMark(4); + + return b; + } + + /** + * Singly rotates the subtree left about the current node, + * recoloring along the way. Helper method for add. + * + * @return the subtree's new root + */ + private Node singleRotateLeft() { + Node b = right; + + Highlights.markArray(3, pointer); + Highlights.markArray(4, b.pointer); + + Writes.changeAuxWrites(2); + Writes.startLap(); + right = b.left; + b.left = this; + Writes.stopLap(); + Delays.sleep(0.25); + + b.isRed = false; + isRed = true; + + Highlights.clearMark(3); + Highlights.clearMark(4); + + return b; + } + + /** + * Doubly rotates the subtree right about the current node, recoloring along + * the way. Also known as a left-right rotation. Helper method for add. + * + * @return the subtree's new root + */ + private Node doubleRotateRight() { + + Node newLeft = left.singleRotateLeft(); + Writes.changeAuxWrites(1); + Writes.startLap(); + left = newLeft; + Writes.stopLap(); + Delays.sleep(0.25); + + Node b = singleRotateRight(); + + return b; + } + + /** + * Double rotates the subtree left about the current node, recoloring along + * the way. Also known as a right-left rotation. Helper method for add. + * + * @return the subtree's new root + */ + private Node doubleRotateLeft() { + + Node newRight = right.singleRotateRight(); + Writes.changeAuxWrites(1); + Writes.startLap(); + right = newRight; + Writes.stopLap(); + Delays.sleep(0.25); + + Node b = singleRotateLeft(); + + return b; + } + + /** + * Performs an in-order traversal of the array and writes + * the values of the original array to a sorted temporary array + * + * @param tempArray the temporary array to write the contents of the subtree to + * @param location a pointer to the location in the temporary array to which the + * contents of the current subtree should be written to + * @return The size of subtree, used to determine where the next value should be + * written to. + */ + private int writeToArray(int[] tempArray, int location) { + if(this == NULL_NODE) return 0; + + int leftTreeSize = left.writeToArray(tempArray, location); + int newLocation = location + leftTreeSize; + + Highlights.markArray(1, pointer); + Writes.write(tempArray, newLocation, array[pointer], 0.1, false, true); + + int rightTreeSize = right.writeToArray(tempArray, newLocation + 1); + return leftTreeSize + rightTreeSize + 1; + } + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + // Tells the tree what array is to be sorted + NULL_NODE.array = array; + // Creates a tree of size 0, to which all elements will be added + Node root = NULL_NODE; + + // This loop adds every element of the array to be sorted into the tree + for(int i = 0; i < length; i++) { + Highlights.markArray(1, i); // Highlights the element being added + Node.AddContainer container = root.add(i); + + Highlights.clearMark(2); + + Writes.changeAuxWrites(1); + Writes.startLap(); + root = container.node; + Writes.stopLap(); + Delays.sleep(0.25); + + Highlights.markArray(2, root.pointer); + root.isRed = false; // Root of a red-black tree must always be black + Delays.sleep(0.25); + + Highlights.clearAllMarks(); // Clearing all just in case + } + + // Write the contents of the tree to a temporary array + int[] tempArray = new int[length]; + root.writeToArray(tempArray, 0); + Highlights.clearMark(1); // No more elements being transferred to temporary array + + // Write the contents of the temporary array back to the main array + for(int i = 0; i < length; i++) { + Writes.write(array, i, tempArray[i], 1, true, false); + } + } +} diff --git a/src/sorts/insert/ShellSort.java b/src/main/java/io/github/arrayv/sorts/insert/ShellSort.java similarity index 80% rename from src/sorts/insert/ShellSort.java rename to src/main/java/io/github/arrayv/sorts/insert/ShellSort.java index 231ea1c5..4f9a2042 100644 --- a/src/sorts/insert/ShellSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/ShellSort.java @@ -1,33 +1,32 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.ShellSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.ShellSorting; // Shell sort variant retrieved from: // https://www.cs.princeton.edu/~rs/talks/shellsort.ps -final public class ShellSort extends ShellSorting { +public final class ShellSort extends ShellSorting { public ShellSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Shell"); this.setRunAllSortsName("Shell Sort"); this.setRunSortName("Shellsort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + public void finishQuickShell(int[] array, int currentLen) { this.quickShellSort(array, 0, currentLen); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.shellSort(array, currentLength); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/ShellSortParallel.java b/src/main/java/io/github/arrayv/sorts/insert/ShellSortParallel.java similarity index 89% rename from src/sorts/insert/ShellSortParallel.java rename to src/main/java/io/github/arrayv/sorts/insert/ShellSortParallel.java index b45a3f3f..6d5b1044 100644 --- a/src/sorts/insert/ShellSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/insert/ShellSortParallel.java @@ -1,27 +1,26 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.ShellSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.ShellSorting; -final public class ShellSortParallel extends ShellSorting { +public final class ShellSortParallel extends ShellSorting { public ShellSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Shell (Parallel)"); this.setRunAllSortsName("Parallel Shell Sort"); this.setRunSortName("Parallel Shellsort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] array; private int[] gaps; - + private class GappedInsertionSort extends Thread { private int a, b, g; GappedInsertionSort(int a, int b, int g) { @@ -33,49 +32,49 @@ public void run() { ShellSortParallel.this.gappedInsertion(a, b, g); } } - + private void gappedInsertion(int a, int b, int g) { for(int i = a+g; i < b; i+=g) { if(Reads.compareIndices(this.array, i-g, i, 1, true) > 0) { int tmp = this.array[i], j = i; Highlights.clearMark(2); - + do { Writes.write(this.array, j, this.array[j-g], 1, true, false); j -= g; } while(j-g >= a && Reads.compareValues(this.array[j-g], tmp) > 0); - + Writes.write(this.array, j, tmp, 1, true, false); } } } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.array = array; this.gaps = this.ExtendedCiuraGaps; - + int k = 0; - + for(; this.gaps[k] >= currentLength; k++); for(; k < this.gaps.length; k++) { int g = this.gaps[k]; int t = Math.min(g, currentLength-g); - + GappedInsertionSort[] ins = new GappedInsertionSort[t]; for(int i = 0; i < t; i++) ins[i] = new GappedInsertionSort(i, currentLength, g); - + for(GappedInsertionSort s : ins) s.start(); for(GappedInsertionSort s : ins) { try { s.join(); - } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } -} \ No newline at end of file +} diff --git a/src/sorts/insert/SimplifiedLibrarySort.java b/src/main/java/io/github/arrayv/sorts/insert/SimplifiedLibrarySort.java similarity index 92% rename from src/sorts/insert/SimplifiedLibrarySort.java rename to src/main/java/io/github/arrayv/sorts/insert/SimplifiedLibrarySort.java index 3c209355..3c72216f 100644 --- a/src/sorts/insert/SimplifiedLibrarySort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/SimplifiedLibrarySort.java @@ -1,10 +1,10 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class SimplifiedLibrarySort extends Sort { +public final class SimplifiedLibrarySort extends Sort { public SimplifiedLibrarySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,47 +37,46 @@ public SimplifiedLibrarySort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Simplified Library Sort"); this.setRunSortName("Simplified Library Sort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + //simple library sort with O(n) extra memory + counter & pointer array (n size combined) - + private final int R = 4; //rebalancing factor (gaps have dynamic size) - + private BinaryInsertionSort binaryInsert; - + private int getMinLevel(int n) { while(n >= 32) n = (n-1)/R+1; return n; } - + private int binarySearch(int[] array, int a, int b, int val, double sleep) { while(a < b) { int m = a+(b-a)/2; Highlights.markArray(3, m); Delays.sleep(sleep); - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; else a = m+1; } Highlights.clearMark(3); - + return a; } - + private void rebalance(int[] array, int[] temp, int[] cnts, int[] locs, int m, int b) { //do a partial sum to find locations Highlights.clearMark(2); for(int i = 0; i < m; i++) Writes.write(cnts, i+1, cnts[i+1]+cnts[i]+1, 1, true, true); - + //place books in gaps into their correct locations for(int i = m, j = 0; i < b; i++, j++) { Highlights.markArray(2, i); @@ -90,56 +89,56 @@ private void rebalance(int[] array, int[] temp, int[] cnts, int[] locs, int m, i Writes.write(cnts, i, cnts[i]+1, 0, false, true); } Highlights.clearMark(2); - + //copy back to array & sort the gaps Writes.arraycopy(temp, 0, array, 0, b, 1, true, false); this.binaryInsert.customBinaryInsert(array, 0, cnts[0]-1, 0.5); for(int i = 0; i < m-1; i++) this.binaryInsert.customBinaryInsert(array, cnts[i], cnts[i+1]-1, 0.5); this.binaryInsert.customBinaryInsert(array, cnts[m-1], cnts[m], 0.5); - + //reset count array - for(int i = 0; i < m+2; i++) + for(int i = 0; i < m+2; i++) Writes.write(cnts, i, 0, 0, false, true); } @Override public void runSort(int[] array, int length, int bucketCount) { this.binaryInsert = new BinaryInsertionSort(this.arrayVisualizer); - + if(length < 32) { this.binaryInsert.customBinaryInsert(array, 0, length, 1); return; } - + int j = this.getMinLevel(length); this.binaryInsert.customBinaryInsert(array, 0, j, 1); - + int maxLevel = j; for(; maxLevel*R < length; maxLevel *= R); - - int[] temp = Writes.createExternalArray(length), + + int[] temp = Writes.createExternalArray(length), cnts = Writes.createExternalArray(maxLevel+2), locs = Writes.createExternalArray(length-maxLevel); - + for(int i = j, k = 0; i < length; i++) { if(R*j == i) { this.rebalance(array, temp, cnts, locs, j, i); j = i; k = 0; } - + //search which gap a book goes and save the result Highlights.markArray(2, i); int loc = this.binarySearch(array, 0, j, array[i], 0.5); - + Writes.write(cnts, loc+1, cnts[loc+1]+1, 0, false, true); Writes.write(locs, k++, loc, 0, false, true); } this.rebalance(array, temp, cnts, locs, j, length); - + Writes.deleteExternalArray(temp); Writes.deleteExternalArray(cnts); Writes.deleteExternalArray(locs); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/SplaySort.java b/src/main/java/io/github/arrayv/sorts/insert/SplaySort.java similarity index 82% rename from src/sorts/insert/SplaySort.java rename to src/main/java/io/github/arrayv/sorts/insert/SplaySort.java index 3ff88d3f..ee927a65 100644 --- a/src/sorts/insert/SplaySort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/SplaySort.java @@ -1,87 +1,86 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +public final class SplaySort extends Sort { -final public class SplaySort extends Sort { - //Splay sort is an adaptive algorithm based on splay tree data structure //It is O(n log n) in the average/worst case, and O(n) in the best case when the data is mostly sorted - + public SplaySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Splay"); this.setRunAllSortsName("Splay Sort"); this.setRunSortName("Splaysort"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + // Splay tree code retrieved from https://www.geeksforgeeks.org/splay-tree-set-2-insert-delete/ - - final private class Node { + + final private class Node { int key; Node left, right; - public Node(int item) { + public Node(int item) { key = item; - left = right = null; + left = right = null; } - - } - - private Node root; + + } + + private Node root; private int index, length; private Node treeWrite(Node element, int at) { Node node = new Node(0); - + if(at > 0 && at < this.length) Highlights.markArray(1, at - 1); Writes.changeAuxWrites(1); Writes.startLap(); node = element; Writes.stopLap(); - + Delays.sleep(0.25); - + return node; } - + private Node leftRotate(Node x, int depth) { Node y = x.right; x.right = treeWrite(y.left, depth * 2 + 1); y.left = treeWrite(x, depth * 4 + 2); - return y; + return y; } - + private Node rightRotate(Node x, int depth) { Node y = x.left; x.left = treeWrite(y.right, depth * 2); y.right = treeWrite(x, depth * 4 + 1); - return y; + return y; } private void insert(int key) { this.root = this.treeWrite(insertRec(this.root, key, 1), 1); Writes.changeAllocAmount(1); - } - + } + private Node splay(Node root, int key, int depth) { if (root == null) { return root; } - + if (Reads.compareValues(root.key, key) == 1) { if (root.left == null) { return root; } - + if (Reads.compareValues(root.left.key, key) == 1) { root.left.left = treeWrite(splay(root.left.left, key, depth * 4), depth * 4); root = treeWrite(rightRotate(root, depth), depth); @@ -96,7 +95,7 @@ private Node splay(Node root, int key, int depth) { if (root.right == null) { return root; } - + if (Reads.compareValues(root.right.key, key) == 1) { root.right.left = treeWrite(splay(root.right.left, key, depth * 4 + 2), depth * 4 + 2); if (root.right.left != null) { @@ -109,16 +108,16 @@ private Node splay(Node root, int key, int depth) { return (root.right == null) ? root : leftRotate(root, depth); } } - - private Node insertRec(Node root, int key, int depth) { - if (root == null) { + + private Node insertRec(Node root, int key, int depth) { + if (root == null) { root = treeWrite(new Node(key), 1); - return root; - } - + return root; + } + root = splay(root, key, depth); Node n = new Node(key); - + if (Reads.compareValues(root.key, key) == 1) { n.right = treeWrite(root, 3); n.left = treeWrite(root.left, 2); @@ -129,30 +128,30 @@ private Node insertRec(Node root, int key, int depth) { root.right = treeWrite(null, depth * 2 + 1); } return n; - } + } - private void traverseRec(Node root, int[] array) { - if (root != null) { - this.traverseRec(root.left, array); - Writes.write(array, this.index++, root.key, 1, true, false); - this.traverseRec(root.right, array); - } - } + private void traverseRec(Node root, int[] array) { + if (root != null) { + this.traverseRec(root.left, array); + Writes.write(array, this.index++, root.key, 1, true, false); + this.traverseRec(root.right, array); + } + } private void treeIns(int arr[]) { for(int i = 0; i < this.length; i++) { Highlights.markArray(2, i); this.insert(arr[i]); - } + } Highlights.clearMark(2); } @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.length = currentLength; - this.treeIns(array); + this.treeIns(array); this.index = 0; - this.traverseRec(this.root, array); + this.traverseRec(this.root, array); Writes.changeAllocAmount(-length); } -} \ No newline at end of file +} diff --git a/src/sorts/insert/TreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/TreeSort.java similarity index 95% rename from src/sorts/insert/TreeSort.java rename to src/main/java/io/github/arrayv/sorts/insert/TreeSort.java index 29c2d43b..57d0315c 100644 --- a/src/sorts/insert/TreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/TreeSort.java @@ -1,32 +1,31 @@ -package sorts.insert; +package io.github.arrayv.sorts.insert; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /** * An implementation of a tree sort using an unbalanced * (aka naive) binary search tree (BST) - * + * * @author Sam Walko (Anonymous0726) */ -final public class TreeSort extends Sort { +public final class TreeSort extends Sort { public TreeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Tree"); this.setRunAllSortsName("Tree Sort (Unbalanced)"); this.setRunSortName("Tree sort (Unbalanced)"); this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private Node NULL_NODE = new Node(); - + /** * The fundamental building block of any programming tree. Each node is the * root of its own subtree. In general, a node has the data being stored at @@ -36,10 +35,10 @@ public TreeSort(ArrayVisualizer arrayVisualizer) { private class Node { // main array (poor encapsulation since it's all the same but w/e) private int[] array; - + private int pointer; // index in main array of the element contained here private Node left, right; // left and right subtrees - + // Default constructor, and constructor for NULL_NODE private Node() { // Shouldn't point to anything by default @@ -47,17 +46,17 @@ private Node() { this.left = NULL_NODE; this.right = NULL_NODE; } - + // Constructor for a node with a pointer private Node(int[] array, int pointer) { this(); this.array = array; this.pointer = pointer; } - + /** * Recursively adds an element to the subtree whose root is this node - * + * * @param addPointer A pointer to the array telling what element is to be inserted * @return the Node to be added at this point */ @@ -67,44 +66,44 @@ private Node add(int addPointer) { Highlights.clearMark(1); // No longer comparing to previous leaves return new Node(array, addPointer); // Create the new node and return it } - + // If there's an element already here, we need to compare them to // determine whether it should be placed in the left or the right subtree. // Thus, mark the element at the pointer for comparison. Highlights.markArray(2, pointer); - + // Case 2: The element is smaller and thus belongs in the left subtree if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { Delays.sleep(0.25); - + // Recursively get the root of the new left subtree Node newLeaf = left.add(addPointer); - + Highlights.markArray(2, pointer); - + // Set the root of the new left subtree as such Writes.changeAuxWrites(1); Writes.startLap(); left = newLeaf; Writes.stopLap(); - + Delays.sleep(0.05); return this; // return this node } - + // Case 3: The element is equal or larger and thus belongs in the right subtree // Note: As equality also results in right subtree, this sort is stable Delays.sleep(0.25); - + // Recursively get the root of the new right subtree Node newLeaf = right.add(addPointer); - + // Set the root of the new right subtree as such Writes.changeAuxWrites(1); Writes.startLap(); right = newLeaf; Writes.stopLap(); - + Delays.sleep(0.05); return this; // return this node } @@ -112,7 +111,7 @@ private Node add(int addPointer) { /** * Performs an in-order traversal of the array and writes * the values of the original array to a sorted temporary array - * + * * @param tempArray the temporary array to write the contents of the subtree to * @param location a pointer to the location in the temporary array to which the * contents of the current subtree should be written to @@ -121,41 +120,41 @@ private Node add(int addPointer) { */ private int writeToArray(int[] tempArray, int location) { if(this == NULL_NODE) return 0; - + int leftTreeSize = left.writeToArray(tempArray, location); int newLocation = location + leftTreeSize; - + Highlights.markArray(1, pointer); Writes.write(tempArray, newLocation, array[pointer], 0.1, false, true); - + int rightTreeSize = right.writeToArray(tempArray, newLocation + 1); return leftTreeSize + rightTreeSize + 1; } } - + @Override public void runSort(int[] array, int length, int bucketCount) { // Tells the tree what array is to be sorted NULL_NODE.array = array; // Creates a tree of size 0, to which all elements will be added Node root = NULL_NODE; - + // This loop adds every element of the array to be sorted into the tree for(int i = 0; i < length; i++) { Highlights.markArray(1, i); Node newRoot = root.add(i); - + Highlights.clearMark(2); - + Writes.changeAuxWrites(1); Writes.startLap(); root = newRoot; Writes.stopLap(); Delays.sleep(0.25); - + Highlights.clearAllMarks(); // Clearing all just in case } - + // Write the contents of the tree to a temporary array int[] tempArray = new int[length]; root.writeToArray(tempArray, 0); diff --git a/src/sorts/merge/AndreySort.java b/src/main/java/io/github/arrayv/sorts/merge/AndreySort.java similarity index 91% rename from src/sorts/merge/AndreySort.java rename to src/main/java/io/github/arrayv/sorts/merge/AndreySort.java index 529e3720..7e0019b6 100644 --- a/src/sorts/merge/AndreySort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/AndreySort.java @@ -1,7 +1,7 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; public class AndreySort extends Sort { public AndreySort(ArrayVisualizer arrayVisualizer) { @@ -11,14 +11,13 @@ public AndreySort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Andrey Astrelin's In-Place Merge Sort"); this.setRunSortName("Andreysort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void sort(int[] arr, int a, int b) { while(b > 1) { int k = 0; @@ -32,18 +31,18 @@ private void sort(int[] arr, int a, int b) { b--; } } - - private void aswap(int[] arr, int arr1, int arr2, int l) { + + private void aswap(int[] arr, int arr1, int arr2, int l) { while(l-- > 0) { Writes.swap(arr, arr1++, arr2++, 1, true, false); } } - + // arr1(-l1..0] :merge: arr2(-l2..0] -> arr2(-l2..l1] private int backmerge(int[] arr, int arr1, int l1, int arr2, int l2) { int arr0 = arr2 + l1; for(;;) { - if(Reads.compareValues(arr[arr1], arr[arr2]) > 0) { + if(Reads.compareValues(arr[arr1], arr[arr2]) > 0) { Writes.swap(arr, arr1--, arr0--, 1, true, false); if(--l1 == 0) { return 0; @@ -62,7 +61,7 @@ private int backmerge(int[] arr, int arr1, int l1, int arr2, int l2) { } while(--l1 != 0); return res; } - + // merge arr[p0..p1) by buffer arr[p1..p1+r) private void rmerge(int[] arr, int a, int l, int r) { for(int i = 0; i < l; i += r) { @@ -72,7 +71,7 @@ private void rmerge(int[] arr, int a, int l, int r) { if(Reads.compareValues(arr[a + q], arr[a + j]) > 0) { q = j; } - } + } if(q != i) { aswap(arr, a + i, a + q, r); // swap it with current position } @@ -82,7 +81,7 @@ private void rmerge(int[] arr, int a, int l, int r) { } } } - + private int rbnd(int len) { len = len / 2; int k = 0; @@ -99,10 +98,10 @@ private void msort(int[] arr, int a, int len) { sort(arr, a, len); return; } - + int r = rbnd(len); int lr = (len / r - 1) * r; - + for(int p = 2; p <= lr; p += 2) { if(Reads.compareValues(arr[a + (p - 2)], arr[a + (p - 1)]) > 0) { Writes.swap(arr, a + (p - 2), a + (p - 1), 1, true, false); @@ -110,12 +109,12 @@ private void msort(int[] arr, int a, int len) { if((p & 2) != 0) { continue; } - + aswap(arr, a + (p - 2), a + p, 2); - + int m = len - p; int q = 2; - + for(;;) { int q0 = 2 * q; if(q0 > m || (p & q0) != 0) { @@ -124,17 +123,17 @@ private void msort(int[] arr, int a, int len) { backmerge(arr, a + (p - q - 1), q, a + (p + q - 1), q); q = q0; } - + backmerge(arr, a + (p + q - 1), q, a + (p - q - 1), q); int q1 = q; q *= 2; - + while((q & p) == 0) { q *= 2; rmerge(arr, a + (p - q), q, q1); } } - + int q1 = 0; for(int q = r; q< lr; q *= 2) { if((lr & q) != 0) { @@ -144,16 +143,16 @@ private void msort(int[] arr, int a, int len) { } } } - + int s = len - lr; msort(arr, a + lr, s); aswap(arr, a, a + lr, s); s += backmerge(arr, a + (s - 1), s, a + (lr - 1), lr - s); msort(arr, a, s); } - + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.msort(array, 0, sortLength); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/BlockSwapMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/BlockSwapMergeSort.java similarity index 90% rename from src/sorts/merge/BlockSwapMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/BlockSwapMergeSort.java index 30b22b20..dcba6a75 100644 --- a/src/sorts/merge/BlockSwapMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/BlockSwapMergeSort.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2019 Piotr Grochowski @@ -30,70 +30,69 @@ this software and associated documentation files (the "Software"), to deal in */ //refactored version of original implementation by @Piotr Grochowski (in place merge 2) -final public class BlockSwapMergeSort extends Sort { +public final class BlockSwapMergeSort extends Sort { public BlockSwapMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Block-Swap Merge"); this.setRunAllSortsName("Block-Swap Merge Sort"); this.setRunSortName("Block-Swap Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private int binarySearchMid(int[] array, int start, int mid, int end) { int a = 0, b = Math.min(mid-start, end-mid), m = a+(b-a)/2; - + while(b > a) { if(Reads.compareValues(array[mid-m-1], array[mid+m]) == 1) a = m+1; else - b = m; - + b = m; + m = a+(b-a)/2; } - + return m; } - + public void multiSwapMerge(int[] array, int start, int mid, int end) { int m = this.binarySearchMid(array, start, mid, end); - + while(m > 0) { this.multiSwap(array, mid-m, mid, m); this.multiSwapMerge(array, mid, mid+m, end); - + end = mid; mid -= m; - + m = this.binarySearchMid(array, start, mid, end); } } - + public void multiSwapMergeSort(int[] array, int a, int b) { int len = b-a, i; - + for(int j = 1; j < len; j *= 2) { for(i = a; i + 2*j <= b; i += 2*j) this.multiSwapMerge(array, i, i+j, i+2*j); - + if(i + j < b) this.multiSwapMerge(array, i, i+j, b); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.multiSwapMergeSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/BottomUpMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/BottomUpMergeSort.java similarity index 93% rename from src/sorts/merge/BottomUpMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/BottomUpMergeSort.java index 1b9e9f6e..71d67e7b 100644 --- a/src/sorts/merge/BottomUpMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/BottomUpMergeSort.java @@ -1,12 +1,12 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; public final class BottomUpMergeSort extends Sort { private int[] scratchArray; private int copyLength; - + public BottomUpMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -14,7 +14,6 @@ public BottomUpMergeSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Bottom-up Merge Sort"); this.setRunSortName("Bottom-up Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -64,32 +63,32 @@ private void merge(int[] array, int currentLength, int index, int mergeSize) { this.copyLength = left; } } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.scratchArray = Writes.createExternalArray(currentLength); int mergeSize = 2; - + while(mergeSize <= currentLength) { this.copyLength = currentLength; - + for(int i = 0; i < currentLength; i += mergeSize) { this.merge(array, currentLength, i, mergeSize); } - + this.Highlights.clearMark(2); - + for(int i = 0; i < this.copyLength; i++) { this.Writes.write(array, i, this.scratchArray[i], 1, true, false); } - + mergeSize *= 2; } if((mergeSize / 2) != currentLength) { this.merge(array, currentLength, 0, mergeSize); - + this.Highlights.clearMark(2); - + for(int i = 0; i < currentLength; i++) { this.Writes.write(array, i, this.scratchArray[i], 1, true, false); } @@ -97,4 +96,4 @@ public void runSort(int[] array, int currentLength, int bucketCount) { Writes.deleteExternalArray(this.scratchArray); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/BufferedStoogeSort.java b/src/main/java/io/github/arrayv/sorts/merge/BufferedStoogeSort.java similarity index 91% rename from src/sorts/merge/BufferedStoogeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/BufferedStoogeSort.java index f0ddb00d..d190e630 100644 --- a/src/sorts/merge/BufferedStoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/BufferedStoogeSort.java @@ -1,97 +1,96 @@ -/** - * - */ -package sorts.merge; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author _fluffyy - * @author thatsOven - * - */ -public final class BufferedStoogeSort extends Sort { - - /** - * @param arrayVisualizer - */ - public BufferedStoogeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Buffered Stooge"); - this.setRunAllSortsName("Buffered Stooge Sort"); - this.setRunSortName("Buffered Stoogesort"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int compare(int[] arr, int x, int y) { - this.Highlights.markArray(0, x); - this.Highlights.markArray(1, y); - return this.Reads.compareValues(arr[x], arr[y]); - } - - public void wrapper(int[] arr, int start, int stop) { - if (stop - start > 1) { - if (stop - start == 2 && compare(arr, start, stop - 1) == 1) { - this.Writes.swap(arr, start, stop - 1, 1.0D, true, false); - } - if (stop - start > 2) { - int third = (int) Math.ceil((stop - start) / 3.0D) + start; - int twoThird = (int) Math.ceil((stop - start) / 3.0D * 2.0D) + start; - if (twoThird - third < third) { - twoThird--; - } - if ((stop - start - 2) % 3 == 0) { - twoThird--; - } - wrapper(arr, third, twoThird); - wrapper(arr, twoThird, stop); - int left = third; - int right = twoThird; - int bufferStart = start; - while (left < twoThird && right < stop) { - if (compare(arr, left, right) == 1) { - this.Writes.swap(arr, bufferStart, right, 1.0D, true, false); - right++; - } else { - this.Writes.swap(arr, bufferStart, left, 1.0D, true, false); - left++; - } - bufferStart++; - } - while (right < stop) { - this.Writes.swap(arr, bufferStart, right, 1.0D, true, false); - right++; - bufferStart++; - } - wrapper(arr, twoThird, stop); - left = twoThird - 1; - right = stop - 1; - while (right > left && left >= start) { - if (compare(arr, left, right) == 1) { - for (int i = left; i < right; i++) { - this.Writes.swap(arr, i, i + 1, 0.3D, true, false); - } - left--; - } - right--; - } - } - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - // TODO Auto-generated method stub - wrapper(array, 0, sortLength); - - } - -} +/** + * + */ +package io.github.arrayv.sorts.merge; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * @author _fluffyy + * @author thatsOven + * + */ +public final class BufferedStoogeSort extends Sort { + + /** + * @param arrayVisualizer + */ + public BufferedStoogeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + // TODO Auto-generated constructor stub + this.setSortListName("Buffered Stooge"); + this.setRunAllSortsName("Buffered Stooge Sort"); + this.setRunSortName("Buffered Stoogesort"); + this.setCategory("Merge Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.setBogoSort(false); + } + + private int compare(int[] arr, int x, int y) { + this.Highlights.markArray(0, x); + this.Highlights.markArray(1, y); + return this.Reads.compareValues(arr[x], arr[y]); + } + + public void wrapper(int[] arr, int start, int stop) { + if (stop - start > 1) { + if (stop - start == 2 && compare(arr, start, stop - 1) == 1) { + this.Writes.swap(arr, start, stop - 1, 1.0D, true, false); + } + if (stop - start > 2) { + int third = (int) Math.ceil((stop - start) / 3.0D) + start; + int twoThird = (int) Math.ceil((stop - start) / 3.0D * 2.0D) + start; + if (twoThird - third < third) { + twoThird--; + } + if ((stop - start - 2) % 3 == 0) { + twoThird--; + } + wrapper(arr, third, twoThird); + wrapper(arr, twoThird, stop); + int left = third; + int right = twoThird; + int bufferStart = start; + while (left < twoThird && right < stop) { + if (compare(arr, left, right) == 1) { + this.Writes.swap(arr, bufferStart, right, 1.0D, true, false); + right++; + } else { + this.Writes.swap(arr, bufferStart, left, 1.0D, true, false); + left++; + } + bufferStart++; + } + while (right < stop) { + this.Writes.swap(arr, bufferStart, right, 1.0D, true, false); + right++; + bufferStart++; + } + wrapper(arr, twoThird, stop); + left = twoThird - 1; + right = stop - 1; + while (right > left && left >= start) { + if (compare(arr, left, right) == 1) { + for (int i = left; i < right; i++) { + this.Writes.swap(arr, i, i + 1, 0.3D, true, false); + } + left--; + } + right--; + } + } + } + } + + @Override + public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { + // TODO Auto-generated method stub + wrapper(array, 0, sortLength); + + } + +} diff --git a/src/sorts/merge/ImprovedInPlaceMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/ImprovedInPlaceMergeSort.java similarity index 91% rename from src/sorts/merge/ImprovedInPlaceMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/ImprovedInPlaceMergeSort.java index 9c20bdd6..e8b75d87 100644 --- a/src/sorts/merge/ImprovedInPlaceMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/ImprovedInPlaceMergeSort.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ImprovedInPlaceMergeSort extends Sort { +public final class ImprovedInPlaceMergeSort extends Sort { public ImprovedInPlaceMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Improved In-Place Merge"); this.setRunAllSortsName("Improved In-Place Merge Sort"); this.setRunSortName("Improved In-Place Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -47,42 +46,42 @@ public ImprovedInPlaceMergeSort(ArrayVisualizer arrayVisualizer) { private void push(int[] array, int p, int a, int b, double sleep) { if(a == b) return; - + int temp = array[p]; Writes.write(array, p, array[a], sleep, true, false); - + for(int i = a+1; i < b; i++) Writes.write(array, i-1, array[i], sleep, true, false); - + Writes.write(array, b-1, temp, sleep, true, false); } - + private void merge(int[] array, int a, int m, int b, double sleep) { int i = a, j = m; - + Highlights.clearMark(1); while(i < m && j < b) { Highlights.markArray(2, i); Highlights.markArray(3, j); Delays.sleep(1); - + if(Reads.compareValues(array[i], array[j]) == 1) j++; else this.push(array, i++, m, j, sleep); } - + Highlights.clearAllMarks(); while(i < m) this.push(array, i++, m, b, sleep); } private void mergeSort(int[] array, int a, int b, double sleep) { int m = a+(b-a)/2; - + if(b-a > 2) { if(b-a > 3) this.mergeSort(array, a, m, 2*sleep); this.mergeSort(array, m, b, 2*sleep); } - + this.merge(array, a, m, b, sleep); } @@ -90,4 +89,4 @@ private void mergeSort(int[] array, int a, int b, double sleep) { public void runSort(int[] array, int currentLength, int bucketCount) { this.mergeSort(array, 0, currentLength, Math.max(1.0 / currentLength, 0.001)); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/InPlaceMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/InPlaceMergeSort.java similarity index 94% rename from src/sorts/merge/InPlaceMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/InPlaceMergeSort.java index 0947f7b5..6194c5f8 100644 --- a/src/sorts/merge/InPlaceMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/InPlaceMergeSort.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,15 +29,14 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class InPlaceMergeSort extends Sort { +public final class InPlaceMergeSort extends Sort { public InPlaceMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("In-Place Merge"); this.setRunAllSortsName("In-Place Merge Sort"); this.setRunSortName("In-Place Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -52,7 +51,7 @@ private void push(int[] array, int low, int high) { } } } - + private void merge(int[] array, int min, int max, int mid) { int i = min; while(i <= mid) { @@ -87,4 +86,4 @@ else if(max - min == 1) { //only two elements and swaps them public void runSort(int[] array, int currentLength, int bucketCount) { this.mergeSort(array, 0, currentLength - 1); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/IterativeTopDownMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/IterativeTopDownMergeSort.java similarity index 97% rename from src/sorts/merge/IterativeTopDownMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/IterativeTopDownMergeSort.java index a9891a18..16f68de6 100644 --- a/src/sorts/merge/IterativeTopDownMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/IterativeTopDownMergeSort.java @@ -1,7 +1,7 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * @@ -38,7 +38,6 @@ public IterativeTopDownMergeSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Iterative Top-down Merge Sort"); this.setRunSortName("Iterative Top-down Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); diff --git a/src/sorts/merge/LazyStableSort.java b/src/main/java/io/github/arrayv/sorts/merge/LazyStableSort.java similarity index 90% rename from src/sorts/merge/LazyStableSort.java rename to src/main/java/io/github/arrayv/sorts/merge/LazyStableSort.java index 465adfcb..3df7a1d3 100644 --- a/src/sorts/merge/LazyStableSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/LazyStableSort.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.GrailSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.GrailSorting; /* - * + * The MIT License (MIT) Copyright (c) 2013 Andrey Astrelin @@ -38,24 +38,23 @@ this software and associated documentation files (the "Software"), to deal in /* */ /*****************************************/ -final public class LazyStableSort extends GrailSorting { +public final class LazyStableSort extends GrailSorting { public LazyStableSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Lazy Stable"); this.setRunAllSortsName("Lazy Stable Sort"); this.setRunSortName("Lazy Stable Sort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override - public void runSort(int[] array, int length, int bucketCount) { + public void runSort(int[] array, int length, int bucketCount) { this.grailLazyStableSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/MergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/MergeSort.java similarity index 89% rename from src/sorts/merge/MergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/MergeSort.java index 9204ebf3..67253beb 100644 --- a/src/sorts/merge/MergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/MergeSort.java @@ -1,7 +1,7 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.MergeSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.MergeSorting; /* * @@ -29,24 +29,23 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class MergeSort extends MergeSorting { +public final class MergeSort extends MergeSorting { public MergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Merge"); this.setRunAllSortsName("Merge Sort"); this.setRunSortName("Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.mergeSort(array, length, false); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/MergeSortParallel.java b/src/main/java/io/github/arrayv/sorts/merge/MergeSortParallel.java similarity index 93% rename from src/sorts/merge/MergeSortParallel.java rename to src/main/java/io/github/arrayv/sorts/merge/MergeSortParallel.java index ff9cf06b..03394464 100644 --- a/src/sorts/merge/MergeSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/merge/MergeSortParallel.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2021 aphitorite @@ -28,25 +28,24 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class MergeSortParallel extends Sort { +public final class MergeSortParallel extends Sort { public MergeSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Merge (Parallel)"); this.setRunAllSortsName("Parallel Merge Sort"); this.setRunSortName("Parallel Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] array; private int[] tmp; - + private class MergeSort extends Thread { private int a, b; MergeSort(int a, int b) { @@ -57,10 +56,10 @@ public void run() { MergeSortParallel.this.mergeSort(a, b); } } - + private void merge(int a, int m, int b) { int i = a, j = m, k = a; - + while(i < m && j < b) { if(Reads.compareValues(array[i], array[j]) <= 0) { Highlights.markArray(1, i); @@ -79,33 +78,33 @@ private void merge(int a, int m, int b) { Highlights.markArray(2, j); Writes.write(tmp, k++, array[j++], 1, false, true); } - + Highlights.clearMark(2); while(a < b) Writes.write(array, a, tmp[a++], 1, true, false); } - + private void mergeSort(int a, int b) { int len = b-a; - + if(len < 2) return; - + int m = (a+b)/2; - + MergeSort left = new MergeSort(a, m); MergeSort right = new MergeSort(m, b); left.start(); right.start(); - + try { left.join(); right.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - + this.merge(a, m, b); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; @@ -113,4 +112,4 @@ public void runSort(int[] array, int length, int bucketCount) { this.mergeSort(0, length); Writes.deleteExternalArray(tmp); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/NewShuffleMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/NewShuffleMergeSort.java similarity index 98% rename from src/sorts/merge/NewShuffleMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/NewShuffleMergeSort.java index 976eda67..56df72b4 100644 --- a/src/sorts/merge/NewShuffleMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/NewShuffleMergeSort.java @@ -1,6 +1,6 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* * @@ -48,7 +48,6 @@ public NewShuffleMergeSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("New Shuffle Merge Sort"); this.setRunSortName("New Shuffle Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); diff --git a/src/sorts/merge/PDMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/PDMergeSort.java similarity index 97% rename from src/sorts/merge/PDMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/PDMergeSort.java index 278022f0..2e81bcf1 100644 --- a/src/sorts/merge/PDMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/PDMergeSort.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 Gaming32 @@ -35,12 +35,11 @@ public class PDMergeSort extends Sort { public PDMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Pattern Defeating Merge"); this.setRunAllSortsName("Pattern-Defeating Merge Sort"); this.setRunSortName("Pattern-Defeating Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -66,7 +65,7 @@ protected void mergeUp(int[] array, int start, int mid, int end) { Writes.write(array, left++, array[right++], 1, true, false); } Highlights.clearMark(2); - + while (left < right) Writes.write(array, left++, copied[bufferPointer++], 0.5, true, false); Highlights.clearAllMarks(); @@ -121,7 +120,7 @@ protected int identifyRun(int[] array, int index, int maxIndex) { boolean cmp = compare(array[index], array[index + 1]); index++; Highlights.markArray(1, index); - + while (index < maxIndex) { Delays.sleep(1); boolean checkCmp = compare(array[index], array[index + 1]); @@ -164,7 +163,7 @@ public void runSort(int[] array, int length, int bucketCount) { // arrayVisualizer.setHeading("PDMerge -- Finding Runs"); int[] runs = findRuns(array, length - 1); copied = Writes.createExternalArray(length / 2); - + // arrayVisualizer.setHeading("PDMerge -- Merging Runs"); while (runCount > 1) { for (int i = 0; i < runCount - 1; i += 2) { @@ -181,4 +180,4 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.deleteExternalArray(runs); Writes.deleteExternalArray(copied); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/QuadSort.java b/src/main/java/io/github/arrayv/sorts/merge/QuadSort.java similarity index 90% rename from src/sorts/merge/QuadSort.java rename to src/main/java/io/github/arrayv/sorts/merge/QuadSort.java index 5d112994..7f02e769 100644 --- a/src/sorts/merge/QuadSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/QuadSort.java @@ -1,7 +1,7 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.QuadSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.QuadSorting; /* Copyright (C) 2014-2021 Igor van den Hoven ivdhoven@gmail.com @@ -29,24 +29,23 @@ a copy of this software and associated documentation files (the // re-implemented to Java, ArrayV by mg-2018, 2021 // 210704 ~ 210816 -final public class QuadSort extends QuadSorting { +public final class QuadSort extends QuadSorting { public QuadSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Quad"); this.setRunAllSortsName("Quad Sort"); this.setRunSortName("Quadsort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.quadSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/RotateMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSort.java similarity index 93% rename from src/sorts/merge/RotateMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/RotateMergeSort.java index da3c8832..5cf587c5 100644 --- a/src/sorts/merge/RotateMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSort.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2020 aphitorite @@ -28,31 +28,30 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class RotateMergeSort extends Sort { +public final class RotateMergeSort extends Sort { public RotateMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Rotate Merge"); this.setRunAllSortsName("Rotate Merge Sort"); //this.setRunAllID("In-Place Merge Sort with Rotations"); this.setRunSortName(/*"In-Place */"Rotate Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + private void rotate(int[] array, int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(array, m-r, m, r); @@ -68,24 +67,24 @@ private void rotate(int[] array, int a, int m, int b) { } } } - + private int binarySearch(int[] array, int a, int b, int value, boolean left) { while(a < b) { int m = a+(b-a)/2; - + boolean comp = left ? Reads.compareValues(value, array[m]) <= 0 : Reads.compareValues(value, array[m]) < 0; - + if(comp) b = m; else a = m+1; } - + return a; } - + private void rotateMerge(int[] array, int a, int m, int b) { int m1, m2, m3; - + if(m-a >= b-m) { m1 = a+(m-a)/2; m2 = this.binarySearch(array, m, b, array[m1], true); @@ -97,25 +96,25 @@ private void rotateMerge(int[] array, int a, int m, int b) { m3 = (m2++)-(m-m1); } this.rotate(array, m1, m, m2); - + if(m2-(m3+1) > 0 && b-m2 > 0) this.rotateMerge(array, m3+1, m2, b); if(m1-a > 0 && m3-m1 > 0) this.rotateMerge(array, a, m1, m3); } - + protected void rotateMergeSort(int[] array, int a, int b) { int len = b-a, i; - + for(int j = 1; j < len; j *= 2) { for(i = a; i + 2*j <= b; i += 2*j) this.rotateMerge(array, i, i+j, i+2*j); - + if(i + j < b) this.rotateMerge(array, i, i+j, b); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.rotateMergeSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/RotateMergeSortParallel.java b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSortParallel.java similarity index 94% rename from src/sorts/merge/RotateMergeSortParallel.java rename to src/main/java/io/github/arrayv/sorts/merge/RotateMergeSortParallel.java index 3f45acf7..c5a8435e 100644 --- a/src/sorts/merge/RotateMergeSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSortParallel.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * The MIT License (MIT) Copyright (c) 2020 aphitorite @@ -28,25 +28,24 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class RotateMergeSortParallel extends Sort { +public final class RotateMergeSortParallel extends Sort { public RotateMergeSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Rotate Merge (Parallel)"); this.setRunAllSortsName("Parallel Rotate Merge Sort"); //this.setRunAllID("In-Place Merge Sort with Rotations"); this.setRunSortName(/*"In-Place */"Parallel Rotate Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); this.setUnreasonableLimit(4096); this.setBogoSort(false); } - + private int[] array; - + private class RotateMergeSort extends Thread { private int a, b; RotateMergeSort(int a, int b) { @@ -69,15 +68,15 @@ public void run() { RotateMergeSortParallel.this.rotateMerge(a, m, b); } } - + private void multiSwap(int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(this.array, a+i, b+i, 1, true, false); } - + private void rotate(int a, int m, int b) { int l = m-a, r = b-m; - + while(l > 0 && r > 0) { if(r < l) { this.multiSwap(m-r, m, r); @@ -93,26 +92,26 @@ private void rotate(int a, int m, int b) { } } } - + private int binarySearch(int a, int b, int value, boolean left) { while(a < b) { int m = a+(b-a)/2; - + boolean comp = left ? Reads.compareValues(value, this.array[m]) <= 0 : Reads.compareValues(value, this.array[m]) < 0; - + if(comp) b = m; else a = m+1; } - + return a; } - + private void rotateMerge(int a, int m, int b) { if(m-a < 1 || b-m < 1) return; - + int m1, m2, m3; - + if(m-a >= b-m) { m1 = a+(m-a)/2; m2 = this.binarySearch(m, b, this.array[m1], true); @@ -124,7 +123,7 @@ private void rotateMerge(int a, int m, int b) { m3 = (m2++)-(m-m1); } this.rotate(m1, m, m2); - + RotateMerge l = new RotateMerge(a, m1, m3); RotateMerge r = new RotateMerge(m3+1, m2, b); l.start(); @@ -136,10 +135,10 @@ private void rotateMerge(int a, int m, int b) { Thread.currentThread().interrupt(); } } - + protected void rotateMergeSort(int a, int b) { if(b-a < 2) return; - + int m = (a+b)/2; RotateMergeSort l = new RotateMergeSort(a, m); RotateMergeSort r = new RotateMergeSort(m, b); @@ -148,16 +147,16 @@ protected void rotateMergeSort(int a, int b) { try { l.join(); r.join(); - } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } this.rotateMerge(a, m, b); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.rotateMergeSort(0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/StacklessRotateMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/StacklessRotateMergeSort.java similarity index 92% rename from src/sorts/merge/StacklessRotateMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/StacklessRotateMergeSort.java index ec767532..d17aac87 100644 --- a/src/sorts/merge/StacklessRotateMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/StacklessRotateMergeSort.java @@ -1,11 +1,11 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; -import utils.IndexedRotations; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.utils.IndexedRotations; /* - * + * The MIT License (MIT) Copyright (c) 2021 aphitorite @@ -29,39 +29,38 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class StacklessRotateMergeSort extends Sort { +public final class StacklessRotateMergeSort extends Sort { public StacklessRotateMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stackless Rotate Merge"); this.setRunAllSortsName("Stackless Rotate Merge Sort"); this.setRunSortName("Stackless Rotate Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void rotate(int[] array, int a, int m, int b) { IndexedRotations.griesMills(array, a, m, b, 0.5, true, false); } - + //@param c - select c smallest elements private void partitionMerge(int[] array, int a, int m, int b, int c) { int lenA = m-a, lenB = b-m; - + if(lenA < 1 || lenB < 1) return; - + if(lenB < lenA) { c = (lenA+lenB)-c; int r1 = 0, r2 = Math.min(c, lenB); - + while(r1 < r2) { int ml = (r1+r2)/2; - + if(Reads.compareValues(array[m-(c-ml)], array[b-ml-1]) > 0) r2 = ml; else @@ -73,10 +72,10 @@ private void partitionMerge(int[] array, int a, int m, int b, int c) { } else { int r1 = 0, r2 = Math.min(c, lenA); - + while(r1 < r2) { int ml = (r1+r2)/2; - + if(Reads.compareValues(array[a+ml], array[m+(c-ml)-1]) > 0) r2 = ml; else @@ -87,40 +86,40 @@ private void partitionMerge(int[] array, int a, int m, int b, int c) { this.rotate(array, a+r1, m, m+(c-r1)); } } - + private void rotateMerge(int[] array, int a, int b, int c) { int i; for(i = a+1; i < b && Reads.compareIndices(array, i-1, i, 0.25, true) <= 0; i++); if(i < b) this.partitionMerge(array, a, i, b, c); } - + public void rotatePartitionMergeSort(int[] array, int a, int b) { int len = b-a; - + for(int i = a+1; i < b; i += 2) if(Reads.compareIndices(array, i-1, i, 0.5, true) > 0) Writes.swap(array, i-1, i, 0.5, true, false); - + for(int j = 2; j < len; j *= 2) { int b1 = 0; - + for(int i = a; i+j < b; i += 2*j) { b1 = Math.min(i+2*j, b); this.partitionMerge(array, i, i+j, b1, j); } - + for(int k = j/2; k > 1; k /= 2) for(int i = a; i+k < b1; i += 2*k) this.rotateMerge(array, i, Math.min(i+2*k, b), k); - + for(int i = a+1; i < b1; i += 2) if(Reads.compareIndices(array, i-1, i, 0.5, true) > 0) Writes.swap(array, i-1, i, 0.5, true, false); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.rotatePartitionMergeSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/StrandSort.java b/src/main/java/io/github/arrayv/sorts/merge/StrandSort.java similarity index 94% rename from src/sorts/merge/StrandSort.java rename to src/main/java/io/github/arrayv/sorts/merge/StrandSort.java index 0b7a79c3..e6772c51 100644 --- a/src/sorts/merge/StrandSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/StrandSort.java @@ -1,10 +1,10 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -28,7 +28,7 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - + public final class StrandSort extends Sort { public StrandSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,39 +37,38 @@ public StrandSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Strand Sort"); this.setRunSortName("Strandsort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + //reverses equal items order private void mergeTo(int[] array, int[] subList, int a, int m, int b) { int i = 0, s = m-a; - + while(i < s && m < b) { if(Reads.compareValues(subList[i], array[m]) < 0) Writes.write(array, a++, subList[i++], 0.5, true, false); - + else Writes.write(array, a++, array[m++], 0.5, true, false); } - + while(i < s) Writes.write(array, a++, subList[i++], 0.5, true, false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int[] subList = Writes.createExternalArray(length); - + int j = length, k = j; - + while(j > 0) { Writes.write(subList, 0, array[0], 1, true, true); k--; - + for(int i = 0, p = 0, m = 1; m < j; m++) { if(Reads.compareValues(array[m], subList[i]) >= 0) { Writes.write(subList, ++i, array[m], 1, true, true); @@ -81,10 +80,10 @@ public void runSort(int[] array, int length, int bucketCount) { } } Highlights.clearMark(2); - + this.mergeTo(array, subList, k, j, length); j = k; } Writes.deleteExternalArray(subList); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/TwinSort.java b/src/main/java/io/github/arrayv/sorts/merge/TwinSort.java similarity index 91% rename from src/sorts/merge/TwinSort.java rename to src/main/java/io/github/arrayv/sorts/merge/TwinSort.java index f1ddc74c..37614fac 100644 --- a/src/sorts/merge/TwinSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/TwinSort.java @@ -1,7 +1,7 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.TwinSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.TwinSorting; /* Copyright (C) 2014-2021 Igor van den Hoven ivdhoven@gmail.com @@ -35,7 +35,7 @@ a copy of this software and associated documentation files (the twinsort 1.1.3.3 */ -final public class TwinSort extends TwinSorting { +public final class TwinSort extends TwinSorting { public TwinSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -43,7 +43,6 @@ public TwinSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Twin Sort"); this.setRunSortName("Twin Sort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -55,4 +54,4 @@ public TwinSort(ArrayVisualizer arrayVisualizer) { public void runSort(int[] array, int currentLength, int bucketCount) { this.twinsort(array, currentLength); } -} \ No newline at end of file +} diff --git a/src/sorts/merge/WeavedMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/WeavedMergeSort.java similarity index 96% rename from src/sorts/merge/WeavedMergeSort.java rename to src/main/java/io/github/arrayv/sorts/merge/WeavedMergeSort.java index 4db6ab1f..edbe96e1 100644 --- a/src/sorts/merge/WeavedMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/WeavedMergeSort.java @@ -1,7 +1,7 @@ -package sorts.merge; +package io.github.arrayv.sorts.merge; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * @@ -38,7 +38,6 @@ public WeavedMergeSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Weaved Merge Sort"); this.setRunSortName("Weaved Mergesort"); this.setCategory("Merge Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -49,7 +48,7 @@ public WeavedMergeSort(ArrayVisualizer arrayVisualizer) { private void merge(int[] array, int[] tmp, int length, int residue, int modulus) { if (residue+modulus >= length) return; - + int low = residue; int high = residue+modulus; int dmodulus = modulus<<1; diff --git a/src/sorts/misc/BurntPancakeSort.java b/src/main/java/io/github/arrayv/sorts/misc/BurntPancakeSort.java similarity index 55% rename from src/sorts/misc/BurntPancakeSort.java rename to src/main/java/io/github/arrayv/sorts/misc/BurntPancakeSort.java index 7544389c..d6ebf120 100644 --- a/src/sorts/misc/BurntPancakeSort.java +++ b/src/main/java/io/github/arrayv/sorts/misc/BurntPancakeSort.java @@ -1,22 +1,16 @@ -package sorts.misc; +package io.github.arrayv.sorts.misc; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; -final public class BurntPancakeSort extends Sort { +@SortMeta( + name = "Burnt Pancake", + runName = "Burnt Pancake Sort" +) +public final class BurntPancakeSort extends Sort { public BurntPancakeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Burnt Pancake"); - this.setRunAllSortsName("Burnt Pancake Sorting"); - this.setRunSortName("Burnt Pancake Sort"); - this.setCategory("Miscellaneous Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -36,4 +30,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } } -} \ No newline at end of file +} diff --git a/src/sorts/misc/PancakeInsertionSort.java b/src/main/java/io/github/arrayv/sorts/misc/PancakeInsertionSort.java similarity index 85% rename from src/sorts/misc/PancakeInsertionSort.java rename to src/main/java/io/github/arrayv/sorts/misc/PancakeInsertionSort.java index 4b0af84b..b3848f06 100644 --- a/src/sorts/misc/PancakeInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/misc/PancakeInsertionSort.java @@ -1,22 +1,15 @@ -package sorts.misc; +package io.github.arrayv.sorts.misc; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; -final public class PancakeInsertionSort extends Sort { +@SortMeta( + name = "Pancake Insertion" +) +public final class PancakeInsertionSort extends Sort { public PancakeInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pancake Insertion"); - this.setRunAllSortsName("Pancake Insertion Sort"); - this.setRunSortName("Pancake Insertionsort"); - this.setCategory("Miscellaneous Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int monoboundFw(int[] array, int start, int end, int value) { @@ -26,7 +19,7 @@ private int monoboundFw(int[] array, int start, int end, int value) { while (top > 1) { mid = top / 2; - + if (Reads.compareValueIndex(array, value, end - mid, 0.5, true) <= 0) { end -= mid; } diff --git a/src/sorts/misc/PancakeSort.java b/src/main/java/io/github/arrayv/sorts/misc/PancakeSort.java similarity index 77% rename from src/sorts/misc/PancakeSort.java rename to src/main/java/io/github/arrayv/sorts/misc/PancakeSort.java index 4b5223cf..70363910 100644 --- a/src/sorts/misc/PancakeSort.java +++ b/src/main/java/io/github/arrayv/sorts/misc/PancakeSort.java @@ -1,60 +1,54 @@ -package sorts.misc; +package io.github.arrayv.sorts.misc; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /* * IDeserve
* https://www.youtube.com/c/IDeserve">https://www.youtube.com/c/IDeserve * Given an array, sort the array using Pancake sort. - * + * * @author Saurabh * https://www.ideserve.co.in/learn/pancake-sorting */ -final public class PancakeSort extends Sort { +@SortMeta( + name = "Pancake", + runName = "Pancake Sort" +) +public final class PancakeSort extends Sort { public PancakeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pancake"); - this.setRunAllSortsName("Pancake Sorting"); - this.setRunSortName("Pancake Sort"); - this.setCategory("Miscellaneous Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + private boolean sorted(int[] array, int length) { for(int i = 0; i < length; i++) { Highlights.markArray(1, i); Delays.sleep(0.025); - + if(Reads.compareValues(array[i], array[i + 1]) > 0) return false; } return true; } - + private int findMax(int[] arr, int end) { int index = 0, max = Integer.MIN_VALUE; for (int i = 0; i <= end; i++) { Highlights.markArray(1, i); - + if (Reads.compareValues(arr[i], max) == 1) { max = arr[i]; index = i; Highlights.markArray(2, i); } - + Delays.sleep(0.025); Highlights.clearMark(1); } return index; } - + @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = length - 1; i >= 0; i--) { @@ -72,4 +66,4 @@ else if(index != i) { else break; } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/sorts/misc/StalinSort.java b/src/main/java/io/github/arrayv/sorts/misc/StalinSort.java new file mode 100644 index 00000000..35b32b0b --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/misc/StalinSort.java @@ -0,0 +1,25 @@ +package io.github.arrayv.sorts.misc; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; + +@SortMeta( + name = "Stalin" +) +public final class StalinSort extends Sort { + public StalinSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { + for (int i = 1; i < currentLength; i++) { + Highlights.markArray(1, i); + Delays.sleep(0.5); + if (Reads.compareValues(array[i - 1], array[i]) > 0) { + Writes.write(array, i, array[i - 1], 0.5, true, false); + } + } + } +} diff --git a/src/main/java/io/github/arrayv/sorts/misc/package-info.java b/src/main/java/io/github/arrayv/sorts/misc/package-info.java new file mode 100644 index 00000000..b0ffd475 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/misc/package-info.java @@ -0,0 +1,4 @@ +@io.github.arrayv.sortdata.SortPackageMeta( + category = "Miscellaneous Sorts" +) +package io.github.arrayv.sorts.misc; diff --git a/src/sorts/quick/TernaryLLQuickSort.java b/src/main/java/io/github/arrayv/sorts/quick/TernaryLLQuickSort.java similarity index 80% rename from src/sorts/quick/TernaryLLQuickSort.java rename to src/main/java/io/github/arrayv/sorts/quick/TernaryLLQuickSort.java index 941d5209..791736bb 100644 --- a/src/sorts/quick/TernaryLLQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/quick/TernaryLLQuickSort.java @@ -1,14 +1,20 @@ -package sorts.quick; +package io.github.arrayv.sorts.quick; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /** * @author Timo Bingmann * Implemented in ArrayV by Gaming32 * https://github.com/bingmann/sound-of-sorting/blob/master/src/SortAlgo.cpp#L536-L595 */ -final public class TernaryLLQuickSort extends Sort { +@SortMeta( + listName = "Ternary LL Quick", + showcaseName = "Quick Sort (ternary, LL ptrs)", + runName = "Quicksort (ternary, LL ptrs)" +) +public final class TernaryLLQuickSort extends Sort { class PivotPair { int first, second; @@ -20,17 +26,6 @@ public PivotPair(int first, int second) { public TernaryLLQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Ternary LL Quick"); - this.setRunAllSortsName("Quick Sort (ternary, LL ptrs)"); - this.setRunSortName("Quicksort (ternary, LL ptrs)"); - this.setCategory("Quick Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int compare(int[] A, int lo, int hi) { @@ -91,7 +86,7 @@ private void quickSortTernaryLL(int[] A, int lo, int hi) { quickSortTernaryLL(A, mid.second, hi); } } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { quickSortTernaryLL(array, 0, currentLength); diff --git a/src/sorts/quick/TernaryLRQuickSort.java b/src/main/java/io/github/arrayv/sorts/quick/TernaryLRQuickSort.java similarity index 83% rename from src/sorts/quick/TernaryLRQuickSort.java rename to src/main/java/io/github/arrayv/sorts/quick/TernaryLRQuickSort.java index 010b16c3..13a0b1d6 100644 --- a/src/sorts/quick/TernaryLRQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/quick/TernaryLRQuickSort.java @@ -1,27 +1,22 @@ -package sorts.quick; +package io.github.arrayv.sorts.quick; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; /** * @author Timo Bingmann * Implemented in ArrayV by Gaming32 * https://github.com/bingmann/sound-of-sorting/blob/master/src/SortAlgo.cpp#L449-L534 */ -final public class TernaryLRQuickSort extends Sort { +@SortMeta( + listName = "Ternary LR Quick", + showcaseName = "Quick Sort (ternary, LR ptrs)", + runName = "Quicksort (ternary, LR ptrs)" +) +public final class TernaryLRQuickSort extends Sort { public TernaryLRQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Ternary LR Quick"); - this.setRunAllSortsName("Quick Sort (ternary, LR ptrs)"); - this.setRunSortName("Quicksort (ternary, LR ptrs)"); - this.setCategory("Quick Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int compare(int[] A, int lo, int hi) { @@ -107,7 +102,7 @@ private void quickSortTernaryLR(int[] A, int lo, int hi) { quickSortTernaryLR(A, lo, lo + num_less - 1); quickSortTernaryLR(A, hi - num_greater + 1, hi); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { quickSortTernaryLR(array, 0, currentLength - 1); diff --git a/src/main/java/io/github/arrayv/sorts/quick/package-info.java b/src/main/java/io/github/arrayv/sorts/quick/package-info.java new file mode 100644 index 00000000..e53fe3de --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/quick/package-info.java @@ -0,0 +1,4 @@ +@io.github.arrayv.sortdata.SortPackageMeta( + category = "Quick Sorts" +) +package io.github.arrayv.sorts.quick; diff --git a/src/sorts/select/AsynchronousSort.java b/src/main/java/io/github/arrayv/sorts/select/AsynchronousSort.java similarity index 91% rename from src/sorts/select/AsynchronousSort.java rename to src/main/java/io/github/arrayv/sorts/select/AsynchronousSort.java index 413b6ff5..93e27996 100644 --- a/src/sorts/select/AsynchronousSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/AsynchronousSort.java @@ -1,14 +1,14 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License -Copyright (c) 2019 w0rthy +Copyright (c) 2021 Gaming32 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -30,22 +30,21 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class AsynchronousSort extends Sort { +public final class AsynchronousSort extends Sort { public AsynchronousSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Asynchronous"); this.setRunAllSortsName("Asynchronous Sort"); this.setRunSortName("Asynchronous Sort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int[] ext = Writes.createExternalArray(length); @@ -83,4 +82,4 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.clearMark(2); insertSort.customInsertSort(array, 0, cur, 0.2, false); } -} \ No newline at end of file +} diff --git a/src/sorts/select/BadSort.java b/src/main/java/io/github/arrayv/sorts/select/BadSort.java similarity index 87% rename from src/sorts/select/BadSort.java rename to src/main/java/io/github/arrayv/sorts/select/BadSort.java index e527fa1a..421a67ab 100644 --- a/src/sorts/select/BadSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BadSort.java @@ -1,22 +1,21 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * This example of an O(n^3) sorting algorithm may be found here, written by James Jensen (StriplingWarrayior on StackOverflow): * https://stackoverflow.com/questions/27389344/is-there-a-sorting-algorithm-with-a-worst-case-time-complexity-of-n3 */ - -final public class BadSort extends Sort { + +public final class BadSort extends Sort { public BadSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Bad"); this.setRunAllSortsName("Bad Sort"); this.setRunSortName("Badsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(true); @@ -29,16 +28,16 @@ public void runSort(int[] array, int currentLen, int bucketCount) { for (int i = 0; i < currentLen; i++) { int shortest = i; Delays.sleep(0.05); - + for (int j = i; j < currentLen; j++) { Highlights.markArray(1, j); Delays.sleep(0.05); - + boolean isShortest = true; for (int k = j + 1; k < currentLen; k++) { Highlights.markArray(2, k); Delays.sleep(0.05); - + if (Reads.compareValues(array[j], array[k]) == 1) { isShortest = false; break; @@ -52,4 +51,4 @@ public void runSort(int[] array, int currentLen, int bucketCount) { Writes.swap(array, i, shortest, 0.05, true, false); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/BaseNMaxHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/BaseNMaxHeapSort.java similarity index 67% rename from src/sorts/select/BaseNMaxHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/BaseNMaxHeapSort.java index a99cf657..6de75c99 100644 --- a/src/sorts/select/BaseNMaxHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BaseNMaxHeapSort.java @@ -1,22 +1,19 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; -final public class BaseNMaxHeapSort extends Sort { +@SortMeta( + name = "Base-N Max Heap", + category = "Selection Sorts", + showcaseName = "Base-N Max Heap Sort, Base 4", + question = "Enter the base for this sort:", + defaultAnswer = 4 +) +public final class BaseNMaxHeapSort extends Sort { public BaseNMaxHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - this.setSortListName("Base-N Max Heap"); - this.setRunAllSortsName("Base-N Max Heap Sort, Base 4"); - this.setRunSortName("Base-N Max Heapsort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(true); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - this.setQuestion("Enter the base for this sort:", 4); } private void siftDown(int[] arr, int base, int node, int stop, double sleep) { @@ -50,4 +47,4 @@ public void runSort(int[] arr, int length, int base) { this.siftDown(arr, base, 0, i, 1); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/BingoSort.java b/src/main/java/io/github/arrayv/sorts/select/BingoSort.java similarity index 89% rename from src/sorts/select/BingoSort.java rename to src/main/java/io/github/arrayv/sorts/select/BingoSort.java index 00c70c81..2b8d045d 100644 --- a/src/sorts/select/BingoSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BingoSort.java @@ -1,47 +1,46 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * Bingo Sort is a variant of Selection Sort which looks through all elements, using the * element with the maximum VALUE instead of the item to be swapped instead of the item. - * + * * This is best suited to use when there are duplicate values in the array because the * sort will run quicker (similar to Counting Sort) - running on O(n+m^2) best case scenario, * otherwise it will run at O(n*m) time complexity, * where "m" is the amount of unique values in the array. - * + * * >> Original source(s): * >> https://en.wikipedia.org/wiki/Selection_sort#Variants * >> https://xlinux.nist.gov/dads/HTML/bingosort.html - * + * * >> Imported and Translated (from Pascal) by Joel "McDude73" Zaleschuk */ -final public class BingoSort extends Sort { +public final class BingoSort extends Sort { public BingoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Bingo"); this.setRunAllSortsName("Bingo Sort"); this.setRunSortName("Bingosort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { double sleep = Math.min(Math.max(10d/this.arrayVisualizer.getUniqueItems(), 0.001), 1); - + int maximum = length - 1; int next = array[maximum]; - + for(int i=maximum-1;i>=0;i--) { if(array[i] > next) { next = array[i]; @@ -53,16 +52,16 @@ public void runSort(int[] array, int length, int bucketCount) { while(maximum > 0) { int val = next; next = array[maximum]; - + for(int j=maximum-1;j>=0;j--) { - + Highlights.markArray(1, array[j]); Highlights.markArray(2, val); - + if(Reads.compareValues(array[j], val) == 0) { Writes.swap(array, j, maximum, 2*sleep, true, false); maximum--; - + } else { if(array[j] > next) { @@ -76,4 +75,4 @@ public void runSort(int[] array, int length, int bucketCount) { } } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/sorts/select/BinomialHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/BinomialHeapSort.java new file mode 100644 index 00000000..b88412ff --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/select/BinomialHeapSort.java @@ -0,0 +1,60 @@ +package io.github.arrayv.sorts.select; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +public final class BinomialHeapSort extends Sort { + public BinomialHeapSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + + this.setSortListName("Binomial Heap"); + this.setRunAllSortsName("Binomial Heap Sort"); + this.setRunSortName("Binomial Heapsort"); + this.setCategory("Selection Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.setBogoSort(false); + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + int maxNode, focus, index, depth; + for (index = 2; index <= length; index += 2) { + maxNode = index; + do { + focus = maxNode; + for (depth = 1; (focus & depth) == 0; depth *= 2) { + if (Reads.compareValues(array[focus - depth - 1], array[maxNode - 1]) > 0) + maxNode = (focus - depth); + } + if (focus != maxNode) { + Writes.swap(array, focus - 1, maxNode - 1, 1, true, false); + } + } while (focus != maxNode); + } + for (index = length; index > 2; index--) { + maxNode = index; + focus = index; + for (depth = 1; focus != 0; depth *= 2) { + if ((focus & depth) != 0) { + if (Reads.compareValues(array[focus - 1], array[maxNode - 1]) > 0) + maxNode = focus; + focus -= depth; + } + } + if (maxNode != index) { + focus = index; + do { + Writes.swap(array, focus - 1, maxNode - 1, 1, true, false); + focus = maxNode; + for (depth = 1; (focus & depth) == 0; depth *= 2) { + if (Reads.compareValues(array[focus - depth - 1], array[maxNode - 1]) > 0) + maxNode = (focus - depth); + } + } while (focus != maxNode); + } + } + } +} diff --git a/src/sorts/select/BinomialSmoothSort.java b/src/main/java/io/github/arrayv/sorts/select/BinomialSmoothSort.java similarity index 91% rename from src/sorts/select/BinomialSmoothSort.java rename to src/main/java/io/github/arrayv/sorts/select/BinomialSmoothSort.java index aa576185..e25a5c15 100644 --- a/src/sorts/select/BinomialSmoothSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BinomialSmoothSort.java @@ -1,17 +1,16 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class BinomialSmoothSort extends Sort { +public final class BinomialSmoothSort extends Sort { public BinomialSmoothSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Binomial Smooth"); this.setRunAllSortsName("Binomial Smooth Sort"); this.setRunSortName("Binomial Smoothsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -25,7 +24,7 @@ private int height(int node){ count++; return count; } - + private void thrift(int[] array, int node, boolean parent, boolean root){ root = root && (node >= (1 << height(node))); if (!root && !parent) @@ -40,7 +39,7 @@ private void thrift(int[] array, int node, boolean parent, boolean root){ Writes.swap(array, node, node - (1 << choice), .65, true, false); thrift(array, node - (1 << choice), (node - (1 << choice)) % 2 ==1, choice == height(node)); } - + @Override public void runSort(int[] array, int length, int bucketCount){ //heapify from 0 to length - 1 @@ -52,4 +51,4 @@ public void runSort(int[] array, int length, int bucketCount){ for (int Child = height(Node) - 1; Child >= 0; Child --) thrift(array, Node - (1 << Child), false, true); } -} \ No newline at end of file +} diff --git a/src/sorts/select/BottomUpHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/BottomUpHeapSort.java similarity index 91% rename from src/sorts/select/BottomUpHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/BottomUpHeapSort.java index ad9f44fd..e23c2a34 100644 --- a/src/sorts/select/BottomUpHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BottomUpHeapSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class BottomUpHeapSort extends Sort { +public final class BottomUpHeapSort extends Sort { public BottomUpHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,31 +37,30 @@ public BottomUpHeapSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Bottom-up Heap Sort"); this.setRunSortName("Bottom-up Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + //source: https://en.wikipedia.org/wiki/Heapsort#Bottom-up_heapsort - + private void siftDown(int[] array, int i, int b) { int j = i; for(; 2*j + 1 < b; j = 2*j + 2 < b ? (Reads.compareValues(array[2*j + 2], array[2*j + 1]) > 0 ? 2*j + 2 : 2*j + 1) : 2*j + 1); for(; Reads.compareValues(array[i], array[j]) > 0; j = (j-1)/2); for(; j > i; j = (j-1)/2) Writes.swap(array, i, j, 1, true, false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { for(int i = (length-1)/2; i >= 0; i--) this.siftDown(array, i, length); - + for(int i = length-1; i > 0; i--) { Writes.swap(array, 0, i, 1, true, false); this.siftDown(array, 0, i); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/ClassicTournamentSort.java b/src/main/java/io/github/arrayv/sorts/select/ClassicTournamentSort.java similarity index 93% rename from src/sorts/select/ClassicTournamentSort.java rename to src/main/java/io/github/arrayv/sorts/select/ClassicTournamentSort.java index ec2ebe07..3c589b2e 100644 --- a/src/sorts/select/ClassicTournamentSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/ClassicTournamentSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class ClassicTournamentSort extends Sort { +public final class ClassicTournamentSort extends Sort { public ClassicTournamentSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,105 +37,104 @@ public ClassicTournamentSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Classic Tournament Sort"); this.setRunSortName("Classic Tournament Sort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private int[] array; private int[] tmp; private int[] tree; - + private int size; - + private int ceilPow2(int n) { int r = 1; while(r < n) r *= 2; return r; } - + private boolean treeCompare(int a, int b) { return Reads.compareIndices(this.array, this.tree[a], this.tree[b], 1, true) <= 0; } - + private void buildTree(int n) { this.size = this.ceilPow2(n)-1; int mod = n&1; int treeSize = n+this.size+mod; - + this.tree = Writes.createExternalArray(treeSize); - + for(int i = 0; i < treeSize; i++) Writes.write(this.tree, i, -1, 0, false, true); - + for(int i = this.size; i < treeSize-mod; i++) { Highlights.markArray(1, i-this.size); Writes.write(this.tree, i, i-this.size, 0.5, false, true); } - + for(int i, j = this.size, k = treeSize-mod; j > 0; j /= 2, k /= 2) { for(i = j; i+1 < k; i += 2) { int val = this.treeCompare(i, i+1) ? this.tree[i] : this.tree[i+1]; - + Writes.write(this.tree, i/2, val, 0, false, true); } if(i < k) Writes.write(this.tree, i/2, this.tree[i], 0, false, true); } } - + private int peek() { return this.array[this.tree[0]]; } - + private int findNext() { int root = this.tree[0]+this.size; - + for(int i = root; i > 0; i = (i-1)/2) Writes.write(this.tree, i, -1, 0, false, true); - + for(int i = root; i > 0; ) { int j = i + ((i&1)<<1)-1; - + int c1 = this.tree[i] >> 31; int c2 = this.tree[j] >> 31; - + int nVal = (c1 & ((c2 & -1) + (~c2 & this.tree[j]))) + (~c1 & ((c2 & this.tree[i]) + (~c2 & -2))); - + if(nVal == -2) { if(i < j) nVal = this.treeCompare(i, j) ? this.tree[i] : this.tree[j]; else nVal = this.treeCompare(j, i) ? this.tree[j] : this.tree[i]; } - + i = (i-1)/2; if(nVal != -1) Writes.write(this.tree, i, nVal, 0, false, true); } - + return this.peek(); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.array = array; - + this.buildTree(length); this.tmp = Writes.createExternalArray(length); - + Highlights.markArray(3, 0); Writes.write(this.tmp, 0, this.peek(), 1, false, true); - + for(int i = 1; i < length; i++) { int val = this.findNext(); - + Highlights.markArray(3, i); Writes.write(this.tmp, i, val, 1, false, true); } Highlights.clearAllMarks(); Writes.arraycopy(this.tmp, 0, array, 0, length, 1, true, false); - + Writes.deleteExternalArray(this.tree); Writes.deleteExternalArray(this.tmp); } -} \ No newline at end of file +} diff --git a/src/sorts/select/ReverseSandpaperSort.java b/src/main/java/io/github/arrayv/sorts/select/CycleSort.java similarity index 52% rename from src/sorts/select/ReverseSandpaperSort.java rename to src/main/java/io/github/arrayv/sorts/select/CycleSort.java index 61b22064..930b93c3 100644 --- a/src/sorts/select/ReverseSandpaperSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/CycleSort.java @@ -1,12 +1,13 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* + * MIT License -Copyright (c) 2021 Gaming32 +Copyright (c) 2021 aphitorite Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,32 +26,60 @@ of this software and associated documentation files (the "Software"), to deal LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ + * + */ -final public class ReverseSandpaperSort extends Sort { - public ReverseSandpaperSort(ArrayVisualizer arrayVisualizer) { +public final class CycleSort extends Sort { + public CycleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Reverse Sandpaper"); - this.setRunAllSortsName("Reverse Sandpaper Sort"); - this.setRunSortName("Reverse Sandpapersort"); + + this.setSortListName("Cycle"); + this.setRunAllSortsName("Cycle Sort"); + this.setRunSortName("Cyclesort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + + private int countLesser(int[] array, int a, int b, int t) { + int r = a; + + for(int i = a+1; i < b; i++) { + Highlights.markArray(1, r); + Highlights.markArray(2, i); + Delays.sleep(0.01); + + r += Reads.compareValues(array[i], t) < 0 ? 1 : 0; + } + Highlights.clearMark(2); + return r; + } + @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - for (int i = 0; i < currentLength - 1; i++) { - for (int j = currentLength - 1; j > i; j--) { - if (Reads.compareIndices(array, i, j, 0.05, true) > 0) { - Writes.swap(array, i, j, 0.05, true, false); - } - } - } + public void runSort(int[] array, int length, int bucketCount) { + for(int i = 0; i < length-1; i++) { + Highlights.markArray(3, i); + + int t = array[i]; + int r = this.countLesser(array, i, length, t); + + if(r != i) { + do { + while(Reads.compareIndexValue(array, r, t, 0.01, true) == 0) r++; + + int t1 = array[r]; + Writes.write(array, r, t, 0.02, false, false); + t = t1; + + r = this.countLesser(array, i, length, t); + } + while(r != i); + + Writes.write(array, i, t, 0.02, false, false); + } + } } } diff --git a/src/sorts/select/DoubleSelectionSort.java b/src/main/java/io/github/arrayv/sorts/select/DoubleSelectionSort.java similarity index 90% rename from src/sorts/select/DoubleSelectionSort.java rename to src/main/java/io/github/arrayv/sorts/select/DoubleSelectionSort.java index cfc9b069..ce6ea565 100644 --- a/src/sorts/select/DoubleSelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/DoubleSelectionSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,33 +29,32 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class DoubleSelectionSort extends Sort { +public final class DoubleSelectionSort extends Sort { public DoubleSelectionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Double Selection"); this.setRunAllSortsName("Double Selection Sort"); this.setRunSortName("Double Selection Sort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int left = 0; int right = length - 1; int smallest = 0; int biggest = 0; - + while(left <= right) { for(int i = left; i <= right; i++) { Highlights.markArray(3, i); - + if(Reads.compareValues(array[i], array[biggest]) == 1) { biggest = i; Highlights.markArray(1, biggest); @@ -66,20 +65,20 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.markArray(2, smallest); Delays.sleep(0.01); } - + Delays.sleep(0.01); } if(biggest == left) biggest = smallest; - + Writes.swap(array, left, smallest, 0.02, true, false); Writes.swap(array, right, biggest, 0.02, true, false); - + left++; right--; - + smallest = left; biggest = right; } } -} \ No newline at end of file +} diff --git a/src/sorts/select/FlippedMinHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/FlippedMinHeapSort.java similarity index 92% rename from src/sorts/select/FlippedMinHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/FlippedMinHeapSort.java index 5b317a52..af93b96f 100644 --- a/src/sorts/select/FlippedMinHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/FlippedMinHeapSort.java @@ -1,7 +1,7 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * @@ -22,15 +22,14 @@ the only real changes are subtracting every array access from (length - 1) the rest is just compacting the code a bit */ -final public class FlippedMinHeapSort extends Sort { +public final class FlippedMinHeapSort extends Sort { public FlippedMinHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Flipped Min Heap"); this.setRunAllSortsName("Flipped Min Heap Sort"); this.setRunSortName("Flipped Reverse Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -62,4 +61,4 @@ public void runSort(int[] array, int length, int bucketCount) { siftDown(array, length, 1, i - 1); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/LazyHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/LazyHeapSort.java similarity index 91% rename from src/sorts/select/LazyHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/LazyHeapSort.java index c10b25eb..080276fc 100644 --- a/src/sorts/select/LazyHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/LazyHeapSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class LazyHeapSort extends Sort { +public final class LazyHeapSort extends Sort { public LazyHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,40 +37,39 @@ public LazyHeapSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Lazy Heap Sort"); this.setRunSortName("Lazy Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private void maxToFront(int[] array, int a, int b) { int max = a; - + for(int i = a+1; i < b; i++) if(Reads.compareIndices(array, i, max, 0.1, true) > 0) max = i; - + Writes.swap(array, max, a, 1, true, false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int s = (int)Math.sqrt(length-1)+1; - + for(int i = 0; i < length; i += s) this.maxToFront(array, i, Math.min(i+s, length)); - + for(int j = length; j > 0;) { int max = 0; - + for(int i = max+s; i < j; i += s) if(Reads.compareIndices(array, i, max, 0.1, true) >= 0) max = i; - + Writes.swap(array, max, --j, 1, true, false); this.maxToFront(array, max, Math.min(max+s, j)); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/MaxHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/MaxHeapSort.java similarity index 86% rename from src/sorts/select/MaxHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/MaxHeapSort.java index b2624596..42975e2d 100644 --- a/src/sorts/select/MaxHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/MaxHeapSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.HeapSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.HeapSorting; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -15,15 +15,14 @@ * */ -final public class MaxHeapSort extends HeapSorting { +public final class MaxHeapSort extends HeapSorting { public MaxHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Max Heap"); this.setRunAllSortsName("Max Heap Sort"); this.setRunSortName("Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -34,7 +33,7 @@ public MaxHeapSort(ArrayVisualizer arrayVisualizer) { public void makeHeap(int[] array, int start, int length, double sleep) { this.heapify(array, start, length, sleep, true); } - + public void customHeapSort(int[] array, int start, int length, double sleep) { this.heapSort(array, start, length, sleep, true); } @@ -43,4 +42,4 @@ public void customHeapSort(int[] array, int start, int length, double sleep) { public void runSort(int[] array, int length, int bucketCount) { this.heapSort(array, 0, length, 1, true); } -} \ No newline at end of file +} diff --git a/src/sorts/select/MinHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/MinHeapSort.java similarity index 83% rename from src/sorts/select/MinHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/MinHeapSort.java index 6dad04f4..0aff34a6 100644 --- a/src/sorts/select/MinHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/MinHeapSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.HeapSorting; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.HeapSorting; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -15,24 +15,23 @@ * */ -final public class MinHeapSort extends HeapSorting { +public final class MinHeapSort extends HeapSorting { public MinHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Min Heap"); this.setRunAllSortsName("Min Heap Sort"); this.setRunSortName("Reverse Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.heapSort(array, 0, length, 1, false); } -} \ No newline at end of file +} diff --git a/src/sorts/select/MinMaxHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/MinMaxHeapSort.java similarity index 94% rename from src/sorts/select/MinMaxHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/MinMaxHeapSort.java index 88756576..2deae8eb 100644 --- a/src/sorts/select/MinMaxHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/MinMaxHeapSort.java @@ -1,21 +1,20 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; // Min-Max Heaps translated from https://github.com/BartMassey/minmaxheap -final public class MinMaxHeapSort extends Sort { +public final class MinMaxHeapSort extends Sort { int[] a; int start, end; public MinMaxHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Min-Max Heap"); this.setRunAllSortsName("Min-Max Heap Sort"); this.setRunSortName("Min-max Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -42,7 +41,6 @@ public boolean is_min_level(int index) { } public void downheap(int i) { - int i0 = i; boolean cf; if (this.is_min_level(i)) { cf = false; diff --git a/src/sorts/select/OutOfPlaceHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/OutOfPlaceHeapSort.java similarity index 93% rename from src/sorts/select/OutOfPlaceHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/OutOfPlaceHeapSort.java index 62c538f7..3b41f724 100644 --- a/src/sorts/select/OutOfPlaceHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/OutOfPlaceHeapSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class OutOfPlaceHeapSort extends Sort { +public final class OutOfPlaceHeapSort extends Sort { public OutOfPlaceHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,28 +37,27 @@ public OutOfPlaceHeapSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Out-of-Place Heap Sort"); this.setRunSortName("Out-of-Place Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + //source: https://en.wikipedia.org/wiki/Heapsort#Bottom-up_heapsort - + private void siftDown(int[] array, int i, int b) { int j = i; for(; 2*j + 1 < b; j = 2*j + 2 < b ? (Reads.compareValues(array[2*j + 2], array[2*j + 1]) > 0 ? 2*j + 2 : 2*j + 1) : 2*j + 1); for(; Reads.compareValues(array[i], array[j]) > 0; j = (j-1)/2); for(; j > i; j = (j-1)/2) Writes.swap(array, i, j, 1, true, false); } - + private void findNext(int[] array, int b) { int i = 0; int l = 1; int r = 2; - + while(r < b && !(array[l] == -1 && array[r] == -1)) { if(array[l] == -1) { Writes.swap(array, i, r, 1, true, false); @@ -82,22 +81,22 @@ else if(Reads.compareValues(array[r], array[l]) > 0) { if(l < b && array[l] != -1) Writes.swap(array, i, l, 1, true, false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { for(int i = (length-1)/2; i >= 0; i--) this.siftDown(array, i, length); - + int[] tmp = Writes.createExternalArray(length); - + for(int i = length-1; i >= 0; i--) { Writes.write(tmp, i, array[0], 0, true, true); Writes.write(array, 0, -1, 1, false, false); - + this.findNext(array, length); } Highlights.clearMark(2); Writes.arraycopy(tmp, 0, array, 0, length, 1, true, false); Writes.deleteExternalArray(tmp); } -} \ No newline at end of file +} diff --git a/src/sorts/select/PoplarHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/PoplarHeapSort.java similarity index 98% rename from src/sorts/select/PoplarHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/PoplarHeapSort.java index c07e4c27..72b6255c 100644 --- a/src/sorts/select/PoplarHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/PoplarHeapSort.java @@ -1,7 +1,7 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * The MIT License (MIT) @@ -35,7 +35,6 @@ public PoplarHeapSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Poplar Heap Sort"); this.setRunSortName("Poplar Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -98,7 +97,7 @@ private void sift(int[] array, int first, int size) { Writes.swap(array, root, max_root, 0.75, true, false); Highlights.clearMark(2); - + size /= 2; if (size < 2) return; @@ -202,9 +201,9 @@ public void heapSort(int[] array, int start, int end) { this.make_heap(array, start, end); this.sort_heap(array, start, end); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.heapSort(array, 0, length); } -} \ No newline at end of file +} diff --git a/src/sorts/select/SelectionSort.java b/src/main/java/io/github/arrayv/sorts/select/SelectionSort.java similarity index 90% rename from src/sorts/select/SelectionSort.java rename to src/main/java/io/github/arrayv/sorts/select/SelectionSort.java index b50438dd..9a872cc8 100644 --- a/src/sorts/select/SelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/SelectionSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -29,31 +29,30 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class SelectionSort extends Sort { +public final class SelectionSort extends Sort { public SelectionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Selection"); this.setRunAllSortsName("Selection Sort"); this.setRunSortName("Selection Sort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = 0; i < length - 1; i++) { int lowestindex = i; - + for (int j = i + 1; j < length; j++) { Highlights.markArray(2, j); Delays.sleep(0.01); - + if (Reads.compareValues(array[j], array[lowestindex]) == -1){ lowestindex = j; Highlights.markArray(1, lowestindex); @@ -63,4 +62,4 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.swap(array, i, lowestindex, 0.02, true, false); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/SmoothSort.java b/src/main/java/io/github/arrayv/sorts/select/SmoothSort.java similarity index 95% rename from src/sorts/select/SmoothSort.java rename to src/main/java/io/github/arrayv/sorts/select/SmoothSort.java index 51ec2fc5..298f7b73 100644 --- a/src/sorts/select/SmoothSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/SmoothSort.java @@ -1,17 +1,16 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class SmoothSort extends Sort { +public final class SmoothSort extends Sort { public SmoothSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Smooth"); this.setRunAllSortsName("Smooth Sort"); this.setRunSortName("Smoothsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -43,12 +42,12 @@ private void sift(int[] A, int pshift, int head) { int rt = head - 1; int lf = head - 1 - LP[pshift - 2]; - + Highlights.markArray(2, rt); Highlights.markArray(3, lf); - + Delays.sleep(0.325); - + if (Reads.compareValues(val, A[lf]) >= 0 && Reads.compareValues(val, A[rt]) >= 0) break; @@ -64,7 +63,7 @@ private void sift(int[] A, int pshift, int head) } } Writes.write(A, head, val, 0.65, true, false); - + Highlights.clearMark(2); Highlights.clearMark(3); } @@ -76,7 +75,7 @@ private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) while (p != 1) { int stepson = head - LP[pshift]; - + if (Reads.compareValues(A[stepson], val) <= 0) break; // current node is greater than head. sift. @@ -88,18 +87,18 @@ private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) int lf = head - 1 - LP[pshift - 2]; Highlights.markArray(2, rt); Highlights.markArray(3, lf); - + Delays.sleep(0.325); - + if (Reads.compareValues(A[rt], A[stepson]) >= 0 || Reads.compareValues(A[lf], A[stepson]) >= 0) break; } Writes.write(A, head, A[stepson], 0.65, true, false); - + Highlights.clearMark(2); Highlights.clearMark(3); - + head = stepson; //int trail = Integer.numberOfTrailingZeros(p & ~1); int trail = Integer.numberOfTrailingZeros(p & ~1); @@ -107,7 +106,7 @@ private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) pshift += trail; isTrusty = false; } - + if (!isTrusty) { Writes.write(A, head, val, 0.65, true, false); this.sift(A, pshift, head); @@ -198,9 +197,9 @@ private void smoothSort(int[] A, int lo, int hi, boolean fullSort) public void smoothHeapify(int[] array, int length) { this.smoothSort(array, 0, length - 1, false); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { this.smoothSort(array, 0, currentLength - 1, true); } -} \ No newline at end of file +} diff --git a/src/sorts/select/StableCycleSort.java b/src/main/java/io/github/arrayv/sorts/select/StableCycleSort.java similarity index 93% rename from src/sorts/select/StableCycleSort.java rename to src/main/java/io/github/arrayv/sorts/select/StableCycleSort.java index 78ff3759..03caa543 100644 --- a/src/sorts/select/StableCycleSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/StableCycleSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StableCycleSort extends Sort { +public final class StableCycleSort extends Sort { public StableCycleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -37,58 +37,57 @@ public StableCycleSort(ArrayVisualizer arrayVisualizer) { this.setRunAllSortsName("Stable Cycle Sort"); this.setRunSortName("Stable Cyclesort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private final int WLEN = 3; - + private boolean getBit(int[] bits, int idx) { int b = (bits[idx >> WLEN]) >> (idx & ((1 << WLEN) - 1)) & 1; return b == 1; } - + private void flag(int[] bits, int idx) { Highlights.markArray(4, idx >> WLEN); Writes.write(bits, idx >> WLEN, bits[idx >> WLEN] | (1 << (idx & ((1 << WLEN) - 1))), 0.02, false, true); } - + private int destination1(int[] array, int[] bits, int a, int b1, int b) { int d = a, e = 0; - + for(int i = a+1; i < b; i++) { Highlights.markArray(2, i); int cmp = Reads.compareValues(array[i], array[a]); - + if(cmp < 0) d++; else if(i < b1 && !this.getBit(bits, i) && cmp == 0) e++; - + Highlights.markArray(3, d); Delays.sleep(0.01); } while(this.getBit(bits, d) || e-- > 0) { d++; - + Highlights.markArray(3, d); Delays.sleep(0.01); } - + return d; } - + @Override public void runSort(int[] array, int length, int bucketCount) { int[] bits = Writes.createExternalArray(((length-1) >> WLEN) + 1); - + for(int i = 0; i < length-1; i++) { if(!this.getBit(bits, i)) { Highlights.markArray(1, i); int j = i; - + do { int k = this.destination1(array, bits, i, j, length); Writes.swap(array, i, k, 0.02, true, false); @@ -100,4 +99,4 @@ public void runSort(int[] array, int length, int bucketCount) { } Writes.deleteExternalArray(bits); } -} \ No newline at end of file +} diff --git a/src/sorts/select/StableSelectionSort.java b/src/main/java/io/github/arrayv/sorts/select/StableSelectionSort.java similarity index 92% rename from src/sorts/select/StableSelectionSort.java rename to src/main/java/io/github/arrayv/sorts/select/StableSelectionSort.java index 227563a5..c086959d 100644 --- a/src/sorts/select/StableSelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/StableSelectionSort.java @@ -1,10 +1,10 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import sorts.templates.Sort; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* - * + * MIT License Copyright (c) 2020 fungamer2 Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,23 +25,22 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class StableSelectionSort extends Sort { - +public final class StableSelectionSort extends Sort { + public StableSelectionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stable Selection"); this.setRunAllSortsName("Stable Selection Sort"); this.setRunSortName("Stable Selection Sort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = 0; i < length - 1; i++) { @@ -64,4 +63,4 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.write(array, pos, tmp, 0.5, true, false); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/TernaryHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/TernaryHeapSort.java similarity index 91% rename from src/sorts/select/TernaryHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/TernaryHeapSort.java index 8314f728..a95ffe18 100644 --- a/src/sorts/select/TernaryHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/TernaryHeapSort.java @@ -1,29 +1,28 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; -final public class TernaryHeapSort extends Sort { +public final class TernaryHeapSort extends Sort { public TernaryHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Ternary Heap"); this.setRunAllSortsName("Ternary Heap Sort"); this.setRunSortName("Ternary Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + // TERNARY HEAP SORT - written by qbit // https://codereview.stackexchange.com/questions/63384/binary-heapsort-and-ternary-heapsort-implementation - + private int heapSize; - + private static int leftBranch(int i) { return 3 * i + 1; } @@ -59,13 +58,13 @@ private void maxHeapify(int[] array, int i) { this.maxHeapify(array, largest); } } - + private void buildMaxTernaryHeap(int[] array, int length) { heapSize = length - 1; for(int i = length - 1 / 3; i >= 0; i--) this.maxHeapify(array, i); } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.buildMaxTernaryHeap(array, length); @@ -77,4 +76,4 @@ public void runSort(int[] array, int length, int bucketCount) { this.maxHeapify(array, 0); } } -} \ No newline at end of file +} diff --git a/src/sorts/select/TournamentSort.java b/src/main/java/io/github/arrayv/sorts/select/TournamentSort.java similarity index 93% rename from src/sorts/select/TournamentSort.java rename to src/main/java/io/github/arrayv/sorts/select/TournamentSort.java index b1417422..cc5bed10 100644 --- a/src/sorts/select/TournamentSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/TournamentSort.java @@ -1,7 +1,7 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; /* * "Some implementations of tournament sort in various languages" @@ -21,18 +21,17 @@ along with this program. If not, see . */ -final public class TournamentSort extends Sort { +public final class TournamentSort extends Sort { private int[] matches; private int tourney; - + public TournamentSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Tournament"); this.setRunAllSortsName("Tournament Sort"); this.setRunSortName("Tournament Sort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); @@ -43,16 +42,16 @@ public TournamentSort(ArrayVisualizer arrayVisualizer) { private int tourneyCompare(int a, int b) { Highlights.markArray(2, a); Highlights.markArray(3, b); - + Delays.sleep(1); - + return Reads.compareValues(a, b); } - + private static boolean isPlayer(int i) { return i <= 0; } - + private void setWinner(int root, int winner) { Writes.write(matches, root, winner, 0, false, true); } @@ -76,11 +75,11 @@ private void setMatch(int root, int winner, int winners, int losers) { this.setWinners(root, winners); this.setLosers(root, losers); } - + private int getPlayer(int i) { return i <= 0 ? Math.abs(i) : this.getWinner(i); } - + private int pop(int[] arr) { int result = arr[this.getPlayer(tourney)]; tourney = TournamentSort.isPlayer(tourney) ? 0 : this.rebuild(arr, tourney); @@ -94,18 +93,18 @@ private static int makePlayer(int i) { private int makeMatch(int[] arr, int top, int bot, int root) { int top_w = this.getPlayer(top); int bot_w = this.getPlayer(bot); - + if (tourneyCompare(arr[top_w], arr[bot_w]) <= 0) this.setMatch(root, top_w, top, bot); else this.setMatch(root, bot_w, bot, top); - + return root; } - + private int knockout(int[] arr, int i, int k, int root) { if (i == k) return TournamentSort.makePlayer(i); - + int j = (i + k) / 2; return this.makeMatch(arr, this.knockout(arr, i, j, 2 * root), this.knockout(arr,j + 1, k, (2 * root) + 3), root); } @@ -113,27 +112,27 @@ private int knockout(int[] arr, int i, int k, int root) { private int rebuild(int[] arr, int root) { if (TournamentSort.isPlayer(this.getWinners(root))) return this.getLosers(root); - + this.setWinners(root, this.rebuild(arr, this.getWinners(root))); - + if (tourneyCompare(arr[this.getPlayer(this.getLosers(root))], arr[this.getPlayer(this.getWinners(root))]) < 0) { this.setWinner(root, this.getPlayer(this.getLosers(root))); - + int temp = this.getLosers(root); - + this.setLosers(root, this.getWinners(root)); this.setWinners(root, temp); } else { this.setWinner(root, this.getPlayer(this.getWinners(root))); } - + return root; } - + private void sort(int[] arr, int currentLen) { int[] copy = Writes.createExternalArray(currentLen); - + for (int i = 0; i < currentLen; i++) { int result = this.pop(arr); Writes.write(copy, i, result, 1, true, true); @@ -141,7 +140,7 @@ private void sort(int[] arr, int currentLen) { Highlights.clearAllMarks(); Writes.arraycopy(copy, 0, arr, 0, currentLen, 1, true, false); - + Writes.deleteExternalArray(copy); } @@ -149,9 +148,9 @@ private void sort(int[] arr, int currentLen) { public void runSort(int[] array, int currentLength, int bucketCount) { this.matches = Writes.createExternalArray(6 * currentLength); this.tourney = this.knockout(array, 0, currentLength - 1, 3); - + this.sort(array, currentLength); Writes.deleteExternalArray(this.matches); } -} \ No newline at end of file +} diff --git a/src/sorts/select/TriangularHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/TriangularHeapSort.java similarity index 91% rename from src/sorts/select/TriangularHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/TriangularHeapSort.java index ff166099..a02b7179 100644 --- a/src/sorts/select/TriangularHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/TriangularHeapSort.java @@ -1,81 +1,80 @@ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author aphitorite - */ -public final class TriangularHeapSort extends Sort { - - public TriangularHeapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Triangular Heap"); - this.setRunAllSortsName("Triangular Heap Sort"); - this.setRunSortName("Triangular Heapsort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public static int triangularRoot(int val) { - return ((int) Math.sqrt((8 * val + 1)) - 1) / 2; - } - - private void siftDown(int[] array, int end, int root) { - int temp = array[root]; - int len = triangularRoot(root); - int left = root + len + 1; - int right = left + 1; - - while (left < end) { - if (right >= end) { - this.Highlights.markArray(2, left); - if (this.Reads.compareValues(array[left], temp) == 1) { - this.Writes.write(array, root, array[left], 0.25D, true, false); - } - - break; - } - int max = (this.Reads.compareValues(array[left], array[right]) >= 0) ? left : right; - - this.Highlights.markArray(2, max); - if (this.Reads.compareValues(array[max], temp) == 1) { - this.Writes.write(array, root, array[max], 0.25D, true, false); - - root = max; - len = triangularRoot(root); - left = root + len + 1; - right = left + 1; - continue; - } - break; - } - this.Writes.write(array, root, temp, 0.25D, true, false); - } - - public void triangularHeapify(int[] array, int length) { - for (int i = length - 1; i >= 0; i--) { - siftDown(array, length, i); - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - // TODO Auto-generated method stub - triangularHeapify(array, length); - for (int i = 1; i < length - 1; i++) { - this.Writes.swap(array, 0, length - i, 0.5D, true, false); - siftDown(array, length - i, 0); - } - if (this.Reads.compareValues(array[0], array[1]) == 1) - this.Writes.swap(array, 0, 1, 0.5D, true, false); - - } - -} +package io.github.arrayv.sorts.select; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + +/** + * @author aphitorite + */ +public final class TriangularHeapSort extends Sort { + + public TriangularHeapSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + // TODO Auto-generated constructor stub + this.setSortListName("Triangular Heap"); + this.setRunAllSortsName("Triangular Heap Sort"); + this.setRunSortName("Triangular Heapsort"); + this.setCategory("Selection Sorts"); + this.setBucketSort(false); + this.setRadixSort(false); + this.setUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.setBogoSort(false); + } + + public static int triangularRoot(int val) { + return ((int) Math.sqrt((8 * val + 1)) - 1) / 2; + } + + private void siftDown(int[] array, int end, int root) { + int temp = array[root]; + int len = triangularRoot(root); + int left = root + len + 1; + int right = left + 1; + + while (left < end) { + if (right >= end) { + this.Highlights.markArray(2, left); + if (this.Reads.compareValues(array[left], temp) == 1) { + this.Writes.write(array, root, array[left], 0.25D, true, false); + } + + break; + } + int max = (this.Reads.compareValues(array[left], array[right]) >= 0) ? left : right; + + this.Highlights.markArray(2, max); + if (this.Reads.compareValues(array[max], temp) == 1) { + this.Writes.write(array, root, array[max], 0.25D, true, false); + + root = max; + len = triangularRoot(root); + left = root + len + 1; + right = left + 1; + continue; + } + break; + } + this.Writes.write(array, root, temp, 0.25D, true, false); + } + + public void triangularHeapify(int[] array, int length) { + for (int i = length - 1; i >= 0; i--) { + siftDown(array, length, i); + } + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + // TODO Auto-generated method stub + triangularHeapify(array, length); + for (int i = 1; i < length - 1; i++) { + this.Writes.swap(array, 0, length - i, 0.5D, true, false); + siftDown(array, length - i, 0); + } + if (this.Reads.compareValues(array[0], array[1]) == 1) + this.Writes.swap(array, 0, 1, 0.5D, true, false); + + } + +} diff --git a/src/sorts/select/WeakHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/WeakHeapSort.java similarity index 82% rename from src/sorts/select/WeakHeapSort.java rename to src/main/java/io/github/arrayv/sorts/select/WeakHeapSort.java index b60b82e0..4b43d00f 100644 --- a/src/sorts/select/WeakHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/WeakHeapSort.java @@ -1,34 +1,33 @@ -package sorts.select; +package io.github.arrayv.sorts.select; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; // Refactored from C++ code written by Manish Bhojasia, found here: // https://www.sanfoundry.com/cpp-program-implement-weak-heap/ -final public class WeakHeapSort extends Sort { +public final class WeakHeapSort extends Sort { public WeakHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Weak Heap"); this.setRunAllSortsName("Weak Heap Sort"); this.setRunSortName("Weak Heapsort"); this.setCategory("Selection Sorts"); - this.setComparisonBased(true); this.setBucketSort(false); this.setRadixSort(false); this.setUnreasonablySlow(false); this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private static int getBitwiseFlag(int[] bits, int x) { return ((bits[(x) >> 3] >> ((x) & 7)) & 1); } - - private void toggleBitwiseFlag(int[] bits, int x) { - int flag = bits[(x) >> 3]; + + private void toggleBitwiseFlag(int[] bits, int x) { + int flag = bits[(x) >> 3]; flag ^= 1 << ((x) & 7); - + Writes.write(bits, (x) >> 3, flag, 0, true, true); } @@ -47,39 +46,39 @@ private void weakHeapMerge(int[] array, int[] bits, int i, int j) { public void runSort(int[] array, int length, int bucketCount) { int n = length; int i, j, x, y, Gparent; - + int bitsLength = (n + 7) / 8; int[] bits = Writes.createExternalArray(bitsLength); - + for (i = 0; i < n / 8; ++i) { Writes.write(bits, i, 0, 0, false, true); } - + for (i = n - 1; i > 0; --i) { j = i; - + while ((j & 1) == WeakHeapSort.getBitwiseFlag(bits, j >> 1)) j >>= 1; Gparent = j >> 1; - + this.weakHeapMerge(array, bits, Gparent, i); } - + for (i = n - 1; i >= 2; --i) { Writes.swap(array, 0, i, 1, true, false); - + x = 1; - + while ((y = 2 * x + WeakHeapSort.getBitwiseFlag(bits, x)) < i) x = y; - + while (x > 0) { this.weakHeapMerge(array, bits, 0, x); x >>= 1; } } - Writes.swap(array, 0, 1, 1, true, false); + Writes.swap(array, 0, 1, 1, true, false); Writes.deleteExternalArray(bits); } -} \ No newline at end of file +} diff --git a/src/sorts/templates/BinaryInsertionSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BinaryInsertionSorting.java similarity index 94% rename from src/sorts/templates/BinaryInsertionSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/BinaryInsertionSorting.java index 0e14d6ac..f4f8ba46 100644 --- a/src/sorts/templates/BinaryInsertionSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BinaryInsertionSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -32,20 +32,20 @@ public abstract class BinaryInsertionSorting extends Sort { protected BinaryInsertionSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected void binaryInsertSort(int[] array, int start, int end, double compSleep, double writeSleep) { for (int i = start; i < end; i++) { int num = array[i]; int lo = start, hi = i; - + while (lo < hi) { int mid = lo + ((hi - lo) / 2); // avoid int overflow! Highlights.markArray(1, lo); Highlights.markArray(2, mid); Highlights.markArray(3, hi); - + Delays.sleep(compSleep); - + if (Reads.compareValues(num, array[mid]) < 0) { // do NOT move equal elements to right of inserted element; this maintains stability! hi = mid; } @@ -55,19 +55,19 @@ protected void binaryInsertSort(int[] array, int start, int end, double compSlee } Highlights.clearMark(3); - + // item has to go into position lo int j = i - 1; - + while (j >= lo) { Writes.write(array, j + 1, array[j], writeSleep, true, false); j--; } Writes.write(array, lo, num, writeSleep, true, false); - + Highlights.clearAllMarks(); } } -} \ No newline at end of file +} diff --git a/src/sorts/templates/BinaryQuickSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BinaryQuickSorting.java similarity index 95% rename from src/sorts/templates/BinaryQuickSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/BinaryQuickSorting.java index be3da144..5104cdec 100644 --- a/src/sorts/templates/BinaryQuickSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BinaryQuickSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; import java.util.LinkedList; import java.util.Queue; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /** * Binary MSD Radix Sort / Binary Quicksort. @@ -56,7 +56,7 @@ public void binaryQuickSort(int[] array, int p, int r, int bit) Queue tasks = new LinkedList<>(); tasks.add(new Task(p, r, bit)); - while (tasks.isEmpty() == false) + while (tasks.isEmpty() == false) { Task task = tasks.remove(); if (task.p < task.r && task.bit >= 0) @@ -73,9 +73,9 @@ public int partition(int[] array, int p, int r, int bit) { int i = p - 1; int j = r + 1; - + Highlights.clearAllMarks(); - + while (true) { // Left is not set i++; @@ -98,4 +98,4 @@ public int partition(int[] array, int p, int r, int bit) return j; } } -} \ No newline at end of file +} diff --git a/src/sorts/templates/BlockMergeSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BlockMergeSorting.java similarity index 94% rename from src/sorts/templates/BlockMergeSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/BlockMergeSorting.java index abdce180..68a2efd2 100644 --- a/src/sorts/templates/BlockMergeSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BlockMergeSorting.java @@ -1,10 +1,10 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import utils.IndexedRotations; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.IndexedRotations; /* - * + * MIT License Copyright (c) 2020-2021 aphitorite @@ -33,16 +33,16 @@ public abstract class BlockMergeSorting extends Sort { protected BlockMergeSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected final int MRUN = 16; - + protected void shiftFW(int[] array, int a, int m, int b) { while(m < b) Writes.swap(array, a++, m++, 1, true, false); } protected void shiftBW(int[] array, int a, int m, int b) { while(m > a) Writes.swap(array, --b, --m, 1, true, false); } - + protected void shiftFWExt(int[] array, int a, int m, int b) { Highlights.clearMark(2); while(m < b) Writes.write(array, a++, array[m++], 1, true, false); @@ -51,7 +51,7 @@ protected void shiftBWExt(int[] array, int a, int m, int b) { Highlights.clearMark(2); while(m > a) Writes.write(array, --b, array[--m], 1, true, false); } - + protected void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; @@ -64,26 +64,26 @@ protected void insertToBW(int[] array, int a, int b) { while(a < b) Writes.write(array, a, array[++a], 0.5, true, false); Writes.write(array, a, temp, 0.5, true, false); } - + protected void multiSwap(int[] array, int a, int b, int len) { for(int i = 0; i < len; i++) Writes.swap(array, a+i, b+i, 1, true, false); } - + protected void rotate(int[] array, int a, int m, int b) { Highlights.clearMark(2); IndexedRotations.cycleReverse(array, a, m, b, 1, true, false); } - + protected int leftBinSearch(int[] array, int a, int b, int val) { while(a < b) { int m = a+(b-a)/2; Highlights.markArray(2, m); Delays.sleep(0.25); - - if(Reads.compareValues(val, array[m]) <= 0) + + if(Reads.compareValues(val, array[m]) <= 0) b = m; - else + else a = m+1; } return a; @@ -93,26 +93,26 @@ protected int rightBinSearch(int[] array, int a, int b, int val) { int m = a+(b-a)/2; Highlights.markArray(2, m); Delays.sleep(0.25); - - if(Reads.compareValues(val, array[m]) < 0) + + if(Reads.compareValues(val, array[m]) < 0) b = m; - else + else a = m+1; } return a; } - + protected boolean buildRuns(int[] array, int a, int b) { boolean noSort = true; int i = a+1, j = a; - + while(i < b) { if(Reads.compareIndices(array, i-1, i++, 1, true) == 1) { while(i < b && Reads.compareIndices(array, i-1, i, 1, true) == 1) i++; Writes.reversal(array, j, i-1, 1, true, false); } else while(i < b && Reads.compareIndices(array, i-1, i, 1, true) <= 0) i++; - + if(i < b) { noSort = false; j = i - (i-j-1)%this.MRUN - 1; //a%b, if(a%b == 0) -> a = b @@ -125,7 +125,7 @@ protected boolean buildRuns(int[] array, int a, int b) { } return noSort; } - + protected int findKeys(int[] array, int a, int b, int nKeys, int n) { int p = a, pEnd = a+nKeys; @@ -134,14 +134,14 @@ protected int findKeys(int[] array, int a, int b, int nKeys, int n) { Highlights.markArray(1, i); Delays.sleep(1); int loc = this.leftBinSearch(array, p, pEnd, array[i]); - + if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, p, pEnd, i); int inc = i-pEnd; loc += inc; p += inc; pEnd += inc; - + this.insertTo(array, pEnd, loc); nKeys++; pEnd++; @@ -158,7 +158,7 @@ protected int findKeysBW(int[] array, int a, int b, int nKeys, int n) { Highlights.markArray(1, i); Delays.sleep(1); int loc = this.leftBinSearch(array, p, pEnd, array[i]); - + if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, i+1, p, pEnd); int inc = p-(i+1); @@ -166,33 +166,33 @@ protected int findKeysBW(int[] array, int a, int b, int nKeys, int n) { pEnd -= inc; p -= inc+1; nKeys++; - + this.insertToBW(array, i, loc-1); } } this.rotate(array, p, pEnd, b); return nKeys; } - + protected void binaryInsertion(int[] array, int a, int b) { for(int i = a+1; i < b; i++) this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); } - + protected boolean boundCheck(int[] array, int a, int m, int b) { return m >= b || Reads.compareValues(array[m-1], array[m]) <= 0; } - + protected void mergeBW(int[] array, int a, int m, int b, int p) { if(this.boundCheck(array, a, m, b)) return; - + int pLen = b-m; this.multiSwap(array, m, p, pLen); - + int i = pLen-1, j = m-1, k = b-1; - + while(i >= 0 && j >= a) { - if(Reads.compareValues(array[p+i], array[j]) >= 0) + if(Reads.compareValues(array[p+i], array[j]) >= 0) Writes.swap(array, k--, p+(i--), 1, true, false); else Writes.swap(array, k--, j--, 1, true, false); @@ -201,134 +201,134 @@ protected void mergeBW(int[] array, int a, int m, int b, int p) { } protected void mergeTo(int[] array, int a, int m, int b, int p) { int i = a, j = m; - + while(i < m && j < b) { if(Reads.compareValues(array[i], array[j]) <= 0) Writes.swap(array, p++, i++, 1, true, false); - else + else Writes.swap(array, p++, j++, 1, true, false); } while(i < m) Writes.swap(array, p++, i++, 1, true, false); while(j < b) Writes.swap(array, p++, j++, 1, true, false); } protected void pingPongMerge(int[] array, int a, int m1, int m2, int m3, int b, int p) { - if(Reads.compareValues(array[m1-1], array[m1]) > 0 + if(Reads.compareValues(array[m1-1], array[m1]) > 0 || (m3 < b && Reads.compareValues(array[m3-1], array[m3]) > 0)) { int p1 = p + m2-a, pEnd = p + b-a; - + this.mergeTo(array, a, m1, m2, p); this.mergeTo(array, m2, m3, b, p1); this.mergeTo(array, p, p1, pEnd, a); } else this.mergeBW(array, a, m2, b, p); } - + protected void mergeFWExt(int[] array, int[] tmp, int a, int m, int b) { int s = m-a; - + Writes.arraycopy(array, a, tmp, 0, s, 1, true, true); - + int i = 0, j = m; - + while(i < s && j < b) { if(Reads.compareValues(tmp[i], array[j]) <= 0) Writes.write(array, a++, tmp[i++], 1, true, false); else Writes.write(array, a++, array[j++], 1, true, false); } - while(i < s) Writes.write(array, a++, tmp[i++], 1, true, false); + while(i < s) Writes.write(array, a++, tmp[i++], 1, true, false); } protected void mergeBWExt(int[] array, int[] tmp, int a, int m, int b) { int s = b-m; - + Writes.arraycopy(array, m, tmp, 0, s, 1, true, true); - + int i = s-1, j = m-1; - + while(i >= 0 && j >= a) { if(Reads.compareValues(tmp[i], array[j]) >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); else Writes.write(array, --b, array[j--], 1, true, false); } - while(i >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); + while(i >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); } - + protected void mergeWithBufFW(int[] array, int a, int m, int b, int p) { int i = m; - + while(a < m && i < b) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[a], array[i]) <= 0) Writes.swap(array, p++, a++, 1, true, false); else Writes.swap(array, p++, i++, 1, true, false); } - + if(a > p) this.shiftFW(array, p, a, m); - + this.shiftFW(array, p, i, b); } protected void mergeWithBufBW(int[] array, int a, int m, int b, int p) { int i = m-1; b--; - + while(b >= m && i >= a) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[b], array[i]) >= 0) Writes.swap(array, --p, b--, 1, true, false); else Writes.swap(array, --p, i--, 1, true, false); } - + if(p > b) this.shiftBW(array, m, b+1, p); - + this.shiftBW(array, a, i+1, p); } protected void mergeWithBufFWExt(int[] array, int a, int m, int b, int p) { int i = m; - + while(a < m && i < b) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[a], array[i]) <= 0) Writes.write(array, p++, array[a++], 1, true, false); else Writes.write(array, p++, array[i++], 1, true, false); } - + if(a > p) this.shiftFWExt(array, p, a, m); - + this.shiftFWExt(array, p, i, b); } protected void mergeWithBufBWExt(int[] array, int a, int m, int b, int p) { int i = m-1; b--; - + while(b >= m && i >= a) { Highlights.markArray(2, i); - + if(Reads.compareValues(array[b], array[i]) >= 0) Writes.write(array, --p, array[b--], 1, true, false); else Writes.write(array, --p, array[i--], 1, true, false); } - + if(p > b) this.shiftBWExt(array, m, b+1, p); - + this.shiftBWExt(array, a, i+1, p); } - + protected void inPlaceMerge(int[] array, int a, int m, int b) { while(a < m && m < b) { a = this.rightBinSearch(array, a, m, array[m]); - + if(a == m) return; - + int i = this.leftBinSearch(array, m, b, array[a]); - + this.rotate(array, a, m, i); - + int t = i-m; m = i; a += t+1; @@ -337,15 +337,15 @@ protected void inPlaceMerge(int[] array, int a, int m, int b) { protected void inPlaceMergeBW(int[] array, int a, int m, int b) { while(b > m && m > a) { int i = this.rightBinSearch(array, a, m, array[b-1]); - + this.rotate(array, i, m, b); - + int t = m-i; m = i; b -= t+1; - + if(m == a) break; - + b = this.leftBinSearch(array, m, b, array[m-1]); } } diff --git a/src/sorts/templates/BogoSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BogoSorting.java similarity index 99% rename from src/sorts/templates/BogoSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/BogoSorting.java index abb0924e..12b53a74 100644 --- a/src/sorts/templates/BogoSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BogoSorting.java @@ -1,11 +1,11 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; import java.util.concurrent.ThreadLocalRandom; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * MIT License Copyright (c) 2019 w0rthy diff --git a/src/sorts/templates/CircleSorting.java b/src/main/java/io/github/arrayv/sorts/templates/CircleSorting.java similarity index 90% rename from src/sorts/templates/CircleSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/CircleSorting.java index 1209117a..61d73383 100644 --- a/src/sorts/templates/CircleSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/CircleSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -18,31 +18,31 @@ public abstract class CircleSorting extends Sort { protected CircleSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected int end; - - protected int circleSortRoutine(int[] array, int lo, int hi, int swapCount, double sleep) { + + protected int circleSortRoutine(int[] array, int lo, int hi, int swapCount, double sleep) { if (lo == hi) return swapCount; - + int high = hi; int low = lo; int mid = (hi - lo) / 2; - + while (lo < hi) { if (hi < this.end && Reads.compareIndices(array, lo, hi, sleep / 2, true) > 0) { Writes.swap(array, lo, hi, sleep, true, false); swapCount++; } - + lo++; hi--; } - + swapCount = this.circleSortRoutine(array, low, low + mid, swapCount, sleep); if(low + mid + 1 < this.end) swapCount = this.circleSortRoutine(array, low + mid + 1, high, swapCount, sleep); - + return swapCount; } -} \ No newline at end of file +} diff --git a/src/sorts/templates/CombSorting.java b/src/main/java/io/github/arrayv/sorts/templates/CombSorting.java similarity index 94% rename from src/sorts/templates/CombSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/CombSorting.java index 4df6011d..3debbaaf 100644 --- a/src/sorts/templates/CombSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/CombSorting.java @@ -1,10 +1,10 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; /* - * + * The MIT License (MIT) Copyright (c) 2012 Daniel Imms, http://www.growingwiththeweb.com @@ -30,11 +30,11 @@ this software and associated documentation files (the "Software"), to deal in public abstract class CombSorting extends Sort { private InsertionSort insertSorter; - + protected CombSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected void combSort(int[] array, int length, double shrink, boolean hybrid) { insertSorter = new InsertionSort(this.arrayVisualizer); @@ -56,7 +56,7 @@ protected void combSort(int[] array, int length, double shrink, boolean hybrid) { if(hybrid && (gap <= Math.min(8, length * 0.03125))) { gap = 0; - + insertSorter.customInsertSort(array, 0, length, 0.5, false); break; } @@ -67,10 +67,10 @@ protected void combSort(int[] array, int length, double shrink, boolean hybrid) } Highlights.markArray(1, i); Highlights.markArray(2, i + gap); - + Delays.sleep(0.25); Highlights.clearMark(1); } } } -} \ No newline at end of file +} diff --git a/src/sorts/templates/GrailSorting.java b/src/main/java/io/github/arrayv/sorts/templates/GrailSorting.java similarity index 97% rename from src/sorts/templates/GrailSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/GrailSorting.java index df6d5006..b0e1e805 100644 --- a/src/sorts/templates/GrailSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/GrailSorting.java @@ -1,10 +1,10 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import sorts.exchange.OptimizedGnomeSort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.exchange.OptimizedGnomeSort; /* - * + * The MIT License (MIT) Copyright (c) 2013 Andrey Astrelin @@ -50,16 +50,16 @@ this software and associated documentation files (the "Software"), to deal in final class GrailPair { private int leftOverLen; private int leftOverFrag; - + protected GrailPair(int len, int frag) { this.leftOverLen = len; this.leftOverFrag = frag; } - + protected int getLeftOverLen() { return leftOverLen; } - + protected int getLeftOverFrag() { return leftOverFrag; } @@ -67,35 +67,35 @@ protected int getLeftOverFrag() { public abstract class GrailSorting extends Sort { private OptimizedGnomeSort grailInsertSorter; - + final private int grailStaticBufferLen = 32; //Buffer length changed due to less numbers in this program being sorted than what Mr. Astrelin used for testing. - + protected GrailSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected int getStaticBuffer() { return this.grailStaticBufferLen; } - + private void grailSwap(int[] arr, int a, int b) { Writes.swap(arr, a, b, 1, true, false); } - - private void grailMultiSwap(int[] arr, int a, int b, int swapsLeft) { - while(swapsLeft != 0) { + + private void grailMultiSwap(int[] arr, int a, int b, int swapsLeft) { + while(swapsLeft != 0) { this.grailSwap(arr, a++, b++); swapsLeft--; } } - + protected void grailRotate(int[] array, int pos, int lenA, int lenB) { while(lenA != 0 && lenB != 0) { if(lenA <= lenB) { this.grailMultiSwap(array, pos, pos + lenA, lenA); pos += lenA; lenB -= lenA; - } + } else { this.grailMultiSwap(array, pos + (lenA - lenB), pos + lenA, lenB); lenA -= lenB; @@ -135,7 +135,7 @@ private int grailFindKeys(int[] arr, int pos, int len, int numKeys) { while(dist < len && foundKeys < numKeys) { if(dist < (len - 1)) Highlights.markArray(3, dist + 1); Delays.sleep(1); - + //Binary Search left int loc = this.grailBinSearch(arr, pos + firstKey, foundKeys, pos + dist, true); if(loc == foundKeys || Reads.compareValues(arr[pos + dist], arr[pos + (firstKey + loc)]) != 0) { @@ -147,14 +147,14 @@ private int grailFindKeys(int[] arr, int pos, int len, int numKeys) { else { Highlights.clearMark(2); } - + dist++; } Highlights.clearMark(3); this.grailRotate(arr, pos, firstKey, foundKeys); - + Highlights.clearMark(2); - + return foundKeys; } @@ -197,8 +197,8 @@ protected void grailMergeWithoutBuffer(int[] arr, int pos, int len1, int len2) { // aBlockCount are regular blocks from stream A. // lastLen is length of last (irregular) block from stream B, that should go before nblock2 blocks. // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, aBlockCount = 0 is possible. - private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, - int blockCount, int blockLen, boolean havebuf, int aBlockCount, + private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, + int blockCount, int blockLen, boolean havebuf, int aBlockCount, int lastLen) { if(blockCount == 0) { @@ -216,7 +216,7 @@ private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, for(int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += blockLen) { restToProcess = processIndex - leftOverLen; int nextFrag = Reads.compareValues(arr[keysPos + keyIndex], arr[midkey]) < 0 ? 0 : 1; - + if(nextFrag == leftOverFrag) { if(havebuf) this.grailMultiSwap(arr, pos + restToProcess - blockLen, pos + restToProcess, leftOverLen); restToProcess = processIndex; @@ -258,7 +258,7 @@ private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, } } } - + // arr[dist..-1] - buffer, arr[0, leftLen - 1] ++ arr[leftLen, leftLen + rightLen - 1] // -> arr[dist, dist + leftLen + rightLen - 1] private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int dist) { @@ -270,14 +270,14 @@ private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int d while(right < rightLen) { if(left == leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (dist++), pos + (right++)); - } - else this.grailSwap(arr, pos + (dist++), pos + (left++)); + } + else this.grailSwap(arr, pos + (dist++), pos + (left++)); Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - + if(dist != left) this.grailMultiSwap(arr, pos + dist, pos + left, leftLen - left); } private void grailMergeRight(int[] arr, int pos, int leftLen, int rightLen, int dist) { @@ -288,14 +288,14 @@ private void grailMergeRight(int[] arr, int pos, int leftLen, int rightLen, int while(left >= 0) { if(right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (mergedPos--), pos + (left--)); - } + } else this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); if(pos + left >= 0) Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - + if(right != mergedPos) { while(right >= leftLen) this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); } @@ -316,7 +316,7 @@ private GrailPair grailSmartMergeWithoutBuffer(int[] arr, int pos, int leftOverL if (typeFrag != 0) { //Binary Search left foundLen = this.grailBinSearch(arr, pos + len1, len2, pos, true); - } else { + } else { //Binary Search right foundLen = this.grailBinSearch(arr, pos + len1, len2, pos, false); } @@ -352,7 +352,7 @@ private GrailPair grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, } Highlights.clearMark(3); Highlights.clearMark(4); - + int length, fragment = leftOverFrag; if(left < leftEnd) { length = leftEnd - left; @@ -371,9 +371,9 @@ private GrailPair grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, private GrailPair grailSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, int leftOverFrag, int blockLen) { int dist = 0 - blockLen, left = 0, right = leftOverLen, leftEnd = right, rightEnd = right + blockLen; int typeFrag = 1 - leftOverFrag; // 1 if inverted - + Highlights.clearMark(2); - + while(left < leftEnd && right < rightEnd) { if(Reads.compareValues(arr[pos + left], arr[pos + right]) - typeFrag < 0) { Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, false); @@ -384,7 +384,7 @@ private GrailPair grailSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, i } Highlights.clearMark(2); Highlights.clearMark(3); - + int length, fragment = leftOverFrag; if(left < leftEnd) { length = leftEnd - left; @@ -404,7 +404,7 @@ private void grailMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEn rightEnd += leftEnd; Highlights.clearMark(2); - + while(right < rightEnd) { if(left == leftEnd || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, false); @@ -415,7 +415,7 @@ private void grailMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEn } Highlights.clearMark(2); Highlights.clearMark(3); - + if(dist != left) { while(left < leftEnd) Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, false); } @@ -431,7 +431,7 @@ private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, i int blockCount, int regBlockLen, int aBlockCount, int lastLen) { Highlights.clearMark(2); - + if(blockCount == 0) { int aBlocksLen = aBlockCount * regBlockLen; this.grailMergeLeftWithXBuf(arr, pos, aBlocksLen, lastLen, 0 - regBlockLen); @@ -449,12 +449,12 @@ private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, i if(nextFrag == leftOverFrag) { Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, false); - + restToProcess = processIndex; leftOverLen = regBlockLen; } else { GrailPair results = this.grailSmartMergeWithXBuf(arr, pos + restToProcess, leftOverLen, leftOverFrag, regBlockLen); - leftOverLen = results.getLeftOverLen(); + leftOverLen = results.getLeftOverLen(); leftOverFrag = results.getLeftOverFrag(); } } @@ -463,7 +463,7 @@ private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, i if(lastLen != 0) { if(leftOverFrag != 0) { Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, false); - + restToProcess = processIndex; leftOverLen = regBlockLen * aBlockCount; leftOverFrag = 0; @@ -481,7 +481,7 @@ private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, i // build blocks of length buildLen // input: [-buildLen, -1] elements are buffer // output: first buildLen elements are buffer, blocks 2 * buildLen and last subblock sorted - private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen, + private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen, int[] extbuf, int bufferPos, int extBufLen) { int buildBuf = buildLen < extBufLen ? buildLen : extBufLen; @@ -490,7 +490,7 @@ private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen, int extraDist, part; if(buildBuf != 0) { Writes.arraycopy(arr, pos - buildBuf, extbuf, bufferPos, buildBuf, 1, true, true); - + for(int dist = 1; dist < len; dist += 2) { extraDist = 0; if(Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) extraDist = 1; @@ -515,9 +515,9 @@ private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen, for(; left < len; left++) Writes.write(arr, pos + left - part, arr[pos + left], 1, true, false); } pos -= part; - } + } Writes.arraycopy(extbuf, bufferPos, arr, pos + len, buildBuf, 1, true, false); - } + } else { for(int dist = 1; dist < len; dist += 2) { extraDist = 0; @@ -561,7 +561,7 @@ private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen, // buildLen and nkeys are powers of 2. (2 * buildLen / regBlockLen) keys are guaranteed private void grailCombineBlocks(int[] arr, int keyPos, int pos, int len, int buildLen, int regBlockLen, boolean havebuf, int[] buffer, int bufferPos) { - + int combineLen = len / (2 * buildLen); int leftOver = len % (2 * buildLen); if(leftOver <= buildLen) { @@ -578,7 +578,7 @@ private void grailCombineBlocks(int[] arr, int keyPos, int pos, int len, int bui int blockCount = (i == combineLen ? leftOver : 2 * buildLen) / regBlockLen; this.grailInsertSort(arr, keyPos, blockCount + (i == combineLen ? 1 : 0)); - + int midkey = buildLen / regBlockLen; for(int index = 1; index < blockCount; index++) { @@ -615,7 +615,7 @@ private void grailCombineBlocks(int[] arr, int keyPos, int pos, int len, int bui this.grailMergeBuffersLeftWithXBuf(arr, keyPos, keyPos + midkey, blockPos, blockCount - aBlockCount, regBlockLen, aBlockCount, lastLen); } - else this.grailMergeBuffersLeft(arr, keyPos, keyPos + midkey, blockPos, + else this.grailMergeBuffersLeft(arr, keyPos, keyPos + midkey, blockPos, blockCount - aBlockCount, regBlockLen, havebuf, aBlockCount, lastLen); } if(buffer != null) { @@ -658,14 +658,14 @@ protected void grailLazyStableSort(int[] arr, int pos, int len) { protected void grailCommonSort(int[] arr, int pos, int len, int[] buffer, int bufferPos, int bufferLen) { this.grailInsertSorter = new OptimizedGnomeSort(this.arrayVisualizer); - + if(len <= 16) { this.grailInsertSort(arr, pos, len); return; } - + int blockLen = 1; - while(blockLen * blockLen < len) blockLen *= 2; + while(blockLen * blockLen < len) blockLen *= 2; int numKeys = (len - 1) / blockLen + 1; @@ -713,16 +713,16 @@ protected void grailCommonSort(int[] arr, int pos, int len, int[] buffer, int bu regBlockLen = (2 * buildLen) / calcKeys; } } - this.grailCombineBlocks(arr, pos, pos + dist, len - dist, buildLen, regBlockLen, buildBufEnabled, + this.grailCombineBlocks(arr, pos, pos + dist, len - dist, buildLen, regBlockLen, buildBufEnabled, buildBufEnabled && regBlockLen <= bufferLen ? buffer : null, bufferPos); - + Highlights.clearMark(2); } this.grailInsertSort(arr, pos, dist); - this.grailMergeWithoutBuffer(arr, pos, dist, len - dist); + this.grailMergeWithoutBuffer(arr, pos, dist, len - dist); } - + private void grailInPlaceMerge(int[] arr, int pos, int len1, int len2) { if(len1 < 3 || len2 < 3) { this.grailMergeWithoutBuffer(arr, pos, len1, len2); @@ -777,4 +777,4 @@ protected void grailInPlaceMergeSort(int[] arr, int start, int len) { if(rest > part) this.grailInPlaceMerge(arr, left, part, rest - part); } } -} \ No newline at end of file +} diff --git a/src/sorts/templates/HeapSorting.java b/src/main/java/io/github/arrayv/sorts/templates/HeapSorting.java similarity index 94% rename from src/sorts/templates/HeapSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/HeapSorting.java index 594faf82..3f74316a 100644 --- a/src/sorts/templates/HeapSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/HeapSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -18,13 +18,13 @@ public abstract class HeapSorting extends Sort { protected HeapSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + private void siftDown(int[] array, int root, int dist, int start, double sleep, boolean isMax) { int compareVal = 0; - + if(isMax) compareVal = -1; else compareVal = 1; - + while (root <= dist / 2) { int leaf = 2 * root; if (leaf < dist && Reads.compareValues(array[start + leaf - 1], array[start + leaf]) == compareVal) { @@ -47,19 +47,19 @@ protected void heapify(int[] arr, int low, int high, double sleep, boolean isMax siftDown(arr, i, length, low, sleep, isMax); } } - - // This version of heap sort works for max and min variants, alongside sorting + + // This version of heap sort works for max and min variants, alongside sorting // partial ranges of an array. protected void heapSort(int[] arr, int start, int length, double sleep, boolean isMax) { heapify(arr, start, length, sleep, isMax); - + for (int i = length - start; i > 1; i--) { Writes.swap(arr, start, start + i - 1, sleep, true, false); siftDown(arr, 1, i - 1, start, sleep, isMax); } - + if(!isMax) { Writes.reversal(arr, start, start + length - 1, 1, true, false); } } -} \ No newline at end of file +} diff --git a/src/sorts/templates/InsertionSorting.java b/src/main/java/io/github/arrayv/sorts/templates/InsertionSorting.java similarity index 92% rename from src/sorts/templates/InsertionSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/InsertionSorting.java index 96cbc3d7..b912a648 100644 --- a/src/sorts/templates/InsertionSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/InsertionSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -32,15 +32,15 @@ public abstract class InsertionSorting extends Sort { protected InsertionSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - - protected void insertionSort(int[] array, int start, int end, double sleep, boolean auxwrite) { + + protected void insertionSort(int[] array, int start, int end, double sleep, boolean auxwrite) { int pos; int current; - + for(int i = start; i < end; i++) { current = array[i]; pos = i - 1; - + while(pos >= start && Reads.compareValues(array[pos], current) > 0){ Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); pos--; diff --git a/src/sorts/templates/IterativeCircleSorting.java b/src/main/java/io/github/arrayv/sorts/templates/IterativeCircleSorting.java similarity index 93% rename from src/sorts/templates/IterativeCircleSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/IterativeCircleSorting.java index 6dff09c6..67a6f735 100644 --- a/src/sorts/templates/IterativeCircleSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/IterativeCircleSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * Copyright (c) rosettacode.org. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 @@ -18,22 +18,22 @@ public abstract class IterativeCircleSorting extends Sort { protected IterativeCircleSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected int end; - + protected int circleSortRoutine(int[] array, int length, double sleep) { int swapCount = 0; for (int gap = length / 2; gap > 0; gap /= 2) { for (int start = 0; start + gap < this.end; start += 2 * gap) { int high = start + 2 * gap - 1; int low = start; - + while (low < high) { if (high < this.end && Reads.compareIndices(array, low, high, sleep / 2, true) > 0) { Writes.swap(array, low, high, sleep, true, false); swapCount++; } - + low++; high--; } @@ -41,4 +41,4 @@ protected int circleSortRoutine(int[] array, int length, double sleep) { } return swapCount; } -} \ No newline at end of file +} diff --git a/src/sorts/templates/KotaSorting.java b/src/main/java/io/github/arrayv/sorts/templates/KotaSorting.java similarity index 97% rename from src/sorts/templates/KotaSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/KotaSorting.java index 7ca43d03..18945945 100644 --- a/src/sorts/templates/KotaSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/KotaSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * MIT License Copyright (c) 2020 aphitorite @@ -27,7 +27,7 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - + /** * KotaSort / EctaSort * @@ -48,20 +48,20 @@ public abstract class KotaSorting extends Sort { protected KotaSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + private final int CACHE_SIZE = 32; - + private int[] tags; private int[] cache; - + private int bufPos; private int blockLen; private int tagLen; private int bufLen; private int effMem; - + private boolean ext; - + private void rotate(int[] array, int start, int split, int end) { int temp; while(split < end && split > start){ @@ -97,14 +97,14 @@ private void rotate(int[] array, int start, int split, int end) { } } } - + /*private void rotate(int[] array, int a, int m, int b) { Writes.reversal(array, a, b-1, 1, true, false); m = a+b-m; Writes.reversal(array, a, m-1, 1, true, false); Writes.reversal(array, m, b-1, 1, true, false); }*/ - + private void kotaSwap(int[] array, int a, int b, boolean aux) { if(aux) { Highlights.markArray(2, b); @@ -112,27 +112,27 @@ private void kotaSwap(int[] array, int a, int b, boolean aux) { } else Writes.swap(array, a, b, 1, true, false); } - + private int binarySearch(int[] array, int start, int end, int value, boolean left) { int a = start, b = end; - + while(a < b) { int m = (a+b)/2; boolean comp; - + if(left) comp = Reads.compareValues(value, array[m]) <= 0; else comp = Reads.compareValues(value, array[m]) < 0; - + if(comp) b = m; else a = m+1; } - + return a; } - + private int findKeys(int[] array, int start, int end, int num) { int numKeys = 1, pos = start, posEnd = start+1; - + for(int i = start+1; i < end && numKeys < num; i++) { Highlights.markArray(2, i); Delays.sleep(1); @@ -151,7 +151,7 @@ private int findKeys(int[] array, int start, int end, int num) { this.rotate(array, start, pos, posEnd); return numKeys; } - + private void swapToTags(int[] array, int a, int i, boolean aux) { if(aux) { Highlights.markArray(1, a); @@ -165,7 +165,7 @@ private void swapToTags(int[] array, int a, int i, boolean aux) { Delays.sleep(9); } } - + /** Shifts values across a range determined by @param a, m, b @param left determines which length's order is maintained @@ -182,9 +182,9 @@ private void shift(int[] array, int a, int m, int b, boolean left, boolean aux) this.kotaSwap(array, a++, m++, aux); } } - + //NOTE: BW = backwards version - + /** Swap groups of items of blockLen at starting points @param a, b (BW: the starting points here would be the end points inclusive) @@ -193,12 +193,12 @@ private void multiSwap(int[] array, int a, int b, int len, boolean aux) { for(int i = 0; i < len; i++) this.kotaSwap(array, a+i, b+i, aux); } - + private void multiSwapBW(int[] array, int a, int b, int len, boolean aux) { for(int i = 0; i < len; i++) this.kotaSwap(array, a-i, b-i, aux); } - + /** Performs a selection sort on the tagged blocks Tag values are unique so this doesn't affect stability @@ -208,7 +208,7 @@ private void multiSwapBW(int[] array, int a, int b, int len, boolean aux) { private void blockSelect(int[] array, int pos, int count) { for(int j = 0; j < count; j++) { int start = pos+j*this.blockLen, min = start; - + for(int i = j+1; i < count; i++) { int sel = pos+i*this.blockLen; if(Reads.compareValues(array[sel], array[min]) == -1) @@ -219,11 +219,11 @@ private void blockSelect(int[] array, int pos, int count) { } Highlights.clearMark(2); } - + private void blockSelectBW(int[] array, int pos, int count) { for(int j = 0; j < count; j++) { int start = pos-j*this.blockLen, min = start; - + for(int i = j+1; i < count; i++) { int sel = pos-i*this.blockLen; if(Reads.compareValues(array[sel], array[min]) == -1) @@ -234,7 +234,7 @@ private void blockSelectBW(int[] array, int pos, int count) { } Highlights.clearMark(2); } - + /** (EctaSort) Performs a cycle sort on the tagged blocks to make optimal # of writes EctaSort's [0, 1, 2, 3, 4...] generated tag values allows this to make O(n) comparisons during the merging process @@ -244,61 +244,61 @@ private void blockSelectBW(int[] array, int pos, int count) { private void blockCycle(int[] array, int pos, int count, int p) { for(int j = 0; j < count; j++) { int start = pos+j*this.blockLen; - + if(j != array[start]) { int first = array[start]; int val = j; - + this.multiSwap(array, p, start, this.blockLen, true); - + while(val != first) { int valStart = pos+val*this.blockLen; - + int k = j+1, next = pos+k*this.blockLen; while(Reads.compareValues(array[next], val) != 0) next = pos+(++k)*this.blockLen; - + val = k; this.multiSwap(array, valStart, next, this.blockLen, true); } - + first = pos+first*this.blockLen; this.multiSwap(array, first, p, this.blockLen, true); } - + this.swapToTags(array, start, j, true); } } - + private void blockCycleBW(int[] array, int pos, int count, int p) { for(int j = 0; j < count; j++) { int start = pos-j*this.blockLen; - + if(j != array[start]) { int first = array[start]; int val = j; - + this.multiSwapBW(array, p, start, this.blockLen, true); - + while(val != first) { int valStart = pos-val*this.blockLen; - + int k = j+1, next = pos-k*this.blockLen; while(Reads.compareValues(array[next], val) != 0) next = pos-(++k)*this.blockLen; - + val = k; this.multiSwapBW(array, valStart, next, this.blockLen, true); } - + first = pos-first*this.blockLen; this.multiSwapBW(array, first, p, this.blockLen, true); } - + this.swapToTags(array, start, j, true); } } - + /** O(n) worst case in-place merge algorithm @param [a, m) is the first range @@ -309,7 +309,7 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { this.dualMerge(array, a, m, b, this.bufLen); return; } - + /** @var i, j are the pointers to the halves @var k counts up to blockLen and resets @@ -322,12 +322,12 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { int leftAD = this.bufLen, rightAD = 0; int left = i-this.bufLen, right = j; int tagCount = 0; - + //merge as many block sized sequences to the left //no block tagging happens here while(i < m && leftAD >= rightAD) { //j will never be >= b k = 0; - + while(i < m && k < this.blockLen) { if(Reads.compareValues(array[i], array[j]) <= 0) { this.kotaSwap(array, left++, i++, this.ext); @@ -340,15 +340,15 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { k++; } } - + int selStart = left; //where to start selecting the blocks back in place - + while(i < m && j < b) { //merge as many block sized sequences to the right while(i < m && j < b && rightAD > leftAD) { first = right; k = 0; - + while(i < m && j < b && k < this.blockLen) { if(Reads.compareValues(array[i], array[j]) <= 0) { this.kotaSwap(array, right++, i++, this.ext); @@ -371,7 +371,7 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { this.kotaSwap(array, right++, j++, this.ext); k++; } - + if(k == this.blockLen) //if block is not complete don't tag this.swapToTags(array, first, tagCount++, auxTag); else { @@ -381,12 +381,12 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { right = first; } } - + //merge as many block sized sequences to the left while(i < m && j < b && leftAD >= rightAD) { first = left; k = 0; - + while(i < m && j < b && k < this.blockLen) { if(Reads.compareValues(array[i], array[j]) <= 0) { this.kotaSwap(array, left++, i++, this.ext); @@ -408,7 +408,7 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { leftAD--; k++; } - + if(k == this.blockLen) this.swapToTags(array, first, tagCount++, auxTag); else { @@ -434,16 +434,16 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { if(auxTag) this.blockCycle(array, selStart, tagCount, b-this.bufLen); else this.blockSelect(array, selStart, tagCount); } - + private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { int i = m-1, j = b-1, k, first; int leftAD = 0, rightAD = this.bufLen; int left = i, right = j+this.bufLen; int tagCount = 0; - + while(j >= m && rightAD >= leftAD) { k = 0; - + while(j >= m && k < this.blockLen) { if(Reads.compareValues(array[i], array[j]) == 1) { this.kotaSwap(array, right--, i--, this.ext); @@ -456,14 +456,14 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { k++; } } - + int selStart = right; - + while(j >= m && i >= a) { while(j >= m && i >= a && leftAD > rightAD) { first = left; k = 0; - + while(j >= m && i >= a && k < this.blockLen) { if(Reads.compareValues(array[i], array[j]) == 1) { this.kotaSwap(array, left--, i--, this.ext); @@ -485,7 +485,7 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { this.kotaSwap(array, left--, i--, this.ext); k++; } - + if(k == this.blockLen) this.swapToTags(array, first, tagCount++, auxTag); else { @@ -494,11 +494,11 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { left = first; } } - + while(j >= m && i >= a && rightAD >= leftAD) { first = right; k = 0; - + while(j >= m && i >= a && k < this.blockLen) { if(Reads.compareValues(array[i], array[j]) == 1) { this.kotaSwap(array, right--, i--, this.ext); @@ -520,7 +520,7 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { rightAD--; k++; } - + if(k == this.blockLen) this.swapToTags(array, first, tagCount++, auxTag); else { @@ -530,7 +530,7 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { } } } - + if(j < m && rightAD == this.blockLen && tagCount > 0) { this.multiSwapBW(array, right, left+this.blockLen, this.blockLen, this.ext); } @@ -542,11 +542,11 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { this.shift(array, left+1, right+1-rightAD, right+1, true, this.ext); } if(i >= a) this.shift(array, a, i+1, i+1+this.bufLen, true, this.ext); - + if(auxTag) this.blockCycleBW(array, selStart, tagCount, a-1+this.bufLen); else this.blockSelectBW(array, selStart, tagCount); } - + /** O(n) worst case in-place merge algorithm when merging ~sqrt(n) sized sequences @param [a, m) is the first range @@ -554,34 +554,34 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { */ private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - + while(i < j && j < b){ if(Reads.compareValues(array[i], array[j]) == 1) { k = this.binarySearch(array, j, b, array[i], true); this.rotate(array, i, j, k); - + i += k-j; j = k; - } + } else i++; } } - + private void inPlaceMergeBW(int[] array, int a, int m, int b) { int i = m-1, j = b-1, k; - + while(j > i && i >= a){ if(Reads.compareValues(array[i], array[j]) >= 0) { k = this.binarySearch(array, a, i+1, array[j], true); this.rotate(array, k, i+1, j+1); - + j -= (i+1)-k; i = k-1; - } + } else j--; } } - + /** O(n^2) worst case in-place merge algorithm Much faster for merging small lists and lists with very few unique values @@ -590,44 +590,44 @@ private void inPlaceMergeBW(int[] array, int a, int m, int b) { */ private void inPlaceMerge2(int[] array, int start, int mid, int end) { int i = start, m = mid, k = mid, q; - + while(m < end) { if(Reads.compareValues(array[m-1], array[m]) <= 0) return; - + while(i < m-1 && Reads.compareValues(array[i], array[m]) <= 0) i++; Writes.swap(array, i++, k++, 1, true, false); - + while(i < m) { Highlights.markArray(3, m); while(i < m && k < end && Reads.compareValues(array[m], array[k]) == 1) Writes.swap(array, i++, k++, 1, true, false); Highlights.clearMark(3); - + if(i >= m) break; - + else if(k >= end) { this.rotate(array, i, m, end); return; } - + else if(k-m >= m-i) { this.rotate(array, i, m, k); break; } - + q = m; while(i < m && q < k && Reads.compareValues(array[q], array[k]) <= 0) Writes.swap(array, i++, q++, 1, true, false); this.rotate(array, m, q, k); } - + m = k; } - + Highlights.clearMark(3); } - + /** O(n^2) worst case in-place stable sort Makes fewer moves than binary insertion in the worst case but can make 2x more comparisons @@ -636,19 +636,19 @@ else if(k-m >= m-i) { */ protected void inPlaceMergeSort2(int[] array, int start, int end) { int length = end - start, j; - + for(int i = 1; i < length; i *= 2) { for(j = start; j + 2*i < end; j += 2*i) this.inPlaceMerge2(array, j, j+i, j+2*i); - + if(j + i < end) this.inPlaceMerge2(array, j, j+i, end); } } - + private void mergeWithBuf(int[] array, int a, int m, int b, int l) { int i = a, j = m, k = a-l; - + while(i < m && j < b) { if(Reads.compareValues(array[i], array[j]) <= 0) this.kotaSwap(array, k++, i++, this.ext); @@ -657,29 +657,29 @@ private void mergeWithBuf(int[] array, int a, int m, int b, int l) { } while(j < b) this.kotaSwap(array, k++, j++, this.ext); - + this.shift(array, k, i, m, false, this.ext); } - + private void dualMerge(int[] array, int a, int m, int b, int l) { if(b-m <= l) { this.mergeWithBuf(array, a, m, b, l); } else { int i = a, j = m, k = a-l; - + while(k < i && i < m) { if(Reads.compareValues(array[i], array[j]) <= 0) this.kotaSwap(array, k++, i++, this.ext); else this.kotaSwap(array, k++, j++, this.ext); } - - if(k < i) + + if(k < i) this.shift(array, j-l, j, b, false, this.ext); else { int i2 = m-1, j2 = b-1; k = (m-1)+(b-j); - + while(i2 >= i && j2 >= j) { if(Reads.compareValues(array[i2], array[j2]) == 1) this.kotaSwap(array, k--, i2--, this.ext); @@ -691,25 +691,25 @@ private void dualMerge(int[] array, int a, int m, int b, int l) { } } } - + private void dualMergeBW(int[] array, int a, int m, int b, int l) { int i = m-1, j = b-1, k = b-1+l; - + while(k > j && j >= m) { - if(Reads.compareValues(array[i], array[j]) == 1) + if(Reads.compareValues(array[i], array[j]) == 1) this.kotaSwap(array, k--, i--, this.ext); else this.kotaSwap(array, k--, j--, this.ext); } - + if(j < m) this.shift(array, a, i+1, i+1+l, true, this.ext); else { int i2 = a, j2 = m; i++; j++; k = m-(i-a); - + while(i2 < i && j2 < j) { - if(Reads.compareValues(array[i2], array[j2]) <= 0) + if(Reads.compareValues(array[i2], array[j2]) <= 0) this.kotaSwap(array, k++, i2++, this.ext); else this.kotaSwap(array, k++, j2++, this.ext); @@ -718,11 +718,11 @@ private void dualMergeBW(int[] array, int a, int m, int b, int l) { this.kotaSwap(array, k++, i2++, this.ext); } } - + private void mergeWithBufStatic(int[] array, int a, int m, int b, int p, boolean bw) { if(m-a < 1 || b-m < 1) return; - + int i, j, k, q; if(bw) { i = (b-m)-1; j = m-1; k = b-1; @@ -751,7 +751,7 @@ private void mergeWithBufStatic(int[] array, int a, int m, int b, int p, boolean } } } - + private void mergeExtBuf(int[] array, int a, int b, boolean bw) { int i, j, k, m; if(bw) { @@ -787,101 +787,102 @@ private void mergeExtBuf(int[] array, int a, int b, boolean bw) { } } } - + private boolean kotaIterator(int[] array, int start, int end, boolean auxTag) { int i = 1, j, effStart = start+this.bufLen, length = end-effStart; - + if(!this.ext) { while(i < 16) { for(j = effStart; j + 2*i < end; j += 2*i) this.inPlaceMerge2(array, j, j+i, j+2*i); - + if(j + i < end) this.inPlaceMerge2(array, j, j+i, end); - + i *= 2; } } - + while(i <= this.bufLen) { int l = i; - + for(j = effStart; j + 2*i < end; j += 2*i) this.mergeWithBuf(array, j, j+i, j+2*i, l); - + if(j + i < end) this.mergeWithBuf(array, j, j+i, end, l); else this.shift(array, j-l, j, end, false, this.ext); - + i *= 2; - + for(j = effStart-l; j + 2*i < end-l; j += 2*i); - + if(j + i < end-l) this.dualMergeBW(array, j, j+i, end-l, l); else this.shift(array, j, end-l, end, true, this.ext); - + for(j -= 2*i; j >= effStart-l; j -= 2*i) this.dualMergeBW(array, j, j+i, j+2*i, l); - + i *= 2; - + if(this.ext && this.effMem < Math.min(i, this.bufLen)) { Highlights.clearMark(2); Writes.arraycopy(this.cache, 0, array, effStart-this.effMem, this.effMem, 1, true, false); this.ext = false; } } - + while(i < length) { for(j = effStart; j + 2*i < end; j += 2*i) this.blockMerge(array, j, j+i, j+2*i, auxTag); - + if(j + i < end) this.blockMerge(array, j, j+i, end, auxTag); else this.shift(array, j-this.bufLen, j, end, false, this.ext); - + i *= 2; if(i >= length) return true; - + for(j = start; j + 2*i < end-this.bufLen; j += 2*i); - + if(j + i < end-this.bufLen) this.blockMergeBW(array, j, j+i, end-this.bufLen, auxTag); else this.shift(array, j, end-this.bufLen, end, true, this.ext); - + for(j -= 2*i; j >= start; j -= 2*i) this.blockMergeBW(array, j, j+i, j+2*i, auxTag); - + i *= 2; } - + return false; } - + //@param ignoredValues + @SuppressWarnings("unused") private void kotaSortLimited(int[] array, int start, int end) { - + // TODO for aphitorite: implement } - + protected void kotaSort(int[] array, int start, int end) { int length = end - start; if(length <= 128) { this.inPlaceMergeSort2(array, start, end); return; } - + this.ext = false; this.bufPos = start; for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); //ceiling power of 2 sqrt - + int ideal = this.blockLen*2; this.bufLen = this.findKeys(array, start, end, ideal); - + if(this.bufLen < ideal) { if(this.bufLen == 1) { return; @@ -897,10 +898,10 @@ else if(this.bufLen <= 16) { return; } } - + ideal = length/this.blockLen; this.tagLen = this.findKeys(array, start+this.bufLen, end, ideal); - + if(this.tagLen < ideal) { if(this.tagLen <= 16) { this.inPlaceMergeSort2(array, start, end); @@ -913,25 +914,25 @@ else if(this.bufLen <= 16) { return; } } - + int bufStart = start+this.tagLen; int effStart = bufStart+this.bufLen; int bufEnd = start+this.bufLen; this.shift(array, start, bufEnd, effStart, false, false); - + boolean bw = this.kotaIterator(array, bufStart, end, false); - + if(bw) { int endStart = end-this.bufLen; this.multiSwap(array, start, endStart, this.tagLen, false); this.mergeWithBufStatic(array, start, bufStart, endStart, endStart, false); this.inPlaceMergeSort2(array, endStart, end); - + int mid = endStart+this.blockLen; int pos = this.binarySearch(array, start, endStart, array[mid-1], true); this.rotate(array, pos, endStart, mid); pos += this.blockLen; - + this.multiSwapBW(array, end-1, pos-1, this.blockLen, false); this.mergeWithBufStatic(array, start, pos-this.blockLen, pos, mid, true); this.inPlaceMergeSort2(array, mid, end); @@ -940,70 +941,70 @@ else if(this.bufLen <= 16) { else { this.mergeWithBufStatic(array, bufEnd, effStart, end, start, false); this.inPlaceMergeSort2(array, start, bufEnd); - + int mid = start+this.blockLen; int pos = this.binarySearch(array, bufEnd, end, array[mid], true); this.rotate(array, mid, bufEnd, pos); pos -= this.blockLen; - + this.multiSwap(array, start, pos, this.blockLen, false); this.mergeWithBufStatic(array, pos, pos+this.blockLen, end, start, false); this.inPlaceMergeSort2(array, start, mid); this.inPlaceMerge(array, start, mid, pos); } } - + protected void ectaSort(int[] array, int start, int end) { int length = end - start; if(length <= 16) { this.inPlaceMergeSort2(array, start, end); return; } - + this.ext = true; this.bufPos = start; for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); this.bufLen = this.blockLen*2; this.effMem = this.bufLen; this.cache = Writes.createExternalArray(this.bufLen); - + int effStart = start+this.bufLen; this.inPlaceMergeSort2(array, start, effStart); Highlights.clearMark(2); Writes.arraycopy(array, start, this.cache, 0, this.bufLen, 1, true, true); - + if(this.bufLen < length/4) { this.tagLen = length/this.blockLen; - + this.tags = Writes.createExternalArray(this.tagLen); for(int i = 0; i < this.tagLen; i++) Writes.write(this.tags, i, i, 0, false, true); } - + boolean bw = this.kotaIterator(array, start, end, true); this.mergeExtBuf(array, start, end, bw); Writes.deleteExternalArray(this.cache); Writes.deleteExternalArray(this.tags); } - + protected void kotaSortDynamicBuf(int[] array, int start, int end) { int length = end - start; if(length <= 16) { this.inPlaceMergeSort2(array, start, end); return; } - + this.ext = true; this.bufPos = start; for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); this.bufLen = this.blockLen*2; this.effMem = this.bufLen; - + if(this.bufLen < length/4) { int ideal = length/this.blockLen; this.tagLen = this.findKeys(array, start, end, ideal); - + if(this.tagLen < ideal) { if(this.tagLen <= 16) { this.inPlaceMergeSort2(array, start, end); @@ -1017,49 +1018,49 @@ protected void kotaSortDynamicBuf(int[] array, int start, int end) { } } } else this.tagLen = 0; - + this.cache = Writes.createExternalArray(this.bufLen); - + int bufStart = start+this.tagLen; int effStart = bufStart+this.bufLen; - + this.inPlaceMergeSort2(array, bufStart, effStart); Highlights.clearMark(2); Writes.arraycopy(array, bufStart, this.cache, 0, this.bufLen, 1, true, true); - + boolean bw = this.kotaIterator(array, bufStart, end, false); this.mergeExtBuf(array, bufStart, end, bw); this.inPlaceMerge(array, start, bufStart, end); Writes.deleteExternalArray(this.cache); } - + protected void kotaSortStaticBuf(int[] array, int start, int end) { if(this.CACHE_SIZE < 4) { this.kotaSort(array, start, end); return; } - + int length = end - start; if(length <= 16) { this.inPlaceMergeSort2(array, start, end); return; } - + this.ext = true; this.bufPos = start; for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); this.bufLen = this.blockLen*2; this.effMem = Math.min(CACHE_SIZE, this.bufLen); - + if(this.effMem == this.bufLen) { this.kotaSortDynamicBuf(array, start, end); return; } - + int ideal = this.blockLen*2; this.bufLen = this.findKeys(array, start, end, ideal); - + if(this.bufLen < ideal) { if(this.bufLen == 1) { return; @@ -1075,11 +1076,11 @@ else if(this.bufLen <= 16) { return; } } - + if(this.bufLen < length/4) { ideal = length/this.blockLen; this.tagLen = this.findKeys(array, start+this.bufLen, end, ideal); - + if(this.tagLen < ideal) { if(this.tagLen <= 16) { this.inPlaceMergeSort2(array, start, end); @@ -1093,29 +1094,29 @@ else if(this.bufLen <= 16) { } } } else this.tagLen = 0; - + int bufStart = start+this.tagLen; int effStart = bufStart+this.bufLen; int bufEnd = start+this.bufLen; this.shift(array, start, bufEnd, effStart, false, false); - + this.cache = Writes.createExternalArray(this.effMem); Highlights.clearMark(2); Writes.arraycopy(array, effStart-this.effMem, this.cache, 0, this.effMem, 1, true, true); - + boolean bw = this.kotaIterator(array, bufStart, end, false); - + if(bw) { int endStart = end-this.bufLen; this.multiSwap(array, start, endStart, this.tagLen, false); this.mergeWithBufStatic(array, start, bufStart, endStart, endStart, false); this.inPlaceMergeSort2(array, endStart, end); - + int mid = endStart+this.blockLen; int pos = this.binarySearch(array, start, endStart, array[mid-1], true); this.rotate(array, pos, endStart, mid); pos += this.blockLen; - + this.multiSwapBW(array, end-1, pos-1, this.blockLen, false); this.mergeWithBufStatic(array, start, pos-this.blockLen, pos, mid, true); this.inPlaceMergeSort2(array, mid, end); @@ -1124,12 +1125,12 @@ else if(this.bufLen <= 16) { else { this.mergeWithBufStatic(array, bufEnd, effStart, end, start, false); this.inPlaceMergeSort2(array, start, bufEnd); - + int mid = start+this.blockLen; int pos = this.binarySearch(array, bufEnd, end, array[mid], true); this.rotate(array, mid, bufEnd, pos); pos -= this.blockLen; - + this.multiSwap(array, start, pos, this.blockLen, false); this.mergeWithBufStatic(array, pos, pos+this.blockLen, end, start, false); this.inPlaceMergeSort2(array, start, mid); @@ -1138,4 +1139,4 @@ else if(this.bufLen <= 16) { Writes.deleteExternalArray(this.cache); } -} \ No newline at end of file +} diff --git a/src/sorts/templates/MergeSorting.java b/src/main/java/io/github/arrayv/sorts/templates/MergeSorting.java similarity index 93% rename from src/sorts/templates/MergeSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/MergeSorting.java index fb8040af..25385087 100644 --- a/src/sorts/templates/MergeSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/MergeSorting.java @@ -1,10 +1,10 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.BinaryInsertionSort; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -31,11 +31,11 @@ of this software and associated documentation files (the "Software"), to deal public abstract class MergeSorting extends Sort { private BinaryInsertionSort binaryInserter; - + protected MergeSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + private void merge(int[] array, int[] tmp, int start, int mid, int end, boolean binary) { if(start == mid) return; @@ -48,16 +48,16 @@ else if(end - start < 64 && binary) { else { merge(array, tmp, start, (mid+start)/2, mid, binary); merge(array, tmp, mid, (mid+end)/2, end, binary); - + int low = start; int high = mid; - + for(int nxt = 0; nxt < end - start; nxt++){ if(low >= mid && high >= end) break; - + Highlights.markArray(1, low); Highlights.markArray(2, high); - + if(low < mid && high >= end){ Highlights.clearMark(2); Writes.write(tmp, nxt, array[low++], 1, false, true); @@ -74,27 +74,27 @@ else if(Reads.compareValues(array[low], array[high]) <= 0){ } } Highlights.clearMark(2); - + for(int i = 0; i < end - start; i++){ Writes.write(array, start + i, tmp[i], 1, true, false); } } } - + protected void mergeSort(int[] array, int length, boolean binary) { binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); - + if(length < 32 && binary) { binaryInserter.customBinaryInsert(array, 0, length, 0.333); return; } - + int[] tmp = Writes.createExternalArray(length); - + int start = 0; int end = length; int mid = start + ((end - start) / 2); - + merge(array, tmp, start, mid, end, binary); Writes.deleteExternalArray(tmp); diff --git a/src/sorts/templates/MultiWayMergeSorting.java b/src/main/java/io/github/arrayv/sorts/templates/MultiWayMergeSorting.java similarity index 96% rename from src/sorts/templates/MultiWayMergeSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/MultiWayMergeSorting.java index ca7fed32..ec312be3 100644 --- a/src/sorts/templates/MultiWayMergeSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/MultiWayMergeSorting.java @@ -1,9 +1,9 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * MIT License Copyright (c) 2021 aphitorite @@ -32,7 +32,7 @@ public abstract class MultiWayMergeSorting extends Sort { protected MultiWayMergeSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected boolean keyLessThan(int[] src, int[] pa, int a, int b) { int cmp = Reads.compareValues(src[pa[a]], src[pa[b]]); return cmp < 0 || (cmp == 0 && Reads.compareOriginalValues(a, b) < 0); @@ -64,18 +64,18 @@ protected void kWayMerge(int[] src, int[] dest, int[] heap, int[] pa, int[] pb, for(int i = (size-1)/2; i >= 0; i--) this.siftDown(src, heap, pa, heap[i], i, size); - + for(int i = 0; size > 0; i++) { int min = heap[0]; - + Highlights.markArray(2, pa[min]); - + Writes.write(dest, i, src[pa[min]], 0.5, !auxWrite, auxWrite); Writes.write(pa, min, pa[min]+1, 0, false, true); if(pa[min] == pb[min]) this.siftDown(src, heap, pa, heap[--size], 0, size); - else + else this.siftDown(src, heap, pa, heap[0], 0, size); } } diff --git a/src/sorts/templates/PDQSorting.java b/src/main/java/io/github/arrayv/sorts/templates/PDQSorting.java similarity index 98% rename from src/sorts/templates/PDQSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/PDQSorting.java index bc5d7701..fa98a977 100644 --- a/src/sorts/templates/PDQSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/PDQSorting.java @@ -1,10 +1,10 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import sorts.select.MaxHeapSort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.select.MaxHeapSort; /* - * + * pdqsort.h - Pattern-defeating quicksort. Copyright (c) 2015 Orson Peters This software is provided 'as-is', without any express or implied warranty. In no event will the @@ -40,34 +40,34 @@ public boolean getPresortBool() { public abstract class PDQSorting extends Sort { private MaxHeapSort heapSorter; - + final private int insertSortThreshold = 24; final private int nintherThreshold = 128; final private int partialInsertSortLimit = 8; final private int blockSize = 64; final private int cachelineSize = 64; - + private int[] leftOffsets; private int[] rightOffsets; protected PDQSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected void newHeapSorter(MaxHeapSort heapSort) { heapSorter = heapSort; } - + protected void visualizeAux() { leftOffsets = Writes.createExternalArray(blockSize + cachelineSize); rightOffsets = Writes.createExternalArray(blockSize + cachelineSize); } - + protected void deleteAux() { Writes.deleteExternalArray(leftOffsets); Writes.deleteExternalArray(rightOffsets); } - + // Returns floor(log2(n)), assumes n > 0. public static int pdqLog(int n) { int log = 0; @@ -119,7 +119,7 @@ private void pdqUnguardInsertSort(int[] array, int begin, int end) { int tmp = array[sift]; do { - Writes.write(array, sift--, array[siftMinusOne], sleep, true, false); + Writes.write(array, sift--, array[siftMinusOne], sleep, true, false); } while (Reads.compareValues(tmp, array[--siftMinusOne]) < 0); Writes.write(array, sift, tmp, sleep, true, false); @@ -146,7 +146,7 @@ private boolean pdqPartialInsertSort(int[] array, int begin, int end) { if (Reads.compareValues(array[sift], array[siftMinusOne]) < 0) { int tmp = array[sift]; - do { + do { Writes.write(array, sift--, array[siftMinusOne], sleep, true, false); } while (sift != begin && Reads.compareValues(tmp, array[--siftMinusOne]) < 0); @@ -174,7 +174,7 @@ private void pdqSortThree(int[] array, int a, int b, int c) { // With Branchless PDQSort, in order to better estimate the gains in speed from branchless partioning, we treat the writes to the offset arrays // and specialized less than comparison as negligible, and only record time from elements being swapped into position. By no means is this // exact, yet it is a much closer estimate than what was happening before with recording time for every block being written. - private void pdqSwapOffsets(int[] array, int first, int last, int[] leftOffsets, int leftOffsetsPos, + private void pdqSwapOffsets(int[] array, int first, int last, int[] leftOffsets, int leftOffsetsPos, int[] rightOffsets, int rightOffsetsPos, int num, boolean useSwaps) { if (useSwaps) { // This case is needed for the descending distribution, where we need @@ -386,7 +386,7 @@ private PDQPair pdqPartRight(int[] array, int begin, int end) { // Find the first element strictly smaller than the pivot. We have to guard this search if // there was no element before *first. - if (first - 1 == begin) + if (first - 1 == begin) while (first < last && !(Reads.compareValues(array[--last], pivot) < 0)) { Highlights.markArray(2, last); Delays.sleep(0.25); @@ -441,12 +441,12 @@ private int pdqPartLeft(int[] array, int begin, int end) { Delays.sleep(0.25); } - if (last + 1 == end) + if (last + 1 == end) while (first < last && !(Reads.compareValues(pivot, array[++first]) < 0)) { Highlights.markArray(1, first); Delays.sleep(0.25); } - else + else while ( !(Reads.compareValues(pivot, array[++first]) < 0)) { Highlights.markArray(1, first); Delays.sleep(0.25); @@ -511,7 +511,7 @@ protected void pdqLoop(int[] array, int begin, int end, boolean Branchless, int PDQPair partResult = Branchless ? this.pdqPartRightBranchless(array, begin, end) : this.pdqPartRight(array, begin, end); - + int pivotPos = partResult.getPivotPosition(); boolean alreadyParted = partResult.getPresortBool(); @@ -556,7 +556,7 @@ protected void pdqLoop(int[] array, int begin, int end, boolean Branchless, int // If we were decently balanced and we tried to sort an already partitioned // sequence, try to use insertion sort. if (alreadyParted && pdqPartialInsertSort(array, begin, pivotPos) - && pdqPartialInsertSort(array, pivotPos + 1, end)) + && pdqPartialInsertSort(array, pivotPos + 1, end)) return; } @@ -567,4 +567,4 @@ && pdqPartialInsertSort(array, pivotPos + 1, end)) leftmost = false; } } -} \ No newline at end of file +} diff --git a/src/sorts/templates/QuadSorting.java b/src/main/java/io/github/arrayv/sorts/templates/QuadSorting.java similarity index 93% rename from src/sorts/templates/QuadSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/QuadSorting.java index f91ba781..3673a391 100644 --- a/src/sorts/templates/QuadSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/QuadSorting.java @@ -1,7 +1,7 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import utils.*; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.*; /* Copyright (C) 2014-2021 Igor van den Hoven ivdhoven@gmail.com @@ -33,32 +33,32 @@ a copy of this software and associated documentation files (the class QuadSortBase { int pta, end, ptt, key; // original C version uses pointer trick, had to refactor using index instead - + Reads Reads; Writes Writes; Highlights Highlights; Delays Delays; - + public QuadSortBase(ArrayVisualizer arrayVisualizer) { Reads = arrayVisualizer.getReads(); Writes = arrayVisualizer.getWrites(); Highlights = arrayVisualizer.getHighlights(); Delays = arrayVisualizer.getDelays(); } - + void swapTwo(int[] array, int start) { if(Reads.compareIndices(array, start, start+1, 1, true) > 0) Writes.swap(array, start, start+1, 1, true, false); } - + void swapThree(int[] array, int start) { if(Reads.compareIndices(array, start, start+1, 1, true) > 0) { if(Reads.compareIndices(array, start, start+2, 1, true) <= 0) Writes.swap(array, start, start+1, 1, true, false); - + else if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) Writes.swap(array, start, start+2, 1, true, false); - + else { int temp = array[start]; Writes.write(array, start, array[start+1], 1, true, false); @@ -66,7 +66,7 @@ else if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) Writes.write(array, start+2, temp, 1, true, false); } } - + else if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) { if(Reads.compareIndices(array, start, start+2, 1, true) > 0) { int temp = array[start+2]; @@ -74,25 +74,25 @@ else if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) { Writes.write(array, start+1, array[start], 1, true, false); Writes.write(array, start, temp, 1, true, false); } - + else { Writes.swap(array, start+2, start+1, 1, true, false); } } } - + void swapFour(int[] array, int start) { if(Reads.compareIndices(array, start, start+1, 1, true) > 0) Writes.swap(array, start, start+1, 1, true, false); - + if(Reads.compareIndices(array, start+2, start+3, 1, true) > 0) Writes.swap(array, start+2, start+3, 1, true, false); - + if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) { if(Reads.compareIndices(array, start, start+2, 1, true) <= 0) { if(Reads.compareIndices(array, start+1, start+3, 1, true) <= 0) Writes.swap(array, start+1, start+2, 1, true, false); - + else { int temp = array[start+1]; Writes.write(array, start+1, array[start+2], 1, true, false); @@ -100,19 +100,19 @@ void swapFour(int[] array, int start) { Writes.write(array, start+3, temp, 1, true, false); } } - + else if(Reads.compareIndices(array, start, start+3, 1, true) > 0) { Writes.swap(array, start+1, start+3, 1, true, false); Writes.swap(array, start, start+2, 1, true, false); } - + else if(Reads.compareIndices(array, start+1, start+3, 1, true) <= 0) { int temp = array[start+1]; Writes.write(array, start+1, array[start], 1, true, false); Writes.write(array, start, array[start+2], 1, true, false); Writes.write(array, start+2, temp, 1, true, false); } - + else { int temp = array[start+1]; Writes.write(array, start+1, array[start], 1, true, false); @@ -122,65 +122,65 @@ else if(Reads.compareIndices(array, start+1, start+3, 1, true) <= 0) { } } } - + void swapFive(int[] array, int start) { end = start+4; pta = end++; ptt = pta--; - + if(Reads.compareIndices(array, pta, ptt, 1, true) > 0) { key = array[ptt]; Writes.write(array, ptt--, array[pta--], 1, true, false); - + if(pta > start && Reads.compareValues(array[pta-1], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); Writes.write(array, ptt--, array[pta--], 1, true, false); } - + if(pta >= start && Reads.compareValues(array[pta], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); } - + array[ptt] = key; } } - + void tailSwapEight(int[] array, int start) { pta = end++; ptt = pta--; - + if(Reads.compareIndices(array, pta, ptt, 1, true) > 0) { key = array[ptt]; Writes.write(array, ptt--, array[pta--], 1, true, false); - + if(Reads.compareValues(array[pta-2], key) > 0) { for(int i=0; i<3; i++) Writes.write(array, ptt--, array[pta--], 1, true, false); } - + if(pta > start && Reads.compareValues(array[pta-1], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); Writes.write(array, ptt--, array[pta--], 1, true, false); } - + if(pta >= start && Reads.compareValues(array[pta], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); } - + array[ptt] = key; } } - + void swapSix(int[] array, int start) { this.swapFive(array, start); this.tailSwapEight(array, start); } - + void swapSeven(int[] array, int start) { this.swapSix(array, start); this.tailSwapEight(array, start); } - + void swapEight(int[] array, int start) { this.swapSeven(array, start); this.tailSwapEight(array, start); @@ -190,275 +190,275 @@ void swapEight(int[] array, int start) { // things in quadsort.c public abstract class QuadSorting extends Sort { QuadSortBase qs; - + public QuadSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); qs = new QuadSortBase(arrayVisualizer); } - + // ~4 items: sorting network // 5~ items: unguarded insertion sort protected void tailSwap(int[] array, int start, int nmemb) { int mid, top, offset; - + switch(nmemb) { case 0: case 1: return; - + case 2: qs.swapTwo(array, start); return; - + case 3: qs.swapThree(array, start); return; - + case 4: qs.swapFour(array, start); return; - + case 5: qs.swapFour(array, start); qs.swapFive(array, start); return; - + case 6: qs.swapFour(array, start); qs.swapSix(array, start); return; - + case 7: qs.swapFour(array, start); qs.swapSeven(array, start); return; - + case 8: qs.swapFour(array, start); qs.swapEight(array, start); return; } - + qs.swapFour(array, start); qs.swapEight(array, start); - + qs.end = start+8; offset = 8; - + while(offset < nmemb) { top = offset++; qs.pta = qs.end++; qs.ptt = qs.pta--; - + if(Reads.compareIndices(array, qs.pta, qs.ptt, 1, true) <= 0) continue; - + int temp = array[qs.ptt]; - + while(top > 1) { mid = top/2; if(Reads.compareValues(array[qs.pta-mid], temp) > 0) qs.pta -= mid; - + top -= mid; } - + // memmove(pta+1, pta, (ptt-pta) * sizeof(VAR)); for(int i=qs.ptt; i > qs.pta; i--) Writes.write(array, i, array[i-1], 1, true, false); - + Writes.write(array, qs.pta, temp, 1, true, false); } - + Highlights.clearAllMarks(); } - + // merge 4 4 into 8 from main array to aux array // auxOffset must be either 0 or 8 void parityMerge4(int[] from, int start, int[] dest, int auxOffset) { int ptl, ptr; int auxP = auxOffset; - + ptl = start; ptr = start+4; - + for(int i=0; i<3; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, auxP++, from[ptl++], 1, true, true); - + else Writes.write(dest, auxP++, from[ptr++], 1, true, true); } - + Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, auxP, from[ptl], 1, true, true); - + else Writes.write(dest, auxP, from[ptr], 1, true, true); - + ptl = start+3; ptr = start+7; auxP += 4; - + for(int i=0; i<3; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, auxP--, from[ptl--], 1, true, true); - + else Writes.write(dest, auxP--, from[ptr--], 1, true, true); } - + Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, auxP, from[ptl], 1, true, true); - + else Writes.write(dest, auxP, from[ptr], 1, true, true); - + Highlights.clearAllMarks(); } - + // merge 8 8 into 16 from aux array to main array void parityMerge8(int[] from, int start, int[] dest) { int ptl, ptr; int mainP = start; - + ptl = 0; ptr = 8; - + for(int i=0; i<7; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, mainP++, from[ptl++], 1, true, false); - + else Writes.write(dest, mainP++, from[ptr++], 1, true, false); } - + Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, mainP, from[ptl], 1, true, false); - + else Writes.write(dest, mainP, from[ptr], 1, true, false); - + ptl = 7; ptr = 15; mainP += 8; - + for(int i=0; i<7; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, mainP--, from[ptl--], 1, true, false); - + else Writes.write(dest, mainP--, from[ptr--], 1, true, false); } - + Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - + if(Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, mainP, from[ptl], 1, true, false); - + else Writes.write(dest, mainP, from[ptr], 1, true, false); - + Highlights.clearAllMarks(); } - + // merge 4 4 4 4 into 16 using the above two methods // with analyzing already sorted runs void parityMerge16(int[] array, int start, int[] aux) { - if(Reads.compareIndices(array, start+3, start+4, 4, true) <= 0 && - Reads.compareIndices(array, start+7, start+8, 4, true) <= 0 && + if(Reads.compareIndices(array, start+3, start+4, 4, true) <= 0 && + Reads.compareIndices(array, start+7, start+8, 4, true) <= 0 && Reads.compareIndices(array, start+11, start+12, 4, true) <= 0) return; - + this.parityMerge4(array, start, aux, 0); this.parityMerge4(array, start+8, aux, 8); - + this.parityMerge8(aux, start, array); } - + // (partially) writes second block into aux array and then merge with first block void partialBackwardMerge(int[] array, int[] aux, int start, int nmemb, int block) { int r, m, e, s; // right, middle, end, swap - + m = start + block; e = start + nmemb - 1; r = m--; - + if(Reads.compareIndices(array, m, r, 1, true) <= 0) return; - + while(Reads.compareIndices(array, m, e, 1, true) <= 0) e--; - + Highlights.clearAllMarks(); for(int i=r; i < r+(e-m); i++) { Writes.write(aux, i-r, array[i], 1, false, true); Highlights.markArray(1, i); } - + s = e-r; Writes.write(array, e--, array[m--], 1, true, false); - + if(Reads.compareValues(array[start], aux[0]) <= 0) { do { while(Reads.compareValues(array[m], aux[s]) > 0) { Highlights.markArray(2, m); Writes.write(array, e--, array[m--], 1, true, false); } - + Highlights.markArray(2, m); Writes.write(array, e--, aux[s--], 1, true, false); } while(s >= 0); } - + else { do { while(Reads.compareValues(array[m], aux[s]) <= 0) { Highlights.markArray(2, m); Writes.write(array, e--, aux[s--], 1, true, false); } - + Highlights.markArray(2, m); Writes.write(array, e--, array[m--], 1, true, false); } while(m >= start); - + do Writes.write(array, e--, aux[s--], 1, true, false); while (s >= 0); } } - + // bottom up merge sort, performs on array size from 16 to 255 after parity merge // or performs after quad merge on array size from 256 void tailMerge(int[] array, int[] aux, int start, int nmemb, int block) { int pta, pte; // different from qs.pta - + pte = start + nmemb; while(block < nmemb) { pta = start; - + for (pta = start ; pta + block < pte ; pta += block * 2) { if (pta + block * 2 < pte) @@ -474,26 +474,26 @@ void tailMerge(int[] array, int[] aux, int start, int nmemb, int block) { block *= 2; } } - + // normal merge method with some optimizations // like analyzing already sorted runs void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, boolean toAux) { int l, r, m, e; // left, right, middle, end int mergeP = toAux ? auxStart : start; - + l = toAux ? start : auxStart; r = toAux ? (start+block) : (auxStart+block); m = r; e = r + block; - + Highlights.clearAllMarks(); if(toAux) { Highlights.markArray(1, r-1); Highlights.markArray(2, e-1); Delays.sleep(1); } - + if(Reads.compareValues(from[r-1], from[e-1]) <= 0) { leftFirst: do { @@ -507,7 +507,7 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo Writes.write(dest, mergeP++, from[l++], toAux ? 0 : 1, !toAux, toAux); continue leftFirst; } - + if(toAux) { Highlights.markArray(1, l); Highlights.markArray(2, r); @@ -516,7 +516,7 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo Writes.write(dest, mergeP++, from[r++], toAux ? 0 : 1, !toAux, toAux); } } while(l < m); - + do { if(toAux) { Highlights.markArray(1, l-1); @@ -526,7 +526,7 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo Writes.write(dest, mergeP++, from[r++], toAux ? 0 : 1, !toAux, toAux); } while(r < e); } - + else { rightFirst: do { @@ -540,7 +540,7 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo Writes.write(dest, mergeP++, from[r++], toAux ? 0 : 1, !toAux, toAux); continue rightFirst; } - + if(toAux) { Highlights.markArray(1, l); Highlights.markArray(2, r); @@ -549,7 +549,7 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo Writes.write(dest, mergeP++, from[l++], toAux ? 0 : 1, !toAux, toAux); } } while(r < e); - + do { if(toAux) { Highlights.markArray(1, l); @@ -560,94 +560,94 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo } while(l < m); } } - + // main memory: [A][B][C][D] // swap memory: [A B] step 1 // swap memory: [A B][C D] step 2 // main memory: [A B C D] step 3 - + // merge 4 blocks into 1 block like above comment void quadMergeBlock(int[] array, int start, int[] aux, int block) { int pts, c, cMax; int blockX2 = block*2; - + cMax = start + block; - + // if first 2 blocks are sorted if(Reads.compareIndices(array, cMax-1, cMax, 20, true) <= 0) { cMax += blockX2; - + // if second 2 blocks are sorted if(Reads.compareIndices(array, cMax-1, cMax, 20, true) <= 0) { cMax -= block; - + // ...and entire 4 blocks are sorted if(Reads.compareIndices(array, cMax-1, cMax, 20, true) <= 0) { return; } - + pts = 0; c = start; - + do { Writes.write(aux, pts, array[c++], 1, false, true); Highlights.markArray(1, pts+start); pts++; } while(c < cMax); // step 1 - + cMax = c + blockX2; do { Writes.write(aux, pts, array[c++], 1, false, true); Highlights.markArray(1, pts+start); pts++; } while(c < cMax); // step 2 - + this.forwardMerge(array, aux, start, 0, blockX2, false); // step 3 return; } - + pts = 0; c = start; cMax = start + blockX2; - + do { Writes.write(aux, pts, array[c++], 1, false, true); Highlights.markArray(1, pts+start); pts++; } while(c < cMax); // step 1 } - + else this.forwardMerge(aux, array, start, 0, block, true); // step 1 - + this.forwardMerge(aux, array, start+blockX2, blockX2, block, true); // step 2 this.forwardMerge(array, aux, start, 0, blockX2, false); // step 3 } - + // quad merges the entire array // this fallbacks to tail merge if (current block size)*2 is greater than array size void quadMerge(int[] array, int[] aux, int start, int nmemb, int block) { int pta, pte; // different from qs.pta - + pte = start + nmemb; block *= 4; - + while(block*2 <= nmemb) { pta = start; do { this.quadMergeBlock(array, pta, aux, block/4); - + pta += block; } while(pta+block <= pte); - + this.tailMerge(array, aux, pta, pte-pta, block/4); - + block *= 4; } this.tailMerge(array, aux, start, nmemb, block/4); } - + // pre-sorting process; basically 4-item sorting network // detects strictly decreasing runs and reverses them // if entire array is decreasing this performs only 1 reversal and returns @@ -656,10 +656,10 @@ int quadSwap(int[] array, int start, int nmemb) { int[] swap = Writes.createExternalArray(16); int count, reverse; int pta, pts = 0, ptt = 0, temp = 0; - + pta = start; count = nmemb/4; - + swapper: while(count-- > 0) { while(true) { @@ -670,20 +670,20 @@ int quadSwap(int[] array, int start, int nmemb) { pta += 4; break; } - + Writes.swap(array, pta+2, pta+3, 1, true, false); } Writes.swap(array, pta, pta+1, 1, true, false); } - + else if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) Writes.swap(array, pta+2, pta+3, 1, true, false); - + if(Reads.compareIndices(array, pta+1, pta+2, 1, true) > 0) { if(Reads.compareIndices(array, pta, pta+2, 1, true) <= 0) { if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) Writes.swap(array, pta+1, pta+2, 1, true, false); - + else { temp = array[pta+1]; Writes.write(array, pta+1, array[pta+2], 1, true, false); @@ -691,19 +691,19 @@ else if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) Writes.write(array, pta+3, temp, 1, true, false); } } - + else if(Reads.compareIndices(array, pta, pta+3, 1, true) > 0) { Writes.swap(array, pta+1, pta+3, 1, true, false); Writes.swap(array, pta, pta+2, 1, true, false); } - + else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { temp = array[pta+1]; Writes.write(array, pta+1, array[pta], 1, true, false); Writes.write(array, pta, array[pta+2], 1, true, false); Writes.write(array, pta+2, temp, 1, true, false); } - + else { temp = array[pta+1]; Writes.write(array, pta+1, array[pta], 1, true, false); @@ -715,7 +715,7 @@ else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { pta += 4; continue swapper; } - + while(true) { if(count-- > 0) { if(Reads.compareIndices(array, pta, pta+1, 1, true) > 0) { @@ -730,15 +730,15 @@ else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { } Writes.swap(array, pta, pta+1, 1, true, false); } - + else if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) Writes.swap(array, pta+2, pta+3, 1, true, false); - + if(Reads.compareIndices(array, pta+1, pta+2, 1, true) > 0) { if(Reads.compareIndices(array, pta, pta+2, 1, true) <= 0) { if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) Writes.swap(array, pta+1, pta+2, 1, true, false); - + else { temp = array[pta+1]; Writes.write(array, pta+1, array[pta+2], 1, true, false); @@ -746,19 +746,19 @@ else if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) Writes.write(array, pta+3, temp, 1, true, false); } } - + else if(Reads.compareIndices(array, pta, pta+3, 1, true) > 0) { Writes.swap(array, pta, pta+2, 1, true, false); Writes.swap(array, pta+1, pta+3, 1, true, false); } - + else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { temp = array[pta]; Writes.write(array, pta, array[pta+2], 1, true, false); Writes.write(array, pta+2, array[pta+1], 1, true, false); Writes.write(array, pta+1, temp, 1, true, false); } - + else { temp = array[pta]; Writes.write(array, pta, array[pta+2], 1, true, false); @@ -767,47 +767,47 @@ else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { Writes.write(array, pta+1, temp, 1, true, false); } } - + ptt = pta-1; reverse = (ptt-pts)/2; - + Writes.changeReversals(1); do { Writes.swap(array, pts++, ptt--, 1, true, false); } while(reverse-- > 0); - + pta += 4; continue swapper; } - + if(pts == start) { switch(nmemb % 4) { case 3: if(Reads.compareIndices(array, pta+1, pta+2, 1, true) <= 0) break; - + case 2: if(Reads.compareIndices(array, pta, pta+1, 1, true) <= 0) break; - + case 1: if(Reads.compareIndices(array, pta-1, pta, 1, true) <= 0) break; - + case 0: ptt = pts+nmemb-1; reverse = (ptt-pts)/2; - + Writes.changeReversals(1); do { Writes.swap(array, pts++, ptt--, 1, true, false); } while(reverse-- > 0); - + Writes.deleteExternalArray(swap); return 1; } } - + ptt = pta - 1; reverse = (ptt-pts)/2; Writes.changeReversals(1); @@ -818,27 +818,27 @@ else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { } } this.tailSwap(array, pta, nmemb%4); - + pta = start; count = nmemb/16; while(count-- > 0) { this.parityMerge16(array, pta, swap); pta += 16; } - + if(nmemb%16 > 4) this.tailMerge(array, swap, pta, nmemb%16, 4); - + Writes.deleteExternalArray(swap); return 0; } - + // main sorting method protected void quadSort(int[] array, int start, int length) { if(length < 16) { this.tailSwap(array, start, length); } - + else if(length < 256) { if(this.quadSwap(array, start, length) == 0) { int[] swap = Writes.createExternalArray(128); @@ -846,7 +846,7 @@ else if(length < 256) { Writes.deleteExternalArray(swap); } } - + else { if(this.quadSwap(array, start, length) == 0) { int[] swap = Writes.createExternalArray(length/2); @@ -855,18 +855,18 @@ else if(length < 256) { } } } - + // main sorting method with given swap array protected void quadSortSwap(int[] array, int[] swap, int start, int length) { if(length < 16) { this.tailSwap(array, start, length); } - + else if(length < 256) { if(this.quadSwap(array, start, length) == 0) this.tailMerge(array, swap, start, length, 16); } - + else { if(this.quadSwap(array, start, length) == 0) this.quadMerge(array, swap, start, length, 16); diff --git a/src/sorts/templates/ShatterSorting.java b/src/main/java/io/github/arrayv/sorts/templates/ShatterSorting.java similarity index 93% rename from src/sorts/templates/ShatterSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/ShatterSorting.java index 3d35f857..7da06c02 100644 --- a/src/sorts/templates/ShatterSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/ShatterSorting.java @@ -1,11 +1,11 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; import java.util.ArrayList; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -35,34 +35,34 @@ public abstract class ShatterSorting extends Sort { protected ShatterSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected void shatterPartition(int[] array, int length, int num) { int shatters = (int) Math.ceil(length / (double) num); - + @SuppressWarnings("unchecked") ArrayList[] registers = new ArrayList[shatters]; - + for(int i = 0; i < shatters; i++) { registers[i] = new ArrayList<>(); } - + for(int i = 0; i < length; i++){ Writes.arrayListAdd(registers[array[i] / num], array[i]); Highlights.markArray(1, i); - + Writes.mockWrite(length, array[i] / num, array[i], 0.5); } - + Writes.transcribe(array, registers, 0, true, false); Writes.deleteExternalArray(registers); } - + protected void shatterSort(int[] array, int length, int num) { int shatters = (int) Math.ceil(length / (double) num); - + shatterPartition(array, length, num); - + int[] tmp = Writes.createExternalArray(num); for(int i = 0; i < shatters; i++) { for(int j = 0; j < num; j++) { @@ -70,33 +70,33 @@ protected void shatterSort(int[] array, int length, int num) { Writes.write(tmp, j, -1, 0.5, false, true); else Writes.write(tmp, j, array[i * num + j], 0.5, false, true); - + Highlights.markArray(2, i * num + j); } - + Highlights.clearMark(2); - + for(int j = 0; j < tmp.length; j++) { int tmpj = tmp[j]; - + if(i * num + (tmpj % num) >= length || tmpj == -1) { break; } - + Writes.write(array, i * num + (tmpj % num), tmpj, 1, false, false); Highlights.markArray(1, i * num + (tmpj % num)); } - + Highlights.clearMark(1); } Writes.deleteExternalArray(tmp); } - + protected void simpleShatterSort(int[] array, int length, int num, int rate) { for(int i = num; i > 1; i = i / rate) { shatterPartition(array, length, i); } shatterPartition(array, length, 1); } -} \ No newline at end of file +} diff --git a/src/sorts/templates/ShellSorting.java b/src/main/java/io/github/arrayv/sorts/templates/ShellSorting.java similarity index 94% rename from src/sorts/templates/ShellSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/ShellSorting.java index 74529835..09e7a5ea 100644 --- a/src/sorts/templates/ShellSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/ShellSorting.java @@ -1,6 +1,6 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; // Shell sort variant retrieved from: // https://www.cs.princeton.edu/~rs/talks/shellsort.ps @@ -26,16 +26,16 @@ public abstract class ShellSorting extends Sort { protected ShellSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + protected void shellSort(int[] array, int length) { int incs[] = ExtendedCiuraGaps; - + for (int k = 0; k < incs.length; k++) { if(incs == PowersOfThreeGaps) { if(incs[k] < length/3) { for (int h = incs[k], i = h; i < length; i++) { //ArrayVisualizer.setCurrentGap(incs[k]); - + int v = array[i]; int j = i; @@ -46,9 +46,9 @@ protected void shellSort(int[] array, int length) { { Writes.write(array, j, array[j - h], 1, false, false); j -= h; - + Highlights.markArray(1, j); - + if(j - h >= 0) { Highlights.markArray(2, j - h); } @@ -57,14 +57,14 @@ protected void shellSort(int[] array, int length) { } } Writes.write(array, j, v, 1, true, false); - } + } } } else { if(incs[k] < length) { for (int h = incs[k], i = h; i < length; i++) { //ArrayVisualizer.setCurrentGap(incs[k]); - + int v = array[i]; int j = i; @@ -75,9 +75,9 @@ protected void shellSort(int[] array, int length) { { Writes.write(array, j, array[j - h], 1, false, false); j -= h; - + Highlights.markArray(1, j); - + if(j - h >= 0) { Highlights.markArray(2, j - h); } @@ -104,7 +104,7 @@ protected void quickShellSort(int[] array, int lo, int hi) { while (j >= h && Reads.compareValues(array[j-h], v) == 1) { Highlights.markArray(1, j); - + Writes.write(array, j, array[j - h], 1, true, false); j -= h; } @@ -112,4 +112,4 @@ protected void quickShellSort(int[] array, int lo, int hi) { } } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/sorts/templates/Sort.java b/src/main/java/io/github/arrayv/sorts/templates/Sort.java new file mode 100644 index 00000000..33dbbe19 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/templates/Sort.java @@ -0,0 +1,283 @@ +package io.github.arrayv.sorts.templates; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Delays; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Reads; +import io.github.arrayv.utils.Writes; +import io.github.arrayv.sortdata.SortMeta; + +public abstract class Sort { + private Object[] deprecatedMetadataTable = null; + + protected ArrayVisualizer arrayVisualizer; + + protected Delays Delays; + protected Highlights Highlights; + protected Reads Reads; + protected Writes Writes; + + protected Sort(ArrayVisualizer arrayVisualizer) { + this.arrayVisualizer = arrayVisualizer; + + this.Delays = arrayVisualizer.getDelays(); + this.Highlights = arrayVisualizer.getHighlights(); + this.Reads = arrayVisualizer.getReads(); + this.Writes = arrayVisualizer.getWrites(); + } + + private void initDeprecatedMetadataTable() { + if (deprecatedMetadataTable != null) return; + deprecatedMetadataTable = new Object[] { + true, "", "", "", "", false, false, false, 0, null, 0 + }; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public boolean isFromExtraSorts() { + return arrayVisualizer.getSortAnalyzer().didSortComeFromExtra(getClass()); + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public boolean isSortEnabled() { + initDeprecatedMetadataTable(); + return (boolean)deprecatedMetadataTable[0]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public String getSortListName() { + initDeprecatedMetadataTable(); + return (String)deprecatedMetadataTable[1]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public String getRunAllSortsName() { + initDeprecatedMetadataTable(); + return (String)deprecatedMetadataTable[2]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public String getRunSortName() { + initDeprecatedMetadataTable(); + return (String)deprecatedMetadataTable[3]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public String getCategory() { + initDeprecatedMetadataTable(); + return (String)deprecatedMetadataTable[4]; + } + + /** + * Whether this sort is a comparison sort or a distribution sort + * @deprecated This method now always returns false, as this information is no longer stored + * @return false + */ + @Deprecated + public boolean isComparisonBased() { + return false; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public boolean usesBuckets() { + initDeprecatedMetadataTable(); + return (boolean)deprecatedMetadataTable[5]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public boolean isRadixSort() { + initDeprecatedMetadataTable(); + return (boolean)deprecatedMetadataTable[6]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public boolean isUnreasonablySlow() { + initDeprecatedMetadataTable(); + return (int)deprecatedMetadataTable[8] > 0; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public int getUnreasonableLimit() { + initDeprecatedMetadataTable(); + return (int)deprecatedMetadataTable[8]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public boolean isBogoSort() { + initDeprecatedMetadataTable(); + return (boolean)deprecatedMetadataTable[7]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public String getQuestion() { + initDeprecatedMetadataTable(); + return (String)deprecatedMetadataTable[9]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public int getDefaultAnswer() { + initDeprecatedMetadataTable(); + return (int)deprecatedMetadataTable[10]; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void enableSort(boolean enabled) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[0] = enabled; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setSortListName(String listName) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[1] = listName; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setRunAllSortsName(String showcaseName) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[2] = showcaseName; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setRunSortName(String runName) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[3] = runName; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setCategory(String category) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[4] = category; + } + + /** + * Sets whether this sort is a comparison sort or a distribution sort + * @deprecated This method doesn't do anything, as this information is no longer stored + * @param comparisonBased Whether this sort is a comparison sort or a distribution sort + */ + @Deprecated + public void setComparisonBased(boolean comparisonBased) { + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public void setBucketSort(boolean bucketSort) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[5] = bucketSort; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setRadixSort(boolean radixSort) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[6] = radixSort; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. This method also no longer does anything. + */ + @Deprecated + public void setUnreasonablySlow(boolean unreasonableSlow) { + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + public void setUnreasonableLimit(int unreasonableLimit) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[8] = unreasonableLimit; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setBogoSort(boolean bogoSort) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[7] = bogoSort; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setQuestion(String question) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[9] = question; + } + + /** + * @deprecated Please move to the new {@link SortMeta} API. + */ + @Deprecated + protected void setQuestion(String question, int defaultAnswer) { + initDeprecatedMetadataTable(); + deprecatedMetadataTable[9] = question; + deprecatedMetadataTable[10] = defaultAnswer; + } + + public static int validateAnswer(int answer) { + return answer; + } + + public abstract void runSort(int[] array, int sortLength, int bucketCount) throws Exception; //bucketCount will be zero for comparison-based sorts +} diff --git a/src/sorts/templates/TimSorting.java b/src/main/java/io/github/arrayv/sorts/templates/TimSorting.java similarity index 95% rename from src/sorts/templates/TimSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/TimSorting.java index 358db1af..12737237 100644 --- a/src/sorts/templates/TimSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/TimSorting.java @@ -1,10 +1,10 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import utils.Delays; -import utils.Highlights; -import utils.Reads; -import utils.Writes; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Delays; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Reads; +import io.github.arrayv.utils.Writes; /* * Copyright (C) 2008 The Android Open Source Project @@ -52,18 +52,18 @@ * (privately) instantiable; a TimSort instance holds the state of an ongoing * sort, assuming the input array is large enough to warrant the full-blown * TimSort. Small arrays are sorted in place, using a binary insertion sort. - * + * * @author Josh Bloch - * + * * Tailored to ArrayVisualizer by MusicTheorist */ -final public class TimSorting { +public final class TimSorting { private Delays Delays; private Highlights Highlights; private Reads Reads; private Writes Writes; - + /** * This is the minimum sized sequence that will be merged. Shorter * sequences will be lengthened by calling binarySort. If the entire @@ -126,18 +126,18 @@ final public class TimSorting { private int stackSize = 0; // Number of pending runs on stack private final int[] runBase; private final int[] runLen; - + public static int getMinRun() { return TimSorting.MIN_MERGE / 2; } - - // Easy patch for preventing gallop and merge methods from going out-of-bounds + + // Easy patch for preventing gallop and merge methods from going out-of-bounds private void markArray(int marker, int markPosition) { if(markPosition >= 0 && markPosition < this.len) { this.Highlights.markArray(marker, markPosition); } } - + /** * Creates a TimSort instance to maintain the state of an ongoing sort. * @@ -146,12 +146,12 @@ private void markArray(int marker, int markPosition) { public TimSorting(int[] a, int currentLen, ArrayVisualizer arrayVisualizer) { this.a = a; this.len = currentLen; - + this.Delays = arrayVisualizer.getDelays(); this.Highlights = arrayVisualizer.getHighlights(); this.Reads = arrayVisualizer.getReads(); this.Writes = arrayVisualizer.getWrites(); - + // Allocate temp storage (which may be increased later if necessary) int[] newArray = Writes.createExternalArray(this.len < 2 * INITIAL_TMP_STORAGE_LENGTH ? this.len >>> 1 : INITIAL_TMP_STORAGE_LENGTH); @@ -172,7 +172,7 @@ public TimSorting(int[] a, int currentLen, ArrayVisualizer arrayVisualizer) { this.runBase = Writes.createExternalArray(stackLen); this.runLen = Writes.createExternalArray(stackLen); } - + public void customSort(int[] a, int start, int length) { TimSorting.sort(this, a, start, length); this.Writes.deleteExternalArray(this.tmp); @@ -193,7 +193,7 @@ public static void sort(TimSorting timSort, int[] a, int length) { } static void sort(TimSorting timSort, int[] a, int lo, int hi) { TimSorting ts = timSort; - + int nRemaining = hi - lo; // If array is small, do a "mini-TimSort" with no merges if (nRemaining < MIN_MERGE) { @@ -210,26 +210,26 @@ static void sort(TimSorting timSort, int[] a, int lo, int hi) { do { // Identify next run int runLen = countRunAndMakeAscending(ts, a, lo, hi); - + // If run is short, extend to min(minRun, nRemaining) if (runLen < minRun) { int force = nRemaining <= minRun ? nRemaining : minRun; - binarySort(ts, a, lo, lo + force, lo + runLen); + binarySort(ts, a, lo, lo + force, lo + runLen); runLen = force; } // Push run onto pending-run stack, and maybe merge ts.pushRun(lo, runLen); ts.mergeCollapse(); - + // Advance to find next run lo += runLen; nRemaining -= runLen; } while (nRemaining != 0); - + // Merge all remaining runs to complete sort ts.mergeForceCollapse(); } - + /** * Sorts the specified portion of the specified array using a binary * insertion sort. This is the best method for sorting small numbers @@ -248,22 +248,22 @@ static void sort(TimSorting timSort, int[] a, int lo, int hi) { * not already known to be sorted (@code lo <= start <= hi} * @param c comparator to used for the sort */ - + // Here, we do not use the Binary Insertion Sort included in ArrayVisualizer, as TimSort // outfits it with a start index and uses the arraycopy method - + @SuppressWarnings("fallthrough") private static void binarySort(TimSorting ts, int[] a, int lo, int hi, int start) { if (start == lo) start++; - + for ( ; start < hi; start++) { int pivot = a[start]; - + // Set left (and right) to the index where a[start] (pivot) belongs int left = lo; int right = start; - + /* * Invariants: * pivot >= all in [lo, left). @@ -272,13 +272,13 @@ private static void binarySort(TimSorting ts, int[] a, int lo, int hi, int start while (left < right) { // Another good way to prevent integer overflow with left + right! int mid = (left + right) >>> 1; - + if (ts.Reads.compareValues(pivot, a[mid]) < 0) right = mid; else left = mid + 1; } - + /* * The invariants still hold: pivot >= all in [lo, left) and * pivot < all in [left, start), so pivot belongs at left. Note @@ -289,15 +289,15 @@ private static void binarySort(TimSorting ts, int[] a, int lo, int hi, int start int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case switch(n) { - case 2: ts.Writes.write(a, left + 2, a[left + 1], 1, true, false); + case 2: ts.Writes.write(a, left + 2, a[left + 1], 1, true, false); case 1: ts.Writes.write(a, left + 1, a[left], 1, true, false); break; - default: ts.Writes.reversearraycopy(a, left, a, left + 1, n, 1, true, false); + default: ts.Writes.arraycopy(a, left, a, left + 1, n, 1, true, false); } ts.Writes.write(a, left, pivot, 1, true, false); } } - + /** * Returns the length of the run beginning at the specified position in * the specified array and reverses the run if it is descending (ensuring @@ -327,7 +327,7 @@ private static int countRunAndMakeAscending(TimSorting ts, int[] a, int lo, int int runHi = lo + 1; if (runHi == hi) return 1; - + // Find end of run, and reverse range if descending if (ts.Reads.compareValues(a[runHi++], a[lo]) < 0) { // Descending while(runHi < hi && ts.Reads.compareValues(a[runHi], a[runHi - 1]) < 0) { @@ -345,7 +345,7 @@ private static int countRunAndMakeAscending(TimSorting ts, int[] a, int lo, int } return runHi - lo; } - + /** * Reverse the specified range of the specified array. * @@ -357,7 +357,7 @@ private static void reverseRange(TimSorting ts, int[] a, int lo, int hi) { ts.Writes.reversal(a, lo, hi - 1, 1, true, false); ts.Highlights.clearMark(2); } - + /** * Returns the minimum acceptable run length for an array of the specified * length. Natural runs shorter than this will be extended with @@ -383,7 +383,7 @@ public static int minRunLength(int n) { } return n + r; } - + /** * Pushes the specified run onto the pending-run stack. * @@ -395,7 +395,7 @@ private void pushRun(int runBase, int runLen) { this.runLen[this.stackSize] = runLen; this.stackSize++; } - + /** * Examines the stack of runs waiting to be merged and merges adjacent runs * until the stack invariants are reestablished: @@ -406,7 +406,7 @@ private void pushRun(int runBase, int runLen) { * This method is called each time a new run is pushed onto the stack, * so the invariants are guaranteed to hold for i < stackSize upon * entry to the method. - * + * * Thanks to Stijn de Gouw, Jurriaan Rot, Frank S. de Boer, * Richard Bubel and Reiner Hahnle, this is fixed with respect to * the analysis in "On the Worst-Case Complexity of TimSort" by @@ -425,7 +425,7 @@ private void mergeCollapse() { mergeAt(n); } } - + /** * Merges all runs on the stack until only one remains. This method is * called once, to complete the sort. @@ -438,7 +438,7 @@ private void mergeForceCollapse() { mergeAt(n); } } - + /** * Merges the two runs at stack indices i and i+1. Run i must be * the penultimate or antepenultimate run on the stack. In other words, @@ -449,12 +449,12 @@ private void mergeForceCollapse() { private void mergeAt(int i) { this.Highlights.clearMark(1); this.Highlights.clearMark(2); - + int base1 = this.runBase[i]; int len1 = this.runLen[i]; int base2 = this.runBase[i + 1]; int len2 = this.runLen[i + 1]; - + /* * Record the length of the combined runs; if i is the 3rd-last * run now, also slide over the last run (which isn't involved @@ -466,7 +466,7 @@ private void mergeAt(int i) { this.runLen[i + 1] = this.runLen[i + 2]; } this.stackSize--; - + /* * Find where the first element of run2 goes in run1. Prior elements * in run1 can be ignored (because they're already in place). @@ -476,7 +476,7 @@ private void mergeAt(int i) { len1 -= k; if (len1 == 0) return; - + /* * Find where the last element of run1 goes in run2. Subsequent elements * in run2 can be ignored (because they're already in place). @@ -484,17 +484,17 @@ private void mergeAt(int i) { len2 = gallopLeft(this, this.a[base1 + len1 - 1], this.a, base2, len2, len2 - 1); if (len2 == 0) return; - + // Merge remaining runs, using tmp array with min(len1, len2) elements if (len1 <= len2) mergeLo(this, base1, len1, base2, len2); else mergeHi(this, base1, len1, base2, len2); - + this.Highlights.clearMark(1); this.Highlights.clearMark(2); } - + /** * Locates the position at which to insert the specified key into the * specified sorted range; if the range contains an element equal to key, @@ -516,57 +516,57 @@ private void mergeAt(int i) { private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len, int hint) { int lastOfs = 0; int ofs = 1; - + ts.markArray(3, base + hint); ts.Delays.sleep(1); - + if (ts.Reads.compareValues(key, a[base + hint]) > 0) { // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] int maxOfs = len - hint; - + ts.markArray(3, base + hint + ofs); ts.Delays.sleep(1); - - while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint + ofs]) > 0) { + + while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint + ofs]) > 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; if (ofs <= 0) // int overflow ofs = maxOfs; - + ts.markArray(3, base + hint + ofs); ts.Delays.sleep(1); } if (ofs > maxOfs) ofs = maxOfs; - + // Make offsets relative to base lastOfs += hint; ofs += hint; } else { // key <= a[base + hint] // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] final int maxOfs = hint + 1; - + ts.markArray(3, base + hint - ofs); ts.Delays.sleep(1); - + while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint - ofs]) <= 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; if (ofs <= 0) // int overflow ofs = maxOfs; - + ts.markArray(3, base + hint - ofs); ts.Delays.sleep(1); } if (ofs > maxOfs) ofs = maxOfs; - + // Make offsets relative to base int tmp = lastOfs; lastOfs = hint - ofs; ofs = hint - tmp; } - + /* * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere * to the right of lastOfs but no farther right than ofs. Do a binary @@ -575,10 +575,10 @@ private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len lastOfs++; while (lastOfs < ofs) { int m = lastOfs + ((ofs - lastOfs) >>> 1); - + ts.markArray(3, base + m); ts.Delays.sleep(1); - + if (ts.Reads.compareValues(key, a[base + m]) > 0) lastOfs = m + 1; // a[base + m] < key else @@ -603,29 +603,29 @@ private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len private static int gallopRight(TimSorting ts, int key, int[] a, int base, int len, int hint) { int ofs = 1; int lastOfs = 0; - + ts.markArray(3, base + hint); ts.Delays.sleep(1); - + if (ts.Reads.compareValues(key, a[base + hint]) < 0) { // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] int maxOfs = hint + 1; - + ts.markArray(3, base + hint - ofs); ts.Delays.sleep(1); - + while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint - ofs]) < 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; if (ofs <= 0) // int overflow ofs = maxOfs; - + ts.markArray(3, base + hint - ofs); ts.Delays.sleep(1); } if (ofs > maxOfs) ofs = maxOfs; - + // Make offsets relative to b int tmp = lastOfs; lastOfs = hint - ofs; @@ -633,27 +633,27 @@ private static int gallopRight(TimSorting ts, int key, int[] a, int base, int le } else { // a[b + hint] <= key // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] int maxOfs = len - hint; - + ts.markArray(3, base + hint + ofs); ts.Delays.sleep(1); - + while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint + ofs]) >= 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; if (ofs <= 0) // int overflow ofs = maxOfs; - + ts.markArray(3, base + hint + ofs); ts.Delays.sleep(1); } if (ofs > maxOfs) ofs = maxOfs; - + // Make offsets relative to b lastOfs += hint; ofs += hint; } - + /* * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to * the right of lastOfs but no farther right than ofs. Do a binary @@ -662,10 +662,10 @@ private static int gallopRight(TimSorting ts, int key, int[] a, int base, int le lastOfs++; while (lastOfs < ofs) { int m = lastOfs + ((ofs - lastOfs) >>> 1); - + ts.markArray(3, base + m); ts.Delays.sleep(1); - + if (ts.Reads.compareValues(key, a[base + m]) < 0) ofs = m; // key < a[b + m] else @@ -695,11 +695,11 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { int[] a = ts.a; // For performance int[] tmp = ensureCapacity(len1); ts.Writes.arraycopy(a, base1, tmp, 0, len1, 1, true, true); - + int cursor1 = 0; // Indexes into tmp array int cursor2 = base2; // Indexes int a int dest = base1; // Indexes int a - + // Move first element of second run and deal with degenerate cases ts.Writes.write(a, dest++, a[cursor2++], 1, false, false); ts.markArray(1, dest); @@ -714,7 +714,7 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { ts.markArray(1, dest + len2); return; } - + int minGallop = ts.minGallop; // " " " " " outer: while (true) { @@ -742,7 +742,7 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { break outer; } } while ((count1 | count2) < minGallop); - + /* * One run is winning so consistently that galloping may be a * huge win. So try that, and continue galloping until (if ever) @@ -763,7 +763,7 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { ts.markArray(2, cursor2); if (--len2 == 0) break outer; - + count2 = gallopLeft(ts, tmp[cursor1], a, cursor2, len2, 0); if (count2 != 0) { ts.Writes.arraycopy(a, cursor2, a, dest, count2, 1, true, false); @@ -784,7 +784,7 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { minGallop += 2; // Penalize for leaving gallop mode } // End of "outer" loop ts.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field - + if (len1 == 1) { ts.Writes.arraycopy(a, cursor2, a, dest, len2, 1, true, false); ts.Writes.write(a, dest + len2, tmp[cursor1], 1, false, false); // Last elt of run 1 to end of merge @@ -796,7 +796,7 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { ts.Writes.arraycopy(tmp, cursor1, a, dest, len1, 1, true, false); } } - + /** * Like mergeLo, except that this method should be called only if * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method @@ -813,34 +813,34 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { int[] a = ts.a; // For performance int[] tmp = ensureCapacity(len2); ts.Writes.arraycopy(a, base2, tmp, 0, len2, 1, true, true); - + int cursor1 = base1 + len1 - 1; // Indexes into a int cursor2 = len2 - 1; // Indexes into tmp array int dest = base2 + len2 - 1; // Indexes into a - + // Move last element of first run and deal with degenerate cases ts.Writes.write(a, dest--, a[cursor1--], 1, false, false); ts.markArray(1, dest); ts.markArray(2, cursor1); if (--len1 == 0) { - ts.Writes.reversearraycopy(tmp, 0, a, dest - (len2 - 1), len2, 1, true, false); + ts.Writes.arraycopy(tmp, 0, a, dest - (len2 - 1), len2, 1, true, false); return; } if (len2 == 1) { dest -= len1; cursor1 -= len1; - ts.Writes.reversearraycopy(a, cursor1 + 1, a, dest + 1, len1, 1, true, false); + ts.Writes.arraycopy(a, cursor1 + 1, a, dest + 1, len1, 1, true, false); ts.Writes.write(a, dest, tmp[cursor2], 1, false, false); ts.markArray(1, dest); return; } - + int minGallop = ts.minGallop; // " " " " " outer: while (true) { int count1 = 0; // Number of times in a row that first run won int count2 = 0; // Number of times in a row that second run won - + /* * Do the straightforward thing until (if ever) one run * appears to win consistently. @@ -863,7 +863,7 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { break outer; } } while ((count1 | count2) < minGallop); - + /* * One run is winning so consistently that galloping may be a * huge win. So try that, and continue galloping until (if ever) @@ -875,7 +875,7 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { dest -= count1; cursor1 -= count1; len1 -= count1; - ts.Writes.reversearraycopy(a, cursor1 + 1, a, dest + 1, count1, 1, true, false); + ts.Writes.arraycopy(a, cursor1 + 1, a, dest + 1, count1, 1, true, false); if (len1 == 0) break outer; } @@ -883,13 +883,13 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { ts.markArray(1, dest); if (--len2 == 1) break outer; - + count2 = len2 - gallopLeft(ts, a[cursor1], tmp, 0, len2, len2 - 1); if (count2 != 0) { dest -= count2; cursor2 -= count2; len2 -= count2; - ts.Writes.reversearraycopy(tmp, cursor2 + 1, a, dest + 1, count2, 1, true, false); + ts.Writes.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2, 1, true, false); if (len2 <= 1) // len2 == 1 || len2 == 0 break outer; } @@ -905,18 +905,18 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { minGallop += 2; // Penalize for leaving gallop mode } // End of "outer" loop ts.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field - + if (len2 == 1) { dest -= len1; cursor1 -= len1; - ts.Writes.reversearraycopy(a, cursor1 + 1, a, dest + 1, len1, 1, true, false); + ts.Writes.arraycopy(a, cursor1 + 1, a, dest + 1, len1, 1, true, false); ts.Writes.write(a, dest, tmp[cursor2], 1, false, false); // Move first elt of run2 to front of merge ts.markArray(1, dest); } else if (len2 == 0) { throw new IllegalArgumentException( "Comparison method violates its general contract!"); } else { - ts.Writes.reversearraycopy(tmp, 0, a, dest - (len2 - 1), len2, 1, true, false); + ts.Writes.arraycopy(tmp, 0, a, dest - (len2 - 1), len2, 1, true, false); } } /** @@ -947,4 +947,4 @@ private int[] ensureCapacity(int minCapacity) { } return this.tmp; } -} \ No newline at end of file +} diff --git a/src/sorts/templates/TwinSorting.java b/src/main/java/io/github/arrayv/sorts/templates/TwinSorting.java similarity index 97% rename from src/sorts/templates/TwinSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/TwinSorting.java index 17bfa764..e1547f7c 100644 --- a/src/sorts/templates/TwinSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/TwinSorting.java @@ -1,6 +1,6 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; /* Copyright (C) 2014-2021 Igor van den Hoven ivdhoven@gmail.com @@ -28,7 +28,7 @@ a copy of this software and associated documentation files (the CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - + Ported to arrayV by mg-2018, 2021 */ @@ -40,7 +40,7 @@ public abstract class TwinSorting extends Sort { public TwinSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + // nmemb = item count private int twinSwap(int[] array, int left, int nmemb) { int index, start, end; @@ -53,7 +53,7 @@ private int twinSwap(int[] array, int left, int nmemb) { index += 2; continue; } - + start = index; index += 2; @@ -67,7 +67,7 @@ private int twinSwap(int[] array, int left, int nmemb) { while (start < end) Writes.swap(array, (start++)+left, (end--)+left, 1, true, false); - + return 1; } } @@ -90,14 +90,14 @@ private int twinSwap(int[] array, int left, int nmemb) { Writes.changeReversals(1); while (start < end) Writes.swap(array, (start++)+left, (end--)+left, 1, true, false); - + end = nmemb - 2; index += 2; } return 0; } - + // Bottom up merge sort. It copies the right block to swap, next merges // starting at the tail ends of the two sorted blocks. // Can be used stand alone. Uses at most nmemb / 2 swap memory. @@ -120,7 +120,7 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) c_max = s + block; d_max = a + block * 2; } - + else { c_max = s + nmemb - (offset + block); d_max = 0 + nmemb; @@ -157,12 +157,12 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) Highlights.markArray(2, c+left+offset); Writes.write(array, (e--)+left, array[(d--)+left], 1, true, false); } - + Highlights.markArray(2, c+left+offset); Writes.write(array, (e--)+left, swap[c--], 1, true, false); } } - + else { Highlights.clearMark(2); Writes.write(array, (e--)+left, array[(d--)+left], 1, true, false); @@ -173,37 +173,37 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) Highlights.markArray(2, c+left+offset); Writes.write(array, (e--)+left, swap[c--], 1, true, false); } - + Writes.write(array, (e--)+left, array[(d--)+left], 1, true, false); } - + while(c >= s) { Highlights.markArray(2, c+left+offset); Writes.write(array, (e--)+left, swap[c--], 1, true, false); } - + } } block *= 2; } } - + protected void twinsortSwap(int[] array, int start, int[] swap, int nmemb) { if(twinSwap(array, start, nmemb) == 0) tailMerge(array, start, swap, nmemb, 2); } - + public void twinsort(int[] array, int nmemb) { if(twinSwap(array, 0, nmemb) == 0) { int[] swap = Writes.createExternalArray(nmemb/2); tailMerge(array, 0, swap, nmemb, 2); - + Writes.deleteExternalArray(swap); } } - + public void tailsort(int[] array, int nmemb) { if(nmemb < 2) @@ -211,7 +211,7 @@ public void tailsort(int[] array, int nmemb) int[] swap = Writes.createExternalArray(nmemb/2); tailMerge(array, 0, swap, nmemb, 1); - + Writes.deleteExternalArray(swap); } -} \ No newline at end of file +} diff --git a/src/sorts/templates/UnstableGrailSorting.java b/src/main/java/io/github/arrayv/sorts/templates/UnstableGrailSorting.java similarity index 97% rename from src/sorts/templates/UnstableGrailSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/UnstableGrailSorting.java index 5e91f2d3..2a2aaab5 100644 --- a/src/sorts/templates/UnstableGrailSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/UnstableGrailSorting.java @@ -1,10 +1,10 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import sorts.exchange.OptimizedGnomeSort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.exchange.OptimizedGnomeSort; /* - * + * The MIT License (MIT) Copyright (c) 2013 Andrey Astrelin @@ -49,29 +49,29 @@ this software and associated documentation files (the "Software"), to deal in public abstract class UnstableGrailSorting extends Sort { private OptimizedGnomeSort grailInsertSorter; - + protected UnstableGrailSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - + private void grailSwap(int[] arr, int a, int b) { Writes.swap(arr, a, b, 1, true, false); } - - private void grailMultiSwap(int[] arr, int a, int b, int swapsLeft) { - while(swapsLeft != 0) { + + private void grailMultiSwap(int[] arr, int a, int b, int swapsLeft) { + while(swapsLeft != 0) { this.grailSwap(arr, a++, b++); swapsLeft--; } } - + protected void grailRotate(int[] array, int pos, int lenA, int lenB) { while(lenA != 0 && lenB != 0) { if(lenA <= lenB) { this.grailMultiSwap(array, pos, pos + lenA, lenA); pos += lenA; lenB -= lenA; - } + } else { this.grailMultiSwap(array, pos + (lenA - lenB), pos + lenA, lenB); lenA -= lenB; @@ -163,12 +163,12 @@ private void grailMergeBuffersLeft(int[] arr, int pos, int blockCount, int block if(lastLen != 0) { leftOverLen += blockLen * aBlockCount; this.grailMergeLeft(arr, pos + restToProcess, leftOverLen, lastLen, -blockLen); - + } else { this.grailMultiSwap(arr, pos + restToProcess, pos + (restToProcess - blockLen), leftOverLen); } } - + // arr[dist..-1] - buffer, arr[0, leftLen - 1] ++ arr[leftLen, leftLen + rightLen - 1] // -> arr[dist, dist + leftLen + rightLen - 1] private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int dist) { @@ -180,14 +180,14 @@ private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int d while(right < rightLen) { if(left == leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (dist++), pos + (right++)); - } - else this.grailSwap(arr, pos + (dist++), pos + (left++)); + } + else this.grailSwap(arr, pos + (dist++), pos + (left++)); Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - + if(dist != left) this.grailMultiSwap(arr, pos + dist, pos + left, leftLen - left); } private void grailMergeRight(int[] arr, int pos, int leftLen, int rightLen, int dist) { @@ -198,14 +198,14 @@ private void grailMergeRight(int[] arr, int pos, int leftLen, int rightLen, int while(left >= 0) { if(right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (mergedPos--), pos + (left--)); - } + } else this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); if(pos + left >= 0) Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - + if(right != mergedPos) { while(right >= leftLen) this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); } @@ -225,7 +225,7 @@ private int grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, int b } Highlights.clearMark(3); Highlights.clearMark(4); - + int length; if(left < leftEnd) { length = leftEnd - left; @@ -330,12 +330,12 @@ private void grailCombineBlocks(int[] arr, int pos, int len, int buildLen, int r protected void grailCommonSort(int[] arr, int pos, int len) { this.grailInsertSorter = new OptimizedGnomeSort(this.arrayVisualizer); - + if(len <= 16) { this.grailInsertSort(arr, pos, len); return; } - + int blockLen = 1; while(blockLen * blockLen < len) blockLen *= 2; int buildLen = blockLen; @@ -345,11 +345,11 @@ protected void grailCommonSort(int[] arr, int pos, int len) { // 2 * buildLen are built while(len - blockLen > (buildLen *= 2)) { this.grailCombineBlocks(arr, pos + blockLen, len - blockLen, buildLen, blockLen); - + Highlights.clearMark(2); } this.grailInsertSort(arr, pos, blockLen); this.grailMergeWithoutBuffer(arr, pos, blockLen, len - blockLen); } -} \ No newline at end of file +} diff --git a/src/sorts/templates/WikiSorting.java b/src/main/java/io/github/arrayv/sorts/templates/WikiSorting.java similarity index 96% rename from src/sorts/templates/WikiSorting.java rename to src/main/java/io/github/arrayv/sorts/templates/WikiSorting.java index e0e1054f..0cec6df4 100644 --- a/src/sorts/templates/WikiSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/WikiSorting.java @@ -1,14 +1,14 @@ -package sorts.templates; +package io.github.arrayv.sorts.templates; -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import utils.Delays; -import utils.Highlights; -import utils.Reads; -import utils.Writes; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.insert.InsertionSort; +import io.github.arrayv.utils.Delays; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Reads; +import io.github.arrayv.utils.Writes; /* - * + * This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or @@ -64,11 +64,11 @@ int length() { final class Pull { public int from, to, count; public Range range; - + public Pull() { this.range = new Range(0, 0); } - + void reset() { this.range.set(0, 0); this.from = 0; @@ -143,48 +143,48 @@ int length() { } } -final public class WikiSorting { +public final class WikiSorting { // use a small cache to speed up some of the operations // since the cache size is fixed, it's still O(1) memory! // just keep in mind that making it too small ruins the point (nothing will fit into it), // and making it too large also ruins the point (so much for "low memory"!) private InsertionSort InsertSort; - + private Delays Delays; private Highlights Highlights; private Reads Reads; private Writes Writes; - + private static int cache_size = 0; private int[] cache; // note that you can easily modify the above to allocate a dynamically sized cache // good choices for the cache size are: - + // (size + 1)/2 – turns into a full-speed standard merge sort since everything fits into the cache // sqrt((size + 1)/2) + 1 – this will be the size of the A blocks at the largest level of merges, // so a buffer of this size would allow it to skip using internal or in-place merges for anything - + // Original static buffer = 512 – chosen from careful testing as a good balance between fixed-size memory use and run time // ArrayVisualizer static buffer = 32, as the numbers of items we use for visual purposes is relatively small - + // 0 – if the system simply cannot allocate any extra memory whatsoever, no memory works just fine - + public WikiSorting(InsertionSort insertionSort, ArrayVisualizer arrayVisualizer, int cacheChoice) { this.InsertSort = insertionSort; - + this.Delays = arrayVisualizer.getDelays(); this.Highlights = arrayVisualizer.getHighlights(); this.Reads = arrayVisualizer.getReads(); this.Writes = arrayVisualizer.getWrites(); - + cache_size = cacheChoice; - + if(cache_size != 0) this.cache = Writes.createExternalArray(cache_size); else this.cache = null; } - + public static void sort(WikiSorting WikiSort, int[] array, int currentLen) { WikiSort.Sort(array, currentLen); if (WikiSort.cache != null) WikiSort.Writes.deleteExternalArray(WikiSort.cache); @@ -311,9 +311,9 @@ void Rotate(int[] array, int amount, Range range, boolean use_cache) { } else { if (range2.length() <= cache_size) { if (cache != null) { - Writes.reversearraycopy(array, range2.start, cache, 0, range2.length(), 1, true, true); - Writes.reversearraycopy(array, range1.start, array, range2.end - range1.length(), range1.length(), 1, true, false); - Writes.reversearraycopy(cache, 0, array, range1.start, range2.length(), 1, true, false); + Writes.arraycopy(array, range2.start, cache, 0, range2.length(), 1, true, true); + Writes.arraycopy(array, range1.start, array, range2.end - range1.length(), range1.length(), 1, true, false); + Writes.arraycopy(cache, 0, array, range1.start, range2.length(), 1, true, false); } return; } @@ -324,20 +324,20 @@ void Rotate(int[] array, int amount, Range range, boolean use_cache) { int lenA = range1.length(); int lenB = range2.length(); int pos = range.start; - + while(lenA != 0 && lenB != 0) { if(lenA <= lenB) { this.BlockSwap(array, pos, pos + lenA, lenA); pos += lenA; lenB -= lenA; - } + } else { this.BlockSwap(array, pos + (lenA - lenB), pos + lenA, lenB); lenA -= lenB; } } */ - + Reverse(array, range1); Reverse(array, range2); Reverse(array, range); @@ -354,10 +354,10 @@ void MergeInto(int[] from, Range A, Range B, int[] into, int at_index, boolean t while (true) { if (Reads.compareValues(from[B_index], from[A_index]) >= 0) { Writes.write(into, insert_index, from[A_index], 1, false, tempwrite); - + if(tempwrite) Highlights.markArray(1, A_index); else Highlights.markArray(1, insert_index); - + A_index++; insert_index++; if (A_index == A_last) { @@ -367,10 +367,10 @@ void MergeInto(int[] from, Range A, Range B, int[] into, int at_index, boolean t } } else { Writes.write(into, insert_index, from[B_index], 1, false, tempwrite); - + if(tempwrite) Highlights.markArray(1, B_index); else Highlights.markArray(1, insert_index); - + B_index++; insert_index++; if (B_index == B_last) { @@ -410,7 +410,7 @@ void MergeExternal(int[] array, Range A, Range B) { } Highlights.clearMark(3); Highlights.clearMark(4); - + // copy the remainder of A into the final array if (cache != null) { Writes.arraycopy(cache, A_index, array, insert_index, A_last - A_index, 1, true, false); @@ -443,7 +443,7 @@ void MergeInternal(int[] array, Range A, Range B, Range buffer) { } } Highlights.clearMark(3); - + // swap the remainder of A into the final array BlockSwap(array, buffer.start + A_count, A.start + insert, A.length() - A_count); } @@ -461,11 +461,11 @@ void MergeInPlace(int[] array, Range A, Range B) { but WikiSort almost always uses subarrays that are roughly the same size) normally this is incredibly suboptimal, but this function is only called - when none of the A or B blocks in any subarray contained 2√A unique values, + when none of the A or B blocks in any subarray contained 2 sqrt(A) unique values, which places a hard limit on the number of times this will ACTUALLY need to binary search and rotate. - according to my analysis the worst case is √A rotations performed on √A items + according to my analysis the worst case is sqrt(A) rotations performed on sqrt(A) items once the constant factors are removed, which ends up being O(n) again, this is NOT a general-purpose solution – it only works well in this case! @@ -620,7 +620,7 @@ void Sort(int[] array, int len) { } else { // if A1, B1, A2, and B2 are all in order, skip doing anything else if (Reads.compareValues(array[B2.start], array[A2.end - 1]) >= 0 && Reads.compareValues(array[A2.start], array[B1.end - 1]) >= 0) continue; - + // copy A1 and B1 into the cache in the same order Writes.arraycopy(array, A1.start, cache, 0, A1.length(), 1, true, true); Writes.arraycopy(array, B1.start, cache, A1.length(), B1.length(), 1, true, true); @@ -682,7 +682,7 @@ void Sort(int[] array, int len) { } } else { // this is where the in-place merge logic starts! - // 1. pull out two internal buffers each containing √A unique values + // 1. pull out two internal buffers each containing sqrt(A) unique values // 1a. adjust block_size and buffer_size if we couldn't find enough unique values // 2. loop over the A and B subarrays within this level of the merge sort // 3. break A and B into blocks of size 'block_size' @@ -718,11 +718,11 @@ void Sort(int[] array, int len) { find_separately = true; } - // we need to find either a single contiguous space containing 2√A unique values (which will be split up into two buffers of size √A each), - // or we need to find one buffer of < 2√A unique values, and a second buffer of √A unique values, + // we need to find either a single contiguous space containing 2 sqrt(A) unique values (which will be split up into two buffers of size sqrt(A) each), + // or we need to find one buffer of < 2 sqrt(A) unique values, and a second buffer of sqrt(A) unique values, // OR if we couldn't find that many unique values, we need the largest possible buffer we can get - // in the case where it couldn't find a single buffer of at least √A unique values, + // in the case where it couldn't find a single buffer of at least sqrt(A) unique values, // all of the Merge steps must be replaced by a different merge algorithm (MergeInPlace) iterator.begin(); @@ -747,14 +747,14 @@ void Sort(int[] array, int len) { pull_index = 1; if (count == buffer_size + buffer_size) { - // we were able to find a single contiguous section containing 2√A unique values, + // we were able to find a single contiguous section containing 2 sqrt(A) unique values, // so this section can be used to contain both of the internal buffers we'll need buffer1.set(A.start, A.start + buffer_size); buffer2.set(A.start + buffer_size, A.start + count); break; } else if (find == buffer_size + buffer_size) { - // we found a buffer that contains at least √A unique values, but did not contain the full 2√A unique values, - // so we still need to find a second separate buffer of at least √A unique values + // we found a buffer that contains at least sqrt(A) unique values, but did not contain the full 2 sqrt(A) unique values, + // so we still need to find a second separate buffer of at least sqrt(A) unique values buffer1.set(A.start, A.start + count); find = buffer_size; } else if (block_size <= cache_size) { @@ -766,7 +766,7 @@ void Sort(int[] array, int len) { buffer1 = new Range(A.start, A.start + count); find_separately = false; } else { - // we found a second buffer in an 'A' subarray containing √A unique values, so we're done! + // we found a second buffer in an 'A' subarray containing sqrt(A) unique values, so we're done! buffer2.set(A.start, A.start + count); break; } @@ -797,14 +797,14 @@ void Sort(int[] array, int len) { pull_index = 1; if (count == buffer_size + buffer_size) { - // we were able to find a single contiguous section containing 2√A unique values, + // we were able to find a single contiguous section containing 2 sqrt(A) unique values, // so this section can be used to contain both of the internal buffers we'll need buffer1.set(B.end - count, B.end - buffer_size); buffer2.set(B.end - buffer_size, B.end); break; } else if (find == buffer_size + buffer_size) { - // we found a buffer that contains at least √A unique values, but did not contain the full 2√A unique values, - // so we still need to find a second separate buffer of at least √A unique values + // we found a buffer that contains at least sqrt(A) unique values, but did not contain the full 2sqrt(A) unique values, + // so we still need to find a second separate buffer of at least sqrt(A) unique values buffer1.set(B.end - count, B.end); find = buffer_size; } else if (block_size <= cache_size) { @@ -820,7 +820,7 @@ void Sort(int[] array, int len) { // we need to adjust the end point for that A subarray so it knows to stop redistributing its values before reaching buffer2 if (pull[0].range.start == A.start) pull[0].range.end -= pull[1].count; - // we found a second buffer in an 'B' subarray containing √A unique values, so we're done! + // we found a second buffer in an 'B' subarray containing sqrt(A) unique values, so we're done! buffer2.set(B.end - count, B.end); break; } @@ -881,7 +881,7 @@ void Sort(int[] array, int len) { A.start += pull[0].count; // if the internal buffer takes up the entire A or B subarray, then there's nothing to merge - // this only happens for very small subarrays, like √4 = 2, 2 * (2 internal buffers) = 4, + // this only happens for very small subarrays, like sqrt(4) = 2, 2 * (2 internal buffers) = 4, // which also only happens when cache_size is small or 0 since it'd otherwise use MergeExternal if (A.length() == 0) continue; } else if (pull[0].from < pull[0].to) { @@ -1025,7 +1025,7 @@ else if (buffer2.length() > 0) } Highlights.clearMark(2); - + // when we're finished with this merge step we should have the one or two internal buffers left over, where the second buffer is all jumbled up // insertion sort the second buffer, then redistribute the buffers back into the array using the opposite process used for creating the buffer @@ -1060,9 +1060,9 @@ else if (buffer2.length() > 0) } } } - + // double the size of each A and B subarray that will be merged in the next level if (!iterator.nextLevel()) break; } } -} \ No newline at end of file +} diff --git a/src/sorts/tests/RotationTest.java b/src/main/java/io/github/arrayv/sorts/tests/RotationTest.java similarity index 80% rename from src/sorts/tests/RotationTest.java rename to src/main/java/io/github/arrayv/sorts/tests/RotationTest.java index e7c0b07a..7054a634 100644 --- a/src/sorts/tests/RotationTest.java +++ b/src/main/java/io/github/arrayv/sorts/tests/RotationTest.java @@ -1,11 +1,12 @@ -package sorts.tests; +package io.github.arrayv.sorts.tests; -import main.ArrayVisualizer; -import sorts.templates.Sort; -import utils.Rotations; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; +import io.github.arrayv.utils.Rotations; /* - * + * The MIT License (MIT) Copyright (c) 2021 ArrayV 4.0 Team @@ -29,28 +30,22 @@ this software and associated documentation files (the "Software"), to deal in * */ -final public class RotationTest extends Sort { +@SortMeta( + listName = "Rotations", + showcaseName = "Rotation Test", + runName = "Rotation Test" +) +public final class RotationTest extends Sort { final double BLOCK_DIV = 6.98; public RotationTest(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Rotations"); - this.setRunAllSortsName("Rotation Test"); - this.setRunSortName("Rotation Test"); - this.setCategory("Tests"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + @Override public void runSort(int[] array, int length, int bucketCount) { int blockSize = (int)(length / BLOCK_DIV); - + for (int i = 0; i < blockSize; i++) { Writes.write(array, i, i + length - blockSize, 0.05, false, false); } diff --git a/src/main/java/io/github/arrayv/sorts/tests/package-info.java b/src/main/java/io/github/arrayv/sorts/tests/package-info.java new file mode 100644 index 00000000..0f359ee4 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/tests/package-info.java @@ -0,0 +1,4 @@ +@io.github.arrayv.sortdata.SortPackageMeta( + category = "Tests" +) +package io.github.arrayv.sorts.tests; diff --git a/src/utils/AntiQSort.java b/src/main/java/io/github/arrayv/utils/AntiQSort.java similarity index 86% rename from src/utils/AntiQSort.java rename to src/main/java/io/github/arrayv/utils/AntiQSort.java index dd327299..4c706e28 100644 --- a/src/utils/AntiQSort.java +++ b/src/main/java/io/github/arrayv/utils/AntiQSort.java @@ -1,9 +1,9 @@ -package utils; +package io.github.arrayv.utils; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; public class AntiQSort { - private ArrayVisualizer arrayVisualizer; + private final ArrayVisualizer arrayVisualizer; private int[] data; private int nmemb; private int gas; @@ -25,13 +25,13 @@ public int compare(int ap, int bp) { a = ap; b = bp; - + if (data[a] == gas && data[b] == gas) if (a == candidate) data[a] = frozen++; else data[b] = frozen++; - + if (data[a] == gas) { candidate = a; return 1; @@ -42,11 +42,7 @@ public int compare(int ap, int bp) { return -1; } - if (data[a] < data[b]) - return -1; - if (data[a] > data[b]) - return 1; - return 0; + return Integer.compare(data[a], data[b]); } public void beginSort(int[] refs, int nmemb) { diff --git a/src/utils/ArrayFileWriter.java b/src/main/java/io/github/arrayv/utils/ArrayFileWriter.java similarity index 85% rename from src/utils/ArrayFileWriter.java rename to src/main/java/io/github/arrayv/utils/ArrayFileWriter.java index 812c18f9..7500d121 100644 --- a/src/utils/ArrayFileWriter.java +++ b/src/main/java/io/github/arrayv/utils/ArrayFileWriter.java @@ -1,18 +1,20 @@ -package utils; +package io.github.arrayv.utils; + +import io.github.arrayv.panes.JErrorPane; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import panes.JErrorPane; - public final class ArrayFileWriter { + private ArrayFileWriter() { + } + public static boolean writeArray(String fileName, int[] array, int length) { try { FileWriter writer = new FileWriter(fileName); write(writer, array, length); - } - catch (IOException e) { + } catch (IOException e) { JErrorPane.invokeErrorMessage(e); return false; } @@ -23,8 +25,7 @@ public static boolean writeArray(File file, int[] array, int length) { try { FileWriter writer = new FileWriter(file); write(writer, array, length); - } - catch (IOException e) { + } catch (IOException e) { JErrorPane.invokeErrorMessage(e); return false; } diff --git a/src/main/java/io/github/arrayv/utils/ArrayVList.java b/src/main/java/io/github/arrayv/utils/ArrayVList.java new file mode 100644 index 00000000..2a3fca30 --- /dev/null +++ b/src/main/java/io/github/arrayv/utils/ArrayVList.java @@ -0,0 +1,466 @@ +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; + +import java.util.*; +import java.util.function.Consumer; + +public class ArrayVList extends AbstractList implements RandomAccess, java.io.Serializable { + private static final int DEFAULT_CAPACITY = 128; + private static final double DEFAULT_GROW_FACTOR = 2; + + private static ArrayVisualizer arrayVisualizer; + // @checkstyle:off StaticVariableNameCheck + private static Reads Reads; + private static Writes Writes; + // @checkstyle:on StaticVariableNameCheck + + int[] internal; + double growFactor; + int count, capacity; + + public ArrayVList() { + this(DEFAULT_CAPACITY, DEFAULT_GROW_FACTOR); + } + + public ArrayVList(int capacity) { + this(capacity, DEFAULT_GROW_FACTOR); + } + + public ArrayVList(int capacity, double growFactor) { + if (arrayVisualizer == null) { + arrayVisualizer = ArrayVisualizer.getInstance(); + Reads = arrayVisualizer.getReads(); + Writes = arrayVisualizer.getWrites(); + } + this.internal = new int[capacity]; + arrayVisualizer.getArrays().add(internal); + this.count = 0; + this.capacity = capacity; + this.growFactor = growFactor; + } + + public void delete() { + Writes.changeAllocAmount(-count); + arrayVisualizer.getArrays().remove(internal); + this.internal = null; + this.count = 0; + this.capacity = 0; + } + + @Override + public int size() { + return count; + } + + @Override + public boolean isEmpty() { + return count == 0; + } + + @Override + public boolean contains(Object o) { + return indexOf(o) > -1; + } + + @Override + public Object[] toArray() { + Integer[] result = new Integer[count]; + for (int i = 0; i < count; i++) { + result[i] = internal[i]; + } + return result; + } + + @Override + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + if (a.length < count) { + for (int i = 0; i < count; i++) { + a[i] = (T)Integer.valueOf(internal[i]); + } + return a; + } + return (T[])toArray(); + } + + protected void grow() { + int newCapacity = (int)Math.ceil(capacity * growFactor); + int[] newInternal = new int[newCapacity]; + System.arraycopy(internal, 0, newInternal, 0, count); + ArrayList arrays = arrayVisualizer.getArrays(); + arrays.set(arrays.indexOf(internal), newInternal); + this.capacity = newCapacity; + this.internal = newInternal; + } + + public boolean add(int e, double sleep, boolean mark) { + if (count == capacity) { + grow(); + } + Writes.write(internal, count++, e, sleep, mark, true); + Writes.changeAllocAmount(1); + return true; + } + + @Override + public boolean add(Integer e) { + return add(e, 0, false); + } + + private void fastRemove(int index) { + int numMoved = count - index - 1; + if (numMoved > 0) + Writes.arraycopy(internal, index + 1, internal, index, numMoved, 0, false, true); + internal[--count] = 0; + Writes.changeAllocAmount(-1); + } + + @Override + public boolean remove(Object o) { + if (o == null) { + return false; + } else { + for (int i = 0; i < count; i++) { + if (o.equals(internal[i])) { + fastRemove(i); + return true; + } + } + } + return false; + } + + @Override + public boolean containsAll(Collection c) { + return false; + } + + @Override + public boolean addAll(Collection c) { + return false; + } + + @Override + public boolean addAll(int index, Collection c) { + return false; + } + + @Override + public boolean removeAll(Collection c) { + return false; + } + + @Override + public boolean retainAll(Collection c) { + return false; + } + + @Override + public void clear() { + Arrays.fill(internal, 0, count, 0); + Writes.changeAllocAmount(-count); + count = 0; + } + + @Override + public Integer get(int index) { + return internal[index]; + } + + public Integer set(int index, int element, double sleep, boolean mark) { + rangeCheck(index); + int old = internal[index]; + Writes.write(internal, index, element, sleep, mark, true); + return old; + } + + @Override + public Integer set(int index, Integer element) { + return set(index, element, 0, false); + } + + private String outOfBoundsMsg(int index) { + return "Index: " + index + ", Size: " + this.count; + } + + protected void removeRange(int fromIndex, int toIndex) { + int numMoved = count - toIndex; + System.arraycopy(internal, toIndex, internal, fromIndex, + numMoved); + + int sizeOffset = toIndex - fromIndex; + int newSize = count - sizeOffset; + Arrays.fill(internal, newSize, count, 0); + count = newSize; + Writes.changeAllocAmount(-sizeOffset); + } + + private void rangeCheck(int index) { + if (index >= count) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + @Override + public void add(int index, Integer element) { + + } + + @Override + public Integer remove(int index) { + rangeCheck(index); + int old = internal[index]; + fastRemove(index); + return old; + } + + @Override + public int indexOf(Object o) { + if (o == null) { + return -1; + } + if (!(o instanceof Integer)) { + return -1; + } + int value = (Integer)o; + for (int i = 0; i < count; i++) { + if (Reads.compareValues(internal[i], value) == 0) { + return i; + } + } + return -1; + } + + @Override + public int lastIndexOf(Object o) { + if (o == null) { + return -1; + } + if (!(o instanceof Integer)) { + return -1; + } + int value = (Integer)o; + for (int i = count - 1; i >= 0; i--) { + if (Reads.compareValues(internal[i], value) == 0) { + return i; + } + } + return -1; + } + + @Override + public Iterator iterator() { + return new Itr(); + } + + @Override + public ListIterator listIterator() { + return new ListItr(0); + } + + @Override + public ListIterator listIterator(int index) { + return new ListItr(index); + } + + private class Itr implements Iterator { + int cursor; // index of next element to return + int lastRet = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != count; + } + + public Integer next() { + int i = cursor; + if (i >= count) + throw new NoSuchElementException(); + cursor = i + 1; + return ArrayVList.this.internal[lastRet = i]; + } + + public void remove() { + if (lastRet < 0) + throw new IllegalStateException(); + + try { + ArrayVList.this.remove(lastRet); + cursor = lastRet; + lastRet = -1; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + @Override + public void forEachRemaining(Consumer consumer) { + Objects.requireNonNull(consumer); + final int size = ArrayVList.this.capacity; + int i = cursor; + if (i >= size) { + return; + } + final int[] internal = ArrayVList.this.internal; + if (i >= internal.length) { + throw new ConcurrentModificationException(); + } + while (i != size) { + consumer.accept(internal[i++]); + } + // update once at end of iteration to reduce heap write traffic + cursor = i; + lastRet = i - 1; + } + } + + private class ListItr extends Itr implements ListIterator { + ListItr(int index) { + super(); + cursor = index; + } + + public boolean hasPrevious() { + return cursor != 0; + } + + public int nextIndex() { + return cursor; + } + + public int previousIndex() { + return cursor - 1; + } + + public Integer previous() { + int i = cursor - 1; + if (i < 0) + throw new NoSuchElementException(); + int[] internal = ArrayVList.this.internal; + if (i >= internal.length) + throw new ConcurrentModificationException(); + cursor = i; + return internal[lastRet = i]; + } + + public void set(Integer e) { + if (lastRet < 0) + throw new IllegalStateException(); + + try { + ArrayVList.this.set(lastRet, e); + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + public void add(Integer e) { + try { + int i = cursor; + ArrayVList.this.add(i, e); + cursor = i + 1; + lastRet = -1; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + } + + @Override + public List subList(int fromIndex, int toIndex) { + return new SubList(this, 0, fromIndex, toIndex); + } + + private class SubList extends AbstractList implements RandomAccess { + private final ArrayVList parent; + private final int parentOffset; + private final int offset; + int size; + + SubList(ArrayVList parent, + int offset, int fromIndex, int toIndex) { + this.parent = parent; + this.parentOffset = fromIndex; + this.offset = offset + fromIndex; + this.size = toIndex - fromIndex; + } + + @SuppressWarnings("unused") + public Integer set(int index, int e) { + rangeCheck(index); + int oldValue = ArrayVList.this.internal[offset + index]; + ArrayVList.this.internal[offset + index] = e; + return oldValue; + } + + public Integer get(int index) { + rangeCheck(index); + return ArrayVList.this.internal[offset + index]; + } + + public int size() { + return this.size; + } + + @SuppressWarnings("unused") + public void add(int index, int e) { + rangeCheckForAdd(index); + parent.add(parentOffset + index, e); + size++; + } + + public Integer remove(int index) { + rangeCheck(index); + int result = parent.remove(parentOffset + index); + this.size--; + return result; + } + + protected void removeRange(int fromIndex, int toIndex) { + parent.removeRange(parentOffset + fromIndex, + parentOffset + toIndex); + this.size -= toIndex - fromIndex; + } + + public Iterator iterator() { + return listIterator(); + } + + public ListIterator listIterator(final int index) { + return null; + } + + public List subList(int fromIndex, int toIndex) { + return null; + // subListRangeCheck(fromIndex, toIndex, size); + // return new SubList(this, offset, fromIndex, toIndex); + } + + private void rangeCheck(int index) { + if (index < 0 || index >= this.size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private void rangeCheckForAdd(int index) { + if (index < 0 || index > this.size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+this.size; + } + + public Spliterator spliterator() { + return null; + } + } + + static void subListRangeCheck(int fromIndex, int toIndex, int size) { + if (fromIndex < 0) + throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); + if (toIndex > size) + throw new IndexOutOfBoundsException("toIndex = " + toIndex); + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex + ")"); + } +} diff --git a/src/main/java/io/github/arrayv/utils/CommonUtils.java b/src/main/java/io/github/arrayv/utils/CommonUtils.java new file mode 100644 index 00000000..375d49db --- /dev/null +++ b/src/main/java/io/github/arrayv/utils/CommonUtils.java @@ -0,0 +1,39 @@ +package io.github.arrayv.utils; + +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.Map; + +public final class CommonUtils { + private CommonUtils() { + } + + public static String replace(String s, String from, String to) { + int i = s.indexOf(from); + if (i == -1) { + // Fast path: no replacements necessary + return s; + } + StringBuilder result = new StringBuilder(s.length() + 16); + int last = 0; + do { + result.append(s, last, i); + result.append(to); + last = i; + i = s.indexOf(from, i + from.length()); + } while (i != -1); + result.append(s, last + from.length(), s.length()); + return result.toString(); + } + + @SuppressWarnings("unchecked") + public static Map.Entry[] createPairArray(Object... values) { + if ((values.length & 1) != 0) { + throw new IllegalArgumentException("Must be an even number of values"); + } + Map.Entry[] result = new Map.Entry[values.length >> 1]; + for (int i = 0, j = 0; i < result.length; i++, j += 2) { + result[i] = new SimpleImmutableEntry<>((L)values[j], (R)values[j + 1]); + } + return result; + } +} diff --git a/src/utils/Delays.java b/src/main/java/io/github/arrayv/utils/Delays.java similarity index 58% rename from src/utils/Delays.java rename to src/main/java/io/github/arrayv/utils/Delays.java index 2c6777ea..8c8453be 100644 --- a/src/utils/Delays.java +++ b/src/main/java/io/github/arrayv/utils/Delays.java @@ -1,15 +1,17 @@ -package utils; +package io.github.arrayv.utils; -import java.text.DecimalFormat; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; -import main.ArrayVisualizer; -import panes.JErrorPane; +import java.text.DecimalFormat; +import java.util.concurrent.atomic.AtomicInteger; /* - * + * MIT License Copyright (c) 2019 w0rthy +Copyright (c) 2020-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,48 +33,41 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Delays { - private ArrayVisualizer arrayVisualizer; - - private volatile double SLEEPRATIO; - private volatile boolean SKIPPED; - - private double addamt; +public final class Delays { + private volatile double sleepRatio; + private volatile boolean skipped; + private double delay; - private double nanos; - + private volatile double currentDelay; private volatile boolean paused; - - private DecimalFormat formatter; - - private Sounds Sounds; - + private final AtomicInteger noStepping = new AtomicInteger(); + private volatile boolean stepping; + + private final DecimalFormat formatter; + + private final Sounds Sounds; + public Delays(ArrayVisualizer arrayVisualizer) { - this.arrayVisualizer = arrayVisualizer; - - this.SLEEPRATIO = 1.0; - this.SKIPPED = false; - this.addamt = 0; - + this.sleepRatio = 1.0; + this.skipped = false; + this.formatter = arrayVisualizer.getNumberFormat(); this.Sounds = arrayVisualizer.getSounds(); } - + public String displayCurrentDelay() { - if(this.SKIPPED) + if (this.skipped) return "Canceled"; - if(this.paused) + if (this.paused && !stepping) return "Paused"; - - String currDelay = ""; - if(this.currentDelay == 0) { + + String currDelay; + if (this.currentDelay == 0) { currDelay = "0"; - } - else if(this.currentDelay < 0.001) { + } else if (this.currentDelay < 0.001) { currDelay = "< 0.001"; - } - else { + } else { currDelay = formatter.format(this.currentDelay); } return currDelay + "ms"; @@ -91,9 +86,8 @@ public void updateCurrentDelay(double oldRatio, double newRatio) { this.delay = (this.delay * oldRatio) / newRatio; this.currentDelay = this.delay; this.Sounds.changeNoteDelayAndFilter((int) this.currentDelay); - this.addamt = 0; - - if(this.currentDelay < 0) { + + if (this.currentDelay < 0) { this.delay = this.currentDelay = 0; } } @@ -102,61 +96,91 @@ public void updateDelayForTimeSort(double value) { this.setDisplayedDelay(value); this.Sounds.changeNoteDelayAndFilter((int) value); } - + public double getSleepRatio() { - return this.SLEEPRATIO; + return this.sleepRatio; } public void setSleepRatio(double sleepRatio) { - this.SLEEPRATIO = sleepRatio; + this.sleepRatio = sleepRatio; } - + public boolean skipped() { - return this.SKIPPED; + return this.skipped; } - public void changeSkipped(boolean Bool) { - this.SKIPPED = Bool; - if(this.SKIPPED) this.Sounds.changeNoteDelayAndFilter(1); + public void changeSkipped(boolean skipped) { + this.skipped = skipped; + if (this.skipped) this.Sounds.changeNoteDelayAndFilter(1); } public boolean paused() { return this.paused; } - public void changePaused(boolean Bool) { - this.paused = Bool; - this.Sounds.toggleSound(!Bool); + public void changePaused(boolean paused) { + this.paused = paused; + this.Sounds.toggleSound(!paused); } public void togglePaused() { - this.changePaused(!this.paused);; + this.changePaused(!this.paused); + } + + public void disableStepping() { + if (noStepping.incrementAndGet() < 0) { + noStepping.set(0); + throw new IllegalStateException("Stepping toggle overflow"); + } + } + + public void enableStepping() { + if (noStepping.decrementAndGet() < 0) { + noStepping.set(0); + throw new IllegalStateException("Stepping toggle underflow"); + } + if (canStep()) { + // Step has ended + stepping = false; + } + } + + public boolean canStep() { + return noStepping.get() == 0; + } + + public boolean isStepping() { + return stepping; } - + + public void beginStepping() { + if (canStep()) { + stepping = true; + } + } + public void sleep(double millis) { - if(millis <= 0) { + if (millis <= 0) { return; } - - this.delay += (millis * (1 / this.SLEEPRATIO)); - this.currentDelay = (millis * (1 / this.SLEEPRATIO)); - + + this.delay += (millis * (1 / this.sleepRatio)); + this.currentDelay = (millis * (1 / this.sleepRatio)); + this.Sounds.changeNoteDelayAndFilter((int) this.currentDelay); - + try { // With this for loop, you can change the speed of sorts without waiting for the current delay to finish. - if(!this.SKIPPED) { - this.arrayVisualizer.toggleVisualUpdates(false); - while(this.paused || this.delay >= 1) { + if (!this.skipped) { + while (this.delay >= 1) { + //noinspection BusyWait Thread.sleep(1); - if (!this.paused) + if (!this.paused || stepping) this.delay--; } - this.arrayVisualizer.toggleVisualUpdates(true); - } - else { + } else { this.delay = 0; } - } catch(Exception ex) { + } catch (Exception ex) { JErrorPane.invokeErrorMessage(ex); } - + this.currentDelay = 0; } -} \ No newline at end of file +} diff --git a/src/utils/Distributions.java b/src/main/java/io/github/arrayv/utils/Distributions.java similarity index 67% rename from src/utils/Distributions.java rename to src/main/java/io/github/arrayv/utils/Distributions.java index dd26c35b..c7c44d65 100644 --- a/src/utils/Distributions.java +++ b/src/main/java/io/github/arrayv/utils/Distributions.java @@ -1,14 +1,16 @@ -package utils; +package io.github.arrayv.utils; + +import io.github.arrayv.dialogs.LoadCustomDistributionDialog; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; import java.io.File; import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.List; import java.util.Random; import java.util.Scanner; -import dialogs.LoadCustomDistributionDialog; -import main.ArrayVisualizer; -import panes.JErrorPane; - /* * MIT License @@ -41,10 +43,10 @@ public String getName() { return "Linear"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = i; } }, @@ -53,19 +55,19 @@ public String getName() { return "Few Unique"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); Random random = new Random(); int l = 0, r, t = Math.min(currentLen, 8); - for(int i = 0; i < t; i++) - if(random.nextDouble() < 0.5) l++; + for (int i = 0; i < t; i++) + if (random.nextDouble() < 0.5) l++; r = currentLen-(t-l); int i = 0; - for(; i < l; i++) array[i] = (int) (currentLen * 0.25); - for(; i < r; i++) array[i] = currentLen / 2; - for(; i < currentLen; i++) array[i] = (int) (currentLen * 0.75); + for (; i < l; i++) array[i] = (int) (currentLen * 0.25); + for (; i < r; i++) array[i] = currentLen / 2; + for (; i < currentLen; i++) array[i] = (int) (currentLen * 0.75); } }, EQUAL { @@ -73,8 +75,8 @@ public String getName() { return "No Unique"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int val = currentLen / 2; for (int i = 0; i < currentLen; i++) { @@ -87,11 +89,11 @@ public String getName() { return "Random"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); Random random = new Random(); - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = random.nextInt(currentLen); } }, @@ -100,10 +102,10 @@ public String getName() { return "Quadratic"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = (int)(Math.pow(i, 2)/currentLen); } }, @@ -112,10 +114,10 @@ public String getName() { return "Square Root"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = (int)(Math.sqrt(i)*Math.sqrt(currentLen)); } }, @@ -124,12 +126,12 @@ public String getName() { return "Cubic (Centered)"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int power = 3; double mid = (currentLen-1)/2d; - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = (int)(Math.pow(i - mid, power)/Math.pow(mid, power-1) + mid); } }, @@ -138,12 +140,12 @@ public String getName() { return "Quintic (Centered)"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int power = 5; double mid = (currentLen-1)/2d; - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = (int)(Math.pow(i - mid, power)/Math.pow(mid, power-1) + mid); } }, @@ -152,15 +154,15 @@ public String getName() { return "Cube Root (Centered)"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int p = 3; double h = currentLen/2d; - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { double val = i/h - 1, root = val < 0 ? -Math.pow(-val, 1d/p) : Math.pow(val, 1d/p); - + array[i] = (int)(h * (root + 1)); } } @@ -170,15 +172,15 @@ public String getName() { return "Fifth Root (Centered)"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int p = 5; double h = currentLen/2d; - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { double val = i/h - 1, root = val < 0 ? -Math.pow(-val, 1d/p) : Math.pow(val, 1d/p); - + array[i] = (int)(h * (root + 1)); } } @@ -188,12 +190,12 @@ public String getName() { return "Sine Wave"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int n = currentLen-1; double c = 2*Math.PI/n; - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = (int)(n * (Math.sin(c * i)+1)/2); } }, @@ -202,12 +204,12 @@ public String getName() { return "Cosine Wave"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int n = currentLen-1; double c = 2*Math.PI/n; - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = (int)(n * (Math.cos(c * i)+1)/2); } }, @@ -216,8 +218,8 @@ public String getName() { return "Perlin Noise"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); Random random = new Random(); int[] perlinNoise = new int[currentLen]; @@ -226,37 +228,37 @@ public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { float randomStart = (float) (random.nextInt(currentLen)); int octave = (int) (Math.log(currentLen) / Math.log(2)); - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { int value = (int) (PerlinNoise.returnFracBrownNoise(randomStart, octave) * currentLen); perlinNoise[i] = value; randomStart += step; } int minimum = Integer.MAX_VALUE; - for(int i = 0; i < currentLen; i++) { - if(perlinNoise[i] < minimum) { + for (int i = 0; i < currentLen; i++) { + if (perlinNoise[i] < minimum) { minimum = perlinNoise[i]; } } minimum = Math.abs(minimum); - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { perlinNoise[i] += minimum; } double maximum = Double.MIN_VALUE; - for(int i = 0; i < currentLen; i++) { - if(perlinNoise[i] > maximum) { + for (int i = 0; i < currentLen; i++) { + if (perlinNoise[i] > maximum) { maximum = perlinNoise[i]; } } double scale = currentLen / maximum; - if(scale < 1.0 || scale > 1.8) { - for(int i = 0; i < currentLen; i++) { + if (scale < 1.0 || scale > 1.8) { + for (int i = 0; i < currentLen; i++) { perlinNoise[i] = (int) (perlinNoise[i] * scale); } } - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { array[i] = Math.min(perlinNoise[i], currentLen-1); } } @@ -266,11 +268,11 @@ public String getName() { return "Perlin Noise Curve"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); - for(int i = 0; i < currentLen; i++) { - int value = 0 - (int) (PerlinNoise.returnNoise((float) i / currentLen) * currentLen); + for (int i = 0; i < currentLen; i++) { + int value = -(int)(PerlinNoise.returnNoise((float)i / currentLen) * currentLen); array[i] = Math.min(value, currentLen-1); } } @@ -280,14 +282,14 @@ public String getName() { return "Bell Curve"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); double step = 8d / currentLen; double position = -4; int constant = 1264; double factor = currentLen / 512d; - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { double square = Math.pow(position, 2); double negativeSquare = 0 - square; double halfNegSquare = negativeSquare / 2d; @@ -306,30 +308,33 @@ public String getName() { return "Ruler"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int step = Math.max(1, currentLen/256); - int floorLog2 = (int)(Math.log(currentLen/step)/Math.log(2)); + int floorLog2 = (int)(Math.log((double)currentLen/step)/Math.log(2)); int lowest; - for(lowest = step; 2*lowest <= currentLen/4; lowest*=2); + //noinspection StatementWithEmptyBody + for (lowest = step; 2*lowest <= currentLen/4; lowest*=2); boolean[] digits = new boolean[floorLog2+2]; int i, j; - for(i = 0; i+step <= currentLen; i+=step) { - for(j = 0; digits[j]; j++); + for (i = 0; i+step <= currentLen; i+=step) { + //noinspection StatementWithEmptyBody + for (j = 0; digits[j]; j++); digits[j] = true; - for(int k = 0; k < step; k++) { + for (int k = 0; k < step; k++) { int value = currentLen/2 - Math.min((1 << j)*step, lowest); array[i+k] = value; } - for(int k = 0; k < j; k++) digits[k] = false; + for (int k = 0; k < j; k++) digits[k] = false; } - for(j = 0; digits[j]; j++); + //noinspection StatementWithEmptyBody + for (j = 0; digits[j]; j++); digits[j] = true; - while(i < currentLen) { + while (i < currentLen) { int value = Math.max(currentLen/2 - (1 << j)*step, currentLen/4); array[i++] = value; } @@ -340,11 +345,11 @@ public String getName() { return "Blancmange Curve"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int floorLog2 = (int)(Math.log(currentLen)/Math.log(2)); - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { int value = (int)(currentLen * curveSum(floorLog2, (double)i/currentLen)); array[i] = value; } @@ -352,7 +357,7 @@ public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { public double curveSum(int n, double x) { double sum = 0; - while(n >= 0) + while (n >= 0) sum += curve(n--, x); return sum; } @@ -370,24 +375,24 @@ public String getName() { return "Cantor Function"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); cantor(array, 0, currentLen, 0, currentLen-1); } public void cantor(int[] array, int a, int b, int min, int max) { - if(b-a < 1 || max == min) return; + if (b-a < 1 || max == min) return; int mid = (min+max)/2; - if(b-a == 1) { + if (b-a == 1) { array[a] = mid; return; } int t1 = (a+a+b)/3, t2 = (a+b+b+2)/3; - for(int i = t1; i < t2; i++) + for (int i = t1; i < t2; i++) array[i] = mid; this.cantor(array, a, t1, min, mid); @@ -399,31 +404,31 @@ public String getName() { return "Sum of Divisors"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int[] n = new int[currentLen]; n[0] = 0; n[1] = 1; double max = 1; - for(int i = 2; i < currentLen; i++) { + for (int i = 2; i < currentLen; i++) { n[i] = sumDivisors(i); - if(n[i] > max) max = n[i]; + if (n[i] > max) max = n[i]; } double scale = Math.min((currentLen-1)/max, 1); - for(int i = 0; i < currentLen; i++) { + for (int i = 0; i < currentLen; i++) { array[i] = (int)(n[i]*scale); } } public int sumDivisors(int n) { int sum = n+1; - for(int i = 2; i <= (int)Math.sqrt(n); i++) { - if(n % i == 0) { - if(i == n/i) sum += i; - else sum += i + n/i; + for (int i = 2; i <= (int)Math.sqrt(n); i++) { + if (n % i == 0) { + if (i == n/i) sum += i; + else sum += i + n/i; } } return sum; @@ -434,26 +439,26 @@ public String getName() { return "Fly Straight, Damnit!"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); int[] fsd = new int[currentLen]; double max; max = fsd[0] = fsd[1] = 1; - for(int i = 2; i < currentLen; i++) { + for (int i = 2; i < currentLen; i++) { int g = gcd(fsd[i-1], i); fsd[i] = fsd[i-1]/g + (g==1 ? i+1 : 0); - if(fsd[i] > max) max = fsd[i]; + if (fsd[i] > max) max = fsd[i]; } double scale = Math.min((currentLen-1)/max, 1); - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) array[i] = (int)(fsd[i]*scale); } public int gcd(int a, int b) { if (b==0) return a; - return gcd(b,a%b); + return gcd(b, a%b); } }, REVLOG { @@ -461,11 +466,11 @@ public String getName() { return "Decreasing Random"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); Random random = new Random(); - for(int i = 0; i < currentLen; i++){ + for (int i = 0; i < currentLen; i++){ int r = random.nextInt(currentLen - i) + i; array[i] = r; } @@ -476,10 +481,45 @@ public String getName() { return "Modulo Function"; } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int n = ArrayVisualizer.getCurrentLength(); - - for(int i = 0; i < n; i++) array[i] = 2*(n%(i+1)); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int n = arrayVisualizer.getCurrentLength(); + + for (int i = 0; i < n; i++) array[i] = 2*(n%(i+1)); + } + }, + TOTIENT { // O(n) + @Override + public String getName() { + return "Euler Totient Function"; + } + @Override + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int n = arrayVisualizer.getCurrentLength(); + + int[] minPrimeFactors = new int[n]; + List primes = new ArrayList<>(); + + array[0] = 0; + array[1] = 1; + for (int i = 2; i < n; i++) { + if (minPrimeFactors[i] == 0) { + primes.add(i); + + minPrimeFactors[i] = i; + array[i] = i - 1; + } + + for (int prime : primes) { + if (i * prime >= n) break; + + boolean last = prime == minPrimeFactors[i]; + + minPrimeFactors[i * prime] = prime; + array[i * prime] = array[i] * (last ? prime : prime - 1); + + if (last) break; + } + } } }, CUSTOM { @@ -489,19 +529,18 @@ public String getName() { return "Custom"; } @Override - public void selectDistribution(int[] array, ArrayVisualizer ArrayVisualizer) { + public void selectDistribution(int[] array, ArrayVisualizer arrayVisualizer) { LoadCustomDistributionDialog dialog = new LoadCustomDistributionDialog(); File file = dialog.getFile(); Scanner scanner; try { scanner = new Scanner(file); - } - catch (FileNotFoundException e) { + } catch (FileNotFoundException e) { JErrorPane.invokeErrorMessage(e); return; } scanner.useDelimiter("\\s+"); - this.refarray = new int[ArrayVisualizer.getMaximumLength()]; + this.refarray = new int[arrayVisualizer.getMaximumLength()]; int current = 0; while (scanner.hasNext()) { this.refarray[current++] = Integer.parseInt(scanner.next()); @@ -510,8 +549,8 @@ public void selectDistribution(int[] array, ArrayVisualizer ArrayVisualizer) { scanner.close(); } @Override - public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void initializeArray(int[] array, ArrayVisualizer arrayVisualizer) { + int currentLen = arrayVisualizer.getCurrentLength(); double scale = (double)this.length / currentLen; for (int i = 0; i < currentLen; i++) { array[i] = (int)(this.refarray[(int)(i * scale)] / scale); @@ -520,6 +559,7 @@ public void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer) { }; public abstract String getName(); - public void selectDistribution(int[] array, ArrayVisualizer ArrayVisualizer) {} - public abstract void initializeArray(int[] array, ArrayVisualizer ArrayVisualizer); -} \ No newline at end of file + public void selectDistribution(int[] array, ArrayVisualizer arrayVisualizer) { + } + public abstract void initializeArray(int[] array, ArrayVisualizer arrayVisualizer); +} diff --git a/src/utils/Highlights.java b/src/main/java/io/github/arrayv/utils/Highlights.java similarity index 57% rename from src/utils/Highlights.java rename to src/main/java/io/github/arrayv/utils/Highlights.java index a72f2381..bca1537e 100644 --- a/src/utils/Highlights.java +++ b/src/main/java/io/github/arrayv/utils/Highlights.java @@ -1,12 +1,13 @@ -package utils; +package io.github.arrayv.utils; -import java.util.Arrays; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; -import main.ArrayVisualizer; -import panes.JErrorPane; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -31,172 +32,187 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Highlights { - private volatile int[] Highlights; +public final class Highlights { + private volatile int[] highlights; private volatile byte[] markCounts; - + private volatile int maxHighlightMarked; // IMPORTANT: This stores the index one past the farthest highlight used, so that a value // of 0 means no highlights are in use, and iteration is more convenient. - + // The Highlights array is huge and slows down the visualizer if all its indices are read. // In an attempt to speed up scanning through all highlights while also giving anyone room // to use the full array, this variable keeps track of the farthest highlight in use. The // Highlights array thus only needs to be scanned up to index maxHighightMarked. - + // If an highlight is used with markArray() that is higher than maxPossibleMarked, the // variable is updated. If the farthest highlight is removed with clearMark(), the next // farthest highlight is found and updates maxIndexMarked. - + // Trivially, clearAllMarks() resets maxIndexMarked to zero. This variable also serves // as a subtle design hint for anyone who wants to add an algorithm to the app to highlight // array positions at low indices which are close together. - + // This way, the program runs more efficiently, and looks pretty. :) - - private volatile int markCount; - - private boolean FANCYFINISH; + + private final AtomicInteger markCount; + + private boolean showFancyFinishes; private volatile boolean fancyFinish; - private volatile int trackFinish; - - private ArrayVisualizer ArrayVisualizer; - - public Highlights(ArrayVisualizer ArrayVisualizer, int maximumLength) { - this.ArrayVisualizer = ArrayVisualizer; - + private final AtomicInteger trackFinish = new AtomicInteger(); + + private final ArrayVisualizer arrayVisualizer; + private Delays Delays; + + public Highlights(ArrayVisualizer arrayVisualizer, int maximumLength) { + this.arrayVisualizer = arrayVisualizer; + try { - this.Highlights = new int[maximumLength]; + this.highlights = new int[maximumLength]; this.markCounts = new byte[maximumLength]; } catch (OutOfMemoryError e) { JErrorPane.invokeCustomErrorMessage("Failed to allocate mark arrays. The program will now exit."); System.exit(1); } - this.FANCYFINISH = true; + this.showFancyFinishes = true; this.maxHighlightMarked = 0; - this.markCount = 0; - - Arrays.fill(Highlights, -1); + this.markCount = new AtomicInteger(); + + Arrays.fill(highlights, -1); Arrays.fill(markCounts, (byte)0); } - + + public void postInit() { + if (Delays != null) { + throw new IllegalStateException(); + } + this.Delays = arrayVisualizer.getDelays(); + } + public boolean fancyFinishEnabled() { - return this.FANCYFINISH; + return this.showFancyFinishes; } - public void toggleFancyFinishes(boolean Bool) { - this.FANCYFINISH = Bool; + public void toggleFancyFinishes(boolean showFancyFinishes) { + this.showFancyFinishes = showFancyFinishes; } - + public boolean fancyFinishActive() { return this.fancyFinish; } - public void toggleFancyFinish(boolean Bool) { - this.fancyFinish = Bool; + public void toggleFancyFinish(boolean fancyFinish) { + this.fancyFinish = fancyFinish; } - + public int getFancyFinishPosition() { - return this.trackFinish; + return this.trackFinish.get(); } public void incrementFancyFinishPosition() { - this.trackFinish++; + this.trackFinish.incrementAndGet(); } public void resetFancyFinish() { - this.trackFinish = -1; // Magic number that clears the green sweep animation + this.trackFinish.set(-1); // Magic number that clears the green sweep animation } - - //TODO: Move Analysis to Highlights - public void toggleAnalysis(boolean Bool) { - this.ArrayVisualizer.toggleAnalysis(Bool); + + public void toggleAnalysis(boolean analysis) { + this.arrayVisualizer.toggleAnalysis(analysis); } - + public int getMaxHighlight() { return this.maxHighlightMarked; } public int getMarkCount() { - return this.markCount; + return this.markCount.get(); } - + private void incrementIndexMarkCount(int i) { - if(markCounts[i] != (byte)-1) { + if (i >= markCounts.length) return; + if (markCounts[i] != (byte)-1) { + if (markCounts[i] == 0) { + markCount.incrementAndGet(); + } markCounts[i]++; } } private void decrementIndexMarkCount(int i) { - if(markCounts[i] == (byte)-1) { + if (i >= markCounts.length) return; + if (markCounts[i] == (byte)-1) { int count = 0; - for(int h = 0; h < this.maxHighlightMarked; h++) { - if(Highlights[h] == i) { + for (int h = 0; h < this.maxHighlightMarked; h++) { + if (highlights[h] == i) { count++; - if(count > Byte.toUnsignedInt((byte)-1)) { + if (count > 255) { return; } } } + } else if (markCounts[i] == 0) { + markCount.decrementAndGet(); } markCounts[i]--; } - + //Consider revising highlightList(). public int[] highlightList() { - return this.Highlights; + return this.highlights; } public boolean containsPosition(int arrayPosition) { + if (arrayPosition >= markCounts.length) return false; return this.markCounts[arrayPosition] != 0; } public synchronized void markArray(int marker, int markPosition) { try { - if(markPosition < 0) { - if(markPosition == -1) throw new Exception("Highlights.markArray(): Invalid position! -1 is reserved for the clearMark method."); - else if(markPosition == -5) throw new Exception("Highlights.markArray(): Invalid position! -5 was the constant originally used to unmark numbers in the array. Instead, use the clearMark method."); + if (markPosition < 0) { + if (markPosition == -1) throw new Exception("Highlights.markArray(): Invalid position! -1 is reserved for the clearMark method."); + else if (markPosition == -5) throw new Exception("Highlights.markArray(): Invalid position! -5 was the constant originally used to unmark numbers in the array. Instead, use the clearMark method."); else throw new Exception("Highlights.markArray(): Invalid position!"); - } - else { - if(Highlights[marker] == markPosition) { + } else { + if (highlights[marker] == markPosition) { return; } - if(Highlights[marker] == -1) { - this.markCount++; + Delays.disableStepping(); + if (highlights[marker] != -1) { + decrementIndexMarkCount(highlights[marker]); } - else { - decrementIndexMarkCount(Highlights[marker]); - } - Highlights[marker] = markPosition; + highlights[marker] = markPosition; incrementIndexMarkCount(markPosition); - - if(marker >= this.maxHighlightMarked) { + + if (marker >= this.maxHighlightMarked) { this.maxHighlightMarked = marker + 1; } } - } - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); } - ArrayVisualizer.updateNow(); + arrayVisualizer.updateNow(); + Delays.enableStepping(); } public synchronized void clearMark(int marker) { - if(Highlights[marker] == -1) { + if (highlights[marker] == -1) { return; } - this.markCount--; - decrementIndexMarkCount(Highlights[marker]); - Highlights[marker] = -1; // -1 is used as the magic number to unmark a position in the main array - - if(marker == this.maxHighlightMarked) { + Delays.disableStepping(); + decrementIndexMarkCount(highlights[marker]); + highlights[marker] = -1; // -1 is used as the magic number to unmark a position in the main array + + if (marker == this.maxHighlightMarked) { this.maxHighlightMarked = marker; - while(maxHighlightMarked > 0 && Highlights[maxHighlightMarked-1] == -1) { + while (maxHighlightMarked > 0 && highlights[maxHighlightMarked-1] == -1) { maxHighlightMarked--; } } - ArrayVisualizer.updateNow(); + arrayVisualizer.updateNow(); + Delays.enableStepping(); } public synchronized void clearAllMarks() { - for(int i = 0; i < this.maxHighlightMarked; i++) { - if(Highlights[i] != -1) { - markCounts[Highlights[i]] = 0; + Delays.disableStepping(); + for (int i = 0; i < this.maxHighlightMarked; i++) { + if (highlights[i] != -1) { + markCounts[highlights[i]] = 0; } } - Arrays.fill(this.Highlights, 0, this.maxHighlightMarked, -1); + Arrays.fill(this.highlights, 0, this.maxHighlightMarked, -1); this.maxHighlightMarked = 0; - this.markCount = 0; - ArrayVisualizer.updateNow(); + this.markCount.set(0); + arrayVisualizer.updateNow(); + Delays.enableStepping(); } -} \ No newline at end of file +} diff --git a/src/utils/IndexedRotations.java b/src/main/java/io/github/arrayv/utils/IndexedRotations.java similarity index 93% rename from src/utils/IndexedRotations.java rename to src/main/java/io/github/arrayv/utils/IndexedRotations.java index f50bd233..098209f1 100644 --- a/src/utils/IndexedRotations.java +++ b/src/main/java/io/github/arrayv/utils/IndexedRotations.java @@ -1,6 +1,9 @@ -package utils; +package io.github.arrayv.utils; + +public final class IndexedRotations { + private IndexedRotations() { + } -public class IndexedRotations { public static void griesMills(int[] array, int start, int mid, int end, double pause, boolean mark, boolean auxwrite) { Rotations.griesMills(array, start, mid - start, end - mid, pause, mark, auxwrite); } @@ -24,7 +27,7 @@ public static void helium(int[] array, int start, int mid, int end, double pause public static void cycleReverse(int[] array, int start, int mid, int end, double pause, boolean mark, boolean auxwrite) { Rotations.cycleReverse(array, start, mid - start, end - mid, pause, mark, auxwrite); } - + public static void bridge(int[] array, int start, int mid, int end, double pause, boolean mark, boolean auxwrite) { Rotations.bridge(array, start, mid - start, end - mid, pause, mark, auxwrite); } diff --git a/src/main/java/io/github/arrayv/utils/PerlinNoise.java b/src/main/java/io/github/arrayv/utils/PerlinNoise.java new file mode 100644 index 00000000..d425ccd4 --- /dev/null +++ b/src/main/java/io/github/arrayv/utils/PerlinNoise.java @@ -0,0 +1,54 @@ +package io.github.arrayv.utils; + +// MASSIVE thanks to https://github.com/keijiro/PerlinNoise +public final class PerlinNoise { + private static final int[] PERM = { + 151, 160, 137, 91, 90, 15, + 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, + 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, + 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, + 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, + 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, + 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, + 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, + 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, + 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, + 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, + 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, + 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180, + 151 + }; + + private PerlinNoise() { + } + + private static float fade(float t) { + return t * t * t * (t * (t * 6 - 15) + 10); + } + + private static float grad(int hash, float x) { + return (hash & 1) == 0 ? x : -x; + } + + private static float lerp(float t, float a, float b) { + return a + t * (b - a); + } + + public static float returnNoise(float x) { + int index = ((int) Math.floor(x)) & 0xff; + x -= Math.floor(x); + float u = fade(x); + return lerp(u, grad(PERM[index], x), grad(PERM[index + 1], x - 1)) * 2; + } + + public static float returnFracBrownNoise(float x, int octave) { + float f = 0.0f; + float w = 0.5f; + for (int i = 0; i < octave; i++) { + f += w * returnNoise(x); + x *= 2.0f; + w *= 0.5f; + } + return f; + } +} diff --git a/src/utils/Reads.java b/src/main/java/io/github/arrayv/utils/Reads.java similarity index 56% rename from src/utils/Reads.java rename to src/main/java/io/github/arrayv/utils/Reads.java index a17b2574..dc2e1f57 100644 --- a/src/utils/Reads.java +++ b/src/main/java/io/github/arrayv/utils/Reads.java @@ -1,9 +1,10 @@ -package utils; +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; import java.text.DecimalFormat; import java.util.ArrayList; - -import main.ArrayVisualizer; +import java.util.concurrent.atomic.AtomicLong; /* * @@ -31,99 +32,93 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Reads { - private volatile long comparisons; - public volatile ArrayList networkIndices; +public final class Reads { + private final AtomicLong comparisons; + private final ArrayList networkIndices; - private ArrayVisualizer ArrayVisualizer; + private final ArrayVisualizer arrayVisualizer; - private DecimalFormat formatter; + private final DecimalFormat formatter; - private Delays Delays; - private Highlights Highlights; - private Timer Timer; + private final Delays Delays; + private final Highlights Highlights; + private final Timer Timer; public Reads(ArrayVisualizer arrayVisualizer) { - this.ArrayVisualizer = arrayVisualizer; + this.arrayVisualizer = arrayVisualizer; - this.comparisons = 0; + this.comparisons = new AtomicLong(); this.networkIndices = new ArrayList<>(); - this.Delays = ArrayVisualizer.getDelays(); - this.Highlights = ArrayVisualizer.getHighlights(); - this.Timer = ArrayVisualizer.getTimer(); + this.Delays = arrayVisualizer.getDelays(); + this.Highlights = arrayVisualizer.getHighlights(); + this.Timer = arrayVisualizer.getTimer(); - this.formatter = ArrayVisualizer.getNumberFormat(); + this.formatter = arrayVisualizer.getNumberFormat(); } public void resetStatistics() { - this.comparisons = 0; + this.comparisons.set(0); } public void addComparison() { - this.comparisons++; + this.comparisons.incrementAndGet(); } public String getStats() { - if(this.comparisons < 0) { - this.comparisons = Long.MIN_VALUE; + if (this.comparisons.get() < 0) { + this.comparisons.set(Long.MIN_VALUE); return "Over " + this.formatter.format(Long.MAX_VALUE); - } - else { - if(this.comparisons == 1) return this.comparisons + " Comparison"; - else return this.formatter.format(this.comparisons) + " Comparisons"; + } else { + if (this.comparisons.get() == 1) return this.comparisons + " Comparison"; + else return this.formatter.format(this.comparisons) + " Comparisons"; } } public long getComparisons() { - return this.comparisons; + return this.comparisons.get(); } public void setComparisons(long value) { - this.comparisons = value; + this.comparisons.set(value); } public int compareValues(int left, int right) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - this.comparisons++; + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + this.comparisons.incrementAndGet(); - if (ArrayVisualizer.doingStabilityCheck()) { - left = ArrayVisualizer.getStabilityValue(left); - right = ArrayVisualizer.getStabilityValue(right); + if (arrayVisualizer.doingStabilityCheck()) { + left = arrayVisualizer.getStabilityValue(left); + right = arrayVisualizer.getStabilityValue(right); } - int cmpVal = 0; + int cmpVal; Timer.startLap("Compare"); - if(left > right) cmpVal = 1; - else if(left < right) cmpVal = -1; - else cmpVal = 0; + cmpVal = Integer.compare(left, right); Timer.stopLap(); - if (!ArrayVisualizer.useAntiQSort()) { - if (ArrayVisualizer.reversedComparator()) { + if (!arrayVisualizer.useAntiQSort()) { + if (arrayVisualizer.reversedComparator()) { return -cmpVal; } return cmpVal; - } - else { - return ArrayVisualizer.antiqCompare(left, right); + } else { + return arrayVisualizer.antiqCompare(left, right); } } public int compareOriginalValues(int left, int right) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - this.comparisons++; + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + this.comparisons.incrementAndGet(); - int cmpVal = 0; + int cmpVal; Timer.startLap("Compare"); - if(left > right) cmpVal = 1; - else if(left < right) cmpVal = -1; - else cmpVal = 0; + cmpVal = Integer.compare(left, right); Timer.stopLap(); @@ -131,12 +126,12 @@ public int compareOriginalValues(int left, int right) { } public int compareIndices(int[] array, int left, int right, double sleep, boolean mark) { - if(mark) { + if (mark) { Highlights.markArray(1, left); Highlights.markArray(2, right); Delays.sleep(sleep); } - if (ArrayVisualizer.generateSortingNetworks()) { + if (arrayVisualizer.generateSortingNetworks()) { networkIndices.add(left); networkIndices.add(right); } @@ -144,7 +139,7 @@ public int compareIndices(int[] array, int left, int right, double sleep, boolea } public int compareOriginalIndices(int[] array, int left, int right, double sleep, boolean mark) { - if(mark) { + if (mark) { Highlights.markArray(1, left); Highlights.markArray(2, right); Delays.sleep(sleep); @@ -153,7 +148,7 @@ public int compareOriginalIndices(int[] array, int left, int right, double sleep } public int compareIndexValue(int[] array, int index, int value, double sleep, boolean mark) { - if(mark) { + if (mark) { Highlights.markArray(1, index); Delays.sleep(sleep); } @@ -161,7 +156,7 @@ public int compareIndexValue(int[] array, int index, int value, double sleep, bo } public int compareOriginalIndexValue(int[] array, int index, int value, double sleep, boolean mark) { - if(mark) { + if (mark) { Highlights.markArray(1, index); Delays.sleep(sleep); } @@ -169,7 +164,7 @@ public int compareOriginalIndexValue(int[] array, int index, int value, double s } public int compareValueIndex(int[] array, int value, int index, double sleep, boolean mark) { - if(mark) { + if (mark) { Highlights.markArray(1, index); Delays.sleep(sleep); } @@ -177,7 +172,7 @@ public int compareValueIndex(int[] array, int value, int index, double sleep, bo } public int compareOriginalValueIndex(int[] array, int value, int index, double sleep, boolean mark) { - if(mark) { + if (mark) { Highlights.markArray(1, index); Delays.sleep(sleep); } @@ -185,143 +180,143 @@ public int compareOriginalValueIndex(int[] array, int value, int index, double s } public int analyzeMax(int[] array, int length, double sleep, boolean mark) { - ArrayVisualizer.toggleAnalysis(true); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(true); + arrayVisualizer.updateNow(); int max = 0; - for(int i = 0; i < length; i++) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - + for (int i = 0; i < length; i++) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + int val = array[i]; - if(ArrayVisualizer.doingStabilityCheck()) - val = ArrayVisualizer.getStabilityValue(val); - + if (arrayVisualizer.doingStabilityCheck()) + val = arrayVisualizer.getStabilityValue(val); + Timer.startLap("Analysis"); - if(val > max) max = val; + if (val > max) max = val; Timer.stopLap(); - if(mark) { + if (mark) { Highlights.markArray(1, i); Delays.sleep(sleep); } } - ArrayVisualizer.toggleAnalysis(false); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(false); + arrayVisualizer.updateNow(); return max; } public int analyzeMin(int[] array, int length, double sleep, boolean mark) { - ArrayVisualizer.toggleAnalysis(true); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(true); + arrayVisualizer.updateNow(); int min = 0; - for(int i = 0; i < length; i++) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - + for (int i = 0; i < length; i++) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + int val = array[i]; - if(ArrayVisualizer.doingStabilityCheck()) - val = ArrayVisualizer.getStabilityValue(val); - + if (arrayVisualizer.doingStabilityCheck()) + val = arrayVisualizer.getStabilityValue(val); + Timer.startLap("Analysis"); - if(val < min) min = val; + if (val < min) min = val; Timer.stopLap(); - if(mark) { + if (mark) { Highlights.markArray(1, i); Delays.sleep(sleep); } } - ArrayVisualizer.toggleAnalysis(false); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(false); + arrayVisualizer.updateNow(); return min; } public int analyzeMaxLog(int[] array, int length, int base, double sleep, boolean mark) { - ArrayVisualizer.toggleAnalysis(true); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(true); + arrayVisualizer.updateNow(); int max = 0; - for(int i = 0; i < length; i++) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - + for (int i = 0; i < length; i++) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + int val = array[i]; - if(ArrayVisualizer.doingStabilityCheck()) - val = ArrayVisualizer.getStabilityValue(val); + if (arrayVisualizer.doingStabilityCheck()) + val = arrayVisualizer.getStabilityValue(val); Timer.startLap("Analysis"); - if(val > max) max = val; + if (val > max) max = val; Timer.stopLap(); - if(mark) { + if (mark) { Highlights.markArray(1, i); Delays.sleep(sleep); } } - ArrayVisualizer.toggleAnalysis(false); - ArrayVisualizer.updateNow(); - + arrayVisualizer.toggleAnalysis(false); + arrayVisualizer.updateNow(); + return (int) (Math.log(max) / Math.log(base)); } public int analyzeMaxCeilingLog(int[] array, int length, int base, double sleep, boolean mark) { - ArrayVisualizer.toggleAnalysis(true); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(true); + arrayVisualizer.updateNow(); int max = 0; - for(int i = 0; i < length; i++) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - + for (int i = 0; i < length; i++) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + int val = array[i]; - if(ArrayVisualizer.doingStabilityCheck()) - val = ArrayVisualizer.getStabilityValue(val); - + if (arrayVisualizer.doingStabilityCheck()) + val = arrayVisualizer.getStabilityValue(val); + Timer.startLap("Analysis"); - if(val > max) max = val; + if (val > max) max = val; Timer.stopLap(); - if(mark) { + if (mark) { Highlights.markArray(1, i); Delays.sleep(sleep); } } - ArrayVisualizer.toggleAnalysis(false); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(false); + arrayVisualizer.updateNow(); return (int) (Math.log(max) / Math.log(base)); } public int analyzeBit(int[] array, int length) { - ArrayVisualizer.toggleAnalysis(true); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(true); + arrayVisualizer.updateNow(); // Find highest bit of highest value int max = 0; - for(int i = 0; i < length; i++) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - + for (int i = 0; i < length; i++) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + int val = array[i]; - if(ArrayVisualizer.doingStabilityCheck()) - val = ArrayVisualizer.getStabilityValue(val); - + if (arrayVisualizer.doingStabilityCheck()) + val = arrayVisualizer.getStabilityValue(val); + Timer.startLap("Analysis"); if (val > max) max = val; @@ -340,15 +335,15 @@ public int analyzeBit(int[] array, int length) { Timer.stopLap(); - ArrayVisualizer.toggleAnalysis(false); - ArrayVisualizer.updateNow(); + arrayVisualizer.toggleAnalysis(false); + arrayVisualizer.updateNow(); return analysis; } public int getDigit(int a, int power, int radix) { - if(ArrayVisualizer.doingStabilityCheck()) - a = ArrayVisualizer.getStabilityValue(a); - + if (arrayVisualizer.doingStabilityCheck()) + a = arrayVisualizer.getStabilityValue(a); + int digit; Timer.startLap(); digit = (int) (a / Math.pow(radix, power)) % radix; @@ -357,9 +352,9 @@ public int getDigit(int a, int power, int radix) { } public boolean getBit(int n, int k) { - if(ArrayVisualizer.doingStabilityCheck()) - n = ArrayVisualizer.getStabilityValue(n); - + if (arrayVisualizer.doingStabilityCheck()) + n = arrayVisualizer.getStabilityValue(n); + // Find boolean value of bit k in n boolean result; Timer.startLap(); @@ -367,4 +362,8 @@ public boolean getBit(int n, int k) { Timer.stopLap(); return result; } + + public ArrayList getNetworkIndices() { + return networkIndices; + } } diff --git a/src/utils/Renderer.java b/src/main/java/io/github/arrayv/utils/Renderer.java similarity index 50% rename from src/utils/Renderer.java rename to src/main/java/io/github/arrayv/utils/Renderer.java index 6fc8f6ed..c5bdc905 100644 --- a/src/utils/Renderer.java +++ b/src/main/java/io/github/arrayv/utils/Renderer.java @@ -1,10 +1,12 @@ -package utils; +package io.github.arrayv.utils; -import main.ArrayVisualizer; -import visuals.VisualStyles; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.visuals.VisualStyles; + +import java.util.concurrent.atomic.AtomicInteger; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -31,59 +33,59 @@ of this software and associated documentation files (the "Software"), to deal // TODO: Many of these methods should exist solely in visual classes -final class WindowState { - private boolean windowUpdated; - private boolean windowResized; - - public WindowState(boolean windowUpdate, boolean windowResize) { - this.windowUpdated = windowUpdate; - this.windowResized = windowResize; - } - - public boolean updated() { - return this.windowUpdated; - } - - public boolean resized() { - return this.windowResized; +public final class Renderer { + private static final class WindowState { + private final boolean windowUpdated; + private final boolean windowResized; + + private WindowState(boolean windowUpdate, boolean windowResize) { + this.windowUpdated = windowUpdate; + this.windowResized = windowResize; + } + + public boolean updated() { + return this.windowUpdated; + } + + public boolean resized() { + return this.windowResized; + } } -} -final public class Renderer { - private volatile double xscl; //TODO: Change to xScale/yScale - private volatile double yscl; + private volatile double xScale; + private volatile double yScale; - private volatile int yoffset; + private final AtomicInteger yoffset = new AtomicInteger(); private volatile int vsize; - public volatile boolean auxActive; + private volatile boolean auxActive; private volatile int length; - + private volatile int amt; - + private int linkedpixdrawx; //TODO: Change names private int linkedpixdrawy; - + private int doth; //TODO: Change names private int dotw; private int dots; //TODO: Change name to dotDims/dotDimensions - - public Renderer(ArrayVisualizer ArrayVisualizer) { - ArrayVisualizer.setWindowHeight(); - ArrayVisualizer.setWindowWidth(); + + public Renderer(ArrayVisualizer arrayVisualizer) { + arrayVisualizer.setWindowHeight(); + arrayVisualizer.setWindowWidth(); } - + public double getXScale() { - return this.xscl; + return this.xScale; } public double getYScale() { - return this.yscl; + return this.yScale; } public int getOffset() { return this.amt; } public int getYOffset() { - return this.yoffset; + return this.yoffset.get(); } public int getViewSize() { return this.vsize; @@ -109,7 +111,7 @@ public int getLineX() { public int getLineY() { return this.linkedpixdrawy; } - + public void setOffset(int amount) { this.amt = amount; } @@ -119,109 +121,117 @@ public void setLineX(int x) { public void setLineY(int y) { this.linkedpixdrawy = y; } - - public static void createRenders(ArrayVisualizer ArrayVisualizer) { - ArrayVisualizer.createVolatileImage(); - ArrayVisualizer.setMainRender(); - ArrayVisualizer.setExtraRender(); + + public static void createRenders(ArrayVisualizer arrayVisualizer) { + arrayVisualizer.createVolatileImage(); + arrayVisualizer.setMainRender(); + arrayVisualizer.setExtraRender(); } - - public static void initializeVisuals(ArrayVisualizer ArrayVisualizer) { - Renderer.createRenders(ArrayVisualizer); - ArrayVisualizer.repositionFrames(); + + public static void initializeVisuals(ArrayVisualizer arrayVisualizer) { + Renderer.createRenders(arrayVisualizer); + arrayVisualizer.repositionFrames(); } - - public static void updateGraphics(ArrayVisualizer ArrayVisualizer) { - Renderer.createRenders(ArrayVisualizer); - ArrayVisualizer.updateVisuals(); + + public static void updateGraphics(ArrayVisualizer arrayVisualizer) { + Renderer.createRenders(arrayVisualizer); + arrayVisualizer.updateVisuals(); } - private static WindowState checkWindowResizeAndReposition(ArrayVisualizer ArrayVisualizer) { + private static WindowState checkWindowResizeAndReposition(ArrayVisualizer arrayVisualizer) { boolean windowUpdate = false; boolean windowResize = false; - - if(ArrayVisualizer.currentHeight() != ArrayVisualizer.windowHeight()) { + + if (arrayVisualizer.currentHeight() != arrayVisualizer.windowHeight()) { windowUpdate = true; windowResize = true; } - if(ArrayVisualizer.currentWidth() != ArrayVisualizer.windowWidth()) { + if (arrayVisualizer.currentWidth() != arrayVisualizer.windowWidth()) { windowUpdate = true; windowResize = true; } - if(ArrayVisualizer.currentX() != ArrayVisualizer.windowXCoordinate()) { + if (arrayVisualizer.currentX() != arrayVisualizer.windowXCoordinate()) { windowUpdate = true; } - if(ArrayVisualizer.currentY() != ArrayVisualizer.windowYCoordinate()) { + if (arrayVisualizer.currentY() != arrayVisualizer.windowYCoordinate()) { windowUpdate = true; } - + return new WindowState(windowUpdate, windowResize); } - - public void updateVisualsStart(ArrayVisualizer ArrayVisualizer) { - WindowState WindowState = checkWindowResizeAndReposition(ArrayVisualizer); - - if(WindowState.updated()) { - ArrayVisualizer.repositionFrames(); - ArrayVisualizer.updateCoordinates(); - + + public void updateVisualsStart(ArrayVisualizer arrayVisualizer) { + WindowState windowState = checkWindowResizeAndReposition(arrayVisualizer); + + if (windowState.updated()) { + arrayVisualizer.repositionFrames(); + arrayVisualizer.updateCoordinates(); + /* - if(v != null && v.isVisible()) + if (v != null && v.isVisible()) v.reposition(); */ - - if(WindowState.resized()) { - ArrayVisualizer.updateDimensions(); - updateGraphics(ArrayVisualizer); + + if (windowState.resized()) { + arrayVisualizer.updateDimensions(); + updateGraphics(arrayVisualizer); } } - - ArrayVisualizer.renderBackground(); - + + arrayVisualizer.renderBackground(); + //CURRENT = WINDOW //WINDOW = C VARIABLES - this.yscl = (double) (this.vsize) / ArrayVisualizer.getCurrentLength(); - - this.dotw = (int) (2 * (ArrayVisualizer.currentWidth() / 640.0)); + this.yScale = (double) (this.vsize) / arrayVisualizer.getCurrentLength(); + + this.dotw = (int) (2 * (arrayVisualizer.currentWidth() / 640.0)); - this.vsize = (ArrayVisualizer.currentHeight() - 96) / (ArrayVisualizer.externalArraysEnabled() ? Math.min(ArrayVisualizer.getArrays().size(), 7) : 1); - this.yoffset = 96; + this.vsize = (arrayVisualizer.currentHeight() - 96) / (arrayVisualizer.externalArraysEnabled() ? Math.min(arrayVisualizer.getArrays().size(), 7) : 1); + this.yoffset.set(96); } - private void updateVisualsPerArray(ArrayVisualizer ArrayVisualizer, int[] array, int length) { - + private void updateVisualsPerArray(ArrayVisualizer arrayVisualizer, int[] array, int length) { + //CURRENT = WINDOW //WINDOW = C VARIABLES - - this.xscl = (double) (ArrayVisualizer.currentWidth() - 40) / length; - + + this.xScale = (double) (arrayVisualizer.currentWidth() - 40) / length; + this.amt = 0; //TODO: rename to barCount - + this.linkedpixdrawx = 0; this.linkedpixdrawy = 0; - + this.doth = (int) (2 * (this.vsize / 480.0)); this.dots = (this.dotw + this.doth) / 2; //TODO: Does multiply/divide by 2 like this cancel out?? this.length = length; - - ArrayVisualizer.resetMainStroke(); + + arrayVisualizer.resetMainStroke(); } - - public void drawVisual(VisualStyles VisualStyles, int[][] arrays, ArrayVisualizer ArrayVisualizer, Highlights Highlights) { - if (ArrayVisualizer.externalArraysEnabled()) { + + public void drawVisual(VisualStyles visualStyle, int[][] arrays, ArrayVisualizer arrayVisualizer, Highlights Highlights) { + if (arrayVisualizer.externalArraysEnabled()) { this.auxActive = true; for (int i = Math.min(arrays.length - 1, 6); i > 0; i--) { if (arrays[i] != null) { - this.updateVisualsPerArray(ArrayVisualizer, arrays[i], arrays[i].length); - VisualStyles.drawVisual(arrays[i], ArrayVisualizer, this, Highlights); - this.yoffset += this.vsize; + this.updateVisualsPerArray(arrayVisualizer, arrays[i], arrays[i].length); + visualStyle.drawVisual(arrays[i], arrayVisualizer, this, Highlights); + this.yoffset.addAndGet(this.vsize); } } this.auxActive = false; } - this.updateVisualsPerArray(ArrayVisualizer, arrays[0], ArrayVisualizer.getCurrentLength()); - VisualStyles.drawVisual(arrays[0], ArrayVisualizer, this, Highlights); + this.updateVisualsPerArray(arrayVisualizer, arrays[0], arrayVisualizer.getCurrentLength()); + visualStyle.drawVisual(arrays[0], arrayVisualizer, this, Highlights); } -} \ No newline at end of file + + public boolean isAuxActive() { + return auxActive; + } + + public void setAuxActive(boolean auxActive) { + this.auxActive = auxActive; + } +} diff --git a/src/utils/Rotations.java b/src/main/java/io/github/arrayv/utils/Rotations.java similarity index 79% rename from src/utils/Rotations.java rename to src/main/java/io/github/arrayv/utils/Rotations.java index 7f74367b..c4b3384a 100644 --- a/src/utils/Rotations.java +++ b/src/main/java/io/github/arrayv/utils/Rotations.java @@ -1,14 +1,14 @@ -package utils; +package io.github.arrayv.utils; -import main.ArrayVisualizer; +import io.github.arrayv.main.ArrayVisualizer; -public class Rotations { - private static Writes Writes; - private static Highlights Highlights; +public final class Rotations { + // @checkstyle:off ConstantNameCheck - Unique case + private static final Writes Writes = ArrayVisualizer.getInstance().getWrites(); + private static final Highlights Highlights = ArrayVisualizer.getInstance().getHighlights(); + // @checkstyle:on ConstantNameCheck - public Rotations(ArrayVisualizer arrayVisualizer) { - Rotations.Writes = arrayVisualizer.getWrites(); - Rotations.Highlights = arrayVisualizer.getHighlights(); + private Rotations() { } // utility functions @@ -27,16 +27,16 @@ private static void blockSwap(int[] array, int a, int b, int len, double pause, private static void shiftForwards(int[] array, int start, int length, double pause, boolean mark, boolean auxwrite) { int temp = array[start]; if (mark) Highlights.clearMark(2); - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Writes.write(array, start + i, array[start + i + 1], pause, mark, auxwrite); } Writes.write(array, start + length, temp, pause, mark, auxwrite); } - private static void shiftBackwards(int[] array, int start, int length, double pause, boolean mark, boolean auxwrite) { + private static void shiftBackwards(int[] array, int start, int length, double pause, boolean mark, boolean auxwrite) { int temp = array[start + length]; if (mark) Highlights.clearMark(2); - for(int i = length; i > 0; i--) { + for (int i = length; i > 0; i--) { Writes.write(array, start + i, array[start + i - 1], pause, mark, auxwrite); } Writes.write(array, start, temp, pause, mark, auxwrite); @@ -55,13 +55,12 @@ private static int swap(int[] arr, int a, int v, double pause, boolean mark, boo // rotation algorithms public static void griesMills(int[] array, int pos, int lenA, int lenB, double pause, boolean mark, boolean auxwrite) { - while(lenA != 0 && lenB != 0) { - if(lenA <= lenB) { + while (lenA != 0 && lenB != 0) { + if (lenA <= lenB) { blockSwap(array, pos, pos + lenA, lenA, pause, mark, auxwrite); pos += lenA; lenB -= lenA; - } - else { + } else { blockSwap(array, pos + (lenA - lenB), pos + lenA, lenB, pause, mark, auxwrite); lenA -= lenB; } @@ -75,25 +74,24 @@ public static void threeReversal(int[] array, int pos, int lenA, int lenB, doubl } public static void holyGriesMills(int[] array, int pos, int lenA, int lenB, double pause, boolean mark, boolean auxwrite) { - while(lenA > 1 && lenB > 1) { - while(lenA <= lenB) { + while (lenA > 1 && lenB > 1) { + while (lenA <= lenB) { blockSwap(array, pos, pos + lenA, lenA, pause, mark, auxwrite); pos += lenA; lenB -= lenA; } - - if(lenA <= 1 || lenB <= 1) break; - - while(lenA > lenB) { + + if (lenA <= 1 || lenB <= 1) break; + + while (lenA > lenB) { swapBlocksBackwards(array, pos + lenA - lenB, pos + lenA, lenB, pause, mark, auxwrite); lenA -= lenB; } } - - if(lenA == 1) { + + if (lenA == 1) { shiftForwards(array, pos, lenB, pause, mark, auxwrite); - } - else if(lenB == 1) { + } else if (lenB == 1) { shiftBackwards(array, pos, lenA, pause, mark, auxwrite); } } @@ -110,15 +108,15 @@ public static void helium(int[] array, int pos, int lenA, int lenB, double pause lenB -= lenA; } } - + if (lenB == 1) shiftBackwards(array, pos, lenA, pause, mark, auxwrite); else if (lenA == 1) shiftForwards(array, pos, lenB, pause, mark, auxwrite); } // by Scandum and Control public static void cycleReverse(int[] array, int pos, int lenA, int lenB, double pause, boolean mark, boolean auxwrite) { - if(lenA < 1 || lenB < 1) return; - + if (lenA < 1 || lenB < 1) return; + int a = pos, b = pos + lenA - 1, c = pos + lenA, @@ -156,34 +154,35 @@ public static void juggling(int[] array, int pos, int lenA, int lenB, double pau if (lenA == 0) return; - for (int cnt = 0, - index = 0, - value = array[pos + index], - startIndex = index; - cnt < length; cnt++) { - int nextIndex = mapIndex(index, lenA, length); + for (int cnt = 0, + index = 0, + value = array[pos + index], + startIndex = index; + cnt < length; cnt++ + ) { + int nextIndex = mapIndex(index, lenA, length); - value = swap(array, pos + nextIndex, value, pause, mark, auxwrite); + value = swap(array, pos + nextIndex, value, pause, mark, auxwrite); - if (nextIndex == startIndex) { - startIndex = index = mapIndex(index, 1, length); - value = array[pos + index]; - } else { - index = nextIndex; - } + if (nextIndex == startIndex) { + startIndex = index = mapIndex(index, 1, length); + value = array[pos + index]; + } else { + index = nextIndex; + } } } - + //by Scandum public static void bridge(int[] array, int pos, int left, int right, double pause, boolean mark, boolean auxwrite) { - if(left < 1 || right < 1) return; - + if (left < 1 || right < 1) return; + int pta = pos, ptb = pos + left, ptc = pos + right, ptd = ptb + right, alloc; - if(left < right) { + if (left < right) { int bridge = right - left; - if(bridge < left) { + if (bridge < left) { int loop = left; int[] swap = new int[bridge]; @@ -192,55 +191,51 @@ public static void bridge(int[] array, int pos, int left, int right, double paus Writes.arraycopy(array, ptb, swap, 0, bridge, pause, mark, true); - while(loop-- > 0) { + while (loop-- > 0) { Writes.write(array, --ptc, array[--ptd], pause/2d, mark, auxwrite); Writes.write(array, ptd, array[--ptb], pause/2d, mark, auxwrite); } Writes.arraycopy(swap, 0, array, pta, bridge, pause, mark, auxwrite); - } - else { + } else { int[] swap = new int[left]; alloc = left; Writes.changeAllocAmount(alloc); - + Writes.arraycopy(array, pta, swap, 0, left, pause, mark, true); Writes.arraycopy(array, ptb, array, pta, right, pause, mark, auxwrite); Writes.arraycopy(swap, 0, array, ptc, left, pause, mark, auxwrite); } - } - else if(right < left) { + } else if (right < left) { int bridge = left - right; - if(bridge < right) { + if (bridge < right) { int loop = right; int[] swap = new int[bridge]; alloc = bridge; Writes.changeAllocAmount(alloc); - + Writes.arraycopy(array, ptc, swap, 0, bridge, pause, mark, true); - - while(loop-- > 0) { - Writes.write(array, ptc++, array[pta], pause/2d, mark, auxwrite); + + while (loop-- > 0) { + Writes.write(array, ptc++, array[pta], pause/2d, mark, auxwrite); Writes.write(array, pta++, array[ptb++], pause/2d, mark, auxwrite); } Writes.arraycopy(swap, 0, array, ptd - bridge, bridge, pause, mark, auxwrite); - } - else { + } else { int[] swap = new int[right]; alloc = right; Writes.changeAllocAmount(alloc); - + Writes.arraycopy(array, ptb, swap, 0, right, pause, mark, true); - while(left-- > 0) + while (left-- > 0) Writes.write(array, --ptd, array[--ptb], pause, mark, auxwrite); Writes.arraycopy(swap, 0, array, pta, right, pause, mark, auxwrite); } - } - else { + } else { alloc = 0; - - while(left-- > 0) + + while (left-- > 0) Writes.swap(array, pta++, ptb++, pause, mark, auxwrite); Highlights.clearMark(2); } diff --git a/src/utils/ShuffleGraph.java b/src/main/java/io/github/arrayv/utils/ShuffleGraph.java similarity index 76% rename from src/utils/ShuffleGraph.java rename to src/main/java/io/github/arrayv/utils/ShuffleGraph.java index 3e115723..1ec97f5c 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/main/java/io/github/arrayv/utils/ShuffleGraph.java @@ -1,31 +1,22 @@ -package utils; - -import java.awt.Graphics2D; -import java.awt.Point; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.shuffleutils.GraphConnection; +import io.github.arrayv.utils.shuffleutils.GraphNode; -import main.ArrayVisualizer; -import utils.shuffle_utils.GraphConnection; -import utils.shuffle_utils.GraphNode; +import java.awt.*; +import java.util.List; +import java.util.*; public class ShuffleGraph implements Collection { - public List nodes; - public List connections; - public GraphNode selected; - public GraphConnection dragging; - public GraphNode dragCandidate; - public double sleepRatio; - - final static int DEFAULT_TEXT_SIZE = 24; + private List nodes; + private List connections; + private GraphNode selected; + private GraphConnection dragging; + private GraphNode dragCandidate; + private double sleepRatio; + + static final int DEFAULT_TEXT_SIZE = 24; Map textSizes = new HashMap<>(); public ShuffleGraph() { @@ -103,7 +94,7 @@ public ShuffleGraph addSingle(Distributions distribution, boolean warped) { public Point findSafeCoordinates(int baseX, int baseY, int offsetX, int offsetY) { Point p = new Point(baseX, baseY); - while (this.nodes.stream().anyMatch(node -> node.x == p.x && node.y == p.y)) { + while (this.nodes.stream().anyMatch(node -> node.getX() == p.getX() && node.getY() == p.getY())) { p.x += offsetX; p.y += offsetY; } @@ -126,11 +117,7 @@ public Iterator iterateConnectedNodes() { } public Iterable connectedNodesIterable() { - return new Iterable() { - public Iterator iterator() { - return ShuffleGraph.this.iterateConnectedNodes(); - } - }; + return ShuffleGraph.this::iterateConnectedNodes; } public void draw(Graphics2D g) { @@ -146,7 +133,7 @@ public void drag(Point rel) { if (this.selected != null) { this.selected.drag(rel); } else if (this.dragging != null) { - Point pos = this.dragging.currentDragPos; + Point pos = this.dragging.getCurrentDragPos(); pos.translate(rel.x, rel.y); boolean foundCandidate = false; ListIterator it = this.nodes.listIterator(this.nodes.size()); @@ -176,7 +163,7 @@ public void select(Point pos) { int removed = 0; for (int i = 0; i < this.connections.size(); i++) { GraphConnection conn = this.connections.get(i - removed); - if (conn.from == node) { + if (conn.getFrom() == node) { this.connections.remove(i - removed); conn.remove(); removed++; @@ -184,7 +171,7 @@ public void select(Point pos) { } this.connections.add(newConnection); this.dragging = newConnection; - node.postConnection = newConnection; + node.setPostConnection(newConnection); this.selected = null; return; } @@ -233,32 +220,31 @@ public int size() { GraphNode node = this.nodes.get(0); while (node != null) { size++; - GraphConnection connect = node.postConnection; + GraphConnection connect = node.getPostConnection(); if (connect == null) { break; } - node = connect.to; + node = connect.getTo(); } return size - 1; } public void clear() { this.nodes.subList(1, this.nodes.size()).clear(); - this.nodes.get(0).postConnection = null; + this.nodes.get(0).setPostConnection(null); } public GraphNode findLast() { GraphNode previous = null; GraphNode node = this.nodes.get(0); while (node != null) { - GraphConnection connect = node.postConnection; + GraphConnection connect = node.getPostConnection(); if (connect == null) { previous = node; - node = null; break; } previous = node; - node = connect.to; + node = connect.getTo(); } return previous; } @@ -277,17 +263,17 @@ public boolean addAll(Collection c) { } GraphNode add(ShuffleInfo shuffle, GraphNode after) { - GraphNode newNode = new GraphNode(shuffle, this, after.x + GraphNode.WIDTH + 15, after.y); - if (after.postConnection == null) { - after.postConnection = new GraphConnection(after, newNode); - this.connections.add(after.postConnection); + GraphNode newNode = new GraphNode(shuffle, this, after.getX() + GraphNode.WIDTH + 15, after.getY()); + if (after.getPostConnection() == null) { + after.setPostConnection(new GraphConnection(after, newNode)); + this.connections.add(after.getPostConnection()); } else { - if (after.postConnection.to != null) { - after.postConnection.to.preConnection = null; + if (after.getPostConnection().getTo() != null) { + after.getPostConnection().getTo().setPreConnection(null); } - after.postConnection.to = newNode; + after.getPostConnection().setTo(newNode); } - newNode.preConnection = after.postConnection; + newNode.setPreConnection(after.getPostConnection()); this.nodes.add(newNode); return newNode; } @@ -298,11 +284,11 @@ GraphNode find(Object o) { } GraphNode node = this.nodes.get(0); while (node != null) { - GraphConnection connect = node.postConnection; + GraphConnection connect = node.getPostConnection(); if (connect == null) { break; } - node = connect.to; + node = connect.getTo(); if (node == null) { break; } @@ -352,11 +338,7 @@ public boolean retainAll(Collection c) { } public Object[] toArray() { - List result = new ArrayList<>(); - for (ShuffleInfo shuffle : this) { - result.add(shuffle); - } - return result.toArray(); + return new ArrayList<>(this).toArray(); } @SuppressWarnings("unchecked") @@ -371,11 +353,11 @@ public T[] toArray(T[] a) { int i = 0; GraphNode node = this.nodes.get(0); while (node != null) { - GraphConnection connect = node.postConnection; + GraphConnection connect = node.getPostConnection(); if (connect == null) { break; } - node = connect.to; + node = connect.getTo(); result[i++] = node.getValue(); } if (i < a.length - 1) { @@ -393,9 +375,61 @@ public Iterator iterator() { return new GraphIterator(this); } - protected class GraphIterator implements Iterator { + public List getNodes() { + return nodes; + } + + public void setNodes(List nodes) { + this.nodes = nodes; + } + + public List getConnections() { + return connections; + } + + public void setConnections(List connections) { + this.connections = connections; + } + + public GraphNode getSelected() { + return selected; + } + + public void setSelected(GraphNode selected) { + this.selected = selected; + } + + public GraphConnection getDragging() { + return dragging; + } + + public void setDragging(GraphConnection dragging) { + this.dragging = dragging; + } + + public GraphNode getDragCandidate() { + return dragCandidate; + } + + public void setDragCandidate(GraphNode dragCandidate) { + this.dragCandidate = dragCandidate; + } + + public double getSleepRatio() { + return sleepRatio; + } + + public Map getTextSizes() { + return textSizes; + } + + public void setTextSizes(Map textSizes) { + this.textSizes = textSizes; + } + + protected static class GraphIterator implements Iterator { NodeIterator it; - + GraphIterator(ShuffleGraph graph) { this.it = new NodeIterator(graph); } @@ -409,25 +443,22 @@ public ShuffleInfo next() { } public void remove() { - this.it.remove();; + this.it.remove(); } } - protected class NodeIterator implements Iterator { + protected static class NodeIterator implements Iterator { GraphNode currentNode, nextNode; - + NodeIterator(ShuffleGraph graph) { this.currentNode = graph.nodes.get(0); this.nextNode = findNext(); } GraphNode findNext() { - GraphConnection connect = this.currentNode.postConnection; + GraphConnection connect = this.currentNode.getPostConnection(); if (connect != null) { - GraphNode next = connect.to; - if (next != null) { - return next; - } + return connect.getTo(); } return null; } diff --git a/src/utils/ShuffleInfo.java b/src/main/java/io/github/arrayv/utils/ShuffleInfo.java similarity index 93% rename from src/utils/ShuffleInfo.java rename to src/main/java/io/github/arrayv/utils/ShuffleInfo.java index 1bcd7acd..7451f7a0 100644 --- a/src/utils/ShuffleInfo.java +++ b/src/main/java/io/github/arrayv/utils/ShuffleInfo.java @@ -1,11 +1,11 @@ -package utils; +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; import java.util.ArrayList; import java.util.List; -import main.ArrayVisualizer; - -final public class ShuffleInfo { +public final class ShuffleInfo { final boolean isDistribution; final Distributions distribution; final Shuffles shuffle; @@ -52,7 +52,7 @@ public boolean isDistribution() { public Distributions getDistribution() { return this.distribution; } - + public Shuffles getShuffle() { return this.shuffle; } @@ -85,15 +85,18 @@ public boolean equals(Object o) { public String getName() { if (this.isDistribution) { + assert this.distribution != null; if (warpDistribution) return "Warped " + this.distribution.getName(); return this.distribution.getName(); } + assert this.shuffle != null; return this.shuffle.getName(); } public void shuffle(int[] array, ArrayVisualizer arrayVisualizer) { if (this.isDistribution) { + assert distribution != null; Writes Writes = arrayVisualizer.getWrites(); int currentLen = arrayVisualizer.getCurrentLength(); double sleep = arrayVisualizer.shuffleEnabled() ? 1 : 0; @@ -111,6 +114,7 @@ public void shuffle(int[] array, ArrayVisualizer arrayVisualizer) { } } } else { + assert shuffle != null; Delays Delays = arrayVisualizer.getDelays(); Highlights Highlights = arrayVisualizer.getHighlights(); Writes Writes = arrayVisualizer.getWrites(); diff --git a/src/utils/Shuffles.java b/src/main/java/io/github/arrayv/utils/Shuffles.java similarity index 64% rename from src/utils/Shuffles.java rename to src/main/java/io/github/arrayv/utils/Shuffles.java index bef257ad..0b87beb8 100644 --- a/src/utils/Shuffles.java +++ b/src/main/java/io/github/arrayv/utils/Shuffles.java @@ -1,20 +1,19 @@ -package utils; +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.select.MaxHeapSort; +import io.github.arrayv.sorts.select.PoplarHeapSort; +import io.github.arrayv.sorts.select.SmoothSort; +import io.github.arrayv.sorts.select.TriangularHeapSort; +import io.github.arrayv.sorts.templates.PDQSorting; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Random; -import main.ArrayVisualizer; - -import sorts.select.PoplarHeapSort; -import sorts.select.SmoothSort; -import sorts.select.MaxHeapSort; -import sorts.select.TriangularHeapSort; -import sorts.templates.PDQSorting; - /* - * + * MIT License Copyright (c) 2020 ArrayV 4.0 Team @@ -44,14 +43,14 @@ public enum Shuffles { // If you want to learn why the random shuffle was changed, // I highly encourage you read this. It's quite fascinating: // http://datagenetics.com/blog/november42014/index.html - + public String getName() { return "Randomly"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); shuffle(array, 0, currentLen, delay ? 1 : 0, Writes); } }, @@ -60,9 +59,9 @@ public String getName() { return "Backwards"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); } }, @@ -71,14 +70,14 @@ public String getName() { return "Slight Shuffle"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); Random random = new Random(); - - for(int i = 0; i < Math.max(currentLen / 20, 1); i++){ + + for (int i = 0; i < Math.max(currentLen / 20, 1); i++){ Writes.swap(array, random.nextInt(currentLen), random.nextInt(currentLen), 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(10); + + if (arrayVisualizer.shuffleEnabled()) Delays.sleep(10); } } }, @@ -87,11 +86,11 @@ public String getName() { return "No Shuffle"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - for(int i = 0; i < currentLen; i++) { + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + for (int i = 0; i < currentLen; i++) { Highlights.markArray(1, i); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); + if (arrayVisualizer.shuffleEnabled()) Delays.sleep(1); } } }, @@ -100,9 +99,9 @@ public String getName() { return "Sorted"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); this.sort(array, 0, currentLen, delay ? 1 : 0, Writes); } }, @@ -111,12 +110,12 @@ public String getName() { return "Naive Randomly"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); Random random = new Random(); - - for(int i = 0; i < currentLen; i++) + + for (int i = 0; i < currentLen; i++) Writes.swap(array, i, random.nextInt(currentLen), delay ? 1 : 0, true, false); } }, @@ -125,9 +124,9 @@ public String getName() { return "Scrambled Tail"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); Random random = new Random(); int[] aux = new int[currentLen]; @@ -148,10 +147,10 @@ public String getName() { return "Scrambled Head"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + Random random = new Random(); int[] aux = new int[currentLen]; int i = currentLen - 1, j = currentLen - 1, k = 0; @@ -162,7 +161,7 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De else Writes.write(array, j--, array[i--], delay ? 1 : 0, true, false); } - Writes.reversearraycopy(aux, 0, array, 0, k, delay ? 1 : 0, true, false); + Writes.arraycopy(aux, 0, array, 0, k, delay ? 1 : 0, true, false); shuffle(array, 0, j, delay ? 2 : 0, Writes); } }, @@ -171,17 +170,16 @@ public String getName() { return "Shifted Element"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); Random random = new Random(); int start = random.nextInt(currentLen); int dest = random.nextInt(currentLen); if (dest < start) { IndexedRotations.holyGriesMills(array, dest, start, start + 1, delay ? 1 : 0, true, false); - } - else { + } else { IndexedRotations.holyGriesMills(array, start, start + 1, dest, delay ? 1 : 0, true, false); } } @@ -191,13 +189,13 @@ public String getName() { return "Noisy"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); Random random = new Random(); - + int i, size = Math.max(4, (int)(Math.sqrt(currentLen)/2)); - for(i = 0; i+size <= currentLen; i += random.nextInt(size-1)+1) + for (i = 0; i+size <= currentLen; i += random.nextInt(size-1)+1) shuffle(array, i, i+size, delay ? 0.5 : 0, Writes); shuffle(array, i, currentLen, delay ? 0.5 : 0, Writes); } @@ -207,15 +205,15 @@ public String getName() { return "Scrambled Odds"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); Random random = new Random(); - - for(int i = 1; i < currentLen; i += 2){ + + for (int i = 1; i < currentLen; i += 2){ int randomIndex = (((random.nextInt(currentLen - i) / 2)) * 2) + i; Writes.swap(array, i, randomIndex, 0, true, false); - - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(2); + + if (arrayVisualizer.shuffleEnabled()) Delays.sleep(2); } } }, @@ -224,19 +222,19 @@ public String getName() { return "Final Merge Pass"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); int count = 2; - + int k = 0; int[] temp = new int[currentLen]; - for(int j = 0; j < count; j++) - for(int i = j; i < currentLen; i+=count) + for (int j = 0; j < count; j++) + for (int i = j; i < currentLen; i+=count) Writes.write(temp, k++, array[i], 0, false, true); - - for(int i = 0; i < currentLen; i++) + + for (int i = 0; i < currentLen; i++) Writes.write(array, i, temp[i], delay ? 1 : 0, true, false); } }, @@ -245,10 +243,10 @@ public String getName() { return "Shuffled Final Merge"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + this.shuffle(array, 0, currentLen, delay ? 0.5 : 0, Writes); Highlights.clearMark(2); this.sort(array, 0, currentLen / 2, delay ? 0.5 : 0, Writes); @@ -260,10 +258,10 @@ public String getName() { return "Shuffled Half"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + this.shuffle(array, 0, currentLen, delay ? 2/3d : 0, Writes); Highlights.clearMark(2); this.sort(array, 0, currentLen / 2, delay ? 2/3d : 0, Writes); @@ -274,10 +272,10 @@ public String getName() { return "Partitioned"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + this.sort(array, 0, currentLen, delay ? 0.5 : 0, Writes); Highlights.clearMark(2); this.shuffle(array, 0, currentLen/2, delay ? 0.5 : 0, Writes); @@ -289,19 +287,19 @@ public String getName() { return "Sawtooth"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); int count = 4; - + int k = 0; int[] temp = new int[currentLen]; - for(int j = 0; j < count; j++) - for(int i = j; i < currentLen; i+=count) + for (int j = 0; j < count; j++) + for (int i = j; i < currentLen; i+=count) Writes.write(temp, k++, array[i], 0, false, true); - - for(int i = 0; i < currentLen; i++) + + for (int i = 0; i < currentLen; i++) Writes.write(array, i, temp[i], delay ? 1 : 0, true, false); } }, @@ -310,18 +308,18 @@ public String getName() { return "Pipe Organ"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); int[] temp = new int[currentLen]; - - for(int i = 0, j = 0; i < currentLen; i+=2){ + + for (int i = 0, j = 0; i < currentLen; i+=2){ temp[j++] = array[i]; } - for(int i = 1, j = currentLen; i < currentLen; i+=2) { + for (int i = 1, j = currentLen; i < currentLen; i+=2) { temp[--j] = array[i]; } - for(int i = 0; i < currentLen; i++){ + for (int i = 0; i < currentLen; i++){ Writes.write(array, i, temp[i], delay ? 1 : 0, true, false); } } @@ -331,20 +329,20 @@ public String getName() { return "Final Bitonic Pass"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); int[] temp = new int[currentLen]; - + Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); Highlights.clearMark(2); - for(int i = 0, j = 0; i < currentLen; i+=2){ + for (int i = 0, j = 0; i < currentLen; i+=2){ temp[j++] = array[i]; } - for(int i = 1, j = currentLen; i < currentLen; i+=2) { + for (int i = 1, j = currentLen; i < currentLen; i+=2) { temp[--j] = array[i]; } - for(int i = 0; i < currentLen; i++){ + for (int i = 0; i < currentLen; i++){ Writes.write(array, i, temp[i], delay ? 1 : 0, true, false); } } @@ -354,23 +352,20 @@ public String getName() { return "Interlaced"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + int[] referenceArray = new int[currentLen]; - for(int i = 0; i < currentLen; i++) { - referenceArray[i] = array[i]; - } + System.arraycopy(array, 0, referenceArray, 0, currentLen); int leftIndex = 1; int rightIndex = currentLen - 1; - for(int i = 1; i < currentLen; i++) { - if(i % 2 == 0) { + for (int i = 1; i < currentLen; i++) { + if (i % 2 == 0) { Writes.write(array, i, referenceArray[leftIndex++], delay ? 1 : 0, true, false); - } - else { + } else { Writes.write(array, i, referenceArray[rightIndex--], delay ? 1 : 0, true, false); } } @@ -381,12 +376,12 @@ public String getName() { return "Double Layered"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - - for(int i = 0; i < currentLen / 2; i += 2) { + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + + for (int i = 0; i < currentLen / 2; i += 2) { Writes.swap(array, i, currentLen - i - 1, 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); + if (arrayVisualizer.shuffleEnabled()) Delays.sleep(1); } } }, @@ -395,18 +390,18 @@ public String getName() { return "Final Radix"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); currentLen -= currentLen % 2; int mid = currentLen/2; int[] temp = new int[mid]; - for(int i = 0; i < mid; i++) + for (int i = 0; i < mid; i++) Writes.write(temp, i, array[i], 0, false, true); - for(int i = mid, j = 0; i < currentLen; i++, j+=2) { + for (int i = mid, j = 0; i < currentLen; i++, j+=2) { Writes.write(array, j, array[i], delay ? 1 : 0, true, false); Writes.write(array, j+1, temp[i-mid], delay ? 1 : 0, true, false); } @@ -417,28 +412,27 @@ public String getName() { return "Real Final Radix"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - - int mask = 0; - for(int i = 0; i < currentLen; i++) - while(mask < array[i]) mask = (mask << 1) + 1; - mask >>= 1; - - int[] counts = new int[mask+2]; - int[] tmp = new int[currentLen]; - - System.arraycopy(array, 0, tmp, 0, currentLen); - - for(int i = 0; i < currentLen; i++) - counts[(array[i]&mask)+1]++; - - for(int i = 1; i < counts.length; i++) - counts[i] += counts[i-1]; - - for(int i = 0; i < currentLen; i++) - Writes.write(array, counts[tmp[i]&mask]++, tmp[i], 1, true, false); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + + int mask = 0; + for (int i = 0; i < currentLen; i++) + while (mask < array[i]) mask = (mask << 1) + 1; + mask >>= 1; + + int[] counts = new int[mask+2]; + int[] tmp = new int[currentLen]; + + System.arraycopy(array, 0, tmp, 0, currentLen); + + for (int i = 0; i < currentLen; i++) + counts[(array[i]&mask)+1]++; + + for (int i = 1; i < counts.length; i++) + counts[i] += counts[i-1]; + + for (int i = 0; i < currentLen; i++) + Writes.write(array, counts[tmp[i]&mask]++, tmp[i], 1, true, false); } }, REC_RADIX { @@ -446,29 +440,29 @@ public String getName() { return "Recursive Final Radix"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + weaveRec(array, 0, currentLen, 1, delay ? 0.5 : 0, Writes); } public void weaveRec(int[] array, int pos, int length, int gap, double delay, Writes Writes) { - if(length < 2) return; - + if (length < 2) return; + int mod2 = length % 2; length -= mod2; int mid = length/2; int[] temp = new int[mid]; - - for(int i = pos, j = 0; i < pos+gap*mid; i+=gap, j++) + + for (int i = pos, j = 0; i < pos+gap*mid; i+=gap, j++) Writes.write(temp, j, array[i], 0, false, true); - - for(int i = pos+gap*mid, j = pos, k = 0; i < pos+gap*length; i+=gap, j+=2*gap, k++) { + + for (int i = pos+gap*mid, j = pos, k = 0; i < pos+gap*length; i+=gap, j+=2*gap, k++) { Writes.write(array, j, array[i], delay, true, false); Writes.write(array, j+gap, temp[k], delay, true, false); } - + weaveRec(array, pos, mid+mod2, 2*gap, delay/2, Writes); weaveRec(array, pos+gap, mid, 2*gap, delay/2, Writes); } @@ -478,19 +472,18 @@ public String getName() { return "Half Rotation"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - - int a = 0, m = (currentLen+1)/2; - - if(currentLen%2 == 0) - while(m < currentLen) Writes.swap(array, a++, m++, delay ? 1 : 0, true, false); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + + int a = 0, m = (currentLen + 1) / 2; + + if (currentLen % 2 == 0) + while (m < currentLen) Writes.swap(array, a++, m++, delay ? 1 : 0, true, false); else { Highlights.clearMark(2); int temp = array[a]; - while(m < currentLen) { + while (m < currentLen) { Writes.write(array, a++, array[m], delay ? 0.5 : 0, true, false); Writes.write(array, m++, array[a], delay ? 0.5 : 0, true, false); } @@ -503,10 +496,10 @@ public String getName() { return "Half Reversed"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); Writes.reversal(array, currentLen/4, (3*currentLen+3)/4-1, delay ? 1 : 0, true, false); } @@ -516,31 +509,31 @@ public String getName() { return "BST Traversal"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); int[] temp = Arrays.copyOf(array, currentLen); - + // credit to sam walko/anon class Subarray { - private int start; - private int end; + private final int start; + private final int end; Subarray(int start, int end) { this.start = start; this.end = end; } } - Queue q = new LinkedList(); + Queue q = new LinkedList<>(); q.add(new Subarray(0, currentLen)); int i = 0; - while(!q.isEmpty()) { + while (!q.isEmpty()) { Subarray sub = q.poll(); - if(sub.start != sub.end) { + if (sub.start != sub.end) { int mid = (sub.start + sub.end)/2; Writes.write(array, i, temp[mid], 0, true, false); - if(ArrayVisualizer.shuffleEnabled()) Delays.sleep(1); + if (arrayVisualizer.shuffleEnabled()) Delays.sleep(1); i++; q.add(new Subarray(sub.start, mid)); q.add(new Subarray(mid+1, sub.end)); @@ -553,40 +546,40 @@ public String getName() { return "Inverted BST"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); int[] temp = new int[currentLen]; - + // credit to sam walko/anon class Subarray { - private int start; - private int end; + private final int start; + private final int end; Subarray(int start, int end) { this.start = start; this.end = end; } } - Queue q = new LinkedList(); + Queue q = new LinkedList<>(); q.add(new Subarray(0, currentLen)); int i = 0; - while(!q.isEmpty()) { + while (!q.isEmpty()) { Subarray sub = q.poll(); - if(sub.start != sub.end) { + if (sub.start != sub.end) { int mid = (sub.start + sub.end)/2; Highlights.markArray(1, mid); Writes.write(temp, i, mid, 0, false, true); - if(delay) Delays.sleep(0.5); + if (delay) Delays.sleep(0.5); i++; q.add(new Subarray(sub.start, mid)); q.add(new Subarray(mid+1, sub.end)); } } int[] temp2 = Arrays.copyOf(array, currentLen); - for(i = 0; i < currentLen; i++) + for (i = 0; i < currentLen; i++) Writes.write(array, temp[i], temp2[i], delay ? 0.5 : 0, true, false); } }, @@ -595,16 +588,16 @@ public String getName() { return "Logarithmic Slopes"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); int[] temp = new int[currentLen]; - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) Writes.write(temp, i, array[i], 0, false, true); Writes.write(array, 0, 0, delay ? 1 : 0, true, false); - for(int i = 1; i < currentLen; i++) { + for (int i = 1; i < currentLen; i++) { int log = (int) (Math.log(i) / Math.log(2)); int power = (int) Math.pow(2, log); int value = temp[2 * (i - power) + 1]; @@ -617,11 +610,11 @@ public String getName() { return "Heapified"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - - MaxHeapSort heapSort = new MaxHeapSort(ArrayVisualizer); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + + MaxHeapSort heapSort = new MaxHeapSort(arrayVisualizer); heapSort.makeHeap(array, 0, currentLen, delay ? 1 : 0); } }, @@ -630,11 +623,10 @@ public String getName() { return "Smoothified"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); - SmoothSort smoothSort = new SmoothSort(ArrayVisualizer); + SmoothSort smoothSort = new SmoothSort(arrayVisualizer); smoothSort.smoothHeapify(array, currentLen); } }, @@ -643,11 +635,10 @@ public String getName() { return "Poplarified"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); - PoplarHeapSort poplarHeapSort = new PoplarHeapSort(ArrayVisualizer); + PoplarHeapSort poplarHeapSort = new PoplarHeapSort(arrayVisualizer); poplarHeapSort.poplarHeapify(array, 0, currentLen); } }, @@ -656,18 +647,18 @@ public String getName() { return "Triangular Heapified"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - - if(delay) Delays.setSleepRatio(Delays.getSleepRatio()*10); - else Delays.changeSkipped(true); - - TriangularHeapSort triangularHeapSort = new TriangularHeapSort(ArrayVisualizer); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + + if (delay) Delays.setSleepRatio(Delays.getSleepRatio()*10); + else Delays.changeSkipped(true); + + TriangularHeapSort triangularHeapSort = new TriangularHeapSort(arrayVisualizer); triangularHeapSort.triangularHeapify(array, currentLen); - - if(delay) Delays.setSleepRatio(Delays.getSleepRatio()/10); - else Delays.changeSkipped(false); + + if (delay) Delays.setSleepRatio(Delays.getSleepRatio()/10); + else Delays.changeSkipped(false); } }, CIRCLE { @@ -675,20 +666,21 @@ public String getName() { return "First Circle Pass"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - Reads Reads = ArrayVisualizer.getReads(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + Reads Reads = arrayVisualizer.getReads(); shuffle(array, 0, currentLen, delay ? 0.5 : 0, Writes); - + int n = 1; - for(; n < currentLen; n*=2); - + //noinspection StatementWithEmptyBody + for (; n < currentLen; n*=2); + circleSortRoutine(array, 0, n-1, currentLen, delay ? 0.5 : 0, Reads, Writes); } - - public void circleSortRoutine(int[] array, int lo, int hi, int end, double sleep, Reads Reads, Writes Writes) { + + public void circleSortRoutine(int[] array, int lo, int hi, int end, double sleep, Reads Reads, Writes Writes) { if (lo == hi) return; int high = hi; @@ -698,13 +690,13 @@ public void circleSortRoutine(int[] array, int lo, int hi, int end, double sleep while (lo < hi) { if (hi < end && Reads.compareIndices(array, lo, hi, sleep / 2, true) > 0) Writes.swap(array, lo, hi, sleep, true, false); - + lo++; hi--; } circleSortRoutine(array, low, low + mid, end, sleep/2, Reads, Writes); - if(low + mid + 1 < end) circleSortRoutine(array, low + mid + 1, high, end, sleep/2, Reads, Writes); + if (low + mid + 1 < end) circleSortRoutine(array, low + mid + 1, high, end, sleep/2, Reads, Writes); } }, PAIRWISE { @@ -712,16 +704,16 @@ public String getName() { return "Final Pairwise Pass"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - Reads Reads = ArrayVisualizer.getReads(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + Reads Reads = arrayVisualizer.getReads(); shuffle(array, 0, currentLen, delay ? 0.5 : 0, Writes); //create pairs - for(int i = 1; i < currentLen; i+=2) - if(Reads.compareIndices(array, i - 1, i, delay ? 0.5 : 0, true) > 0) + for (int i = 1; i < currentLen; i+=2) + if (Reads.compareIndices(array, i - 1, i, delay ? 0.5 : 0, true) > 0) Writes.swap(array, i-1, i, delay ? 0.5 : 0, true, false); Highlights.clearMark(2); @@ -729,14 +721,14 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De int[] temp = new int[currentLen]; //sort the smaller and larger of the pairs separately with pigeonhole sort - for(int m = 0; m < 2; m++) { - for(int k = m; k < currentLen; k+=2) + for (int m = 0; m < 2; m++) { + for (int k = m; k < currentLen; k+=2) Writes.write(temp, array[k], temp[array[k]] + 1, 0, false, true); int i = 0, j = m; - while(true) { - while(i < currentLen && temp[i] == 0) i++; - if(i >= currentLen) break; + while (true) { + while (i < currentLen && temp[i] == 0) i++; + if (i >= currentLen) break; Writes.write(array, j, i, delay ? 0.5 : 0, true, false); @@ -751,18 +743,18 @@ public String getName() { return "Recursive Reversal"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + reversalRec(array, 0, currentLen, delay ? 1 : 0, Writes); } - + public void reversalRec(int[] array, int a, int b, double sleep, Writes Writes) { - if(b-a < 2) return; - + if (b-a < 2) return; + Writes.reversal(array, a, b-1, sleep, true, false); - + int m = (a+b)/2; this.reversalRec(array, a, m, sleep/2, Writes); this.reversalRec(array, m, b, sleep/2, Writes); @@ -773,21 +765,21 @@ public String getName() { return "Gray Code Fractal"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + reversalRec(array, 0, currentLen, false, delay ? 1 : 0, Writes); } - + public void reversalRec(int[] array, int a, int b, boolean bw, double sleep, Writes Writes) { - if(b-a < 3) return; - + if (b-a < 3) return; + int m = (a+b)/2; - - if(bw) Writes.reversal(array, a, m-1, sleep, true, false); - else Writes.reversal(array, m, b-1, sleep, true, false); - + + if (bw) Writes.reversal(array, a, m-1, sleep, true, false); + else Writes.reversal(array, m, b-1, sleep, true, false); + this.reversalRec(array, a, m, false, sleep/2, Writes); this.reversalRec(array, m, b, true, sleep/2, Writes); } @@ -797,27 +789,27 @@ public String getName() { return "Sierpinski Triangle"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); int[] triangle = new int[currentLen]; triangleRec(triangle, 0, currentLen); - + int[] temp = Arrays.copyOf(array, currentLen); - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) Writes.write(array, i, temp[triangle[i]], 1, true, false); } - + public void triangleRec(int[] array, int a, int b) { - if(b-a < 2) return; - if(b-a == 2) { + if (b-a < 2) return; + if (b-a == 2) { array[a+1]++; return; } - + int h = (b-a)/3, t1 = (a+a+b)/3, t2 = (a+b+b+2)/3; - for(int i = a; i < t1; i++) array[i] += h; - for(int i = t1; i < t2; i++) array[i] += 2*h; - + for (int i = a; i < t1; i++) array[i] += h; + for (int i = t1; i < t2; i++) array[i] += 2*h; + triangleRec(array, a, t1); triangleRec(array, t1, t2); triangleRec(array, t2, b); @@ -828,35 +820,35 @@ public String getName() { return "Triangular"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); int[] triangle = new int[currentLen]; - + int j = 0, k = 2; int max = 0; - - for(int i = 1; i < currentLen; i++, j++) { - if(i == k) { + + for (int i = 1; i < currentLen; i++, j++) { + if (i == k) { j = 0; k *= 2; } triangle[i] = triangle[j]+1; - if(triangle[i] > max) max = triangle[i]; + if (triangle[i] > max) max = triangle[i]; } int[] cnt = new int[max+1]; - - for(int i = 0; i < currentLen; i++) + + for (int i = 0; i < currentLen; i++) cnt[triangle[i]]++; - - for(int i = 1; i < cnt.length; i++) + + for (int i = 1; i < cnt.length; i++) cnt[i] += cnt[i-1]; - - for(int i = currentLen-1; i >= 0; i--) + + for (int i = currentLen-1; i >= 0; i--) triangle[i] = --cnt[triangle[i]]; - + int[] temp = Arrays.copyOf(array, currentLen); - for(int i = 0; i < currentLen; i++) + for (int i = 0; i < currentLen; i++) Writes.write(array, i, temp[triangle[i]], delay ? 1 : 0, true, false); } }, @@ -865,11 +857,11 @@ public String getName() { return "Quicksort Adversary"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - - for(int j = currentLen-currentLen%2-2, i = j-1; i >= 0; i-=2, j--) + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + + for (int j = currentLen-currentLen%2-2, i = j-1; i >= 0; i-=2, j--) Writes.swap(array, i, j, delay ? 1 : 0, true, false); } }, @@ -885,18 +877,18 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De int gas, frozen, candidate; final class PDQPair { - private int pivotPosition; - private boolean alreadyPartitioned; - - public PDQPair(int pivotPos, boolean presorted) { + private final int pivotPosition; + private final boolean alreadyPartitioned; + + private PDQPair(int pivotPos, boolean presorted) { this.pivotPosition = pivotPos; this.alreadyPartitioned = presorted; } - + public int getPivotPosition() { return this.pivotPosition; } - + public boolean getPresortBool() { return this.alreadyPartitioned; } @@ -906,16 +898,16 @@ public String getName() { return "PDQ Adversary"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + delay = arrayVisualizer.shuffleEnabled(); sleep = delay ? 1 : 0; - this.Reads = ArrayVisualizer.getReads(); + this.Reads = arrayVisualizer.getReads(); this.Writes = Writes; this.Highlights = Highlights; int[] copy = new int[currentLen]; - + hasCandidate = false; frozen = 1; temp = new int[currentLen]; @@ -925,9 +917,9 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De Writes.write(array, i, i, 0, false, false); Writes.write(temp, i, gas, sleep, true, true); } - + pdqLoop(array, 0, currentLen, false, PDQSorting.pdqLog(currentLen)); - + for (int i = 0; i < currentLen; i++) { Writes.write(array, i, copy[temp[i] - 1], sleep, true, false); } @@ -943,13 +935,13 @@ protected int compare(int ap, int bp) { a = ap; b = bp; - + if (temp[a] == gas && temp[b] == gas) if (a == candidate) temp[a] = frozen++; else temp[b] = frozen++; - + if (temp[a] == gas) { candidate = a; return 1; @@ -960,25 +952,21 @@ protected int compare(int ap, int bp) { return -1; } - if (temp[a] < temp[b]) - return -1; - if (temp[a] > temp[b]) - return 1; - return 0; + return Integer.compare(temp[a], temp[b]); } - protected void pdqLoop(int[] array, int begin, int end, boolean Branchless, int badAllowed) { + protected void pdqLoop(int[] array, int begin, int end, boolean branchless, int badAllowed) { boolean leftmost = true; - + while (true) { int size = end - begin; - + if (size < 24) { if (leftmost) this.pdqInsertSort(array, begin, end); else this.pdqUnguardInsertSort(array, begin, end); return; } - + int halfSize = size / 2; if (size > 128) { this.pdqSortThree(array, begin, begin + halfSize, end - 1); @@ -988,72 +976,72 @@ protected void pdqLoop(int[] array, int begin, int end, boolean Branchless, int Writes.swap(array, begin, begin + halfSize, 1, true, false); Highlights.clearMark(2); } else this.pdqSortThree(array, begin + halfSize, begin, end - 1); - + if (!leftmost && !(compare(array[begin - 1], array[begin]) < 0)) { begin = this.pdqPartLeft(array, begin, end) + 1; continue; } - + PDQPair partResult = this.pdqPartRight(array, begin, end); - - int pivotPos = partResult.getPivotPosition(); - boolean alreadyParted = partResult.getPresortBool(); - - int leftSize = pivotPos - begin; - int rightSize = end - (pivotPos + 1); - boolean highUnbalance = leftSize < size / 8 || rightSize < size / 8; - - if (highUnbalance) { - if (--badAllowed == 0) { - int length = end - begin; - for (int i = length / 2; i >= 1; i--) { - siftDown(array, i, length, begin, sleep, true); - } - return; - } - - if (leftSize >= 24) { - Writes.swap(array, begin, begin + leftSize / 4, sleep, true, false); - Writes.swap(array, pivotPos-1, pivotPos - leftSize / 4, sleep, true, false); - - if (leftSize > 128) { - Writes.swap(array, begin+1, begin + (leftSize / 4 + 1), sleep, true, false); - Writes.swap(array, begin+2, begin + (leftSize / 4 + 2), sleep, true, false); - Writes.swap(array, pivotPos-2, pivotPos - (leftSize / 4 + 1), sleep, true, false); - Writes.swap(array, pivotPos-3, pivotPos - (leftSize / 4 + 2), sleep, true, false); - } - } - - if (rightSize >= 24) { - Writes.swap(array, pivotPos+1, pivotPos + (1 + rightSize / 4), sleep, true, false); - Writes.swap(array, end-1, end - rightSize / 4, sleep, true, false); - - if (rightSize > 128) { - Writes.swap(array, pivotPos+2, pivotPos + (2 + rightSize / 4), sleep, true, false); - Writes.swap(array, pivotPos+3, pivotPos + (3 + rightSize / 4), sleep, true, false); - Writes.swap(array, end-2, end - (1 + rightSize / 4), sleep, true, false); - Writes.swap(array, end-3, end - (2 + rightSize / 4), sleep, true, false); - } - } - Highlights.clearMark(2); - } else { - if (alreadyParted && pdqPartialInsertSort(array, begin, pivotPos) - && pdqPartialInsertSort(array, pivotPos + 1, end)) - return; + + int pivotPos = partResult.getPivotPosition(); + boolean alreadyParted = partResult.getPresortBool(); + + int leftSize = pivotPos - begin; + int rightSize = end - (pivotPos + 1); + boolean highUnbalance = leftSize < size / 8 || rightSize < size / 8; + + if (highUnbalance) { + if (--badAllowed == 0) { + int length = end - begin; + for (int i = length / 2; i >= 1; i--) { + siftDown(array, i, length, begin, sleep, true); + } + return; + } + + if (leftSize >= 24) { + Writes.swap(array, begin, begin + leftSize / 4, sleep, true, false); + Writes.swap(array, pivotPos-1, pivotPos - leftSize / 4, sleep, true, false); + + if (leftSize > 128) { + Writes.swap(array, begin+1, begin + (leftSize / 4 + 1), sleep, true, false); + Writes.swap(array, begin+2, begin + (leftSize / 4 + 2), sleep, true, false); + Writes.swap(array, pivotPos-2, pivotPos - (leftSize / 4 + 1), sleep, true, false); + Writes.swap(array, pivotPos-3, pivotPos - (leftSize / 4 + 2), sleep, true, false); } - - this.pdqLoop(array, begin, pivotPos, Branchless, badAllowed); - begin = pivotPos + 1; - leftmost = false; + } + + if (rightSize >= 24) { + Writes.swap(array, pivotPos+1, pivotPos + (1 + rightSize / 4), sleep, true, false); + Writes.swap(array, end-1, end - rightSize / 4, sleep, true, false); + + if (rightSize > 128) { + Writes.swap(array, pivotPos+2, pivotPos + (2 + rightSize / 4), sleep, true, false); + Writes.swap(array, pivotPos+3, pivotPos + (3 + rightSize / 4), sleep, true, false); + Writes.swap(array, end-2, end - (1 + rightSize / 4), sleep, true, false); + Writes.swap(array, end-3, end - (2 + rightSize / 4), sleep, true, false); + } + } + Highlights.clearMark(2); + } else { + if (alreadyParted && pdqPartialInsertSort(array, begin, pivotPos) + && pdqPartialInsertSort(array, pivotPos + 1, end)) + return; + } + + this.pdqLoop(array, begin, pivotPos, branchless, badAllowed); + begin = pivotPos + 1; + leftmost = false; } } private void siftDown(int[] array, int root, int dist, int start, double sleep, boolean isMax) { - int compareVal = 0; - - if(isMax) compareVal = -1; + int compareVal; + + if (isMax) compareVal = -1; else compareVal = 1; - + while (root <= dist / 2) { int leaf = 2 * root; if (leaf < dist && compare(array[start + leaf - 1], array[start + leaf]) == compareVal) { @@ -1064,8 +1052,7 @@ private void siftDown(int[] array, int root, int dist, int start, double sleep, if (compare(array[start + root - 1], array[start + leaf - 1]) == compareVal) { Writes.swap(array, start + root - 1, start + leaf - 1, 0, true, false); root = leaf; - } - else break; + } else break; } } @@ -1073,22 +1060,22 @@ private PDQPair pdqPartRight(int[] array, int begin, int end) { int pivot = array[begin]; int first = begin; int last = end; - + while (compare(array[++first], pivot) < 0) { Highlights.markArray(1, first); } - - if (first - 1 == begin) + + if (first - 1 == begin) while (first < last && !(compare(array[--last], pivot) < 0)) { Highlights.markArray(2, last); } else - while ( !(compare(array[--last], pivot) < 0)) { + while (!(compare(array[--last], pivot) < 0)) { Highlights.markArray(2, last); } - + boolean alreadyParted = first >= last; - + while (first < last) { Writes.swap(array, first, last, 1, true, false); while (compare(array[++first], pivot) < 0) { @@ -1099,11 +1086,11 @@ private PDQPair pdqPartRight(int[] array, int begin, int end) { } } Highlights.clearMark(2); - + int pivotPos = first - 1; Writes.write(array, begin, array[pivotPos], delay ? 1 : 0, true, false); Writes.write(array, pivotPos, pivot, delay ? 1 : 0, true, false); - + return new PDQPair(pivotPos, alreadyParted); } @@ -1122,7 +1109,7 @@ private boolean pdqPartialInsertSort(int[] array, int begin, int end) { if (compare(array[sift], array[siftMinusOne]) < 0) { int tmp = array[sift]; - do { + do { Writes.write(array, sift--, array[siftMinusOne], sleep, true, false); } while (sift != begin && compare(tmp, array[--siftMinusOne]) < 0); @@ -1137,20 +1124,20 @@ private int pdqPartLeft(int[] array, int begin, int end) { int pivot = array[begin]; int first = begin; int last = end; - + while (compare(pivot, array[--last]) < 0) { Highlights.markArray(2, last); } - - if (last + 1 == end) + + if (last + 1 == end) while (first < last && !(compare(pivot, array[++first]) < 0)) { Highlights.markArray(1, first); } - else - while ( !(compare(pivot, array[++first]) < 0)) { + else + while (!(compare(pivot, array[++first]) < 0)) { Highlights.markArray(1, first); } - + while (first < last) { Writes.swap(array, first, last, 1, true, false); while (compare(pivot, array[--last]) < 0) { @@ -1161,11 +1148,11 @@ private int pdqPartLeft(int[] array, int begin, int end) { } } Highlights.clearMark(2); - + int pivotPos = last; Writes.write(array, begin, array[pivotPos], delay ? 1 : 0, true, false); Writes.write(array, pivotPos, pivot, delay ? 1 : 0, true, false); - + return pivotPos; } @@ -1215,7 +1202,7 @@ private void pdqUnguardInsertSort(int[] array, int begin, int end) { int tmp = array[sift]; do { - Writes.write(array, sift--, array[siftMinusOne], sleep, true, false); + Writes.write(array, sift--, array[siftMinusOne], sleep, true, false); } while (compare(tmp, array[--siftMinusOne]) < 0); Writes.write(array, sift, tmp, sleep, true, false); @@ -1228,51 +1215,51 @@ public String getName() { return "Grailsort Adversary"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - - if(currentLen <= 16) Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + + if (currentLen <= 16) Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); else { int blockLen = 1; - while(blockLen * blockLen < currentLen) blockLen *= 2; - + while (blockLen * blockLen < currentLen) blockLen *= 2; + int numKeys = (currentLen - 1) / blockLen + 1; int keys = blockLen + numKeys; - + shuffle(array, 0, currentLen, delay ? 0.25 : 0, Writes); sort(array, 0, keys, delay ? 0.25 : 0, Writes); Writes.reversal(array, 0, keys-1, delay ? 0.25 : 0, true, false); Highlights.clearMark(2); sort(array, keys, currentLen, delay ? 0.25 : 0, Writes); - + push(array, keys, currentLen, blockLen, delay ? 0.25 : 0, Writes); } } - + public void rotate(int[] array, int a, int m, int b, double sleep, Writes Writes) { Writes.reversal(array, a, m-1, sleep, true, false); Writes.reversal(array, m, b-1, sleep, true, false); Writes.reversal(array, a, b-1, sleep, true, false); } - + public void push(int[] array, int a, int b, int bLen, double sleep, Writes Writes) { int len = b-a, b1 = b - len%bLen, len1 = b1-a; - if(len1 <= 2*bLen) return; - + if (len1 <= 2*bLen) return; + int m = bLen; - while(2*m < len) m *= 2; + while (2*m < len) m *= 2; m += a; - - if(b1-m < bLen) push(array, a, m, bLen, sleep, Writes); + + if (b1-m < bLen) push(array, a, m, bLen, sleep, Writes); else { m = a+b1-m; rotate(array, m-(bLen-2), b1-(bLen-1), b1, sleep, Writes); Writes.multiSwap(array, a, m, sleep/2, true, false); rotate(array, a, m, b1, sleep, Writes); m = a+b1-m; - + push(array, a, m, bLen, sleep/2, Writes); push(array, m, b, bLen, sleep/2, Writes); } @@ -1283,27 +1270,27 @@ public String getName() { return "Shuffle Merge Adversary"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int n = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int n = arrayVisualizer.getCurrentLength(); + boolean delay = arrayVisualizer.shuffleEnabled(); + int[] tmp = new int[n]; int d = 2, end = 1 << (int)(Math.log(n-1)/Math.log(2) + 1); - - while(d <= end) { + + while (d <= end) { int i = 0, dec = 0; double sleep = 1d/d; - - while(i < n) { + + while (i < n) { int j = i; dec += n; - while(dec >= d) { + while (dec >= d) { dec -= d; j++; } int k = j; dec += n; - while(dec >= d) { + while (dec >= d) { dec -= d; k++; } @@ -1313,31 +1300,31 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De d *= 2; } } - + public void shuffleMergeBad(int[] array, int[] tmp, int a, int m, int b, double sleep, Writes Writes) { - if((b-a)%2 == 1) { - if(m-a > b-m) a++; - else b--; + if ((b-a)%2 == 1) { + if (m-a > b-m) a++; + else b--; } shuffleBad(array, tmp, a, b, sleep, Writes); } - + //length is always even public void shuffleBad(int[] array, int[] tmp, int a, int b, double sleep, Writes Writes) { - if(b-a < 2) return; - + if (b-a < 2) return; + int m = (a+b)/2; int s = (b-a-1)/4+1; - + a = m-s; b = m+s; int j = a; - - for(int i = a+1; i < b; i += 2) + + for (int i = a+1; i < b; i += 2) Writes.write(tmp, j++, array[i], sleep, true, true); - for(int i = a; i < b; i += 2) + for (int i = a; i < b; i += 2) Writes.write(tmp, j++, array[i], sleep, true, true); - + Writes.arraycopy(tmp, a, array, a, b-a, sleep, true, false); } }, @@ -1347,49 +1334,50 @@ public String getName() { return "Bit Reversal"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - int len = 1 << (int)(Math.log(ArrayVisualizer.getCurrentLength())/Math.log(2)); - boolean delay = ArrayVisualizer.shuffleEnabled(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); + int len = 1 << (int)(Math.log(arrayVisualizer.getCurrentLength())/Math.log(2)); + boolean delay = arrayVisualizer.shuffleEnabled(); boolean pow2 = len == currentLen; - + int[] temp = Arrays.copyOf(array, currentLen); - for(int i = 0; i < len; i++) array[i] = i; - + for (int i = 0; i < len; i++) array[i] = i; + int m = 0; int d1 = len>>1, d2 = d1+(d1>>1); - - for(int i = 1; i < len-1; i++) { + + for (int i = 1; i < len-1; i++) { int j = d1; - - for( - int k = i, n = d2; - (k&1) == 0; + + //noinspection StatementWithEmptyBody + for ( + int k = i, n = d2; + (k&1) == 0; j -= n, k >>= 1, n >>= 1 ); m += j; - if(m > i) Writes.swap(array, i, m, delay ? 1 : 0, true, false); + if (m > i) Writes.swap(array, i, m, delay ? 1 : 0, true, false); } Highlights.clearMark(2); - - if(!pow2) { - for(int i = len; i < currentLen; i++) + + if (!pow2) { + for (int i = len; i < currentLen; i++) Writes.write(array, i, array[i-len], 0.5, true, false); - + int[] cnt = new int[len]; - - for(int i = 0; i < currentLen; i++) + + for (int i = 0; i < currentLen; i++) cnt[array[i]]++; - - for(int i = 1; i < cnt.length; i++) + + for (int i = 1; i < cnt.length; i++) cnt[i] += cnt[i-1]; - - for(int i = currentLen-1; i >= 0; i--) + + for (int i = currentLen-1; i >= 0; i--) Writes.write(array, i, --cnt[array[i]], 0.5, true, false); } int[] bits = Arrays.copyOf(array, currentLen); - - for(int i = 0; i < currentLen; i++) + + for (int i = 0; i < currentLen; i++) Writes.write(array, i, temp[bits[i]], 0, true, false); } }, @@ -1399,13 +1387,13 @@ public String getName() { return "Randomly w/ Blocks"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); int blockSize = pow2lte((int)Math.sqrt(currentLen)); currentLen -= currentLen%blockSize; - boolean delay = ArrayVisualizer.shuffleEnabled(); + boolean delay = arrayVisualizer.shuffleEnabled(); double sleep = delay ? 1 : 0; - + Random random = new Random(); for (int i = 0; i < currentLen; i += blockSize) { int randomIndex = random.nextInt((currentLen - i) / blockSize) * blockSize + i; @@ -1421,6 +1409,7 @@ private void blockSwap(int[] array, int a, int b, int len, Writes Writes, double private int pow2lte(int value) { int val; + //noinspection StatementWithEmptyBody for (val = 1; val <= value; val <<= 1); return val >> 1; } @@ -1431,13 +1420,13 @@ public String getName() { return "Block Reverse"; } @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { + int currentLen = arrayVisualizer.getCurrentLength(); int blockSize = pow2lte((int)Math.sqrt(currentLen)); currentLen -= currentLen % blockSize; - boolean delay = ArrayVisualizer.shuffleEnabled(); + boolean delay = arrayVisualizer.shuffleEnabled(); double sleep = delay ? 1 : 0; - + int i = 0, j = currentLen - blockSize; while (i < j) { blockSwap(array, i, j, blockSize, Writes, sleep); @@ -1454,41 +1443,42 @@ private void blockSwap(int[] array, int a, int b, int len, Writes Writes, double private int pow2lte(int value) { int val; + //noinspection StatementWithEmptyBody for (val = 1; val <= value; val <<= 1); return val >> 1; } }; - + public void sort(int[] array, int start, int end, double sleep, Writes Writes) { int min = array[start], max = min; - for(int i = start+1; i < end; i++) { - if(array[i] < min) min = array[i]; - else if(array[i] > max) max = array[i]; + for (int i = start+1; i < end; i++) { + if (array[i] < min) min = array[i]; + else if (array[i] > max) max = array[i]; } - + int size = max - min + 1; int[] holes = new int[size]; - - for(int i = start; i < end; i++) + + for (int i = start; i < end; i++) Writes.write(holes, array[i] - min, holes[array[i] - min] + 1, 0, false, true); - - for(int i = 0, j = start; i < size; i++) { - while(holes[i] > 0) { + + for (int i = 0, j = start; i < size; i++) { + while (holes[i] > 0) { Writes.write(holes, i, holes[i] - 1, 0, false, true); Writes.write(array, j, i + min, sleep, true, false); j++; } } } - + public void shuffle(int[] array, int start, int end, double sleep, Writes Writes) { Random random = new Random(); - for(int i = start; i < end; i++){ + for (int i = start; i < end; i++){ int randomIndex = random.nextInt(end - i) + i; Writes.swap(array, i, randomIndex, sleep, true, false); } } - + public abstract String getName(); - public abstract void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes); -} \ No newline at end of file + public abstract void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes); +} diff --git a/src/main/java/io/github/arrayv/utils/SortingNetworkGenerator.java b/src/main/java/io/github/arrayv/utils/SortingNetworkGenerator.java new file mode 100644 index 00000000..d9dad1e9 --- /dev/null +++ b/src/main/java/io/github/arrayv/utils/SortingNetworkGenerator.java @@ -0,0 +1,290 @@ +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; + +import javax.swing.*; +import java.awt.*; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public final class SortingNetworkGenerator { + private static final File SORTING_NETWORKS_DIR = new File("sorting_networks"); + + static { + SORTING_NETWORKS_DIR.mkdirs(); + } + + private static final class Comparator { + final int i1, i2; + + Comparator(int i1, int i2) { + this.i1 = i1; + this.i2 = i2; + } + + @Override + public String toString() { + return i1 + ":" + i2; + } + + @Override + public int hashCode() { + return (i1 << 16) + i2; + } + + boolean overlaps(Comparator other) { + return this.i2 > other.i1 && other.i2 > this.i1; + } + + boolean hasSameInput(Comparator other) { + return this.i1 == other.i1 || + this.i1 == other.i2 || + this.i2 == other.i1 || + this.i2 == other.i2; + } + } + + private static final class WriterBuilderProxy { + final PrintWriter writer; + final StringBuilder builder; + + WriterBuilderProxy(PrintWriter writer) { + this.writer = writer; + this.builder = null; + } + + WriterBuilderProxy(StringBuilder builder) { + this.writer = null; + this.builder = builder; + } + + void write(String s) { + if (builder == null) { + assert writer != null; + writer.write(s); + } else { + builder.append(s); + } + } + + @Override + public String toString() { + if (builder == null) { + assert writer != null; + return writer.toString(); + } else { + return builder.toString(); + } + } + + String getValue() { + if (builder == null) { + throw new IllegalStateException("Cannot getValue() of PrintWriter"); + } + return builder.toString(); + } + } + + private static final int OUT_BUFFER_SIZE = 8192; // 16 KB + + private SortingNetworkGenerator() { + } + + private static boolean encodeNetwork0(final Comparator[] comparators, final int n, final PrintWriter out) { + int scale = 1; + int xScale = scale * 36; + int yScale = scale * 20; + boolean small = comparators.length < 500_000; + + int h = (n + 1) * yScale; + int w = xScale; + List groupComparators = new ArrayList<>(); + List groupPositions = new ArrayList<>(); + + WriterBuilderProxy writer; + ProgressMonitor monitor; + int progress = 0; + out.write(""); + if (small) { + writer = new WriterBuilderProxy(new StringBuilder()); + monitor = new ProgressMonitor( + ArrayVisualizer.getInstance().getWindow(), + "Visualizing sorting network...", + "Generating SVG", + 0, comparators.length + ); + } else { + monitor = new ProgressMonitor( + ArrayVisualizer.getInstance().getWindow(), + "Visualizing sorting network...", + "Pre-calculating image width", + 0, comparators.length * 2 + ); + for (Comparator c : comparators) { + for (Comparator other : groupComparators) { + if (c.hasSameInput(other)) { + for (int otherX : groupPositions) { + if (otherX > w) { + w = otherX; + } + } + w += xScale; + groupComparators.clear(); + groupPositions.clear(); + break; + } + } + int cx = w; + Iterator groupPositionIterator = groupPositions.iterator(); + for (Comparator other : groupComparators) { + // We don't need hasNext checks because groupPositions and + // groupComparators have the same length + int otherX = groupPositionIterator.next(); + if (otherX >= cx && c.overlaps(other)) { + cx = otherX + xScale / 3; + } + } + groupComparators.add(c); + groupPositions.add(cx); + + if ((++progress & 1023) == 0) { + monitor.setProgress(progress); + if (monitor.isCanceled()) return true; + } + } + groupComparators.clear(); + groupPositions.clear(); + monitor.setNote("Writing SVG"); + out.write(""); + w = xScale; + + writer = new WriterBuilderProxy(out); + } + + for (Comparator c : comparators) { + for (Comparator other : groupComparators) { + if (c.hasSameInput(other)) { + for (int otherX : groupPositions) { + if (otherX > w) { + w = otherX; + } + } + w += xScale; + groupComparators.clear(); + groupPositions.clear(); + break; + } + } + + int cx = w; + Iterator groupPositionIterator = groupPositions.iterator(); + for (Comparator other : groupComparators) { + // We don't need hasNext checks because groupPositions and + // groupComparators have the same length + int otherX = groupPositionIterator.next(); + if (otherX >= cx && c.overlaps(other)) { + cx = otherX + xScale / 3; + } + } + + int y0 = (c.i1 + 1) * yScale; + int y1 = (c.i2 + 1) * yScale; + writer.write("" + + "" + + ""); + groupComparators.add(c); + groupPositions.add(cx); + + if ((++progress & 1023) == 0) { + monitor.setProgress(progress); + if (monitor.isCanceled()) return true; + } + } + groupComparators.clear(); + groupPositions.clear(); + + w += xScale; + for (int i = 0; i < n; i++) { + int y = yScale + i * yScale; + writer.write(""); + } + + if (small) { + monitor.setNote("Writing SVG to file"); + out.write(""); + out.write(writer.getValue()); + } + out.write(""); + monitor.close(); + return false; + } + + public static boolean encodeNetwork(Comparator[] comparators, int inputLength, File file) { + try (PrintWriter out = new PrintWriter( + new BufferedWriter( + new OutputStreamWriter( + new FileOutputStream(file), StandardCharsets.UTF_8 + ), OUT_BUFFER_SIZE), + false) + ) { + boolean cancelled = encodeNetwork0(comparators, inputLength, out); + if (cancelled) { + JOptionPane.showMessageDialog(null, "Sorting network visualization cancelled", + "Sorting Network Visualizer", JOptionPane.INFORMATION_MESSAGE); + return false; + } + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e, "Sorting Network Visualizer"); + return false; + } + return true; + } + + public static File encodeNetworkAndDisplay(String name, ArrayList indices, int arrayLength) { + Comparator[] comparators; + try { + comparators = new Comparator[indices.size() / 2]; + for (int i = 0, j = 1; i < comparators.length; i++, j += 2) { + comparators[i] = new Comparator(indices.get(j - 1), indices.get(j)); + } + } catch (OutOfMemoryError e) { + JErrorPane.invokeErrorMessage(e, "Sorting Network Visualizer"); + return null; + } + System.out.println("Length: " + arrayLength + "\tComparators: " + comparators.length / 2); + indices.clear(); + indices.trimToSize(); + File file = new File(SORTING_NETWORKS_DIR, "network_" + name + "_" + arrayLength + ".svg"); + try { + if (!encodeNetwork(comparators, arrayLength, file)) { + return null; + } + } catch (OutOfMemoryError e) { + JErrorPane.invokeCustomErrorMessage( + "ArrayV ran out of memory trying to visualize this sorting network.\n" + + "Either run ArrayV with more memory (or a smaller maximum length) or contemplate your life choices." + ); + return null; + } + boolean shouldOpen = JOptionPane.showConfirmDialog( + ArrayVisualizer.getInstance().getMainWindow(), + "Successfully saved output to file \"" + file + "\"\nWould you like to open it now?", + "Sorting Network Visualizer", + JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE + ) == JOptionPane.YES_OPTION; // false on NO_OPION or CLOSED_OPTION + if (shouldOpen) { + Desktop desktop = Desktop.getDesktop(); + try { + desktop.open(file); + } catch (IOException e) { + JErrorPane.invokeErrorMessage(e, "Open Sorting Network SVG"); + } + } + return file; + } +} diff --git a/src/utils/Sounds.java b/src/main/java/io/github/arrayv/utils/Sounds.java similarity index 59% rename from src/utils/Sounds.java rename to src/main/java/io/github/arrayv/utils/Sounds.java index 1cd9c2f5..ce128033 100644 --- a/src/utils/Sounds.java +++ b/src/main/java/io/github/arrayv/utils/Sounds.java @@ -1,30 +1,26 @@ -package utils; +package io.github.arrayv.utils; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; +import io.github.arrayv.dialogs.LoadingDialog; +import io.github.arrayv.dialogs.SoundbankDialog; +import io.github.arrayv.frames.SoundFrame; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; -import javax.sound.midi.Instrument; -import javax.sound.midi.InvalidMidiDataException; -import javax.sound.midi.MidiChannel; -import javax.sound.midi.MidiSystem; -import javax.sound.midi.MidiUnavailableException; -import javax.sound.midi.Synthesizer; -import javax.swing.JOptionPane; - -import dialogs.LoadingDialog; -import dialogs.SoundbankDialog; -import frames.SoundFrame; -import main.ArrayVisualizer; -import panes.JErrorPane; -import resources.soundfont.SFXFetcher; +import javax.sound.midi.*; +import javax.sound.sampled.SourceDataLine; +import javax.swing.*; +import java.io.*; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; /* - * + * MIT License Copyright (c) 2019 w0rthy +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -46,87 +42,116 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Sounds { - private int[] array; - - private ArrayVisualizer ArrayVisualizer; - - private Thread AudioThread; - - private Highlights Highlights; - +public final class Sounds { + private static final boolean ALLOW_PERCUSSION_SOUNDS = Boolean.getBoolean("arrayv.allowPercussion"); + private static final boolean DISABLE_JITTER_CORRECTION = Boolean.getBoolean("arrayv.disableJitterCorrection"); + + private static final Class SOFT_SYNTHESIZER_CLASS; + + static { + if (DISABLE_JITTER_CORRECTION) { + Class synthesizerClass; + try { + synthesizerClass = Class.forName("com.sun.media.sound.SoftSynthesizer"); + } catch (Exception e) { + synthesizerClass = null; + } + SOFT_SYNTHESIZER_CLASS = synthesizerClass; + } else { + SOFT_SYNTHESIZER_CLASS = null; + } + } + + private final int[] array; + + private final ArrayVisualizer arrayVisualizer; + + private final Thread audioThread; + + private final Highlights Highlights; + private volatile Synthesizer synth; private volatile MidiChannel[] channels; - + private volatile int noteDelay; - + private boolean soundEnabled; - - private volatile boolean SOUND; - private volatile boolean MIDI; - private int NUMCHANNELS; //Number of Audio Channels - private double PITCHMIN; //Minimum Pitch - private double PITCHMAX; //Maximum Pitch - private double SOUNDMUL; - private boolean SOFTERSOUNDS; - - final private int SUSTAIN_PEDAL = 64; - final private int REVERB = 91; - - private String defaultSoundbank = "Default (Yamaha XG Sound Set)"; + + private volatile boolean playSound; + private volatile boolean playSound2; // Yes there're really two fields that are used at different times + private final int numChannels; //Number of Audio Channels + private final double pitchMin; //Minimum Pitch + private final double pitchMax; //Maximum Pitch + private double soundMultiplier; + private boolean softerSounds; + + private static final int SUSTAIN_PEDAL = 64; + private static final int REVERB = 91; + private String selectedSoundbank; - + private int sineWaveIndex; - final private int DEFAULT_SINE_WAVE_INDEX = 193; - final private int DEFAULT_ROCK_ORGAN_INDEX = 16; - + private static final int DEFAULT_SINE_WAVE_INDEX = 193; + private static final int DEFAULT_ROCK_ORGAN_INDEX = 16; + private volatile LoadingDialog infoMsg; - + private volatile int instrumentChoice; private volatile int testInstrumentChoice; - - @SuppressWarnings("unused") + public Sounds(int[] array, ArrayVisualizer arrayVisualizer) { this.array = array; - this.ArrayVisualizer = arrayVisualizer; - this.Highlights = ArrayVisualizer.getHighlights(); - - this.SOUND = true; - this.MIDI = true; - this.NUMCHANNELS = 16; - this.PITCHMIN = 25d; - this.PITCHMAX = 105d; - this.SOUNDMUL = 1d; - + this.arrayVisualizer = arrayVisualizer; + this.Highlights = arrayVisualizer.getHighlights(); + + this.playSound = true; + this.playSound2 = true; + this.numChannels = ALLOW_PERCUSSION_SOUNDS ? 16 : 15; + this.pitchMin = 25d; + this.pitchMax = 105d; + this.soundMultiplier = 1d; + this.noteDelay = 1; - + this.soundEnabled = true; - + try { MidiSystem.getSequencer(false); - this.synth = MidiSystem.getSynthesizer(); - this.synth.open(); - } - catch (MidiUnavailableException e) { + synth = MidiSystem.getSynthesizer(); + if (SOFT_SYNTHESIZER_CLASS != null && SOFT_SYNTHESIZER_CLASS.isInstance(synth)) { + Map params = Collections.singletonMap("jitter correction", Boolean.FALSE); + try { + Method openMethod = SOFT_SYNTHESIZER_CLASS.getDeclaredMethod("open", SourceDataLine.class, Map.class); + openMethod.invoke(synth, null, params); + } catch (IllegalAccessException e) { + synth.open(); // Can't do special opening here. Java 9's module system stops us. + } catch (Exception e) { + System.err.println("Failed to open SoftSynthesizer specially, opening normally"); + e.printStackTrace(); + synth.open(); + } + } else { + synth.open(); + } + } catch (MidiUnavailableException e) { JErrorPane.invokeCustomErrorMessage("The default MIDI device is unavailable, possibly because it is already being used by another application."); this.soundEnabled = false; - } - catch (SecurityException e) { + } catch (SecurityException e) { JErrorPane.invokeErrorMessage(e); this.soundEnabled = false; } - + this.instrumentChoice = 0; this.prepareDefaultSoundbank(); - - this.AudioThread = new Thread() { + + this.audioThread = new Thread("AudioThread") { @Override public void run() { - while(Sounds.this.soundEnabled) { - for(MidiChannel channel : channels) { + while (Sounds.this.soundEnabled) { + for (MidiChannel channel : channels) { channel.allNotesOff(); } - if(SOUND == false || MIDI == false || JErrorPane.errorMessageActive) { + if (!playSound || !playSound2 || JErrorPane.isErrorMessageActive()) { synchronized (Sounds.this) { try { Sounds.this.wait(); @@ -137,54 +162,59 @@ public void run() { continue; } - int noteCount = Math.min(Highlights.getMarkCount(), NUMCHANNELS); - noteCount = noteCount < 0 ? NUMCHANNELS : noteCount; - int voice = 0; + int noteCount = Math.min(Highlights.getMarkCount(), numChannels); + noteCount = noteCount < 0 ? numChannels : noteCount; + int channel = 0; + + int playNoteCount = Math.max(noteCount, 1); + int currentLen = arrayVisualizer.getCurrentLength(); - for(int i : Highlights.highlightList()) { + for (int i : Highlights.highlightList()) { try { - if(i != -1) { - int currentLen = ArrayVisualizer.getCurrentLength(); + if (i != -1) { + if (!ALLOW_PERCUSSION_SOUNDS && channel == 9) { + channel++; + playNoteCount++; + } //PITCH - double pitch = Sounds.this.array[Math.min(Math.max(i, 0), currentLen - 1)] / (double) currentLen * (PITCHMAX - PITCHMIN) + PITCHMIN; + double pitch = Sounds.this.array[Math.min(Math.max(i, 0), currentLen - 1)] / (double) currentLen * (pitchMax - pitchMin) + pitchMin; int pitchmajor = (int) pitch; int pitchminor = (int)((pitch-((int)pitch))*8192d)+8192; - int vel = (int) (Math.pow(PITCHMAX - pitchmajor, 2d) * (Math.pow(noteCount, -0.25)) * 64d * SOUNDMUL) / 2; //I'VE SOLVED IT!! + int vel = (int) (Math.pow(pitchMax - pitchmajor, 2d) * (Math.pow(noteCount, -0.25)) * 64d * soundMultiplier) / 2; //I'VE SOLVED IT!! - if(SOUNDMUL >= 1 && vel < 256) { + if (soundMultiplier >= 1 && vel < 256) { vel *= vel; } - channels[voice].noteOn(pitchmajor, vel); - channels[voice].setPitchBend(pitchminor); - channels[voice].controlChange(REVERB, 10); - - if((++voice % Math.max(noteCount, 1)) == 0) + channels[channel].noteOn(pitchmajor, vel); + channels[channel].setPitchBend(pitchminor); + channels[channel].controlChange(REVERB, 10); + + if (++channel == playNoteCount) break; } - } - catch (Exception e) { + } catch (Exception e) { JErrorPane.invokeErrorMessage(e); } } try { - for(int i = 0; i < Sounds.this.noteDelay; i++) { + for (int i = 0; i < Sounds.this.noteDelay; i++) { sleep(1); } - } catch(Exception e) { + } catch (Exception e) { JErrorPane.invokeErrorMessage(e); } } } }; } - - public boolean isEnabled() { - return this.soundEnabled; - } - + + public boolean isEnabled() { + return this.soundEnabled; + } + public int getInstrumentChoice() { return this.instrumentChoice; } @@ -192,193 +222,184 @@ public void setInstrumentChoice(int choice) { this.instrumentChoice = choice; this.assignInstruments(); } - + public String getSelectedSoundbank() { return this.selectedSoundbank; } - + //TODO: Make infoMsg into reusable class (including Custom Image) public void selectCustomSoundbank(SoundFrame menu) { SoundbankDialog dialog = new SoundbankDialog(); File soundbank = dialog.getFile(); - if(soundbank != null) { + if (soundbank != null) { this.infoMsg = new LoadingDialog(soundbank.getName(), menu); this.prepareCustomSoundbank(soundbank); - if(this.soundEnabled) { + if (this.soundEnabled) { this.selectedSoundbank = soundbank.getName(); } - + this.infoMsg.closeDialog(); } - + menu.dispose(); SoundFrame soundMenu = new SoundFrame(this); soundMenu.setVisible(true); } - + public void selectDefaultSoundbank(SoundFrame menu) { this.infoMsg = new LoadingDialog("resources/soundfont/sfx.sf2", menu); - + this.prepareDefaultSoundbank(); - + this.infoMsg.closeDialog(); menu.dispose(); SoundFrame soundMenu = new SoundFrame(this); soundMenu.setVisible(true); } - + private void prepareDefaultSoundbank() { - this.sineWaveIndex = this.DEFAULT_SINE_WAVE_INDEX; - SFXFetcher sfxFetcher = new SFXFetcher(); - this.loadInstruments(sfxFetcher); - this.selectedSoundbank = this.defaultSoundbank; + this.sineWaveIndex = DEFAULT_SINE_WAVE_INDEX; + InputStream is = getClass().getResourceAsStream("/sfx.sf2"); + this.loadInstruments(is); + this.selectedSoundbank = "Default (Yamaha XG Sound Set)"; } - + private void prepareCustomSoundbank(File file) { - SFXFetcher sfxFetcher = new SFXFetcher(file); - this.loadInstruments(sfxFetcher); + InputStream is; + try { + is = new FileInputStream(file); + } catch (FileNotFoundException e) { + JErrorPane.invokeErrorMessage(e); + return; + } + this.loadInstruments(is); } - + private String formatInstrumentName(String rawName) { int length = rawName.length(); - while(rawName.charAt(length - 1) == ' ') { + while (rawName.charAt(length - 1) == ' ') { length--; } StringBuilder formatter = new StringBuilder(rawName); String formattedName = formatter.substring(0, length); - - if(formattedName.length() > 3) { - if(formattedName.subSequence(0, 4).equals("Type")) { + + if (formattedName.length() > 3) { + if (formattedName.subSequence(0, 4).equals("Type")) { return "Unnamed Sample"; } } return formattedName; } - + public String[] getInstrumentList() { - ArrayList instrumentNames = new ArrayList(); + ArrayList instrumentNames = new ArrayList<>(); Instrument[] instruments = this.synth.getLoadedInstruments(); if (instruments.length == 0) { return new String[0]; } - - String rockOrgan = instruments[this.DEFAULT_ROCK_ORGAN_INDEX].getName(); + + String rockOrgan = instruments[DEFAULT_ROCK_ORGAN_INDEX].getName(); instrumentNames.add("a. Default Sound Effect (" + this.formatInstrumentName(rockOrgan) + ")"); - + this.sineWaveIndex = 0; - while(this.sineWaveIndex < instruments.length && !instruments[this.sineWaveIndex].getName().toLowerCase().trim().contains("sine")) { + while (this.sineWaveIndex < instruments.length && !instruments[this.sineWaveIndex].getName().toLowerCase().trim().contains("sine")) { this.sineWaveIndex++; } - if(this.sineWaveIndex >= instruments.length && this.DEFAULT_SINE_WAVE_INDEX < instruments.length) { - this.sineWaveIndex = this.DEFAULT_SINE_WAVE_INDEX; - } - else if(this.DEFAULT_SINE_WAVE_INDEX >= instruments.length) { + if (this.sineWaveIndex >= instruments.length && DEFAULT_SINE_WAVE_INDEX < instruments.length) { + this.sineWaveIndex = DEFAULT_SINE_WAVE_INDEX; + } else if (DEFAULT_SINE_WAVE_INDEX >= instruments.length) { this.sineWaveIndex = 0; } - + String sineWave = instruments[this.sineWaveIndex].getName(); instrumentNames.add("b. w0rthy's Original Sound Effect (" + this.formatInstrumentName(sineWave) + ")"); - - for(int i = 0; i < instruments.length; i++) { + + for (int i = 0; i < instruments.length; i++) { String nextInstrument = instruments[i].getName(); instrumentNames.add((i + 1) + ". " + this.formatInstrumentName(nextInstrument)); } - + String[] instrumentArray = new String[instruments.length]; - for(int i = 0; i < instruments.length; i++) { + for (int i = 0; i < instruments.length; i++) { instrumentArray[i] = instrumentNames.get(i); } - + return instrumentArray; } - - private void loadInstruments(SFXFetcher sfxFetcher) { - BufferedInputStream stream = sfxFetcher.getStream(); - - try { - this.synth.loadAllInstruments(MidiSystem.getSoundbank(stream)); - } - catch (NullPointerException e) { + + private void loadInstruments(InputStream stream) { + try (BufferedInputStream bis = new BufferedInputStream(stream)) { + this.synth.loadAllInstruments(MidiSystem.getSoundbank(bis)); + } catch (NullPointerException e) { JErrorPane.invokeCustomErrorMessage("soundfont/sfx.sf2 missing: Couldn't find the default soundbank for the program's sound effects! The OS default will be used instead."); - } - catch (InvalidMidiDataException e) { + } catch (InvalidMidiDataException e) { JErrorPane.invokeCustomErrorMessage("soundfont/sfx.sf2 invalid or corrupt: The file for the program's default soundbank was not recognized as a proper MIDI soundfont! The OS default will be used instead."); - } - catch (IOException e) { + } catch (IOException e) { JErrorPane.invokeErrorMessage(e); } - finally { - try { - stream.close(); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - } - - if(this.channels == null) { - this.channels = new MidiChannel[this.NUMCHANNELS]; + + if (this.channels == null) { + this.channels = new MidiChannel[this.numChannels]; } this.assignInstruments(); } - + private void assignInstruments() { try { int programIndex; - - //TODO: Consider making into a function + + //TODO: Consider making into a method switch(this.instrumentChoice) { - case 0: programIndex = this.DEFAULT_ROCK_ORGAN_INDEX; break; - case 1: programIndex = this.sineWaveIndex; break; - default: programIndex = this.instrumentChoice - 2; break; + case 0: programIndex = DEFAULT_ROCK_ORGAN_INDEX; break; + case 1: programIndex = this.sineWaveIndex; break; + default: programIndex = this.instrumentChoice - 2; break; } - - for(int i = 0; i < this.NUMCHANNELS; i++) { + + for (int i = 0; i < this.numChannels; i++) { this.channels[i] = this.synth.getChannels()[i]; this.channels[i].programChange(this.synth.getLoadedInstruments()[programIndex].getPatch().getProgram()); this.channels[i].setChannelPressure(1); } - if(this.channels[0].getProgram() == -1) { + if (this.channels[0].getProgram() == -1) { JErrorPane.invokeCustomErrorMessage("Could not find a valid MIDI instrument."); this.soundEnabled = false; } - } - catch(Exception e) { + } catch (Exception e) { JErrorPane.invokeErrorMessage(e); this.soundEnabled = false; } } - + public void testInstrument(int programIndex) { this.testInstrumentChoice = programIndex; - - if(this.ArrayVisualizer.getSortingThread() != null && this.ArrayVisualizer.getSortingThread().isAlive()) { - new Thread() { + + if (this.arrayVisualizer.isActive()) { + new Thread("TestInstrumentThread") { @Override - public void run() { + public void run() { switch(Sounds.this.testInstrumentChoice) { - case 0: Sounds.this.testInstrumentChoice = Sounds.this.DEFAULT_ROCK_ORGAN_INDEX; break; - case 1: Sounds.this.testInstrumentChoice = Sounds.this.sineWaveIndex; break; - default: Sounds.this.testInstrumentChoice -= 2; break; + case 0: Sounds.this.testInstrumentChoice = DEFAULT_ROCK_ORGAN_INDEX; break; + case 1: Sounds.this.testInstrumentChoice = Sounds.this.sineWaveIndex; break; + default: Sounds.this.testInstrumentChoice -= 2; break; } int savedInstrument; - //TODO: Consider making into a function + //TODO: Consider making into a method switch(Sounds.this.instrumentChoice) { - case 0: savedInstrument = Sounds.this.DEFAULT_ROCK_ORGAN_INDEX; break; - case 1: savedInstrument = Sounds.this.sineWaveIndex; break; - default: savedInstrument = Sounds.this.instrumentChoice - 2; break; + case 0: savedInstrument = DEFAULT_ROCK_ORGAN_INDEX; break; + case 1: savedInstrument = Sounds.this.sineWaveIndex; break; + default: savedInstrument = Sounds.this.instrumentChoice - 2; break; } try { - for(int i = 0; i < Sounds.this.NUMCHANNELS; i++) { - Sounds.this.channels[i].programChange(Sounds.this.synth.getLoadedInstruments()[Sounds.this.testInstrumentChoice].getPatch().getProgram()); + for (int i = 0; i < Sounds.this.numChannels; i++) { + Sounds.this.channels[i].programChange(Sounds.this.synth.getLoadedInstruments()[Sounds.this.testInstrumentChoice].getPatch().getProgram()); } sleep(2000); - for(int i = 0; i < Sounds.this.NUMCHANNELS; i++) { + for (int i = 0; i < Sounds.this.numChannels; i++) { Sounds.this.channels[i].programChange(Sounds.this.synth.getLoadedInstruments()[savedInstrument].getPatch().getProgram()); } } catch (InterruptedException e) { @@ -386,29 +407,28 @@ public void run() { } } }.start(); - } - else { - new Thread() { + } else { + new Thread("TestInstrumentThread") { @Override - public void run() { + public void run() { switch(Sounds.this.testInstrumentChoice) { - case 0: Sounds.this.testInstrumentChoice = Sounds.this.DEFAULT_ROCK_ORGAN_INDEX; break; - case 1: Sounds.this.testInstrumentChoice = Sounds.this.sineWaveIndex; break; - default: Sounds.this.testInstrumentChoice -= 2; break; + case 0: Sounds.this.testInstrumentChoice = DEFAULT_ROCK_ORGAN_INDEX; break; + case 1: Sounds.this.testInstrumentChoice = Sounds.this.sineWaveIndex; break; + default: Sounds.this.testInstrumentChoice -= 2; break; } int savedInstrument; - //TODO: Consider making into a function + //TODO: Consider making into a method switch(Sounds.this.instrumentChoice) { - case 0: savedInstrument = Sounds.this.DEFAULT_ROCK_ORGAN_INDEX; break; - case 1: savedInstrument = Sounds.this.sineWaveIndex; break; - default: savedInstrument = Sounds.this.instrumentChoice - 2; break; + case 0: savedInstrument = DEFAULT_ROCK_ORGAN_INDEX; break; + case 1: savedInstrument = Sounds.this.sineWaveIndex; break; + default: savedInstrument = Sounds.this.instrumentChoice - 2; break; } try { Sounds.this.channels[0].programChange(Sounds.this.synth.getLoadedInstruments()[Sounds.this.testInstrumentChoice].getPatch().getProgram()); - Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); + Sounds.this.channels[0].controlChange(SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(60, 100); Sounds.this.channels[0].noteOn(64, 100); @@ -421,13 +441,13 @@ public void run() { Sounds.this.channels[0].noteOff(64); Sounds.this.channels[0].noteOff(67); Sounds.this.channels[0].noteOff(72); - - Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); - + + Sounds.this.channels[0].controlChange(SUSTAIN_PEDAL, 0); + /* int eighth = 200; int note; - + note = 62; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -435,7 +455,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 67; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -443,7 +463,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 69; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -451,7 +471,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 71; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -459,7 +479,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 71; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -467,7 +487,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 74; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -475,7 +495,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 69; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -483,7 +503,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 69; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -491,7 +511,7 @@ public void run() { Sounds.this.channels[0].noteOff(note); Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); - + note = 71; Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 64); Sounds.this.channels[0].noteOn(note, 100); @@ -500,7 +520,7 @@ public void run() { Sounds.this.channels[0].controlChange(Sounds.this.SUSTAIN_PEDAL, 0); sleep(10); */ - + Sounds.this.channels[0].programChange(Sounds.this.synth.getLoadedInstruments()[savedInstrument].getPatch().getProgram()); } catch (InterruptedException e) { JErrorPane.invokeErrorMessage(e); @@ -509,59 +529,71 @@ public void run() { }.start(); } } - + public synchronized void toggleSounds(boolean val) { - this.SOUND = val; + this.playSound = val; this.notifyAll(); } - + public synchronized void toggleSound(boolean val) { - this.MIDI = val; + this.playSound2 = val; this.notifyAll(); } - + //Double check logic + public void setSofterSounds(boolean softerSounds) { + this.softerSounds = softerSounds; + + if (this.softerSounds) this.soundMultiplier = 0.01; + else this.soundMultiplier = 1; + } + + /** + * @deprecated Use {@link #setSofterSounds} instead. + */ + @Deprecated public void toggleSofterSounds(boolean val) { - this.SOFTERSOUNDS = val; - - if(this.SOFTERSOUNDS) this.SOUNDMUL = 0.01; - else this.SOUNDMUL = 1; + setSofterSounds(val); + } + + //Double check logic + public boolean isSofterSounds() { + return softerSounds; } - + public double getVolume() { - return this.SOUNDMUL; + return this.soundMultiplier; } public void changeVolume(double val) { - this.SOUNDMUL = val; + this.soundMultiplier = val; } - + public void changeNoteDelayAndFilter(int noteFactor) { - if(noteFactor != this.noteDelay) { - if(noteFactor > 1) { + if (noteFactor != this.noteDelay) { + if (noteFactor > 1) { this.noteDelay = noteFactor; - this.SOUNDMUL = 1d / noteFactor; - } - //Double check logic - else { + this.soundMultiplier = 1d / noteFactor; + } else { + //Double check logic this.noteDelay = 1; - - if(this.SOFTERSOUNDS) this.SOUNDMUL = 0.01; - else this.SOUNDMUL = 1; + + if (this.softerSounds) this.soundMultiplier = 0.01; + else this.soundMultiplier = 1; } } } - + public void startAudioThread() { - if(!this.soundEnabled) { + if (!this.soundEnabled) { JOptionPane.showMessageDialog(null, "Sound is disabled.", "Warning", JOptionPane.WARNING_MESSAGE); } - AudioThread.start(); + audioThread.start(); } - + public void closeSynth() { - if(this.soundEnabled) { + if (this.soundEnabled) { this.soundEnabled = false; this.synth.close(); } } -} \ No newline at end of file +} diff --git a/src/utils/Statistics.java b/src/main/java/io/github/arrayv/utils/Statistics.java similarity index 50% rename from src/utils/Statistics.java rename to src/main/java/io/github/arrayv/utils/Statistics.java index 18e23c21..d414b895 100644 --- a/src/utils/Statistics.java +++ b/src/main/java/io/github/arrayv/utils/Statistics.java @@ -1,35 +1,38 @@ -package utils; +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; import java.text.DecimalFormat; -import main.ArrayVisualizer; +public final class Statistics { + private long frameTimeMillis; -final public class Statistics { private String sortCategory; private String sortHeading; private String sortExtraHeading; private String arrayLength; - + + private String framerate; private String sortDelay; private String visualTime; private String estSortTime; - + private String comparisonCount; private String swapCount; private String reversalCount; - + private String mainWriteCount; private String auxWriteCount; private String auxAllocAmount; private String segments; - - private DecimalFormat formatter; - - public Statistics(ArrayVisualizer ArrayVisualizer) { - this.formatter = ArrayVisualizer.getNumberFormat(); - this.updateStats(ArrayVisualizer); + + private final DecimalFormat formatter; + + public Statistics(ArrayVisualizer arrayVisualizer) { + this.formatter = arrayVisualizer.getNumberFormat(); + this.updateStats(arrayVisualizer); } public int[] findSegments(int[] array, int length, boolean reversed) { @@ -46,39 +49,51 @@ public int[] findSegments(int[] array, int length, boolean reversed) { return result; } - public void updateStats(ArrayVisualizer ArrayVisualizer) { - this.sortCategory = ArrayVisualizer.getCategory(); - this.sortHeading = ArrayVisualizer.getHeading(); - this.sortExtraHeading = ArrayVisualizer.getExtraHeading(); - int showUnique = Math.min(ArrayVisualizer.getUniqueItems(), ArrayVisualizer.getCurrentLength()); - this.arrayLength = this.formatter.format(ArrayVisualizer.getCurrentLength()) + " Numbers" - + ", " + this.formatter.format(showUnique) + " Unique"; - - this.sortDelay = "Delay: " + ArrayVisualizer.getDelays().displayCurrentDelay(); - this.visualTime = "Visual Time: " + ArrayVisualizer.getTimer().getVisualTime(); - this.estSortTime = "Sort Time: " + ArrayVisualizer.getTimer().getRealTime(); - - this.comparisonCount = ArrayVisualizer.getReads().getStats(); - this.swapCount = ArrayVisualizer.getWrites().getSwaps(); - this.reversalCount = ArrayVisualizer.getWrites().getReversals(); - - this.mainWriteCount = ArrayVisualizer.getWrites().getMainWrites(); - this.auxWriteCount = ArrayVisualizer.getWrites().getAuxWrites(); - - this.auxAllocAmount = ArrayVisualizer.getWrites().getAllocAmount(); - - int[] shadowarray = ArrayVisualizer.getArray(); - int[] rawSegments = this.findSegments(shadowarray, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.reversedComparator()); + public void updateStats(ArrayVisualizer arrayVisualizer) { + this.sortCategory = arrayVisualizer.getCategory(); + this.sortHeading = arrayVisualizer.getHeading(); + this.sortExtraHeading = arrayVisualizer.getExtraHeading(); + int showUnique = Math.min(arrayVisualizer.getUniqueItems(), arrayVisualizer.getCurrentLength()); + this.arrayLength = this.formatter.format(arrayVisualizer.getCurrentLength()) + " Numbers" + + ", " + this.formatter.format(showUnique) + " Unique"; + + if (frameTimeMillis == 0) { + this.framerate = ">1000 FPS"; + } else { + this.framerate = (int)(1000.0 / frameTimeMillis) + " FPS"; + } + this.sortDelay = "Delay: " + arrayVisualizer.getDelays().displayCurrentDelay(); + this.visualTime = "Visual Time: " + arrayVisualizer.getTimer().getVisualTime(); + this.estSortTime = "Sort Time: " + arrayVisualizer.getTimer().getRealTime(); + + this.comparisonCount = arrayVisualizer.getReads().getStats(); + this.swapCount = arrayVisualizer.getWrites().getSwaps(); + this.reversalCount = arrayVisualizer.getWrites().getReversals(); + + this.mainWriteCount = arrayVisualizer.getWrites().getMainWrites(); + this.auxWriteCount = arrayVisualizer.getWrites().getAuxWrites(); + + this.auxAllocAmount = arrayVisualizer.getWrites().getAllocAmount(); + + int[] shadowarray = arrayVisualizer.getArray(); + int[] rawSegments = this.findSegments(shadowarray, arrayVisualizer.getCurrentLength(), arrayVisualizer.reversedComparator()); String plural = rawSegments[0] == 1 ? "" : "s"; - this.segments = String.valueOf(rawSegments[1]) + "% Sorted (" + String.valueOf(rawSegments[0]) + " Segment" + plural + ")"; + this.segments = rawSegments[1] + "% Sorted (" + rawSegments[0] + " Segment" + plural + ")"; + } + + public void setFrameTimeMillis(long frameTimeMillis) { + this.frameTimeMillis = frameTimeMillis; } - + public String getSortIdentity() { return this.sortCategory + ": " + this.sortHeading; } public String getArrayLength() { return this.arrayLength + this.sortExtraHeading; } + public String getFramerate() { + return this.framerate; + } public String getSortDelay() { return this.sortDelay; } @@ -106,8 +121,7 @@ public String getAuxWriteCount() { public String getAuxAllocAmount() { return this.auxAllocAmount; } - public String getSegments() { return this.segments; } -} \ No newline at end of file +} diff --git a/src/utils/StopSort.java b/src/main/java/io/github/arrayv/utils/StopSort.java similarity index 81% rename from src/utils/StopSort.java rename to src/main/java/io/github/arrayv/utils/StopSort.java index 18607c0b..ccf5ff92 100644 --- a/src/utils/StopSort.java +++ b/src/main/java/io/github/arrayv/utils/StopSort.java @@ -1,4 +1,4 @@ -package utils; +package io.github.arrayv.utils; public class StopSort extends RuntimeException { @@ -6,5 +6,5 @@ public class StopSort extends RuntimeException { * */ private static final long serialVersionUID = 7184503760578707452L; - + } diff --git a/src/utils/Timer.java b/src/main/java/io/github/arrayv/utils/Timer.java similarity index 66% rename from src/utils/Timer.java rename to src/main/java/io/github/arrayv/utils/Timer.java index 6f8568b8..7ce89b7e 100644 --- a/src/utils/Timer.java +++ b/src/main/java/io/github/arrayv/utils/Timer.java @@ -1,12 +1,12 @@ -package utils; +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; import java.text.DecimalFormat; import java.util.Hashtable; -import main.ArrayVisualizer; - /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -31,75 +31,73 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Timer { - private DecimalFormat formatter; - +public final class Timer { + private final DecimalFormat formatter; + private volatile String minuteFormat; private volatile String secondFormat; - + private volatile int elapsedTime; private volatile double realTimer; - private volatile boolean REALTIMER; + private volatile boolean useRealTimer; private volatile double sortRunTime; private volatile boolean timerEnabled; private String operation; - private Hashtable categoricalTimes; - + private final Hashtable categoricalTimes; + private long timeStart; private long timeStop; - - public Timer(ArrayVisualizer ArrayVisualizer) { - this.REALTIMER = true; - + + public Timer(ArrayVisualizer arrayVisualizer) { + this.useRealTimer = true; + this.timeStart = 0; this.timeStop = 0; - - this.formatter = ArrayVisualizer.getNumberFormat(); + + this.formatter = arrayVisualizer.getNumberFormat(); this.categoricalTimes = new Hashtable<>(); } - + public String getVisualTime() { - if(this.timerEnabled) { + if (this.timerEnabled) { this.elapsedTime = (int) ((System.nanoTime() - this.sortRunTime) / 1e+9); - + secondFormat = "" + ((this.elapsedTime % 60) / 10) + (this.elapsedTime % 10); minuteFormat = (this.elapsedTime / 60) + ":" + secondFormat; } - - if(!this.timerEnabled && this.elapsedTime == 0) return "-:--"; - else if(this.elapsedTime >= 60) return minuteFormat; - else if(this.elapsedTime >= 1) return "0:" + secondFormat; - else return "0:00"; + + if (!this.timerEnabled && this.elapsedTime == 0) return "-:--"; + else if (this.elapsedTime >= 60) return minuteFormat; + else if (this.elapsedTime >= 1) return "0:" + secondFormat; + else return "0:00"; } public String prettifyTime(double time) { double realTime = time * 1e-6d; - if(!this.REALTIMER) { + if (!this.useRealTimer) { return "Disabled"; - } - else if(realTime == 0) { - if(this.timerEnabled) return "0.000ms"; - else return "---ms"; - } - else if(realTime < 0.001) return "< 0.001ms"; - else if(realTime >= 60000.000) return "~" + this.formatter.format((int) (realTime / 60000)) + "m" + (int) ((realTime % 60000) / 1000) + "s"; - else if(realTime >= 1000.000) return "~" + this.formatter.format(realTime / 1000) + "s"; - else return "~" + this.formatter.format(realTime) + "ms"; + } else if (realTime == 0) { + if (this.timerEnabled) return "0.000ms"; + else return "---ms"; + } else if (realTime < 0.001) return "< 0.001ms"; + else if (realTime >= 60000.000) return "~" + this.formatter.format((int) (realTime / 60000)) + "m" + (int) ((realTime % 60000) / 1000) + "s"; + else if (realTime >= 1000.000) return "~" + this.formatter.format(realTime / 1000) + "s"; + else return "~" + this.formatter.format(realTime) + "ms"; } - + public String getRealTime() { return prettifyTime(this.realTimer); } - - public void toggleRealTimer(boolean Bool) { - this.REALTIMER = Bool; + + public void toggleRealTimer(boolean useRealTimer) { + this.useRealTimer = useRealTimer; } - + public void enableRealTimer() { - if(REALTIMER) this.timerEnabled = true; + if (useRealTimer) this.timerEnabled = true; this.sortRunTime = System.nanoTime(); this.realTimer = 0; } @@ -107,24 +105,24 @@ public void enableRealTimer() { public void disableRealTimer() { this.timerEnabled = false; } - + public boolean timerEnabled() { return this.timerEnabled; } - + public void startLap(String message) { this.operation = message; this.categoricalTimes.putIfAbsent(message, 0d); - if(this.timerEnabled) this.timeStart = System.nanoTime(); + if (this.timerEnabled) this.timeStart = System.nanoTime(); } public void startLap() { startLap(""); } - + public void stopLap() { this.timeStop = System.nanoTime(); - if(this.timerEnabled) { + if (this.timerEnabled) { double timeDiff = timeStop - timeStart; this.realTimer += timeDiff; this.categoricalTimes.put(this.operation, categoricalTimes.get(this.operation) + timeDiff); @@ -138,8 +136,8 @@ public Hashtable getCategoricalTimes() { void manualAddTime(long milliseconds) { this.realTimer += milliseconds; } - + public void manualSetTime(long milliseconds) { this.realTimer = milliseconds; } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/utils/Writes.java b/src/main/java/io/github/arrayv/utils/Writes.java new file mode 100644 index 00000000..7b0aa6c4 --- /dev/null +++ b/src/main/java/io/github/arrayv/utils/Writes.java @@ -0,0 +1,501 @@ +package io.github.arrayv.utils; + +import io.github.arrayv.main.ArrayVisualizer; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +/** + * + * @author S630690 + */ +public final class Writes { + private final AtomicLong reversals; + private final AtomicLong swaps; + private final AtomicLong auxWrites; + private final AtomicLong writes; + private final AtomicLong allocAmount; + + private final DecimalFormat formatter; + + private final ArrayVisualizer arrayVisualizer; + private final Delays Delays; + private final Highlights Highlights; + private final Timer Timer; + + public Writes(ArrayVisualizer arrayVisualizer) { + this.reversals = new AtomicLong(); + this.swaps = new AtomicLong(); + this.auxWrites = new AtomicLong(); + this.writes = new AtomicLong(); + this.allocAmount = new AtomicLong(); + + this.arrayVisualizer = arrayVisualizer; + this.Delays = arrayVisualizer.getDelays(); + this.Highlights = arrayVisualizer.getHighlights(); + this.Timer = arrayVisualizer.getTimer(); + + this.formatter = arrayVisualizer.getNumberFormat(); + } + + public void resetStatistics() { + this.reversals.set(0); + this.swaps.set(0); + this.auxWrites.set(0); + this.writes.set(0); + this.allocAmount.set(0); + } + + public String getReversals() { + if (this.reversals.get() < 0) { + this.reversals.set(Long.MIN_VALUE); + return "Over " + this.formatter.format(Long.MAX_VALUE); + } else { + if (reversals.get() == 1) return this.reversals + " Reversal"; + else return this.formatter.format(this.reversals) + " Reversals"; + } + } + + public String getSwaps() { + if (this.swaps.get() < 0) { + this.swaps.set(Long.MIN_VALUE); + return "Over " + this.formatter.format(Long.MAX_VALUE); + } else { + if (swaps.get() == 1) return this.swaps + " Swap"; + else return this.formatter.format(this.swaps) + " Swaps"; + } + } + + public String getAuxWrites() { + if (this.auxWrites.get() < 0) { + this.auxWrites.set(Long.MIN_VALUE); + return "Over " + this.formatter.format(Long.MAX_VALUE); + } else { + if (auxWrites.get() == 1) return this.auxWrites + " Write to Auxiliary Array(s)"; + else return this.formatter.format(this.auxWrites) + " Writes to Auxiliary Array(s)"; + } + } + + public String getMainWrites() { + if (this.writes.get() < 0) { + this.writes.set(Long.MIN_VALUE); + return "Over " + this.formatter.format(Long.MAX_VALUE); + } else { + if (writes.get() == 1) return this.writes + " Write to Main Array"; + else return this.formatter.format(this.writes) + " Writes to Main Array"; + } + } + + public String getAllocAmount() { + if (this.allocAmount.get() < 0) { + this.allocAmount.set(Long.MIN_VALUE); + return "Over " + this.formatter.format(Long.MAX_VALUE); + } else { + if (allocAmount.get() == 1) return this.allocAmount + " Item in External Arrays"; + else return this.formatter.format(this.allocAmount) + " Items in External Arrays"; + } + } + + public void changeAuxWrites(int value) { + this.auxWrites.addAndGet(value); + } + + public void changeWrites(int value) { + this.writes.addAndGet(value); + } + + public void changeAllocAmount(int value) { + this.allocAmount.addAndGet(value); + } + + public void clearAllocAmount() { + this.allocAmount.set(0); + } + + public void changeReversals(int value) { + this.reversals.addAndGet(value); + } + + private void updateSwap(boolean auxwrite) { + this.swaps.incrementAndGet(); + if (auxwrite) this.auxWrites.addAndGet(2); + else this.writes.addAndGet(2); + } + + private void markSwap(int a, int b) { + Highlights.markArray(1, a); + Highlights.markArray(2, b); + } + + public void swap(int[] array, int a, int b, double pause, boolean mark, boolean auxwrite) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + if (!auxwrite && a >= arrayVisualizer.getCurrentLength()) { + System.err.println("Warning: write to index " + a + ", which is out of bounds for the current length (" + arrayVisualizer.getCurrentLength() + ")"); + } + if (!auxwrite && b >= arrayVisualizer.getCurrentLength()) { + System.err.println("Warning: write to index " + b + ", which is out of bounds for the current length (" + arrayVisualizer.getCurrentLength() + ")"); + } + + if (mark) this.markSwap(a, b); + + Timer.startLap("Swap"); + + int temp = array[a]; + array[a] = array[b]; + array[b] = temp; + + Timer.stopLap(); + + this.updateSwap(auxwrite); + arrayVisualizer.updateNow(); + Delays.sleep(pause); + } + + public void multiSwap(int[] array, int pos, int to, double sleep, boolean mark, boolean auxwrite) { + if (to - pos > 0) { + for (int i = pos; i < to; i++) { + this.swap(array, i, i + 1, 0, mark, auxwrite); + Delays.sleep(sleep); + } + } else { + for (int i = pos; i > to; i--) { + this.swap(array, i, i - 1, 0, mark, auxwrite); + Delays.sleep(sleep); + } + } + } + + public void reversal(int[] array, int start, int length, double sleep, boolean mark, boolean auxwrite) { + this.reversals.incrementAndGet(); + + for (int i = start; i < start + ((length - start + 1) / 2); i++) { + this.swap(array, i, start + length - i, sleep, mark, auxwrite); + } + } + + public void write(int[] array, int at, int equals, double pause, boolean mark, boolean auxwrite) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + if (!auxwrite && at >= arrayVisualizer.getCurrentLength()) { + System.err.println("Warning: write to index " + at + ", which is out of bounds for the current length (" + arrayVisualizer.getCurrentLength() + ")"); + } + + if (mark) Highlights.markArray(1, at); + + if (auxwrite) auxWrites.incrementAndGet(); + else writes.incrementAndGet(); + + Timer.startLap("Write"); + + array[at] = equals; + + Timer.stopLap(); + + arrayVisualizer.updateNow(); + Delays.sleep(pause); + } + + public void write(T[] array, int at, T equals, double pause, boolean mark) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + if (mark) Highlights.markArray(1, at); + + auxWrites.incrementAndGet(); + + Timer.startLap("Write"); + + array[at] = equals; + + Timer.stopLap(); + + arrayVisualizer.updateNow(); + Delays.sleep(pause); + } + + public void visualClear(int[] array, int index) { + visualClear(array, index, 0); + } + + public void visualClear(int[] array, int index, double delay) { + array[index] = -1; + } + + public void multiDimWrite(int[][] array, int x, int y, int equals, double pause, boolean mark, boolean auxwrite) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + if (mark) Highlights.markArray(1, x); + + if (auxwrite) auxWrites.incrementAndGet(); + else writes.incrementAndGet(); + + Timer.startLap(); + + array[x][y] = equals; + + Timer.stopLap(); + + arrayVisualizer.updateNow(); + Delays.sleep(pause); + } + + public void multiDimWrite(T[][] array, int x, int y, T equals, double pause, boolean mark) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + if (mark) Highlights.markArray(1, x); + + auxWrites.incrementAndGet(); + + Timer.startLap(); + + array[x][y] = equals; + + Timer.stopLap(); + + arrayVisualizer.updateNow(); + Delays.sleep(pause); + } + + //Simulates a write in order to better estimate time for values being written to an ArrayList + public void mockWrite(int length, int pos, int val, double pause) { + if (arrayVisualizer.sortCanceled()) throw new StopSort(); + //noinspection MismatchedReadAndWriteOfArray + int[] mockArray = new int[length]; + + this.auxWrites.incrementAndGet(); + + Timer.startLap(); + + mockArray[pos] = val; + + Timer.stopLap(); + + Delays.sleep(pause); + } + + public void transcribe(int[] array, ArrayList[] registers, int start, boolean mark, boolean auxwrite) { + int total = start; + + for (ArrayList register : registers) { + for (Integer integer : register) { + this.write(array, total++, integer, 0, mark, auxwrite); + if (mark) Delays.sleep(1); + } + this.arrayListClear(register); + } + } + + public void transcribeMSD(int[] array, ArrayList[] registers, int start, int min, double sleep, boolean mark, boolean auxwrite) { + int total = start; + int temp = 0; + + for (ArrayList list : registers) { + total += list.size(); + } + + for (int index = registers.length - 1; index >= 0; index--) { + for (int i = registers[index].size() - 1; i >= 0; i--) { + this.write(array, total + min - temp++ - 1, registers[index].get(i), 0, mark, auxwrite); + if (mark) Delays.sleep(sleep); + } + } + } + + public void fancyTranscribe(int[] array, int length, ArrayList[] registers, double sleep) { + int[] tempArray = this.createExternalArray(length); + boolean[] tempWrite = new boolean[length]; + int radix = registers.length; + + this.transcribe(tempArray, registers, 0, false, true); + auxWrites.addAndGet(-length); + + for (int i = 0; i < length; i++) { + int register = i % radix; + int pos = (register * (length / radix)) + (i / radix); + + if (!tempWrite[pos]) { + this.write(array, pos, tempArray[pos], 0, false, false); + tempWrite[pos] = true; + } + + Highlights.markArray(register, pos); + if (register == 0) Delays.sleep(sleep); + } + for (int i = 0; i < length; i++) { + if (!tempWrite[i]){ + this.write(array, i, tempArray[i], 0, false, false); + } + } + + Highlights.clearAllMarks(); + + this.deleteExternalArray(tempArray); + } + + /** + * Method to mimic {@link System#arraycopy(Object, int, Object, int, int)} + * @see System#arraycopy(Object, int, Object, int, int) + */ + public void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length, double sleep, boolean mark, boolean aux) { + int start, end, dir; + if (src != dest || destPos < srcPos) { + start = 0; + end = length; + dir = 1; + } else { + start = length - 1; + end = -1; + dir = -1; + } + for (int i = start; i != end; i += dir) { + if (mark) { + if (aux) { + Highlights.markArray(1, srcPos + i); + } else { + Highlights.markArray(1, destPos + i); + } + } + write(dest, destPos + i, src[srcPos + i], sleep, false, aux); + } + } + + public int[] copyOfArray(int[] original, int newLength) { + this.allocAmount.addAndGet(newLength); + int[] result = Arrays.copyOf(original, newLength); + arrayVisualizer.getArrays().add(result); + arrayVisualizer.updateNow(); + return result; + } + + public int[] copyOfRangeArray(int[] original, int from, int to) { + this.allocAmount.addAndGet(to - from); + int[] result = Arrays.copyOfRange(original, from, to); + arrayVisualizer.getArrays().add(result); + arrayVisualizer.updateNow(); + return result; + } + + /** + * Same as arraycopy, but used to copy in reverse + * @deprecated Use {@link Writes#arraycopy(int[], int, int[], int, int, double, boolean, boolean)} instead + * @see Writes#arraycopy(int[], int, int[], int, int, double, boolean, boolean) + */ + @Deprecated + public void reversearraycopy(int[] src, int srcPos, int[] dest, int destPos, int length, double sleep, boolean mark, boolean aux) { + arraycopy(src, srcPos, dest, destPos, length, sleep, mark, aux); + } + + public ArrayVList createArrayList() { + return new ArrayVList(); + } + + public ArrayVList createArrayList(int defaultCapacity) { + return new ArrayVList(defaultCapacity); + } + + public int[] createExternalArray(int length) { + this.allocAmount.addAndGet(length); + int[] result = new int[length]; + arrayVisualizer.getArrays().add(result); + arrayVisualizer.updateNow(); + return result; + } + + public void deleteExternalArray(int[] array) { + this.allocAmount.addAndGet(-array.length); + arrayVisualizer.getArrays().remove(array); + arrayVisualizer.updateNow(); + } + + public void deleteExternalArrays(int[]... arrays) { + this.allocAmount.addAndGet(-Arrays.stream(arrays).reduce(0, (a, b) -> (a + b.length), Integer::sum)); + List visArrays = arrayVisualizer.getArrays(); + Arrays.stream(arrays).forEach(visArrays::remove); + arrayVisualizer.updateNow(); + } + + public void arrayListAdd(List aList, int value) { + allocAmount.incrementAndGet(); + aList.add(value); + } + + public void arrayListAdd(List aList, int value, boolean mockWrite, double sleep) { + if (aList instanceof ArrayVList) { + ((ArrayVList)aList).add(value, sleep, false); + return; + } + allocAmount.incrementAndGet(); + aList.add(value); + if (mockWrite) { + this.mockWrite(aList.size(), aList.size() - 1, value, sleep); + } else { + Delays.sleep(sleep); + } + } + + public void arrayListRemoveAt(List aList, int index) { + allocAmount.decrementAndGet(); + aList.remove(index); + } + + public void arrayListClear(List aList) { + if (!(aList instanceof ArrayVList)) + allocAmount.addAndGet(-aList.size()); + aList.clear(); + } + + public void deleteArrayList(List aList) { + if (aList instanceof ArrayVList) { + ((ArrayVList)aList).delete(); + } else { + allocAmount.addAndGet(-aList.size()); + } + } + + public void deleteExternalArray(List[] array) { + for (List aList : array) { + deleteArrayList(aList); + } + } + + //TODO: These methods should be solely controlled by Timer class + public void addTime(long milliseconds) { + if (Timer.timerEnabled()) Timer.manualAddTime(milliseconds); + } + + public void setTime(long milliseconds) { + if (Timer.timerEnabled()) Timer.manualSetTime(milliseconds); + } + + public void startLap() { + if (Timer.timerEnabled()) Timer.startLap(); + } + + public void stopLap() { + if (Timer.timerEnabled()) Timer.stopLap(); + } +} diff --git a/src/utils/m.java b/src/main/java/io/github/arrayv/utils/m.java similarity index 89% rename from src/utils/m.java rename to src/main/java/io/github/arrayv/utils/m.java index 1ab9af7a..fe6ff99f 100644 --- a/src/utils/m.java +++ b/src/main/java/io/github/arrayv/utils/m.java @@ -1,6 +1,10 @@ -package utils; +package io.github.arrayv.utils; +// @checkstyle:off TypeNameCheck public final class m { +// @checkstyle:on TypeNameCheck + private m() { + } /** * Returns the logarithm base BASE of the number X @@ -114,7 +118,8 @@ public static int ceil(double x) { return (int)Math.ceil(x); } - public final double inf = Double.POSITIVE_INFINITY; - public final double NaN = Double.NaN; - + // @checkstyle:off ConstantNameCheck + public static final double inf = Double.POSITIVE_INFINITY; + public static final double NaN = Double.NaN; + // @checkstyle:on ConstantNameCheck } diff --git a/src/utils/shuffle_utils/AWTUtils.java b/src/main/java/io/github/arrayv/utils/shuffleutils/AWTUtils.java similarity index 87% rename from src/utils/shuffle_utils/AWTUtils.java rename to src/main/java/io/github/arrayv/utils/shuffleutils/AWTUtils.java index d94cff2f..07464710 100644 --- a/src/utils/shuffle_utils/AWTUtils.java +++ b/src/main/java/io/github/arrayv/utils/shuffleutils/AWTUtils.java @@ -1,13 +1,14 @@ -package utils.shuffle_utils; +package io.github.arrayv.utils.shuffleutils; -import java.awt.BasicStroke; -import java.awt.Graphics2D; -import java.awt.Stroke; +import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.Rectangle2D; -public class AWTUtils { +public final class AWTUtils { + private AWTUtils() { + } + public static void drawCircle(Graphics2D g, int x, int y, int r) { x = x - r; y = y - r; diff --git a/src/utils/shuffle_utils/GraphConnection.java b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphConnection.java similarity index 72% rename from src/utils/shuffle_utils/GraphConnection.java rename to src/main/java/io/github/arrayv/utils/shuffleutils/GraphConnection.java index 0e0f1e6c..aed06911 100644 --- a/src/utils/shuffle_utils/GraphConnection.java +++ b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphConnection.java @@ -1,15 +1,11 @@ -package utils.shuffle_utils; +package io.github.arrayv.utils.shuffleutils; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Stroke; -import java.awt.Point; +import java.awt.*; import java.util.List; public class GraphConnection { - public GraphNode from, to; - public Point currentDragPos; + private GraphNode from, to; + private Point currentDragPos; public GraphConnection(GraphNode from, GraphNode to) { this.from = from; @@ -49,18 +45,18 @@ public void draw(Graphics2D g) { public void remove() { if (this.from != null) { - this.from.postConnection = null; + this.from.setPostConnection(null); } if (this.to != null) { - this.to.preConnection = null; + this.to.setPreConnection(null); } } public void finishDragging(GraphNode other) { this.to = other; - other.preConnection = this; + other.setPreConnection(this); int removed = 0; - List connections = other.graph.connections; + List connections = other.getGraph().getConnections(); for (int i = 0; i < connections.size(); i++) { GraphConnection conn = connections.get(i - removed); if (conn == this) { @@ -73,4 +69,28 @@ public void finishDragging(GraphNode other) { } } } + + public GraphNode getFrom() { + return from; + } + + public void setFrom(GraphNode node) { + this.from = node; + } + + public GraphNode getTo() { + return to; + } + + public void setTo(GraphNode node) { + this.to = node; + } + + public Point getCurrentDragPos() { + return currentDragPos; + } + + public void setCurrentDragPos(Point pos) { + this.currentDragPos = pos; + } } diff --git a/src/utils/shuffle_utils/GraphNode.java b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphNode.java similarity index 62% rename from src/utils/shuffle_utils/GraphNode.java rename to src/main/java/io/github/arrayv/utils/shuffleutils/GraphNode.java index 2b3243be..84e8fa43 100644 --- a/src/utils/shuffle_utils/GraphNode.java +++ b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphNode.java @@ -1,21 +1,19 @@ -package utils.shuffle_utils; +package io.github.arrayv.utils.shuffleutils; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.geom.Rectangle2D; +import io.github.arrayv.utils.ShuffleGraph; +import io.github.arrayv.utils.ShuffleInfo; -import utils.ShuffleGraph; -import utils.ShuffleInfo; +import java.awt.*; +import java.awt.geom.Rectangle2D; public class GraphNode { public static final int WIDTH = 250; public static final int HEIGHT = 50; - public ShuffleInfo shuffle; - public int x, y; - public ShuffleGraph graph; - public GraphConnection preConnection, postConnection; + private final ShuffleInfo shuffle; + private int x, y; + private ShuffleGraph graph; + private GraphConnection preConnection, postConnection; public GraphNode(ShuffleInfo shuffle, ShuffleGraph graph, int x, int y) { this.shuffle = shuffle; @@ -55,8 +53,8 @@ protected String getShuffleName() { } public void draw(Graphics2D g) { - Color borderColor = this.graph.selected == this ? new Color(128, 128, 255) : new Color(0, 0, 0); - Color leftColor = this.graph.dragCandidate == this ? new Color(128, 128, 255) : borderColor; + Color borderColor = this.graph.getSelected() == this ? new Color(128, 128, 255) : new Color(0, 0, 0); + Color leftColor = this.graph.getDragCandidate() == this ? new Color(128, 128, 255) : borderColor; g.setColor(leftColor); AWTUtils.drawCircle(g, x, y + HEIGHT / 2, 10); g.setColor(borderColor); @@ -89,28 +87,28 @@ public boolean inArea(Point pos) { } public boolean inStartDrag(Point pos) { - return (new Rectangle2D.Double(x + WIDTH - 15, y + HEIGHT / 2 - 10, 30, 20)).contains(pos); + return (new Rectangle2D.Double(x + WIDTH - 15, y + HEIGHT / 2.0 - 10, 30, 20)).contains(pos); } public void delete() { - if (this == this.graph.selected) { - this.graph.selected = null; + if (this == this.graph.getSelected()) { + this.graph.setSelected(null); } - this.graph.nodes.remove(this); + this.graph.getNodes().remove(this); if (this.preConnection != null) { if (this.postConnection == null) { - this.graph.connections.remove(this.preConnection); + this.graph.getConnections().remove(this.preConnection); this.preConnection.remove(); } else { - this.preConnection.to = this.postConnection.to; + this.preConnection.setTo(this.postConnection.getTo()); } } if (this.postConnection != null) { if (this.preConnection == null) { - this.graph.connections.remove(this.postConnection); + this.graph.getConnections().remove(this.postConnection); this.postConnection.remove(); } else { - this.postConnection.from = this.preConnection.from; + this.postConnection.setFrom(this.preConnection.getFrom()); } } } @@ -122,4 +120,44 @@ public Point getPos() { public ShuffleInfo getValue() { return this.shuffle; } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public ShuffleGraph getGraph() { + return graph; + } + + public GraphConnection getPreConnection() { + return preConnection; + } + + public GraphConnection getPostConnection() { + return postConnection; + } + + public void setX(int x) { + this.x = x; + } + + public void setY(int y) { + this.y = y; + } + + public void setGraph(ShuffleGraph graph) { + this.graph = graph; + } + + public void setPreConnection(GraphConnection connection) { + this.preConnection = connection; + } + + public void setPostConnection(GraphConnection connection) { + this.postConnection = connection; + } } diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphReader.java similarity index 73% rename from src/utils/shuffle_utils/GraphReader.java rename to src/main/java/io/github/arrayv/utils/shuffleutils/GraphReader.java index c6df7e52..7becee79 100644 --- a/src/utils/shuffle_utils/GraphReader.java +++ b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphReader.java @@ -1,23 +1,19 @@ -package utils.shuffle_utils; +package io.github.arrayv.utils.shuffleutils; -import java.awt.Point; +import io.github.arrayv.utils.Distributions; +import io.github.arrayv.utils.ShuffleGraph; +import io.github.arrayv.utils.ShuffleInfo; +import io.github.arrayv.utils.Shuffles; + +import java.awt.*; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Scanner; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; -import utils.Distributions; -import utils.ShuffleGraph; -import utils.ShuffleInfo; -import utils.Shuffles; - public final class GraphReader { - public final class MalformedGraphFileException extends Exception { + public static final class MalformedGraphFileException extends Exception { public MalformedGraphFileException() { super(); } @@ -26,17 +22,17 @@ public MalformedGraphFileException(String message) { super(message); } } - - private final class PartialElement { + + private static final class PartialElement { int left, right; - public PartialElement(int left, int right) { + private PartialElement(int left, int right) { this.left = left; this.right = right; } } - public final static int[] COMPATIBLE_VERSIONS = {0, 1, 2, 3}; + public static final int[] COMPATIBLE_VERSIONS = {0, 1, 2, 3}; static Set compatibleVersionsSet; Scanner scanner; @@ -47,10 +43,10 @@ public PartialElement(int left, int right) { public GraphReader() { result = null; if (compatibleVersionsSet == null) { - compatibleVersionsSet = new HashSet<>( + compatibleVersionsSet = Collections.unmodifiableSet( Arrays.stream(COMPATIBLE_VERSIONS) .boxed() - .collect(Collectors.toList()) + .collect(Collectors.toSet()) ); } } @@ -89,19 +85,19 @@ public ShuffleGraph read(Scanner scanner) throws IOException, MalformedGraphFile return result; } - private void read() throws IOException, MalformedGraphFileException { + private void read() throws MalformedGraphFileException { version = scanner.hasNextInt() ? scanner.nextInt() : 0; if (!compatibleVersionsSet.contains(version)) { throw new MalformedGraphFileException("Unsupported version for reading: " + version + " (Supported versions: " - + Arrays.stream(COMPATIBLE_VERSIONS) - .mapToObj(String::valueOf) - .collect(Collectors.joining(", ", "{", "}")) + ")"); + + Arrays.stream(COMPATIBLE_VERSIONS) + .mapToObj(String::valueOf) + .collect(Collectors.joining(", ", "{", "}")) + ")"); } result = new ShuffleGraph(); partialNodes = new ArrayList<>(); if (version >= 2 && scanner.hasNextDouble()) { - result.sleepRatio = scanner.nextDouble(); + result.setSleepRatio(scanner.nextDouble()); } while (scanner.hasNext()) { @@ -118,27 +114,27 @@ private void read() throws IOException, MalformedGraphFileException { } } - for (int i = 1; i < result.nodes.size(); i++) { - GraphNode node = result.nodes.get(i); + for (int i = 1; i < result.getNodes().size(); i++) { + GraphNode node = result.getNodes().get(i); PartialElement partial = partialNodes.get(i - 1); try { if (version < 3) { - node.preConnection = partial.left == -1 ? null : result.connections.get(partial.left); - node.postConnection = partial.right == -1 ? null : result.connections.get(partial.right); + node.setPreConnection(partial.left == -1 ? null : result.getConnections().get(partial.left)); + node.setPostConnection(partial.right == -1 ? null : result.getConnections().get(partial.right)); } else { - if (partial.left != -1 && node.preConnection == null) { - GraphNode from = result.nodes.get(partial.left); + if (partial.left != -1 && node.getPreConnection() == null) { + GraphNode from = result.getNodes().get(partial.left); GraphConnection newConnection = new GraphConnection(from, node); - result.connections.add(newConnection); - from.postConnection = newConnection; - node.preConnection = newConnection; + result.getConnections().add(newConnection); + from.setPostConnection(newConnection); + node.setPreConnection(newConnection); } - if (partial.right != -1 && node.postConnection == null) { - GraphNode to = result.nodes.get(partial.right); + if (partial.right != -1 && node.getPostConnection() == null) { + GraphNode to = result.getNodes().get(partial.right); GraphConnection newConnection = new GraphConnection(node, to); - result.connections.add(newConnection); - node.postConnection = newConnection; - to.preConnection = newConnection; + result.getConnections().add(newConnection); + node.setPostConnection(newConnection); + to.setPreConnection(newConnection); } } } catch (IndexOutOfBoundsException e) { @@ -151,17 +147,17 @@ private void read() throws IOException, MalformedGraphFileException { } if (version >= 2) { - for (int i = 1; i < result.nodes.size(); i++) { - GraphNode node = result.nodes.get(i); - if (node.x == Integer.MIN_VALUE) { // coordinates not specified - if (node.preConnection == null || node.preConnection.from == null) { + for (int i = 1; i < result.getNodes().size(); i++) { + GraphNode node = result.getNodes().get(i); + if (node.getX() == Integer.MIN_VALUE) { // coordinates not specified + if (node.getPreConnection() == null) { Point safePos = result.findSafeCoordinates(100, 100, 20, 20); - node.x = safePos.x; - node.y = safePos.y; + node.setX(safePos.x); + node.setY(safePos.y); } else { - GraphNode previous = node.preConnection.from; - node.x = previous.x + GraphNode.WIDTH + 15; - node.y = previous.y; + GraphNode previous = node.getPreConnection().getFrom(); + node.setX(previous.getX() + GraphNode.WIDTH + 15); + node.setY(previous.getY()); } } } @@ -244,7 +240,7 @@ private void readNode() throws MalformedGraphFileException { } } - result.nodes.add(new GraphNode(shuffleInfo, result, x, y)); + result.getNodes().add(new GraphNode(shuffleInfo, result, x, y)); partialNodes.add(new PartialElement(preConnectionID, postConnectionID)); } @@ -261,10 +257,10 @@ private void readConnection() throws MalformedGraphFileException { } int toNodeID = scanner.nextInt(); - GraphNode fromNode = null, toNode = null; + GraphNode fromNode, toNode; try { - fromNode = fromNodeID == -1 ? null : result.nodes.get(fromNodeID); - toNode = toNodeID == -1 ? null : result.nodes.get(toNodeID); + fromNode = fromNodeID == -1 ? null : result.getNodes().get(fromNodeID); + toNode = toNodeID == -1 ? null : result.getNodes().get(toNodeID); } catch (IndexOutOfBoundsException e) { String message = e.getMessage(); int id = Integer.parseInt(message.split(" ", 3)[1]); @@ -273,9 +269,9 @@ private void readConnection() throws MalformedGraphFileException { throw newError; } GraphConnection connection = new GraphConnection(fromNode, toNode); - result.connections.add(connection); + result.getConnections().add(connection); if (fromNodeID == 0) { - fromNode.postConnection = connection; + fromNode.setPostConnection(connection); } } } diff --git a/src/utils/shuffle_utils/GraphWriter.java b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphWriter.java similarity index 65% rename from src/utils/shuffle_utils/GraphWriter.java rename to src/main/java/io/github/arrayv/utils/shuffleutils/GraphWriter.java index 3aa53863..e6ae14c4 100644 --- a/src/utils/shuffle_utils/GraphWriter.java +++ b/src/main/java/io/github/arrayv/utils/shuffleutils/GraphWriter.java @@ -1,4 +1,6 @@ -package utils.shuffle_utils; +package io.github.arrayv.utils.shuffleutils; + +import io.github.arrayv.utils.ShuffleGraph; import java.io.File; import java.io.FileWriter; @@ -6,8 +8,6 @@ import java.util.HashMap; import java.util.Map; -import utils.ShuffleGraph; - public final class GraphWriter { public static final int VERSION = 3; @@ -29,19 +29,19 @@ public void write(File file) throws IOException { public void write(FileWriter writer) throws IOException { Map nodeMap = new HashMap<>(); - for (int i = 0; i < graph.nodes.size(); i++) { - GraphNode node = graph.nodes.get(i); + for (int i = 0; i < graph.getNodes().size(); i++) { + GraphNode node = graph.getNodes().get(i); nodeMap.put(node, i); } nodeMap.put(null, -1); // Metadata writer.write(VERSION + " "); - writer.write(graph.sleepRatio + "\n"); + writer.write(graph.getSleepRatio() + "\n"); // Nodes - for (int i = 1; i < graph.nodes.size(); i++) { - GraphNode node = graph.nodes.get(i); + for (int i = 1; i < graph.getNodes().size(); i++) { + GraphNode node = graph.getNodes().get(i); writer.write("N "); if (node.getValue().isDistribution()) { writer.write("true "); @@ -51,10 +51,10 @@ public void write(FileWriter writer) throws IOException { writer.write("false "); writer.write(node.getValue().getShuffle().name() + " "); } - writer.write(node.x + " "); - writer.write(node.y + " "); - writer.write((node.preConnection == null ? -1 : nodeMap.get(node.preConnection.from)) + " "); - writer.write((node.postConnection == null ? -1 : nodeMap.get(node.postConnection.to)) + "\n"); + writer.write(node.getX() + " "); + writer.write(node.getY() + " "); + writer.write((node.getPreConnection() == null ? -1 : nodeMap.get(node.getPreConnection().getFrom())) + " "); + writer.write((node.getPostConnection() == null ? -1 : nodeMap.get(node.getPostConnection().getTo())) + "\n"); } writer.close(); diff --git a/src/main/java/io/github/arrayv/visuals/Visual.java b/src/main/java/io/github/arrayv/visuals/Visual.java new file mode 100644 index 00000000..dadd799f --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/Visual.java @@ -0,0 +1,131 @@ +package io.github.arrayv.visuals; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; + +import java.awt.*; + +public abstract class Visual { + protected Graphics2D mainRender; + protected Graphics2D extraRender; + + public Visual(ArrayVisualizer arrayVisualizer) { + this.updateRender(arrayVisualizer); + } + + public void updateRender(ArrayVisualizer arrayVisualizer) { + this.mainRender = arrayVisualizer.getMainRender(); + this.extraRender = arrayVisualizer.getExtraRender(); + } + + public static Color getIntColor(int i, int length) { + return Color.getHSBColor(((float) i / length), 0.8F, 0.8F); + } + + public static void markBar(Graphics2D bar, boolean color, boolean rainbow, boolean analysis) { + if (color || rainbow) { + if (analysis) bar.setColor(Color.LIGHT_GRAY); + else bar.setColor(Color.WHITE); + } else if (analysis) bar.setColor(Color.BLUE); + else bar.setColor(Color.RED); + } + private static void markBarFancy(Graphics2D bar, boolean color, boolean rainbow) { + if (!color && !rainbow) bar.setColor(Color.RED); + else bar.setColor(Color.BLACK); + } + + public static void lineMark(Graphics2D line, double width, boolean color, boolean analysis) { + line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); + if (color) line.setColor(Color.BLACK); + else if (analysis) line.setColor(Color.BLUE); + else line.setColor(Color.RED); + } + + public static void markLineFancy(Graphics2D line, double width) { + line.setColor(Color.GREEN); + line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); + } + + public static void clearLine(Graphics2D line, boolean color, int[] array, int i, int length, double width) { + if (color) line.setColor(getIntColor(array[i], length)); + else line.setColor(Color.WHITE); + line.setStroke(new BasicStroke((float) (3f * (width / 1280f)))); + } + + public static void setRectColor(Graphics2D rect, boolean color, boolean analysis) { + if (color) rect.setColor(Color.WHITE); + else if (analysis) rect.setColor(Color.BLUE); + else rect.setColor(Color.RED); + } + + //The longer the array length, the more bars marked. Makes the visual easier to see when bars are thinner. + public static void colorMarkedBars(int logOfLen, int index, Highlights Highlights, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled, boolean analysis) { + switch(logOfLen) { + // @checkstyle:off LeftCurlyCheck|IndentationCheck + case 15: if (Highlights.containsPosition(index - 15)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 14)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 13)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 12)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 11)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + case 14: if (Highlights.containsPosition(index - 10)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 9)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 8)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + case 13: if (Highlights.containsPosition(index - 7)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 6)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 5)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + case 12: if (Highlights.containsPosition(index - 4)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + if (Highlights.containsPosition(index - 3)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + case 11: if (Highlights.containsPosition(index - 2)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + case 10: if (Highlights.containsPosition(index - 1)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } + default: if (Highlights.containsPosition(index)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); + // @checkstyle:on LeftCurlyCheck|IndentationCheck + } + } + + public static void drawFancyFinish(int logOfLen, int index, int position, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled) { + switch(logOfLen) { + // @checkstyle:off LeftCurlyCheck + case 15: if (index == position - 14) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 14: if (index == position - 13) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 13: if (index == position - 12) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 12: if (index == position - 11) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 11: if (index == position - 10) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 10: if (index == position - 9) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 9: if (index == position - 8) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 8: if (index == position - 7) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 7: if (index == position - 6) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 6: if (index == position - 5) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 5: if (index == position - 4) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 4: if (index == position - 3) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 3: if (index == position - 2) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + case 2: if (index == position - 1) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } + default: if (index == position) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + // @checkstyle:on LeftCurlyCheck + } + } + + public static void drawFancyFinishLine(int logOfLen, int index, int position, Graphics2D mainRender, double width, boolean colorEnabled) { + switch(logOfLen) { + // @checkstyle:off LeftCurlyCheck + case 15: if (index == position - 14) { lineMark(mainRender, width, colorEnabled, false); break; } + case 14: if (index == position - 13) { lineMark(mainRender, width, colorEnabled, false); break; } + case 13: if (index == position - 12) { lineMark(mainRender, width, colorEnabled, false); break; } + case 12: if (index == position - 11) { lineMark(mainRender, width, colorEnabled, false); break; } + case 11: if (index == position - 10) { lineMark(mainRender, width, colorEnabled, false); break; } + case 10: if (index == position - 9) { lineMark(mainRender, width, colorEnabled, false); break; } + case 9: if (index == position - 8) { lineMark(mainRender, width, colorEnabled, false); break; } + case 8: if (index == position - 7) { lineMark(mainRender, width, colorEnabled, false); break; } + case 7: if (index == position - 6) { lineMark(mainRender, width, colorEnabled, false); break; } + case 6: if (index == position - 5) { lineMark(mainRender, width, colorEnabled, false); break; } + case 5: if (index == position - 4) { lineMark(mainRender, width, colorEnabled, false); break; } + case 4: if (index == position - 3) { lineMark(mainRender, width, colorEnabled, false); break; } + case 3: if (index == position - 2) { lineMark(mainRender, width, colorEnabled, false); break; } + case 2: if (index == position - 1) { lineMark(mainRender, width, colorEnabled, false); break; } + default: if (index == position) lineMark(mainRender, width, colorEnabled, false); + // @checkstyle:on LeftCurlyCheck + } + } + + public abstract void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights); +} diff --git a/src/main/java/io/github/arrayv/visuals/VisualStyles.java b/src/main/java/io/github/arrayv/visuals/VisualStyles.java new file mode 100644 index 00000000..76630b44 --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/VisualStyles.java @@ -0,0 +1,130 @@ +package io.github.arrayv.visuals; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public enum VisualStyles { + BARS { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[0].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + RAINBOW { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[1].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + DISP_BARS { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[2].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + COLOR_CIRCLE { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[3].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + DISP_CIRCLE { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[4].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + DISP_CHORDS { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[5].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + DISP_DOTS { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[6].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + DOTS { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[7].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + WAVE_DOTS { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[8].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + CUSTOM_IMAGE { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[9].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + SINE_WAVE { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[10].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + HOOP_STACK { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[11].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + PIXEL_MESH { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[12].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + SPIRAL { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[13].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }, + SPIRAL_DOTS { + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + arrayVisualizer.getVisuals()[14].drawVisual(array, arrayVisualizer, renderer, Highlights); + } + }; + + public VisualStyles getCurrentVisual() { + return this; + } + + public abstract void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights); +} diff --git a/src/main/java/io/github/arrayv/visuals/bars/BarGraph.java b/src/main/java/io/github/arrayv/visuals/bars/BarGraph.java new file mode 100644 index 00000000..6920b6ae --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/bars/BarGraph.java @@ -0,0 +1,59 @@ +package io.github.arrayv.visuals.bars; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +public final class BarGraph extends Visual { + + public BarGraph(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1)) - j; + if (width == 0) continue; + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + else if (arrayVisualizer.colorEnabled()) { + int val = arrayVisualizer.doingStabilityCheck() ? arrayVisualizer.getIndexValue(array[i]): array[i]; + this.mainRender.setColor(getIntColor(val, arrayVisualizer.getCurrentLength())); + } else this.mainRender.setColor(Color.WHITE); + + int val = arrayVisualizer.doingStabilityCheck() && arrayVisualizer.colorEnabled() ? arrayVisualizer.getStabilityValue(array[i]): array[i]; + int y = (int) (((renderer.getViewSize() - 20)) - (val + 1) * renderer.getYScale()); + + this.mainRender.fillRect(j + 20, renderer.getYOffset() + y, width, (int) ((val + 1) * renderer.getYScale())); + j += width; + } + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + int length = Math.min(renderer.getArrayLength(), arrayVisualizer.getCurrentLength()); + + boolean mark = false; + for (int i = 0, j = 0; i < length; i++) { + mark = mark || Highlights.containsPosition(i); + + int width = (int) (renderer.getXScale() * (i + 1)) - j; + if (width == 0) continue; + + if (mark) { + int val = arrayVisualizer.doingStabilityCheck() && arrayVisualizer.colorEnabled() ? arrayVisualizer.getStabilityValue(array[i]): array[i]; + int y = (int) (((renderer.getViewSize() - 20)) - (val + 1) * renderer.getYScale()); + + this.mainRender.fillRect(j + 20, renderer.getYOffset() + y, Math.max(width, 2), (int) ((val + 1) * renderer.getYScale())); + mark = false; + } + j += width; + } + if (arrayVisualizer.externalArraysEnabled()) { + this.mainRender.setColor(Color.BLUE); + this.mainRender.fillRect(0, renderer.getYOffset() + renderer.getViewSize() - 20, arrayVisualizer.currentWidth(), 1); + } + } +} diff --git a/src/main/java/io/github/arrayv/visuals/bars/DisparityBarGraph.java b/src/main/java/io/github/arrayv/visuals/bars/DisparityBarGraph.java new file mode 100644 index 00000000..9e2b9730 --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/bars/DisparityBarGraph.java @@ -0,0 +1,54 @@ +package io.github.arrayv.visuals.bars; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +public final class DisparityBarGraph extends Visual { + + public DisparityBarGraph(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1)) - j; + if (width == 0) continue; + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + + else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + + else this.mainRender.setColor(Color.WHITE); + + double disp = (1 + Math.sin((Math.PI * (array[i] - i)) / arrayVisualizer.getCurrentLength())) * 0.5; + int y = (int) (((renderer.getViewSize() - 20)) - disp * arrayVisualizer.getCurrentLength() * renderer.getYScale()); + + this.mainRender.fillRect(j + 20, renderer.getYOffset() + y, width, (int) (disp * arrayVisualizer.getCurrentLength() * renderer.getYScale())); + j += width; + } + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1)) - j; + + if (Highlights.containsPosition(i)) { + double disp = (1 + Math.sin((Math.PI * (array[i] - i)) / arrayVisualizer.getCurrentLength())) * 0.5; + int y = (int) (((renderer.getViewSize() - 20)) - disp * arrayVisualizer.getCurrentLength() * renderer.getYScale()); + + this.mainRender.fillRect(j + 20, renderer.getYOffset() + y, Math.max(width, 2), (int) (disp * arrayVisualizer.getCurrentLength() * renderer.getYScale())); + } + j += width; + } + if (arrayVisualizer.externalArraysEnabled()) { + this.mainRender.setColor(Color.BLUE); + this.mainRender.fillRect(0, renderer.getYOffset() + renderer.getViewSize() - 20, arrayVisualizer.currentWidth(), 1); + } + } +} diff --git a/src/main/java/io/github/arrayv/visuals/bars/Rainbow.java b/src/main/java/io/github/arrayv/visuals/bars/Rainbow.java new file mode 100644 index 00000000..907dd930 --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/bars/Rainbow.java @@ -0,0 +1,72 @@ +package io.github.arrayv.visuals.bars; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class Rainbow extends Visual { + public Rainbow(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1)) - j; + if (width == 0) continue; + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + else this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + + this.mainRender.fillRect(j + 20, renderer.getYOffset() - 20, width, renderer.getViewSize()); + + j += width; + } + if (arrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); + else this.mainRender.setColor(Color.WHITE); + + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1)) - j; + + if (Highlights.containsPosition(i)) { + + this.mainRender.fillRect(j + 20, renderer.getYOffset() - 20, Math.max(width, 2), renderer.getViewSize()); + } + j += width; + } + if (arrayVisualizer.externalArraysEnabled()) { + this.mainRender.setColor(Color.BLUE); + this.mainRender.fillRect(0, renderer.getYOffset() + renderer.getViewSize() - 20, arrayVisualizer.currentWidth(), 1); + } + } +} diff --git a/src/main/java/io/github/arrayv/visuals/bars/SineWave.java b/src/main/java/io/github/arrayv/visuals/bars/SineWave.java new file mode 100644 index 00000000..36c04eaf --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/bars/SineWave.java @@ -0,0 +1,77 @@ +package io.github.arrayv.visuals.bars; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +/* + * +MIT License + +Copyright (c) 2020 MusicTheorist +Copyright (c) 2021 ArrayV 4.0 Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class SineWave extends Visual { + + public SineWave(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + + else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + + else this.mainRender.setColor(Color.WHITE); + + int width = (int) (renderer.getXScale() * (i + 1)) - j; + + int y = (int) (((renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / renderer.getArrayLength()))) + renderer.halfViewSize() - 20); + this.mainRender.fillRect(j + 20, renderer.getYOffset() + y, Math.max(width, 1), 20); + + j += width; + } + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1)) - j; + + if (Highlights.containsPosition(i)) { + int y = (int) (((renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / renderer.getArrayLength()))) + renderer.halfViewSize() - 20); + this.mainRender.fillRect(j + 20, renderer.getYOffset() + y, Math.max(width, 2), 20); + } + j += width; + } + if (arrayVisualizer.externalArraysEnabled()) { + this.mainRender.setColor(Color.BLUE); + this.mainRender.fillRect(0, renderer.getYOffset() + renderer.getViewSize() - 20, arrayVisualizer.currentWidth(), 1); + } + } +} diff --git a/src/main/java/io/github/arrayv/visuals/circles/ColorCircle.java b/src/main/java/io/github/arrayv/visuals/circles/ColorCircle.java new file mode 100644 index 00000000..7ab525e3 --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/circles/ColorCircle.java @@ -0,0 +1,106 @@ +package io.github.arrayv.visuals.circles; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy +Copyright (c) 2021 ArrayV 4.0 Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class ColorCircle extends Visual { + + public ColorCircle(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth(); + int height = arrayVisualizer.windowHeight(); + + int n = arrayVisualizer.getCurrentLength(); + + double r = Math.min(width, height)/2.75; + int p = (int)(r/12); + + int[] x = new int[3]; + int[] y = new int[3]; + + int[] px = new int[3]; + int[] py = new int[3]; + + this.extraRender.setColor(Color.WHITE); + + x[0] = width/2; + y[0] = height/2; + + double angle = Math.PI * (2d * (n - 1) / n - 0.5); + x[2] = width/2 + (int)(r * Math.cos(angle)); + y[2] = height/2 + (int)(r * Math.sin(angle)); + + for (int i = 0; i < n; i++) { + x[1] = x[2]; + y[1] = y[2]; + + x[2] = width/2 + (int)(r * Math.cos(Math.PI * (2d*i / n - 0.5))); + y[2] = height/2 + (int)(r * Math.sin(Math.PI * (2d*i / n - 0.5))); + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + + else { + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + + if (Highlights.containsPosition(i)) { + if (arrayVisualizer.analysisEnabled()) this.extraRender.setColor(Color.LIGHT_GRAY); + else this.extraRender.setColor(Color.WHITE); + + double angle1 = Math.PI * ((2d * i - 1) / n - 0.5); + px[0] = width/2 + (int)((r + p/4) * Math.cos(angle1)); + py[0] = height/2 + (int)((r + p/4) * Math.sin(angle1)); + + double angle2 = Math.PI * ((2d * i - 1) / n - 0.67); + px[1] = px[0] + (int)(p * Math.cos(angle2)); + py[1] = py[0] + (int)(p * Math.sin(angle2)); + + double angle3 = Math.PI * ((2d * i - 1) / n - 0.33); + px[2] = px[0] + (int)(p * Math.cos(angle3)); + py[2] = py[0] + (int)(p * Math.sin(angle3)); + + this.extraRender.fillPolygon(px, py, 3); + } + } + + if (x[1] != x[2] || y[1] != y[2]) this.mainRender.fillPolygon(x, y, 3); + } + } +} diff --git a/src/visuals/circles/DisparityChords.java b/src/main/java/io/github/arrayv/visuals/circles/DisparityChords.java similarity index 50% rename from src/visuals/circles/DisparityChords.java rename to src/main/java/io/github/arrayv/visuals/circles/DisparityChords.java index ed61df65..4850d207 100644 --- a/src/visuals/circles/DisparityChords.java +++ b/src/main/java/io/github/arrayv/visuals/circles/DisparityChords.java @@ -1,16 +1,14 @@ -package visuals.circles; +package io.github.arrayv.visuals.circles; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Polygon; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; +import java.awt.*; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -36,58 +34,59 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class DisparityChords extends Visual { - - public DisparityChords(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); +public final class DisparityChords extends Visual { + + public DisparityChords(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } - + @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; - - int width = ArrayVisualizer.windowWidth(); - int height = ArrayVisualizer.windowHeight(); - - int n = ArrayVisualizer.getCurrentLength(); + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth(); + int height = arrayVisualizer.windowHeight(); + + int n = arrayVisualizer.getCurrentLength(); double r = Math.min(width, height)/2.5; - - this.mainRender.setStroke(ArrayVisualizer.getThinStroke()); - - for(int i = n-1; i >= 0; i--) { - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - + + this.mainRender.setStroke(arrayVisualizer.getThinStroke()); + + for (int i = n-1; i >= 0; i--) { + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + int ax = width/2 + (int)(r * Math.cos(Math.PI * (2d*i / n - 0.5))); int ay = height/2 + (int)(r * Math.sin(Math.PI * (2d*i / n - 0.5))); int bx = width/2 + (int)(r * Math.cos(Math.PI * (2d*array[i] / n - 0.5))); int by = height/2 + (int)(r * Math.sin(Math.PI * (2d*array[i] / n - 0.5))); - - this.mainRender.drawLine(ax, ay, bx, by); + + this.mainRender.drawLine(ax, ay, bx, by); } - this.mainRender.setStroke(ArrayVisualizer.getDefaultStroke()); - - for(int i = 0; i < n; i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { + this.mainRender.setStroke(arrayVisualizer.getDefaultStroke()); + + for (int i = 0; i < n; i++) { + double x = r * Math.cos(Math.PI * (2d * i / n - 0.5)); + double y = r * Math.sin(Math.PI * (2d * i / n - 0.5)); + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { this.mainRender.setColor(Color.GREEN); - - int ax = width/2 + (int)(r * Math.cos(Math.PI * (2d*i / n - 0.5))); - int ay = height/2 + (int)(r * Math.sin(Math.PI * (2d*i / n - 0.5))); + + int ax = width/2 + (int)x; + int ay = height/2 + (int)y; int bx = width/2 + (int)(r * Math.cos(Math.PI * (2d*array[i] / n - 0.5))); int by = height/2 + (int)(r * Math.sin(Math.PI * (2d*array[i] / n - 0.5))); - - this.mainRender.drawLine(ax, ay, bx, by); - } - else if(Highlights.containsPosition(i)) { - if(ArrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); - else this.mainRender.setColor(Color.WHITE); - - int ax = width/2 + (int)(r * Math.cos(Math.PI * (2d*i / n - 0.5))); - int ay = height/2 + (int)(r * Math.sin(Math.PI * (2d*i / n - 0.5))); + + this.mainRender.drawLine(ax, ay, bx, by); + } else if (Highlights.containsPosition(i)) { + if (arrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); + else this.mainRender.setColor(Color.WHITE); + + int ax = width/2 + (int)x; + int ay = height/2 + (int)y; int bx = width/2 + (int)(r * Math.cos(Math.PI * (2d*array[i] / n - 0.5))); int by = height/2 + (int)(r * Math.sin(Math.PI * (2d*array[i] / n - 0.5))); - - this.mainRender.drawLine(ax, ay, bx, by); + + this.mainRender.drawLine(ax, ay, bx, by); } } } -} \ No newline at end of file +} diff --git a/src/visuals/circles/DisparityCircle.java b/src/main/java/io/github/arrayv/visuals/circles/DisparityCircle.java similarity index 50% rename from src/visuals/circles/DisparityCircle.java rename to src/main/java/io/github/arrayv/visuals/circles/DisparityCircle.java index dcc8aa13..47d6d34f 100644 --- a/src/visuals/circles/DisparityCircle.java +++ b/src/main/java/io/github/arrayv/visuals/circles/DisparityCircle.java @@ -1,16 +1,14 @@ -package visuals.circles; +package io.github.arrayv.visuals.circles; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Polygon; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; +import java.awt.*; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -36,54 +34,52 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class DisparityCircle extends Visual { - - public DisparityCircle(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); +public final class DisparityCircle extends Visual { + + public DisparityCircle(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } - + @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; - - int width = ArrayVisualizer.windowWidth(); - int height = ArrayVisualizer.windowHeight(); - - int n = ArrayVisualizer.getCurrentLength(); + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth(); + int height = arrayVisualizer.windowHeight(); + + int n = arrayVisualizer.getCurrentLength(); double r = Math.min(width, height)/2.5; - - this.extraRender.setStroke(ArrayVisualizer.getThickStroke()); - this.extraRender.setColor(ArrayVisualizer.getHighlightColor()); - + + this.extraRender.setStroke(arrayVisualizer.getThickStroke()); + this.extraRender.setColor(arrayVisualizer.getHighlightColor()); + int[] x = {width/2, 0, 0}; int[] y = {height/2, 0, 0}; - - double disp = (1 + Math.cos((Math.PI * (array[n-1] - (n-1))) / (ArrayVisualizer.getCurrentLength() * 0.5))) * 0.5; - x[2] = width/2 + (int)(disp * r * Math.cos(Math.PI * (2d*(n-1) / n - 0.5))); - y[2] = height/2 + (int)(disp * r * Math.sin(Math.PI * (2d*(n-1) / n - 0.5))); - - for(int i = 0; i < n; i++) { + + double disp = (1 + Math.cos((Math.PI * (array[n-1] - (n-1))) / (arrayVisualizer.getCurrentLength() * 0.5))) * 0.5; + double angle = Math.PI * (2d * (n - 1) / n - 0.5); + x[2] = width/2 + (int)(disp * r * Math.cos(angle)); + y[2] = height/2 + (int)(disp * r * Math.sin(angle)); + + for (int i = 0; i < n; i++) { x[1] = x[2]; y[1] = y[2]; - - disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (ArrayVisualizer.getCurrentLength() * 0.5))) * 0.5; + + disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (arrayVisualizer.getCurrentLength() * 0.5))) * 0.5; x[2] = width/2 + (int)(disp * r * Math.cos(Math.PI * (2d*i / n - 0.5))); y[2] = height/2 + (int)(disp * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) this.mainRender.setColor(Color.GREEN); - - else if(Highlights.containsPosition(i)) { - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - this.extraRender.drawPolygon(x, y, 3); - } - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - + else if (Highlights.containsPosition(i)) { + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + this.extraRender.drawPolygon(x, y, 3); + } else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); else this.mainRender.setColor(Color.WHITE); - - this.mainRender.fillPolygon(x, y, 3); + + this.mainRender.fillPolygon(x, y, 3); } - this.extraRender.setStroke(ArrayVisualizer.getDefaultStroke()); + this.extraRender.setStroke(arrayVisualizer.getDefaultStroke()); } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/visuals/circles/Spiral.java b/src/main/java/io/github/arrayv/visuals/circles/Spiral.java new file mode 100644 index 00000000..509cc953 --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/circles/Spiral.java @@ -0,0 +1,91 @@ +package io.github.arrayv.visuals.circles; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy +Copyright (c) 2021 ArrayV 4.0 Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class Spiral extends Visual { + + public Spiral(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth(); + int height = arrayVisualizer.windowHeight(); + + int n = arrayVisualizer.getCurrentLength(); + double r = Math.min(width, height)/2.5; + + this.extraRender.setStroke(arrayVisualizer.getThickStroke()); + this.extraRender.setColor(arrayVisualizer.getHighlightColor()); + + int[] x = {width/2, 0, 0}; + int[] y = {height/2, 0, 0}; + + double mult = (double) array[n-1] / arrayVisualizer.getCurrentLength() - 1; + mult = 1 - mult*mult; + + double angle = Math.PI * (2d * (n - 1) / n - 0.5); + x[2] = width/2 + (int)(mult * r * Math.cos(angle)); + y[2] = height/2 + (int)(mult * r * Math.sin(angle)); + + for (int i = 0; i < n; i++) { + x[1] = x[2]; + y[1] = y[2]; + + mult = (double) array[i] / arrayVisualizer.getCurrentLength() - 1; + mult = 1 - mult*mult; + + x[2] = width/2 + (int)(mult * r * Math.cos(Math.PI * (2d*i / n - 0.5))); + y[2] = height/2 + (int)(mult * r * Math.sin(Math.PI * (2d*i / n - 0.5))); + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + + else if (Highlights.containsPosition(i)) { + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + this.extraRender.drawPolygon(x, y, 3); + } else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + + else this.mainRender.setColor(Color.WHITE); + + this.mainRender.fillPolygon(x, y, 3); + } + this.extraRender.setStroke(arrayVisualizer.getDefaultStroke()); + } +} diff --git a/src/visuals/dots/DisparityDots.java b/src/main/java/io/github/arrayv/visuals/dots/DisparityDots.java similarity index 52% rename from src/visuals/dots/DisparityDots.java rename to src/main/java/io/github/arrayv/visuals/dots/DisparityDots.java index 7781e722..af4ffc0d 100644 --- a/src/visuals/dots/DisparityDots.java +++ b/src/main/java/io/github/arrayv/visuals/dots/DisparityDots.java @@ -1,16 +1,14 @@ -package visuals.dots; +package io.github.arrayv.visuals.dots; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Polygon; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; +import java.awt.*; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -36,83 +34,81 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class DisparityDots extends Visual { - - public DisparityDots(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); +public final class DisparityDots extends Visual { + + public DisparityDots(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } - + @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; - - int width = ArrayVisualizer.windowWidth(); - int height = ArrayVisualizer.windowHeight(); - - int n = ArrayVisualizer.getCurrentLength(); + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth(); + int height = arrayVisualizer.windowHeight(); + + int n = arrayVisualizer.getCurrentLength(); double r = Math.min(width, height)/2.5; - - if(ArrayVisualizer.linesEnabled()) { - double disp = (1 + Math.cos((Math.PI * (array[n-1] - (n-1))) / (ArrayVisualizer.getCurrentLength() * 0.5))) * 0.5; - int lastX = width/2 + (int)(disp * r * Math.cos(Math.PI * (2d*(n-1) / n - 0.5))); - int lastY = height/2 + (int)(disp * r * Math.sin(Math.PI * (2d*(n-1) / n - 0.5))); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - - for(int i = 0; i < n; i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { + + if (arrayVisualizer.linesEnabled()) { + double disp = (1 + Math.cos((Math.PI * (array[n-1] - (n-1))) / (arrayVisualizer.getCurrentLength() * 0.5))) * 0.5; + double angle = Math.PI * (2d * (n - 1) / n - 0.5); + int lastX = width/2 + (int)(disp * r * Math.cos(angle)); + int lastY = height/2 + (int)(disp * r * Math.sin(angle)); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + + for (int i = 0; i < n; i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { this.mainRender.setColor(Color.GREEN); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(4)); - } - else if(Highlights.containsPosition(i)) { - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(4)); - } - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(4)); + } else if (Highlights.containsPosition(i)) { + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(4)); + } else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(Color.WHITE); - - disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (ArrayVisualizer.getCurrentLength() * 0.5))) * 0.5; + + disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (arrayVisualizer.getCurrentLength() * 0.5))) * 0.5; int x = width/2 + (int)(disp * r * Math.cos(Math.PI * (2d*i / n - 0.5))); int y = height/2 + (int)(disp * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - + this.mainRender.drawLine(lastX, lastY, x, y); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + lastX = x; lastY = y; } - this.mainRender.setStroke(ArrayVisualizer.getDefaultStroke()); - } - else { - int dotS = Renderer.getDotDimensions(); - - for(int i = 0; i < n; i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setStroke(arrayVisualizer.getDefaultStroke()); + } else { + int dotS = renderer.getDotDimensions(); + + for (int i = 0; i < n; i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) this.mainRender.setColor(Color.GREEN); - - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - + + else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(Color.WHITE); - - double disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (ArrayVisualizer.getCurrentLength() * 0.5))) * 0.5; + + double disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (arrayVisualizer.getCurrentLength() * 0.5))) * 0.5; int x = width/2 + (int)(disp * r * Math.cos(Math.PI * (2d*i / n - 0.5))); int y = height/2 + (int)(disp * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - + this.mainRender.fillRect(x, y, dotS, dotS); } - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - - for(int i = 0; i < n; i++) { - if(Highlights.containsPosition(i)) { - double disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (ArrayVisualizer.getCurrentLength() * 0.5))) * 0.5; + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + + for (int i = 0; i < n; i++) { + if (Highlights.containsPosition(i)) { + double disp = (1 + Math.cos((Math.PI * (array[i] - i)) / (arrayVisualizer.getCurrentLength() * 0.5))) * 0.5; int x = width/2 + (int)(disp * r * Math.cos(Math.PI * (2d*i / n - 0.5))); int y = height/2 + (int)(disp * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - + this.mainRender.fillRect(x - 2*dotS, y - 2*dotS, 4*dotS, 4*dotS); } } } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/visuals/dots/ScatterPlot.java b/src/main/java/io/github/arrayv/visuals/dots/ScatterPlot.java new file mode 100644 index 00000000..4397d183 --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/dots/ScatterPlot.java @@ -0,0 +1,113 @@ +package io.github.arrayv.visuals.dots; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class ScatterPlot extends Visual { + public ScatterPlot(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + int offset = 20 + (int) (renderer.getXScale()/2); + + if (arrayVisualizer.linesEnabled()) { + int lastX = 0; + int lastY = (int) (((renderer.getViewSize() - 20)) - (array[0] + 1) * renderer.getYScale()); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + + for (int i = 1, j = (int) renderer.getXScale(); i < renderer.getArrayLength(); i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { + this.mainRender.setColor(Color.GREEN); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(4)); + } else if (Highlights.containsPosition(i)) { + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(4)); + } else if (arrayVisualizer.colorEnabled()) { + int val = arrayVisualizer.doingStabilityCheck() ? arrayVisualizer.getIndexValue(array[i]): array[i]; + this.mainRender.setColor(getIntColor(val, arrayVisualizer.getCurrentLength())); + } else this.mainRender.setColor(Color.WHITE); + + int val = arrayVisualizer.doingStabilityCheck() && arrayVisualizer.colorEnabled() ? arrayVisualizer.getStabilityValue(array[i]): array[i]; + int y = (int) (((renderer.getViewSize() - 20)) - (val + 1) * renderer.getYScale()); + + this.mainRender.drawLine(lastX + offset, renderer.getYOffset() + lastY, j + offset, renderer.getYOffset() + y); + + lastX = j; + lastY = y; + + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + + int width = (int) (renderer.getXScale() * (i + 1)) - j; + j += width; + } + this.mainRender.setStroke(arrayVisualizer.getDefaultStroke()); + } else { + int dotS = renderer.getDotDimensions(); + + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + else if (arrayVisualizer.colorEnabled()) { + int val = arrayVisualizer.doingStabilityCheck() ? arrayVisualizer.getIndexValue(array[i]): array[i]; + this.mainRender.setColor(getIntColor(val, arrayVisualizer.getCurrentLength())); + } else this.mainRender.setColor(Color.WHITE); + + int val = arrayVisualizer.doingStabilityCheck() && arrayVisualizer.colorEnabled() ? arrayVisualizer.getStabilityValue(array[i]): array[i]; + int y = (int) (((renderer.getViewSize() - 20)) - (val + 1) * renderer.getYScale()); + + this.mainRender.fillRect(j + offset, renderer.getYOffset() + y, dotS, dotS); + + int width = (int) (renderer.getXScale() * (i + 1)) - j; + j += width; + } + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + if (Highlights.containsPosition(i)) { + int val = arrayVisualizer.doingStabilityCheck() && arrayVisualizer.colorEnabled() ? arrayVisualizer.getStabilityValue(array[i]): array[i]; + int y = (int) (((renderer.getViewSize() - 20)) - (val + 1) * renderer.getYScale()); + + this.mainRender.fillRect(j + offset - (int)(1.5*dotS), renderer.getYOffset() + y - (int)(1.5*dotS), 4*dotS, 4*dotS); + } + int width = (int) (renderer.getXScale() * (i + 1)) - j; + j += width; + } + } + if (arrayVisualizer.externalArraysEnabled()) { + this.mainRender.setColor(Color.BLUE); + this.mainRender.fillRect(0, renderer.getYOffset() + renderer.getViewSize() - 20, arrayVisualizer.currentWidth(), 1); + } + } +} diff --git a/src/visuals/dots/SpiralDots.java b/src/main/java/io/github/arrayv/visuals/dots/SpiralDots.java similarity index 51% rename from src/visuals/dots/SpiralDots.java rename to src/main/java/io/github/arrayv/visuals/dots/SpiralDots.java index 0bb84856..29aca9b4 100644 --- a/src/visuals/dots/SpiralDots.java +++ b/src/main/java/io/github/arrayv/visuals/dots/SpiralDots.java @@ -1,16 +1,14 @@ -package visuals.dots; +package io.github.arrayv.visuals.dots; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Polygon; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; +import java.awt.*; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -36,82 +34,81 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class SpiralDots extends Visual { - - public SpiralDots(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); +public final class SpiralDots extends Visual { + + public SpiralDots(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } - + @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; - - int width = ArrayVisualizer.windowWidth(); - int height = ArrayVisualizer.windowHeight(); - - int n = ArrayVisualizer.getCurrentLength(); + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth(); + int height = arrayVisualizer.windowHeight(); + + int n = arrayVisualizer.getCurrentLength(); double r = Math.min(width, height)/2.5; - - if(ArrayVisualizer.linesEnabled()) { - double mult = (double) array[n-1] / ArrayVisualizer.getCurrentLength(); - int lastX = width/2 + (int)(mult * r * Math.cos(Math.PI * (2d*(n-1) / n - 0.5))); - int lastY = height/2 + (int)(mult * r * Math.sin(Math.PI * (2d*(n-1) / n - 0.5))); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - - for(int i = 0; i < n; i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + + if (arrayVisualizer.linesEnabled()) { + double mult = (double) array[n-1] / arrayVisualizer.getCurrentLength(); + double angle = Math.PI * (2d * (n - 1) / n - 0.5); + int lastX = width/2 + (int)(mult * r * Math.cos(angle)); + int lastY = height/2 + (int)(mult * r * Math.sin(angle)); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + + for (int i = 0; i < n; i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) this.mainRender.setColor(Color.GREEN); - - if(Highlights.containsPosition(i)) { - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(4)); - } - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - + + if (Highlights.containsPosition(i)) { + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(4)); + } else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(Color.WHITE); - - mult = (double) array[i] / ArrayVisualizer.getCurrentLength(); + + mult = (double) array[i] / arrayVisualizer.getCurrentLength(); int x = width/2 + (int)(mult * r * Math.cos(Math.PI * (2d*i / n - 0.5))); int y = height/2 + (int)(mult * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - + this.mainRender.drawLine(lastX, lastY, x, y); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + lastX = x; lastY = y; } - this.mainRender.setStroke(ArrayVisualizer.getDefaultStroke()); - } - else { - int dotS = Renderer.getDotDimensions(); - - for(int i = 0; i < n; i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setStroke(arrayVisualizer.getDefaultStroke()); + } else { + int dotS = renderer.getDotDimensions(); + + for (int i = 0; i < n; i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) this.mainRender.setColor(Color.GREEN); - - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - + + else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(Color.WHITE); - - double mult = (double) array[i] / ArrayVisualizer.getCurrentLength(); + + double mult = (double) array[i] / arrayVisualizer.getCurrentLength(); int x = width/2 + (int)(mult * r * Math.cos(Math.PI * (2d*i / n - 0.5))); int y = height/2 + (int)(mult * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - + this.mainRender.fillRect(x, y, dotS, dotS); } - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - - for(int i = 0; i < n; i++) { - if(Highlights.containsPosition(i)) { - double mult = (double) array[i] / ArrayVisualizer.getCurrentLength(); + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + + for (int i = 0; i < n; i++) { + if (Highlights.containsPosition(i)) { + double mult = (double) array[i] / arrayVisualizer.getCurrentLength(); int x = width/2 + (int)(mult * r * Math.cos(Math.PI * (2d*i / n - 0.5))); int y = height/2 + (int)(mult * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - + this.mainRender.fillRect(x - 2*dotS, y - 2*dotS, 4*dotS, 4*dotS); } } } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/arrayv/visuals/dots/WaveDots.java b/src/main/java/io/github/arrayv/visuals/dots/WaveDots.java new file mode 100644 index 00000000..8d967574 --- /dev/null +++ b/src/main/java/io/github/arrayv/visuals/dots/WaveDots.java @@ -0,0 +1,111 @@ +package io.github.arrayv.visuals.dots; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import java.awt.*; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy +Copyright (c) 2020 MusicTheorist +Copyright (c) 2021 ArrayV 4.0 Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +public final class WaveDots extends Visual { + public WaveDots(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + int offset = 20 + (int) (renderer.getXScale()/2); + + if (arrayVisualizer.linesEnabled()) { + int lastX = 0; + int lastY = (int) (((renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[0] / renderer.getArrayLength()))) + renderer.halfViewSize() - 20); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + + for (int i = 1, j = (int) renderer.getXScale(); i < renderer.getArrayLength(); i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { + this.mainRender.setColor(Color.GREEN); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(4)); + } else if (Highlights.containsPosition(i)) { + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(4)); + } else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i-1], arrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(Color.WHITE); + + int y = (int) (((renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / renderer.getArrayLength()))) + renderer.halfViewSize() - 20); + + this.mainRender.drawLine(lastX + offset, renderer.getYOffset() + lastY, j + offset, renderer.getYOffset() + y); + + lastX = j; + lastY = y; + + this.mainRender.setStroke(arrayVisualizer.getCustomStroke(2)); + + int width = (int) (renderer.getXScale() * (i + 1)) - j; + j += width; + } + this.mainRender.setStroke(arrayVisualizer.getDefaultStroke()); + } else { + int dotS = renderer.getDotDimensions(); + + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + this.mainRender.setColor(Color.GREEN); + + else if (arrayVisualizer.colorEnabled()) + this.mainRender.setColor(getIntColor(array[i], arrayVisualizer.getCurrentLength())); + + else this.mainRender.setColor(Color.WHITE); + + int y = (int) (((renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / renderer.getArrayLength()))) + renderer.halfViewSize() - 20); + + this.mainRender.fillRect(j + offset, renderer.getYOffset() + y, dotS, dotS); + + int width = (int) (renderer.getXScale() * (i + 1)) - j; + j += width; + } + this.mainRender.setColor(arrayVisualizer.getHighlightColor()); + + for (int i = 0, j = 0; i < renderer.getArrayLength(); i++) { + if (Highlights.containsPosition(i)) { + int y = (int) (((renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / renderer.getArrayLength()))) + renderer.halfViewSize() - 20); + this.mainRender.fillRect(j + offset - (int)(1.5*dotS), renderer.getYOffset() + y - (int)(1.5*dotS), 4*dotS, 4*dotS); + } + int width = (int) (renderer.getXScale() * (i + 1)) - j; + j += width; + } + } + if (arrayVisualizer.externalArraysEnabled()) { + this.mainRender.setColor(Color.BLUE); + this.mainRender.fillRect(0, renderer.getYOffset() + renderer.getViewSize() - 20, arrayVisualizer.currentWidth(), 1); + } + } +} diff --git a/src/visuals/image/CustomImage.java b/src/main/java/io/github/arrayv/visuals/image/CustomImage.java similarity index 54% rename from src/visuals/image/CustomImage.java rename to src/main/java/io/github/arrayv/visuals/image/CustomImage.java index 240c7596..1cf5f205 100644 --- a/src/visuals/image/CustomImage.java +++ b/src/main/java/io/github/arrayv/visuals/image/CustomImage.java @@ -1,34 +1,32 @@ -package visuals.image; +package io.github.arrayv.visuals.image; -import java.awt.Color; -import java.awt.Graphics2D; +import io.github.arrayv.dialogs.CustomImageDialog; +import io.github.arrayv.dialogs.LoadingDialog; +import io.github.arrayv.frames.ImageFrame; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.panes.JErrorPane; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; -import java.io.BufferedInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; - -import javax.imageio.ImageIO; -import javax.swing.JFrame; - -import visuals.Visual; -import dialogs.CustomImageDialog; -import dialogs.LoadingDialog; -import dialogs.SoundbankDialog; -import frames.ImageFrame; -import main.ArrayVisualizer; -import panes.JErrorPane; -import resources.image.ImgFetcher; -import utils.Highlights; -import utils.Renderer; +import java.io.InputStream; /* - * + * MIT License Copyright (c) 2019 w0rthy Copyright (c) 2020 aphitorite +Copyright (c) 2021-2022 ArrayV Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -54,38 +52,35 @@ of this software and associated documentation files (the "Software"), to deal * CustomImage visual and sort bar graph artwork (image/pic.jpg) created by * aphitorite (https://github.com/aphitorite/ArrayVisualizer) */ -final public class CustomImage extends Visual { - public static CustomImage visual; - +public final class CustomImage extends Visual { private volatile BufferedImage img; private volatile int imgHeight; private volatile int imgWidth; - + private boolean imgImported; private boolean imgScaled; private boolean openImgMenu; - + private int windowHeight; private int windowWidth; - + private volatile ImageFrame pictureMenu; private volatile LoadingDialog infoMsg; - - final private String defaultArtwork = "Summer Sorting by aphitorite"; + + private final String defaultArtwork = "Summer Sorting by aphitorite"; private String currentImage; private File imageFile; - - public CustomImage(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - CustomImage.visual = this; + + public CustomImage(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); this.imgImported = false; // Don't load the image unless the user selects the // 'Custom Image' visual. Program initially boots up // faster this way. this.enableImgMenu(); - this.updateWindowDims(ArrayVisualizer); + this.updateWindowDims(arrayVisualizer); this.currentImage = this.defaultArtwork; } - + public BufferedImage getImage() { return this.img; } @@ -95,32 +90,32 @@ public int getImgHeight() { public int getImgWidth() { return this.imgWidth; } - + public String getCurrentImageName() { return this.currentImage; } - + public void enableImgMenu() { this.openImgMenu = true; } - - private void updateImageDims() throws Exception { + + private void updateImageDims() { this.imgHeight = this.img.getHeight(); this.imgWidth = this.img.getWidth(); } - - private void updateWindowDims(ArrayVisualizer ArrayVisualizer) { - this.windowHeight = ArrayVisualizer.windowHeight(); - this.windowWidth = ArrayVisualizer.windowWidth(); + + private void updateWindowDims(ArrayVisualizer arrayVisualizer) { + this.windowHeight = arrayVisualizer.windowHeight(); + this.windowWidth = arrayVisualizer.windowWidth(); } - + private void refreshCustomImage(ImageFrame menu) { menu.dispose(); this.imgImported = false; this.imgScaled = false; this.openImgMenu = true; } - + public void loadDefaultArtwork(ImageFrame menu) { this.currentImage = this.defaultArtwork; this.refreshCustomImage(menu); @@ -128,189 +123,160 @@ public void loadDefaultArtwork(ImageFrame menu) { public void loadCustomImage(ImageFrame menu) { CustomImageDialog dialog = new CustomImageDialog(); this.imageFile = dialog.getFile(); - if(this.imageFile != null) { + if (this.imageFile != null) { this.currentImage = this.imageFile.getName(); this.refreshCustomImage(menu); } } public void loadCustomImage(File file) { this.imageFile = file; - if(this.imageFile != null) { + if (this.imageFile != null) { this.currentImage = this.imageFile.getName(); - this.refreshCustomImage(ImageFrame.defaultFrame); + this.refreshCustomImage(ImageFrame.getDefaultFrame()); } } - - @SuppressWarnings("unused") + private boolean fetchBufferedImage(boolean showInfoMsg, JFrame window) { // New copy of image being imported; has not been scaled yet this.imgScaled = false; - + boolean defaultImage = this.currentImage.equals(this.defaultArtwork); - - if(showInfoMsg) { + + if (showInfoMsg) { String message; - if(defaultImage) { + if (defaultImage) { message = "resources/image/pic.jpg"; - } - else { + } else { message = this.currentImage; } this.infoMsg = new LoadingDialog(message, window); } boolean success = true; - - ImgFetcher imgFetcher; - if(defaultImage) { - imgFetcher = new ImgFetcher(); - } - else { - imgFetcher = new ImgFetcher(this.imageFile); - } - BufferedInputStream stream = imgFetcher.getStream(); - - try { - this.img = ImageIO.read(stream); - } - catch (IOException e) { + + try (InputStream is = defaultImage + ? getClass().getResourceAsStream("/pic.jpg") + : new FileInputStream(imageFile)) { + assert is != null; + this.img = ImageIO.read(is); + } catch (IOException e) { success = false; JErrorPane.invokeErrorMessage(e); - } - catch (IllegalArgumentException e) { + } catch (IllegalArgumentException e) { success = false; - if(defaultImage) { + if (defaultImage) { JErrorPane.invokeCustomErrorMessage("image/pic.jpg missing: Couldn't find the default image for the program's 'Custom Image' visual!"); - } - else { + } else { JErrorPane.invokeCustomErrorMessage(this.currentImage + " missing: ArrayV couldn't find your picture at the given location!"); } } - finally { - try { - stream.close(); - } - catch (NullPointerException e) { - success = false; // A NullPointerException means a null stream, which would have already thrown an IllegalArgumentException - } - catch (Exception e) { - success = false; - JErrorPane.invokeErrorMessage(e); - } - } - + // Update the image dimensions. If this fails, the file wasn't a proper image - if(success) { + if (success) { try { this.updateImageDims(); - } - catch (Exception e) { + } catch (Exception e) { success = false; - if(defaultImage) { + if (defaultImage) { JErrorPane.invokeCustomErrorMessage("image/pic.jpg invalid or corrupt: The file for the program's 'Custom Image' visual was not recognized as a valid image!"); - } - else { + } else { JErrorPane.invokeCustomErrorMessage(this.currentImage + " invalid or corrupt: Your picture was not recognized as a valid image!"); } } } - - if(showInfoMsg) { + + if (showInfoMsg) { this.infoMsg.closeDialog(); } - - if(!success) { + + if (!success) { // If loading a custom file didn't work, then try loading the default artwork instead. - if(!defaultImage) { + if (!defaultImage) { this.currentImage = this.defaultArtwork; return this.fetchBufferedImage(true, window); - } - else { + } else { return false; } - } - else { + } else { return true; } } - + // Many thanks to Jörn Horstmann for providing fast image scaling code. // https://stackoverflow.com/questions/3967731/how-to-improve-the-performance-of-g-drawimage-method-for-resizing-images/3967988#3967988 - @SuppressWarnings("unused") private boolean getScaledImage(int width, int height) throws Exception { boolean success = true; - + // Only fetch a fresh copy of the image if it's been previously scaled. - if(this.imgScaled) { - if(!this.fetchBufferedImage(false, null)) { + if (this.imgScaled) { + if (!this.fetchBufferedImage(false, null)) { throw new Exception(); } } - + double scaleX = (double) width / this.imgWidth; double scaleY = (double) height / this.imgHeight; AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY); AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BICUBIC); try { + //noinspection NonAtomicOperationOnVolatileField this.img = bilinearScaleOp.filter(this.img, new BufferedImage(width, height, this.img.getType())); - + /* * We don't want to resize the cached copy of the image more than once as the quality degrades quickly. * Therefore, keep track of the image being scaled so we can import a fresh copy the next time the window * is resized. */ this.imgScaled = true; - + this.updateImageDims(); - } - catch (IllegalArgumentException e) { + } catch (IllegalArgumentException e) { JErrorPane.invokeCustomErrorMessage("CustomImage.getScaledImage() was called even though the image's dimensions haven't changed!"); - } - catch (Exception e) { + } catch (Exception e) { success = false; JErrorPane.invokeErrorMessage(e); } - + return success; } - - public static void markCustomBar(ArrayVisualizer ArrayVisualizer, Graphics2D bar, Renderer Renderer, int width, boolean analysis) { - if(analysis) { + + public static void markCustomBar(ArrayVisualizer arrayVisualizer, Graphics2D bar, Renderer renderer, int width, boolean analysis) { + if (analysis) { bar.setColor(new Color(0, 0, 1, .5f)); - } - else { + } else { bar.setColor(new Color(1, 0, 0, .5f)); } - bar.fillRect(Renderer.getOffset() + 20, 0, width, ArrayVisualizer.windowHeight()); + bar.fillRect(renderer.getOffset() + 20, 0, width, arrayVisualizer.windowHeight()); } - - @SuppressWarnings("fallthrough") + //The longer the array length, the more bars marked. Makes the visual easier to see when bars are thinner. - public static void colorCustomBars(int logOfLen, int index, Highlights Highlights, ArrayVisualizer ArrayVisualizer, Graphics2D bar, Renderer Renderer, int width, boolean analysis) { + public static void colorCustomBars(int logOfLen, int index, Highlights Highlights, ArrayVisualizer arrayVisualizer, Graphics2D bar, Renderer renderer, int width, boolean analysis) { switch(logOfLen) { - case 15: if(Highlights.containsPosition(index - 15)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 14)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 13)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 12)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 11)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - case 14: if(Highlights.containsPosition(index - 10)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 9)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 8)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - case 13: if(Highlights.containsPosition(index - 7)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 6)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 5)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - case 12: if(Highlights.containsPosition(index - 4)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - if(Highlights.containsPosition(index - 3)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - case 11: if(Highlights.containsPosition(index - 2)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - case 10: if(Highlights.containsPosition(index - 1)) { markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); break; } - default: if(Highlights.containsPosition(index)) markCustomBar(ArrayVisualizer, bar, Renderer, width, analysis); + // @checkstyle:off LeftCurlyCheck|IndentationCheck + case 15: if (Highlights.containsPosition(index - 15)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 14)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 13)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 12)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 11)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + case 14: if (Highlights.containsPosition(index - 10)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 9)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 8)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + case 13: if (Highlights.containsPosition(index - 7)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 6)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 5)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + case 12: if (Highlights.containsPosition(index - 4)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + if (Highlights.containsPosition(index - 3)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + case 11: if (Highlights.containsPosition(index - 2)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + case 10: if (Highlights.containsPosition(index - 1)) { markCustomBar(arrayVisualizer, bar, renderer, width, analysis); break; } + default: if (Highlights.containsPosition(index)) markCustomBar(arrayVisualizer, bar, renderer, width, analysis); + // @checkstyle:on LeftCurlyCheck|IndentationCheck } } - + @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; try { /* @@ -318,11 +284,10 @@ public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Re * Gives debuggers the ability to try another file without having to restart the program. This also is a safe way of * handling exceptions whenever the user clicks the 'Custom Image' button. */ - if(!this.imgImported) { - if(!this.fetchBufferedImage(true, ArrayVisualizer.getMainWindow())) { + if (!this.imgImported) { + if (!this.fetchBufferedImage(true, arrayVisualizer.getMainWindow())) { throw new Exception(); - } - else { + } else { this.imgImported = true; } } @@ -330,63 +295,61 @@ public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Re * Use a fast image scaling method if the window was resized. If an ImagingOpException is thrown, don't continue with * the 'Custom Image' visual. */ - if(this.windowHeight != ArrayVisualizer.currentHeight() || this.windowWidth != ArrayVisualizer.currentWidth()) { - if(!this.getScaledImage(ArrayVisualizer.currentWidth(), ArrayVisualizer.currentHeight())) { + if (this.windowHeight != arrayVisualizer.currentHeight() || this.windowWidth != arrayVisualizer.currentWidth()) { + if (!this.getScaledImage(arrayVisualizer.currentWidth(), arrayVisualizer.currentHeight())) { throw new Exception(); } - this.updateWindowDims(ArrayVisualizer); + this.updateWindowDims(arrayVisualizer); } - - if(this.openImgMenu) { + + if (this.openImgMenu) { this.pictureMenu = new ImageFrame(this); this.pictureMenu.setVisible(true); this.pictureMenu.updatePreview(this); this.openImgMenu = false; } - } - catch (Exception e) { + } catch (Exception e) { JErrorPane.invokeErrorMessage(e); - ArrayVisualizer.setVisual(visuals.VisualStyles.BARS); + arrayVisualizer.setVisual(io.github.arrayv.visuals.VisualStyles.BARS); return; } - - for(int i = 0, j = 0; i < ArrayVisualizer.getCurrentLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1) - j); - if(width == 0) continue; - + + for (int i = 0, j = 0; i < arrayVisualizer.getCurrentLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1) - j); + if (width == 0) continue; + //Cuts the image in respect to each item in the array this.mainRender.drawImage( this.img, j + 20, - 40, - j + 20 + width, - ArrayVisualizer.windowHeight()-10, + 40, + j + 20 + width, + arrayVisualizer.windowHeight()-10, - (int) ((double) this.imgWidth / ArrayVisualizer.getCurrentLength() * array[i]), - 0, - (int) Math.ceil((double) this.imgWidth / ArrayVisualizer.getCurrentLength() * (array[i] + 1)), + (int) ((double) this.imgWidth / arrayVisualizer.getCurrentLength() * array[i]), + 0, + (int) Math.ceil((double) this.imgWidth / arrayVisualizer.getCurrentLength() * (array[i] + 1)), this.imgHeight, null ); j += width; } - for(int i = 0, j = 0; i < ArrayVisualizer.getCurrentLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { + for (int i = 0, j = 0; i < arrayVisualizer.getCurrentLength(); i++) { + int width = (int) (renderer.getXScale() * (i + 1)) - j; + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { this.mainRender.setColor(new Color(0, 1, 0, .5f)); - - if(width > 0) this.mainRender.fillRect(j + 20, 40, width, ArrayVisualizer.windowHeight()-10); - } - else if(Highlights.containsPosition(i)) { - if(ArrayVisualizer.analysisEnabled()) this.mainRender.setColor(new Color(0, 0, 1, .5f)); - else this.mainRender.setColor(new Color(1, 0, 0, .5f)); - - this.mainRender.fillRect(j + 20, 40, Math.max(width, 2), ArrayVisualizer.windowHeight()-10); + + if (width > 0) this.mainRender.fillRect(j + 20, 40, width, arrayVisualizer.windowHeight()-10); + } else if (Highlights.containsPosition(i)) { + if (arrayVisualizer.analysisEnabled()) this.mainRender.setColor(new Color(0, 0, 1, .5f)); + else this.mainRender.setColor(new Color(1, 0, 0, .5f)); + + this.mainRender.fillRect(j + 20, 40, Math.max(width, 2), arrayVisualizer.windowHeight()-10); } j += width; } } -} \ No newline at end of file +} diff --git a/src/visuals/misc/HoopStack.java b/src/main/java/io/github/arrayv/visuals/misc/HoopStack.java similarity index 54% rename from src/visuals/misc/HoopStack.java rename to src/main/java/io/github/arrayv/visuals/misc/HoopStack.java index 37b820b5..e8b19409 100644 --- a/src/visuals/misc/HoopStack.java +++ b/src/main/java/io/github/arrayv/visuals/misc/HoopStack.java @@ -1,14 +1,14 @@ -package visuals.misc; +package io.github.arrayv.visuals.misc; -import java.awt.Color; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; +import java.awt.*; /* - * + * MIT License Copyright (c) 2020-2021 ArrayV 4.0 Team @@ -33,47 +33,46 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class HoopStack extends Visual { - public HoopStack(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); +public final class HoopStack extends Visual { + public HoopStack(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } - + private void drawEllipseFromCenter(int x, int y, int rx, int ry) { this.mainRender.drawOval(x - rx, y - ry, 2*rx, 2*ry); } - + @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth(); + int height = arrayVisualizer.windowHeight(); + int length = arrayVisualizer.getCurrentLength(); - int width = ArrayVisualizer.windowWidth(); - int height = ArrayVisualizer.windowHeight(); - int length = ArrayVisualizer.getCurrentLength(); - int radiusX = height / 3; int radiusY = height / 9; - - this.mainRender.setStroke(ArrayVisualizer.getThinStroke()); - - for(int i = length - 1; i >= 0; i--) { + + this.mainRender.setStroke(arrayVisualizer.getThinStroke()); + + for (int i = length - 1; i >= 0; i--) { double scale = (array[i] + 1) / (double) (length + 1); - + int y = (int) ((height - radiusY * 4) * i / (double) (length - 1)); - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) + + if (Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) this.mainRender.setColor(Color.GREEN); - - else if(Highlights.containsPosition(i)) { - if(ArrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); - else this.mainRender.setColor(Color.WHITE); - - this.mainRender.setStroke(ArrayVisualizer.getDefaultStroke()); - } - else this.mainRender.setColor(getIntColor(array[i], length)); - + + else if (Highlights.containsPosition(i)) { + if (arrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); + else this.mainRender.setColor(Color.WHITE); + + this.mainRender.setStroke(arrayVisualizer.getDefaultStroke()); + } else this.mainRender.setColor(getIntColor(array[i], length)); + this.drawEllipseFromCenter(width / 2, y + radiusY * 2, (int) (scale * radiusX + 0.5), (int) (scale * radiusY + 0.5)); - this.mainRender.setStroke(ArrayVisualizer.getThinStroke()); + this.mainRender.setStroke(arrayVisualizer.getThinStroke()); } - this.mainRender.setStroke(ArrayVisualizer.getDefaultStroke()); + this.mainRender.setStroke(arrayVisualizer.getDefaultStroke()); } -} \ No newline at end of file +} diff --git a/src/visuals/misc/PixelMesh.java b/src/main/java/io/github/arrayv/visuals/misc/PixelMesh.java similarity index 58% rename from src/visuals/misc/PixelMesh.java rename to src/main/java/io/github/arrayv/visuals/misc/PixelMesh.java index 963e6781..58a4c572 100644 --- a/src/visuals/misc/PixelMesh.java +++ b/src/main/java/io/github/arrayv/visuals/misc/PixelMesh.java @@ -1,14 +1,14 @@ -package visuals.misc; +package io.github.arrayv.visuals.misc; -import java.awt.Color; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.utils.Highlights; +import io.github.arrayv.utils.Renderer; +import io.github.arrayv.visuals.Visual; -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; +import java.awt.*; /* - * + * MIT License Copyright (c) 2020-2021 ArrayV 4.0 Team @@ -33,47 +33,46 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class PixelMesh extends Visual { - public PixelMesh(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); +public final class PixelMesh extends Visual { + public PixelMesh(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; - - int width = ArrayVisualizer.windowWidth()-40; - int height = ArrayVisualizer.windowHeight()-50; - int length = ArrayVisualizer.getCurrentLength(); - + public void drawVisual(int[] array, ArrayVisualizer arrayVisualizer, Renderer renderer, Highlights Highlights) { + if (renderer.isAuxActive()) return; + + int width = arrayVisualizer.windowWidth()-40; + int height = arrayVisualizer.windowHeight()-50; + int length = arrayVisualizer.getCurrentLength(); + int sqrt = (int)Math.ceil(Math.sqrt(length)); int square = sqrt*sqrt; double scale = (double)length / square; - + int x = 0; int y = 0; double xStep = (double)width / sqrt; double yStep = (double)height / sqrt; - - for(int i = 0; i < square; i++) { + + for (int i = 0; i < square; i++) { int idx = (int)(i * scale); - - if(Highlights.fancyFinishActive() && idx < Highlights.getFancyFinishPosition()) + + if (Highlights.fancyFinishActive() && idx < Highlights.getFancyFinishPosition()) this.mainRender.setColor(Color.GREEN); - - else if(Highlights.containsPosition(idx)) { - if(ArrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); - else this.mainRender.setColor(Color.WHITE); - } - else this.mainRender.setColor(getIntColor(array[idx], length)); - - this.mainRender.fillRect(20 + (int)(x * xStep), 40 + (int)(y * yStep), + + else if (Highlights.containsPosition(idx)) { + if (arrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); + else this.mainRender.setColor(Color.WHITE); + } else this.mainRender.setColor(getIntColor(array[idx], length)); + + this.mainRender.fillRect(20 + (int)(x * xStep), 40 + (int)(y * yStep), (int)((x+1)*xStep - x*xStep)+1, (int)((y+1)*yStep - y*yStep)+1); - - if(++x == sqrt) { + + if (++x == sqrt) { x = 0; y++; } } } -} \ No newline at end of file +} diff --git a/src/main/resources/META-INF/arrayv/io.github.arrayv.groovyapi.BuiltinScripts b/src/main/resources/META-INF/arrayv/io.github.arrayv.groovyapi.BuiltinScripts new file mode 100644 index 00000000..331041a8 --- /dev/null +++ b/src/main/resources/META-INF/arrayv/io.github.arrayv.groovyapi.BuiltinScripts @@ -0,0 +1,32 @@ +# The MIT License (MIT) +# +# Copyright (c) 2022 ArrayV Team +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +scripts/categories/exchange.groovy +# scripts/categories/quick.groovy +scripts/categories/selection.groovy +scripts/categories/insertion.groovy +scripts/categories/merge.groovy +scripts/categories/distribute.groovy +scripts/categories/concurrent.groovy +scripts/categories/hybrid.groovy +scripts/categories/misc.groovy +scripts/categories/impractical.groovy diff --git a/src/main/resources/META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule b/src/main/resources/META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule new file mode 100644 index 00000000..3ce3ddb0 --- /dev/null +++ b/src/main/resources/META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule @@ -0,0 +1,4 @@ +moduleName=ArrayV +moduleVersion=5.1-SNAPSHOT +extensionClasses=io.github.arrayv.groovyapi.exts.RunSortInfoExtension +staticExtensionClasses= diff --git a/src/main/resources/buildInfo.properties b/src/main/resources/buildInfo.properties new file mode 100644 index 00000000..81b1f6a9 --- /dev/null +++ b/src/main/resources/buildInfo.properties @@ -0,0 +1,2 @@ +version=${project.version} +commitId=${git.commit.id.abbrev} diff --git a/src/resources/image/pic.jpg b/src/main/resources/pic.jpg similarity index 100% rename from src/resources/image/pic.jpg rename to src/main/resources/pic.jpg diff --git a/src/main/resources/scripts/categories/concurrent.groovy b/src/main/resources/scripts/categories/concurrent.groovy new file mode 100644 index 00000000..95b9ccb7 --- /dev/null +++ b/src/main/resources/scripts/categories/concurrent.groovy @@ -0,0 +1,33 @@ +import io.github.arrayv.prompts.SortPrompt + +SortPrompt.setSortThreadForCategory('Concurrent Sorts', 22) { + // Other + run FoldSort go 1024.numbers + run CreaseSort go 1024.numbers + run MatrixSort go 256.numbers, 0.667.speed + + // Recursive + run BitonicSortRecursive go 1024.numbers + run OddEvenMergeSortRecursive go 1024.numbers + run PairwiseSortRecursive go 1024.numbers + run BoseNelsonSortRecursive go 1024.numbers + run WeaveSortRecursive go 1024.numbers + run DiamondSortRecursive go 1024.numbers + run PairwiseMergeSortRecursive go 1024.numbers + + // Parallel + run BitonicSortParallel go 1024.numbers + run OddEvenMergeSortParallel go 1024.numbers + run BoseNelsonSortParallel go 1024.numbers + run WeaveSortParallel go 1024.numbers + + // Iterative + run BitonicSortIterative go 1024.numbers + run OddEvenMergeSortIterative go 1024.numbers + run PairwiseSortIterative go 1024.numbers + run BoseNelsonSortIterative go 1024.numbers + run WeaveSortIterative go 1024.numbers + run MergeExchangeSortIterative go 1024.numbers + run DiamondSortIterative go 1024.numbers + run PairwiseMergeSortIterative go 1024.numbers +} diff --git a/src/main/resources/scripts/categories/distribute.groovy b/src/main/resources/scripts/categories/distribute.groovy new file mode 100644 index 00000000..c67cd423 --- /dev/null +++ b/src/main/resources/scripts/categories/distribute.groovy @@ -0,0 +1,27 @@ +import io.github.arrayv.prompts.SortPrompt + +SortPrompt.setSortThreadForCategory('Distribution Sorts', 18) { + run CountingSort go 2048.numbers, 1.5.speed + run PigeonholeSort go 2048.numbers, 1.5.speed + run GravitySort go 1024.numbers, 0.5.speed + run ClassicGravitySort go 1024.numbers + run StaticSort go 2048.numbers + run IndexSort go 2048.numbers + run AmericanFlagSort go 2048.numbers, 128.buckets, 0.75.speed + run StacklessAmericanFlagSort go 2048.numbers, 128.buckets, 0.75.speed + run LSDRadixSort go 2048.numbers, 4.buckets, 1.5.speed + + def oldSofterSounds = arrayv.sounds.softerSounds + arrayv.sounds.softerSounds = true + run InPlaceLSDRadixSort go 2048.numbers, 10.buckets + arrayv.sounds.softerSounds = oldSofterSounds + + run MSDRadixSort go 2048.numbers, 4.buckets, 1.25.speed + run FlashSort go 2048.numbers + run BinaryQuickSortIterative go 2048.numbers + run BinaryQuickSortRecursive go 2048.numbers + run StacklessBinaryQuickSort go 2048.numbers + run ShatterSort go 2048.numbers, 128.buckets + run SimpleShatterSort go 2048.numbers, 128.buckets + run TimeSort go 512.numbers, 10.buckets, 0.05.speed +} diff --git a/src/main/resources/scripts/categories/exchange.groovy b/src/main/resources/scripts/categories/exchange.groovy new file mode 100644 index 00000000..892c9a95 --- /dev/null +++ b/src/main/resources/scripts/categories/exchange.groovy @@ -0,0 +1,34 @@ +import io.github.arrayv.prompts.SortPrompt +import io.github.arrayv.utils.Shuffles + +SortPrompt.setSortThreadForCategory('Exchange Sorts', 29) { + run UnoptimizedBubbleSort go 512.numbers, 1.5.speed + run BubbleSort go 512.numbers, 1.5.speed + run OptimizedBubbleSort go 512.numbers, 1.5.speed + run UnoptimizedCocktailShakerSort go 512.numbers, 1.25.speed + run CocktailShakerSort go 512.numbers, 1.25.speed + run OptimizedCocktailShakerSort go 512.numbers, 1.25.speed + run OddEvenSort go 512.numbers + run OptimizedStoogeSort go 512.numbers + run OptimizedStoogeSortStudio go 512.numbers + run FunSort go 256.numbers, 2.speed + run GnomeSort go 128.numbers, 0.025.speed + run OptimizedGnomeSort go 128.numbers, 0.025.speed + run BinaryGnomeSort go 128.numbers, 0.025.speed + run SlopeSort go 128.numbers, 0.025.speed + run CombSort go 1024.numbers, 130.buckets + run ThreeSmoothCombSortRecursive go 1024.numbers, 1.25.speed + run ThreeSmoothCombSortParallel go 1024.numbers, 1.25.speed + run ThreeSmoothCombSortIterative go 1024.numbers, 1.25.speed + run ClassicThreeSmoothCombSort go 1024.numbers, 1.25.speed + run CircleSortRecursive go 1024.numbers + run CircleSortIterative go 1024.numbers + run LLQuickSort go 2048.numbers, ((arrayv.arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.5 : 5).speed) + run LRQuickSort go 2048.numbers + run LRQuickSortParallel go 2048.numbers + run DualPivotQuickSort go 2048.numbers + run StableQuickSort go 2048.numbers, ((arrayv.arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 6.5).speed) + run StableQuickSortParallel go 2048.numbers + run ForcedStableQuickSort go 2048.numbers + run TableSort go 1024.numbers, 0.75.speed +} diff --git a/src/main/resources/scripts/categories/hybrid.groovy b/src/main/resources/scripts/categories/hybrid.groovy new file mode 100644 index 00000000..3e083a68 --- /dev/null +++ b/src/main/resources/scripts/categories/hybrid.groovy @@ -0,0 +1,37 @@ +import io.github.arrayv.prompts.SortPrompt +import io.github.arrayv.utils.Shuffles + +SortPrompt.setSortThreadForCategory('Hybrid Sorts', 32) { + run HybridCombSort go 1024.numbers + run IntroCircleSortRecursive go 1024.numbers + run IntroCircleSortIterative go 1024.numbers + run BinaryMergeSort go 2048.numbers + run MergeInsertionSort go 2048.numbers, 1.75.speed + run WeaveMergeSort go 2048.numbers, ((arrayv.arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.65 : 6.5).speed) + run TimSort go 2048.numbers + run CocktailMergeSort go 2048.numbers + run LaziestSort go 1024.numbers + run WikiSort go 2048.numbers + run GrailSort go 2048.numbers + run AdaptiveGrailSort go 2048.numbers + run UnstableGrailSort go 2048.numbers + run SqrtSort go 2048.numbers + run KotaSort go 2048.numbers + run EctaSort go 2048.numbers + run ParallelBlockMergeSort go 2048.numbers + run ParallelGrailSort go 2048.numbers + run FlanSort go 2048.numbers + run RemiSort go 2048.numbers + run ImprovedBlockSelectionSort go 2048.numbers + run MedianMergeSort go 2048.numbers + run BufferPartitionMergeSort go 2048.numbers + run IntroSort go 2048.numbers + run OptimizedBottomUpMergeSort go 2048.numbers + run OptimizedDualPivotQuickSort go 2048.numbers, 0.75.speed + run OptimizedWeaveMergeSort go 1024.numbers, 0.4.speed + run StacklessHybridQuickSort go 2048.numbers, 0.75.speed + run StacklessDualPivotQuickSort go 2048.numbers, 0.75.speed + run PDQBranchedSort go 2048.numbers, 0.75.speed + run PDQBranchlessSort go 2048.numbers, 0.75.speed + run DropMergeSort go 2048.numbers, 0.75.speed +} diff --git a/src/main/resources/scripts/categories/impractical.groovy b/src/main/resources/scripts/categories/impractical.groovy new file mode 100644 index 00000000..9b101bd9 --- /dev/null +++ b/src/main/resources/scripts/categories/impractical.groovy @@ -0,0 +1,37 @@ +import io.github.arrayv.prompts.SortPrompt + +SortPrompt.setSortThreadForCategory('Impractical Sorts', 32) { + run BadSort go 64.numbers, 0.0075.speed + run StoogeSort go 64.numbers, 0.005.speed + run QuadStoogeSort go 64.numbers, 0.005.speed + run SillySort go 64.numbers, 0.5.speed + run SlowSort go 64.numbers, 0.5.speed + run SnuffleSort go 64.numbers, 0.25.speed + run HanoiSort go 8.numbers, 0.025.speed + + // Bogosorts + def oldSofterSounds = arrayv.sounds.softerSounds + arrayv.sounds.softerSounds = true + // The not-bad ones + run SelectionBogoSort go 64.numbers, 1e-9.speed + run BubbleBogoSort go 40.numbers, 1e-9.speed + run CocktailBogoSort go 40.numbers, 1e-9.speed + run LessBogoSort go 32.numbers, 1e-9.speed + run ExchangeBogoSort go 28.numbers, 1e-9.speed + // The meh ones + run MedianQuickBogoSort go 12.numbers, 1e-9.speed + run QuickBogoSort go 9.numbers, 1e-9.speed + run MergeBogoSort go 9.numbers, 1e-9.speed + run SmartGuessSort go 8.numbers, 1e-9.speed + // The scary ones + run BozoSort go 7.numbers, 1e-9.speed + run DeterministicBogoSort go 7.numbers, 1e-9.speed + run SmartBogoBogoSort go 6.numbers, 1e-9.speed + run BogoSort go 6.numbers, 1e-9.speed + run OptimizedGuessSort go 5.numbers, 1e-9.speed + run RandomGuessSort go 5.numbers, 1e-9.speed + run GuessSort go 4.numbers, 1e-9.speed + // aaaaaa + run BogoBogoSort go 4.numbers, 1e-9.speed + arrayv.sounds.softerSounds = oldSofterSounds +} diff --git a/src/main/resources/scripts/categories/insertion.groovy b/src/main/resources/scripts/categories/insertion.groovy new file mode 100644 index 00000000..8f68b55d --- /dev/null +++ b/src/main/resources/scripts/categories/insertion.groovy @@ -0,0 +1,19 @@ +import io.github.arrayv.prompts.SortPrompt +import io.github.arrayv.utils.Shuffles + +SortPrompt.setSortThreadForCategory('Insertion Sorts', 14) { + run InsertionSort go 128.numbers, 0.005.speed + run DoubleInsertionSort go 128.numbers, 0.002.speed + run BinaryInsertionSort go 128.numbers, 0.025.speed + run ShellSort go 256.numbers, 0.1.speed + run RecursiveShellSort go 256.numbers, 0.1.speed + run ShellSortParallel go 256.numbers, 0.1.speed + run SimplifiedLibrarySort go 2048.numbers + run LibrarySort go 2048.numbers + run PatienceSort go 2048.numbers + run ClassicTreeSort go 2048.numbers, ((arrayv.arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 5).speed) + run TreeSort go 2048.numbers, ((arrayv.arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 5).speed) + run AATreeSort go 2048.numbers + run AVLTreeSort go 2048.numbers + run SplaySort go 2048.numbers +} diff --git a/src/main/resources/scripts/categories/merge.groovy b/src/main/resources/scripts/categories/merge.groovy new file mode 100644 index 00000000..074e25e6 --- /dev/null +++ b/src/main/resources/scripts/categories/merge.groovy @@ -0,0 +1,21 @@ +import io.github.arrayv.prompts.SortPrompt + +SortPrompt.setSortThreadForCategory('Merge Sorts', 17) { + run MergeSort go 2048.numbers, 1.5.speed + run BottomUpMergeSort go 2048.numbers, 1.5.speed + run MergeSortParallel go 2048.numbers, 1.5.speed + run IterativeTopDownMergeSort go 2048.numbers, 1.5.speed + run WeavedMergeSort go 2048.numbers, 1.5.speed + run TwinSort go 2048.numbers, 1.5.speed + run PDMergeSort go 2048.numbers + run InPlaceMergeSort go 2048.numbers, 1.5.speed + run ImprovedInPlaceMergeSort go 2048.numbers, 1.5.speed + run LazyStableSort go 256.numbers, 0.2.speed + run BlockSwapMergeSort go 256.numbers, 0.1.speed + run RotateMergeSort go 512.numbers, 0.2.speed + run RotateMergeSortParallel go 512.numbers, 0.2.speed + run AndreySort go 2048.numbers + run NewShuffleMergeSort go 1024.numbers + run StrandSort go 2048.numbers + run BufferedStoogeSort go 256.numbers, 0.2.speed +} diff --git a/src/main/resources/scripts/categories/misc.groovy b/src/main/resources/scripts/categories/misc.groovy new file mode 100644 index 00000000..933fabbd --- /dev/null +++ b/src/main/resources/scripts/categories/misc.groovy @@ -0,0 +1,6 @@ +import io.github.arrayv.prompts.SortPrompt + +SortPrompt.setSortThreadForCategory('Miscellaneous Sorts', 2) { + run PancakeSort go 128.numbers, 0.015.speed + run BurntPancakeSort go 128.numbers, 0.015.speed +} diff --git a/src/main/resources/scripts/categories/quick.groovy b/src/main/resources/scripts/categories/quick.groovy new file mode 100644 index 00000000..f6c9846b --- /dev/null +++ b/src/main/resources/scripts/categories/quick.groovy @@ -0,0 +1,4 @@ +import io.github.arrayv.prompts.SortPrompt + +SortPrompt.setSortThreadForCategory('Quick Sorts', 0) { +} diff --git a/src/main/resources/scripts/categories/selection.groovy b/src/main/resources/scripts/categories/selection.groovy new file mode 100644 index 00000000..7315bd48 --- /dev/null +++ b/src/main/resources/scripts/categories/selection.groovy @@ -0,0 +1,22 @@ +import io.github.arrayv.prompts.SortPrompt + +SortPrompt.setSortThreadForCategory('Selection Sorts', 18) { + run SelectionSort go 128.numbers, 0.01.speed + run DoubleSelectionSort go 128.numbers, 0.01.speed + run StableSelectionSort go 128.numbers, 0.5.speed + run CycleSort go 128.numbers, 0.01.speed + run StableCycleSort go 128.numbers, 0.01.speed + run BingoSort go 128.numbers, 0.1.speed + run MaxHeapSort go 2048.numbers, 1.5.speed + run MinHeapSort go 2048.numbers, 1.5.speed + run FlippedMinHeapSort go 2048.numbers, 1.5.speed + run BaseNMaxHeapSort go 2048.numbers, 4.buckets, 1.5.speed + run TriangularHeapSort go 2048.numbers, 1.5.speed + run WeakHeapSort go 2048.numbers + run TernaryHeapSort go 2048.numbers + run SmoothSort go 2048.numbers, 1.5.speed + run PoplarHeapSort go 2048.numbers + run TournamentSort go 2048.numbers, 1.5.speed + run ClassicTournamentSort go 2048.numbers, 1.5.speed + run AsynchronousSort go 1024.numbers, 1.5.speed +} diff --git a/src/resources/soundfont/sfx.sf2 b/src/main/resources/sfx.sf2 similarity index 100% rename from src/resources/soundfont/sfx.sf2 rename to src/main/resources/sfx.sf2 diff --git a/src/main/resources/stats-config.txt b/src/main/resources/stats-config.txt new file mode 100644 index 00000000..cd273a8a --- /dev/null +++ b/src/main/resources/stats-config.txt @@ -0,0 +1,18 @@ +FONT: Times New Roman * 25 +# fps +# +sort +length + +delay +vtime +stime + +comps +swaps +revs + +wmain +waux +auxlen +segments diff --git a/src/panes/JEnhancedOptionPane.java b/src/panes/JEnhancedOptionPane.java deleted file mode 100644 index b548d413..00000000 --- a/src/panes/JEnhancedOptionPane.java +++ /dev/null @@ -1,31 +0,0 @@ -package panes; - -import java.awt.HeadlessException; - -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.UIManager; - -// Many thanks to Freek de Bruijn on StackOverflow for providing a custom JOptionPane. -// https://stackoverflow.com/questions/14407804/how-to-change-the-default-text-of-buttons-in-joptionpane-showinputdialog?noredirect=1&lq=1 -final public class JEnhancedOptionPane extends JOptionPane { - /** - * - */ - private static final long serialVersionUID = 1L; - - public static String showInputDialog(final String title, final Object message, final Object[] options) throws HeadlessException { - final JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE, - OK_CANCEL_OPTION, null, - options, null); - pane.setWantsInput(true); - pane.setComponentOrientation((getRootFrame()).getComponentOrientation()); - pane.setMessageType(QUESTION_MESSAGE); - pane.selectInitialValue(); - final JDialog dialog = pane.createDialog(null, title); - dialog.setVisible(true); - dialog.dispose(); - final Object value = pane.getInputValue(); - return (value == UNINITIALIZED_VALUE) ? null : (String) value; - } -} \ No newline at end of file diff --git a/src/prompts/SortPrompt.java b/src/prompts/SortPrompt.java deleted file mode 100644 index 207c3ba0..00000000 --- a/src/prompts/SortPrompt.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package prompts; - -import java.awt.event.ActionListener; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.io.File; -import java.util.ArrayList; -import java.util.Hashtable; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JFrame; -import javax.swing.JList; -import javax.swing.JTextField; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import dialogs.ImportSortDialog; -import frames.AppFrame; -import frames.UtilFrame; -import main.ArrayVisualizer; -import main.SortAnalyzer.SortPair; -import panes.JErrorPane; -import threads.*; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -/** - * - * @author S630690 - */ - -final public class SortPrompt extends javax.swing.JFrame implements AppFrame { - - public class PlaceholderTextField extends JTextField { - /** - * Shamelessly copied from https://stackoverflow.com/a/16229082/8840278 - */ - private static final long serialVersionUID = 1L; - private String placeholder; - - public String getPlaceholder() { - return placeholder; - } - - @Override - protected void paintComponent(final Graphics pG) { - super.paintComponent(pG); - - if (placeholder == null || placeholder.length() == 0 || getText().length() > 0) { - return; - } - - final Graphics2D g = (Graphics2D) pG; - g.setRenderingHint( - RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - g.setColor(getDisabledTextColor()); - g.drawString(placeholder, getInsets().left, pG.getFontMetrics() - .getMaxAscent() + getInsets().top); - } - - public void setPlaceholder(final String s) { - placeholder = s; - } - } - - private static int lastCategory = -1; - - private static final long serialVersionUID = 1L; - - private Hashtable categorySortThreads; - - private int[] array; - - private ArrayVisualizer ArrayVisualizer; - private JFrame Frame; - private UtilFrame UtilFrame; - - public SortPrompt(int[] array, ArrayVisualizer arrayVisualizer, JFrame frame, UtilFrame utilFrame) { - this.array = array; - this.ArrayVisualizer = arrayVisualizer; - this.Frame = frame; - this.UtilFrame = utilFrame; - - setAlwaysOnTop(true); - setUndecorated(true); - loadSortThreads(); - initComponents(); - if (lastCategory == -1) { - for (lastCategory = 1; ; lastCategory++) { - jComboBox1.setSelectedIndex(lastCategory); - if (jComboBox1.getSelectedItem().equals("Hybrid Sorts")) { - break; - } - } - } - else { - jComboBox1.setSelectedIndex(lastCategory); - } - jTextField1.requestFocusInWindow(); - loadSorts(); - reposition(); - setVisible(true); - } - - @Override - public void reposition() { - setLocation(Frame.getX()+(Frame.getWidth()-getWidth())/2,Frame.getY()+(Frame.getHeight()-getHeight())/2); - } - - private void loadSortThreads() { - this.categorySortThreads = new Hashtable<>(); - categorySortThreads.put("Concurrent Sorts", new RunConcurrentSorts (ArrayVisualizer)); - categorySortThreads.put("Distribution Sorts", new RunDistributionSorts (ArrayVisualizer)); - categorySortThreads.put("Exchange Sorts", new RunExchangeSorts (ArrayVisualizer)); - categorySortThreads.put("Hybrid Sorts", new RunHybridSorts (ArrayVisualizer)); - categorySortThreads.put("Impractical Sorts", new RunImpracticalSorts (ArrayVisualizer)); - categorySortThreads.put("Insertion Sorts", new RunInsertionSorts (ArrayVisualizer)); - categorySortThreads.put("Merge Sorts", new RunMergeSorts (ArrayVisualizer)); - categorySortThreads.put("Miscellaneous Sorts", new RunMiscellaneousSorts(ArrayVisualizer)); - categorySortThreads.put("Quick Sorts", new RunQuickSorts (ArrayVisualizer)); - categorySortThreads.put("Selection Sorts", new RunSelectionSorts (ArrayVisualizer)); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - // //GEN-BEGIN:initComponents - private void initComponents() { - - this.jComboBox1 = new javax.swing.JComboBox(); - this.jScrollPane1 = new javax.swing.JScrollPane(); - this.jList1 = new javax.swing.JList(); - this.jButton1 = new javax.swing.JButton(); - this.jButton2 = new javax.swing.JButton(); - this.jButton3 = new javax.swing.JButton(); - this.jTextField1 = new PlaceholderTextField(); - - setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - - jComboBox1.setModel(new DefaultComboBoxModel<>(SortPair.getCategories(ArrayVisualizer.getAllSorts()))); - jComboBox1.insertItemAt("All Sorts", 0); - - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - - jList1.setModel(new javax.swing.AbstractListModel() { - - private static final long serialVersionUID = 1L; - - String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; - @Override - public int getSize() { return strings.length; } - @Override - public Object getElementAt(int i) { return strings[i]; } - }); - - jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { - @Override - public void valueChanged(javax.swing.event.ListSelectionEvent evt) { - jList1ValueChanged(evt); - } - }); - - jScrollPane1.setViewportView(this.jList1); - - jComboBox1.addActionListener(new ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jComboBox1SelectionChanged(evt); - } - }); - - jTextField1.setPlaceholder("Search"); - jTextField1.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - jTextField1TextChanged(e); - } - @Override - public void removeUpdate(DocumentEvent e) { - jTextField1TextChanged(e); - } - @Override - public void changedUpdate(DocumentEvent e) { - jTextField1TextChanged(e); - } - }); - - jButton1.setText("Run All Sorts (approx. 30-90 minutes)"); - jButton1.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(); - } - }); - - jButton2.setText("Import Sort"); - jButton2.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton2ActionPerformed(); - } - }); - - jButton3.setText("Run All in Selected Category"); - jButton3.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton3ActionPerformed(); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(25, 25, 25) - .addComponent(this.jComboBox1) - .addGap(25, 25, 25)) - .addGroup(layout.createSequentialGroup() - .addGap(45, 45, 45) - .addComponent(this.jTextField1) - .addGap(45, 45, 45)) - .addGroup(layout.createSequentialGroup() - .addGap(25, 25, 25) - .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(25, 25, 25)) - .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() - .addComponent(this.jButton3)) - .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() - .addComponent(this.jButton1)) - .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() - .addComponent(this.jButton2)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(this.jComboBox1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(this.jTextField1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(this.jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.jButton3) - .addGap(5, 5, 5) - .addComponent(this.jButton1) - .addGap(5, 5, 5) - .addComponent(this.jButton2) - .addGap(5, 5, 5)) - ); - - pack(); - }// //GEN-END:initComponents - - private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed - new Thread(){ - @Override - public void run(){ - RunAllSorts RunAllSorts = new RunAllSorts(ArrayVisualizer); - RunAllSorts.reportAllSorts(array); - } - }.start(); - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jButton1ActionPerformed - - private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed - new Thread(){ - @Override - public void run(){ - File f = new ImportSortDialog().getFile(); - if (f == null) { - return; - } - ArrayVisualizer.getSortAnalyzer().importSort(f); - } - }.start(); - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jButton1ActionPerformed - - private void jButton3ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed - if (categorySortThreads.containsKey(jComboBox1.getSelectedItem())) { - MultipleSortThread thread = categorySortThreads.get(jComboBox1.getSelectedItem()); - try { - thread.reportAllSorts(array, 1, thread.getSortCount()); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - } - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jButton1ActionPerformed - - private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_jList1ValueChanged - @SuppressWarnings("rawtypes") - String sortName = (String)((JList)evt.getSource()).getSelectedValue(); - SortPair sortNotFinal = new SortPair(); - for (SortPair sort : ArrayVisualizer.getAllSorts()) { - if (sort.listName.equals(sortName)) { - sortNotFinal = sort; - break; - } - } - final SortPair selection = sortNotFinal; - new Thread(){ - @Override - public void run() { - if (selection.usesComparisons) { - RunComparisonSort sortThread = new RunComparisonSort(ArrayVisualizer); - sortThread.ReportComparativeSort(array, selection.id); - } - else { - RunDistributionSort sortThread = new RunDistributionSort(ArrayVisualizer); - sortThread.ReportDistributionSort(array, selection.id); - } - } - }.start(); - UtilFrame.jButton1ResetText(); - dispose(); - }//GEN-LAST:event_jList1ValueChanged - - @SuppressWarnings("unchecked") - private void loadSorts() { - int index = jComboBox1.getSelectedIndex(); - String category = (String)jComboBox1.getSelectedItem(); - ArrayList sorts = new ArrayList<>(); - for (SortPair sort : ArrayVisualizer.getAllSorts()) { - if (index == 0 || sort.category.equals(category)) { - if (jTextField1.getText().length() > 0 && - !sort.listName.toLowerCase().contains(jTextField1.getText().toLowerCase())) - continue; - sorts.add(sort.listName); - } - } - jList1.setListData(sorts.toArray()); - if (index == 0) { - jButton3.setEnabled(false); - } - else { - jButton3.setText("Run All ".concat(category)); - jButton3.setEnabled(categorySortThreads.containsKey(category)); - } - } - - private void jComboBox1SelectionChanged(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jList1ValueChanged - loadSorts(); - SortPrompt.lastCategory = jComboBox1.getSelectedIndex(); - }//GEN-LAST:event_jList1ValueChanged - - private void jTextField1TextChanged(DocumentEvent e) {//GEN-FIRST:event_jList1ValueChanged - if (e.getLength() == jTextField1.getText().length()) - jComboBox1.setSelectedIndex(0); - loadSorts(); - }//GEN-LAST:event_jList1ValueChanged - - // Variables declaration - do not modify//GEN-BEGIN:variables - @SuppressWarnings("rawtypes") - private javax.swing.JComboBox jComboBox1; - private javax.swing.JButton jButton1; - private javax.swing.JButton jButton2; - private javax.swing.JButton jButton3; - @SuppressWarnings("rawtypes") - private javax.swing.JList jList1; - private javax.swing.JScrollPane jScrollPane1; - private PlaceholderTextField jTextField1; - // End of variables declaration//GEN-END:variables -} \ No newline at end of file diff --git a/src/resources/Fetcher.java b/src/resources/Fetcher.java deleted file mode 100644 index 818d986e..00000000 --- a/src/resources/Fetcher.java +++ /dev/null @@ -1,39 +0,0 @@ -package resources; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; - -import panes.JErrorPane; - -public abstract class Fetcher { - private BufferedInputStream bufferedStream; - protected String defaultStream; - - public Fetcher(String defaultStream) { - this.defaultStream = defaultStream; - - try { - InputStream input = this.getClass().getResourceAsStream(this.defaultStream); - this.bufferedStream = new BufferedInputStream(input); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - } - - public Fetcher(File file) { - try { - FileInputStream stream = new FileInputStream(file); - this.bufferedStream = new BufferedInputStream(stream); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - } - - public BufferedInputStream getStream() { - return this.bufferedStream; - } -} \ No newline at end of file diff --git a/src/resources/image/arrayv.bmp b/src/resources/image/arrayv.bmp deleted file mode 100644 index fdc8686e..00000000 Binary files a/src/resources/image/arrayv.bmp and /dev/null differ diff --git a/src/resources/sorting_network_master/.gitignore b/src/resources/sorting_network_master/.gitignore deleted file mode 100644 index e04276f9..00000000 --- a/src/resources/sorting_network_master/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.idea -venv diff --git a/src/resources/sorting_network_master/README.md b/src/resources/sorting_network_master/README.md deleted file mode 100644 index 3086d992..00000000 --- a/src/resources/sorting_network_master/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# sorting-network -Python script to check sorting networks and generate sorting network diagrams - -## Usage - -``` -usage: sortingnetwork.py [-h] [-i inputfile] [-o [outputfile]] [-c] [-s [list]] [--svg [outputfile]] - -optional arguments: - -h, --help show this help message and exit - -i inputfile, --input inputfile specify a file containing comparison network definition - -o [outputfile], --output [outputfile] specify a file for saving the comparison network definition - -c, --check check whether it is a sorting network - --show-progress show percent complete while checking whether it is a - sorting network - -s [list], --sort [list] sorts the list using the input comparison network - --svg [outputfile] generate SVG - -``` - -Comparison networks can be specified like this: `0:1,2:3,0:2,1:3,1:2` and can either be loaded from a file using the `--input` argument or if no input file is specified, read from stdin. - -Multiple lines can be used as well, to logically group the comparators at each depth. `0:1,2:3,0:2,1:3,1:2` is the same as this: -``` -0:1,2:3 -0:2,1:3 -1:2 -``` - -## Examples -##### Read a comparison network from a file called example.cn and check whether it is is a sorting network. -``` -./sortingnetwork.py --input example.cn --check -``` - -##### Pipe a comparison network from stdin and check whether it is is a sorting network. -``` -echo "0:1,2:3,0:2,1:3,1:2" | ./sortingnetwork.py --check -``` - -##### Read a comparison network from a file called example.cn and generate SVG to stdout. -``` -./sortingnetwork.py --input example.cn --svg -``` - -##### Read a comparison network from a file called example.cn and generate SVG, saved to a file called output.svg. -``` -./sortingnetwork.py --input example.cn --svg output.svg -``` - -##### Pipe the output to rsvg-convert to generate a PNG (or other format) instead of SVG. -(*rsvg-convert can be installed by using `sudo apt-get install librsvg2-bin` on Ubuntu.*) - -4-input sorting network: -``` -./sortingnetwork.py --input examples/4-input.cn --svg | rsvg-convert > examples/4-input.png -``` - -5-input sorting network: -``` -./sortingnetwork.py --input examples/5-input.cn --svg | rsvg-convert > examples/5-input.png -``` - -##### Use a specified sorting network to sort a list. - -Using a 4-input sorting network to sort a list containing 4 items: -``` -./sortingnetwork.py --input examples/4-input.cn --sort 2,4,1,3 -``` -Outputs -``` -1 -2 -3 -4 -``` - -Using a 5-input sorting network to sort a list containing 5 items: -``` -./sortingnetwork.py --input examples/5-input.cn --sort 5,2,4,1,3 -``` -Outputs -``` -1 -2 -3 -4 -5 -``` - -## Example sorting networks - -### 4-Input - -```text -0:1,2:3 -0:2,1:3 -1:2 -``` - -![4-Input Sorting Network](https://github.com/brianpursley/sorting-network/blob/master/examples/4-input.png) - -### 5-Input - -```text -0:1,3:4 -2:4 -2:3,1:4 -0:3 -0:2,1:3 -1:2 -``` - -![5-Input Sorting Network](https://github.com/brianpursley/sorting-network/blob/master/examples/5-input.png) - -### 16-Input - -```text -0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15 -0:2,1:3,4:6,5:7,8:10,9:11,12:14,13:15 -0:4,1:5,2:6,3:7,8:12,9:13,10:14,11:15 -0:8,1:9,2:10,3:11,4:12,5:13,6:14,7:15 -5:10,6:9,3:12,13:14,7:11,1:2,4:8 -1:4,7:13,2:8,11:14 -2:4,5:6,9:10,11:13,3:8,7:12 -6:8,10:12,3:5,7:9 -3:4,5:6,7:8,9:10,11:12 -6:7,8:9 -``` - -![16-Input Sorting Network](https://github.com/brianpursley/sorting-network/blob/master/examples/16-input.png) - diff --git a/src/resources/sorting_network_master/examples/16-input.cn b/src/resources/sorting_network_master/examples/16-input.cn deleted file mode 100644 index d1b11b83..00000000 --- a/src/resources/sorting_network_master/examples/16-input.cn +++ /dev/null @@ -1,10 +0,0 @@ -0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15 -0:2,1:3,4:6,5:7,8:10,9:11,12:14,13:15 -0:4,1:5,2:6,3:7,8:12,9:13,10:14,11:15 -0:8,1:9,2:10,3:11,4:12,5:13,6:14,7:15 -5:10,6:9,3:12,13:14,7:11,1:2,4:8 -1:4,7:13,2:8,11:14 -2:4,5:6,9:10,11:13,3:8,7:12 -6:8,10:12,3:5,7:9 -3:4,5:6,7:8,9:10,11:12 -6:7,8:9 diff --git a/src/resources/sorting_network_master/examples/16-input.png b/src/resources/sorting_network_master/examples/16-input.png deleted file mode 100644 index 87c7d904..00000000 Binary files a/src/resources/sorting_network_master/examples/16-input.png and /dev/null differ diff --git a/src/resources/sorting_network_master/examples/16-input.svg b/src/resources/sorting_network_master/examples/16-input.svg deleted file mode 100644 index 6ecb1d6d..00000000 --- a/src/resources/sorting_network_master/examples/16-input.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/resources/sorting_network_master/examples/4-input.cn b/src/resources/sorting_network_master/examples/4-input.cn deleted file mode 100644 index 10305967..00000000 --- a/src/resources/sorting_network_master/examples/4-input.cn +++ /dev/null @@ -1,3 +0,0 @@ -0:1,2:3 -0:2,1:3 -1:2 diff --git a/src/resources/sorting_network_master/examples/4-input.png b/src/resources/sorting_network_master/examples/4-input.png deleted file mode 100644 index 5cf2480c..00000000 Binary files a/src/resources/sorting_network_master/examples/4-input.png and /dev/null differ diff --git a/src/resources/sorting_network_master/examples/4-input.svg b/src/resources/sorting_network_master/examples/4-input.svg deleted file mode 100644 index 287af43e..00000000 --- a/src/resources/sorting_network_master/examples/4-input.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/resources/sorting_network_master/examples/5-input.cn b/src/resources/sorting_network_master/examples/5-input.cn deleted file mode 100644 index 256f1226..00000000 --- a/src/resources/sorting_network_master/examples/5-input.cn +++ /dev/null @@ -1,6 +0,0 @@ -0:1,3:4 -2:4 -2:3,1:4 -0:3 -0:2,1:3 -1:2 diff --git a/src/resources/sorting_network_master/examples/5-input.png b/src/resources/sorting_network_master/examples/5-input.png deleted file mode 100644 index 7a219ec9..00000000 Binary files a/src/resources/sorting_network_master/examples/5-input.png and /dev/null differ diff --git a/src/resources/sorting_network_master/examples/5-input.svg b/src/resources/sorting_network_master/examples/5-input.svg deleted file mode 100644 index d5d27bd7..00000000 --- a/src/resources/sorting_network_master/examples/5-input.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/resources/sorting_network_master/out.svg b/src/resources/sorting_network_master/out.svg deleted file mode 100644 index e63a5200..00000000 --- a/src/resources/sorting_network_master/out.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/resources/sorting_network_master/sortingnetwork.py b/src/resources/sorting_network_master/sortingnetwork.py deleted file mode 100644 index 86c41636..00000000 --- a/src/resources/sorting_network_master/sortingnetwork.py +++ /dev/null @@ -1,243 +0,0 @@ - - -''' -The MIT License (MIT) - -Copyright (c) 2015 Brian Pursley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the 'Software'), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -''' - -import argparse -import sys - - -class Comparator: - def __init__(self, s): - inputs = s.strip().split(':') - input1 = int(inputs[0]) - input2 = int(inputs[1]) - if input1 < input2: - self.i1 = input1 - self.i2 = input2 - else: - self.i1 = input2 - self.i2 = input1 - - def __str__(self): - return '%s:%s' % (self.i1, self.i2) - - def __hash__(self): - return ('%s:%s' % (self.i1, self.i2)).__hash__() - - def overlaps(self, other): - return (self.i1 < other.i1 < self.i2) or \ - (self.i1 < other.i2 < self.i2) or \ - (other.i1 < self.i1 < other.i2) or \ - (other.i1 < self.i2 < other.i2) - - def has_same_input(self, other): - return self.i1 == other.i1 or \ - self.i1 == other.i2 or \ - self.i2 == other.i1 or \ - self.i2 == other.i2 - - -class ComparisonNetwork(list): - def __str__(self): - result = '' - group = [] - for c in self: - for other in group: - if c.has_same_input(other): - result += ','.join(map(str, group)) + '\n' - del group[:] - break - group.append(c) - result += ','.join(map(str, group)) - return result - - def is_sorting_network(self, show_progress): - - number_of_inputs = self.get_max_input() + 1 - max_sequence_to_check = (1 << number_of_inputs) - 1 - for i in range(0, max_sequence_to_check): - ones_count = count_ones(i) - if ones_count > 0: - zeros_count = number_of_inputs - ones_count - expected_sorted_sequence = ((1 << ones_count) - 1) << zeros_count - else: - expected_sorted_sequence = 0 - if self.sort_binary_sequence(i) != expected_sorted_sequence: - return False - if show_progress and i % 100 == 0: - print('\rChecking... %s%%' % round(i * 100 / max_sequence_to_check), end='') - if show_progress: - print('\r', end='') - return True - - def sort_binary_sequence(self, sequence): - result = sequence - - for c in self: - - pos0 = (result >> c.i1) & 1 - pos1 = (result >> c.i2) & 1 - if pos0 > pos1: - result ^= (1 << c.i1) | (1 << c.i2) - return result - - def sort_sequence(self, sequence): - result = list(sequence) - for c in self: - if result[c.i1] > result[c.i2]: - result[c.i1], result[c.i2] = result[c.i2], result[c.i1] - return result - - def get_max_input(self): - max_input = 0 - for c in self: - if c.i2 > max_input: - max_input = c.i2 - return max_input - - def svg(self): - scale = 1 - x_scale = scale * 35 - y_scale = scale * 20 - - comparators_svg = '' - w = x_scale - group = {} - for c in self: - - - for other in group: - if c.has_same_input(other): - for _, pos in group.items(): - if pos > w: - w = pos - w += x_scale - group = {} - break - - - cx = w - for other, other_pos in group.items(): - if other_pos >= cx and c.overlaps(other): - cx = other_pos + x_scale / 3 - - - y0 = y_scale + c.i1 * y_scale - y1 = y_scale + c.i2 * y_scale - comparators_svg += \ - '' % (cx, y0, 3) + \ - '' % (cx, y0, cx, y1, 1) + \ - '' % (cx, y1, 3) - - group[c] = cx - - - lines_svg = '' - w += x_scale - n = self.get_max_input() + 1 - for i in range(0, n): - y = y_scale + i * y_scale - lines_svg += '' % ( - 0, y, w, y, 1) - - h = (n + 1) * y_scale - return \ - '' + \ - '' + \ - '' % (w, h) + \ - comparators_svg + \ - lines_svg + \ - '' - - -def count_ones(x): - result = 0 - while x > 0: - result += x & 1 - x = x >> 1 - return result - - -def read_comparison_network(filename): - cn = ComparisonNetwork() - if filename: - with open(filename, 'r') as f: - for line in f: - for c in line.split(','): - cn.append(Comparator(c)) - else: - for line in sys.stdin: - for c in line.split(','): - cn.append(Comparator(c)) - return cn - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('-i', '--input', metavar='inputfile', - help='specify a file containing comparison network definition') - parser.add_argument('-o', '--output', metavar='outputfile', nargs='?', const='', - help='specify a file for saving the comparison network definition') - parser.add_argument('-c', '--check', action='store_true', help='check whether it is a sorting network') - parser.add_argument('--show-progress', action='store_true', help='show percent complete while checking whether it is a sorting network') - parser.add_argument('-s', '--sort', metavar='list', nargs='?', const='', - help='sorts the list using the input comparison network') - parser.add_argument('--svg', metavar='outputfile', nargs='?', const='', help='generate SVG') - args = parser.parse_args() - - if args.check: - cn = read_comparison_network(args.input) - if cn.is_sorting_network(args.show_progress): - print('It is a sorting network!') - else: - print('It is not a sorting network.') - - if args.svg or args.svg == '': - cn = read_comparison_network(args.input) - if args.svg == '': - print(cn.svg()) - else: - with open(args.svg, 'w') as f: - f.write(cn.svg()) - - if args.output or args.output == '': - cn = read_comparison_network(args.input) - if args.output == '': - print(str(cn)) - else: - with open(args.output, 'w') as f: - f.write(str(cn)) - - if args.sort or args.sort == '': - cn = read_comparison_network(args.input) - if args.sort == '': - input_sequence = eval(sys.stdin.readline()) - else: - input_sequence = eval(args.sort) - for sorted_item in cn.sort_sequence(input_sequence): - print(sorted_item) - - -main() diff --git a/src/resources/soundfont/SFXFetcher.java b/src/resources/soundfont/SFXFetcher.java deleted file mode 100644 index 4cc29714..00000000 --- a/src/resources/soundfont/SFXFetcher.java +++ /dev/null @@ -1,15 +0,0 @@ -package resources.soundfont; - -import java.io.File; - -import resources.Fetcher; - -final public class SFXFetcher extends Fetcher { - public SFXFetcher() { - super("sfx.sf2"); - } - - public SFXFetcher(File file) { - super(file); - } -} \ No newline at end of file diff --git a/src/resources/soundfont/sfx_old.sf2 b/src/resources/soundfont/sfx_old.sf2 deleted file mode 100644 index 6445a80a..00000000 Binary files a/src/resources/soundfont/sfx_old.sf2 and /dev/null differ diff --git a/src/sorts/concurrent/ApollyonSort.java b/src/sorts/concurrent/ApollyonSort.java deleted file mode 100644 index 2b9c121f..00000000 --- a/src/sorts/concurrent/ApollyonSort.java +++ /dev/null @@ -1,92 +0,0 @@ -package sorts.concurrent; - -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.CircleSorting; - -final public class ApollyonSort extends CircleSorting { - private boolean direction = true; - - public ApollyonSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Apollyon"); - this.setRunAllSortsName("Apollyon Sort"); - this.setRunSortName("Apollyon Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private static int greatestPowerOfTwoLessThan(int n){ - int k = 1; - while (k < n) { - k = k << 1; - } - return k >> 1; - } - - private void compare(int[] A, int i, int j, boolean dir) - { - int cmp = Reads.compareIndices(A, i, j, 0.5, true); - - if (dir == (cmp == 1)) Writes.swap(A, i, j, 0.5, true, false); - } - - private void apollyonMerge(int[] A, int lo, int n, boolean dir) - { - if (n > 1) - { - int m = greatestPowerOfTwoLessThan(n); - - for (int i = lo; i < lo + n - m; i++) { - this.compare(A, i, i+m, dir); - } - - this.apollyonMerge(A, lo, m, dir); - this.apollyonMerge(A, lo + m, n - m, dir); - } - } - - private void apollyonSort(int[] A, int lo, int n, boolean dir) - { - if (n > 1) - { - int m = n / 2; - this.apollyonSort(A, lo, m, !dir); - this.apollyonMerge(A, lo, n, dir); - } - } - - public void changeDirection(String choice) throws Exception { - if (choice.equals("forward")) this.direction = true; - else if (choice.equals("backward")) this.direction = false; - else throw new Exception("Invalid direction for Apollyon Sort!"); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.end = sortLength; - int threshold = 0, n = 1; - for(; n < sortLength; n*=2, threshold++); - - threshold /= 2; - int iterations = 0; - - this.apollyonSort(array, 0, sortLength, this.direction); - - while (this.circleSortRoutine(array, 0, sortLength - 1, 0, 1) != 0) { - iterations++; - - if (iterations >= threshold) { - InsertionSort Inserter = new InsertionSort(this.arrayVisualizer); - Inserter.customInsertSort(array, 0, sortLength, 0.1, false); - break; - } - } - } -} diff --git a/src/sorts/concurrent/MatrixSortParallel.java b/src/sorts/concurrent/MatrixSortParallel.java deleted file mode 100644 index 138f7794..00000000 --- a/src/sorts/concurrent/MatrixSortParallel.java +++ /dev/null @@ -1,148 +0,0 @@ -package sorts.concurrent; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* -Idea made by Control#2866 in The Studio Discord Server (https://discord.com/invite/2xGkKC2) -*/ - -final public class MatrixSortParallel extends Sort { - - public MatrixSortParallel(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Matrix (Parallel)"); - this.setRunAllSortsName("Parallel Matrix Sort"); - this.setRunSortName("Parallel Matrix Sort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int[] array; - - private volatile boolean did; - - private class Insert extends Thread { - private int a, b, g; - private boolean bw; - - Insert(int a, int b, int g, boolean bw) { - this.a = a; - this.b = b; - this.g = g; - this.bw = bw; - } - public void run() { - MatrixSortParallel.this.insert(a, b, g, bw); - } - } - - private class Reversal extends Thread { - private int a, b; - - Reversal(int a, int b) { - this.a = a; - this.b = b; - } - public void run() { - Writes.reversal(array, a, b-1, 1, true, false); - } - } - - private int sqrt(int n) { - int a = 0, b = Math.min(46341, n); - - while(a < b) { - int m = (a+b)/2; - - if(m*m >= n) b = m; - else a = m+1; - } - - return a; - } - - private void insert(int a, int b, int g, boolean bw) { - for(int i = a+g, j; i < b; i += g) { - int t = array[i]; - - for(j = i; j-g >= a && Reads.compareValues(array[j-g], t) == (bw ? -1 : 1); j -= g) { - this.did = true; - Writes.write(array, j, array[j-g], 1, true, false); - } - Writes.write(array, j, t, 1, true, false); - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.array = array; - - int g = sqrt(sortLength); - Insert[] ins = new Insert[g]; - - int tCnt = (sortLength-1)/g + 1; - this.did = true; - - while(this.did) { - this.did = false; - - int i = 0, j = 0; - boolean bw = false; - - for(; i+g < sortLength; i += g, j++, bw = !bw) - ins[j] = new Insert(i, i+g, 1, bw); - ins[j] = new Insert(i, sortLength, 1, bw); - - for(j = 0; j < tCnt; j++) ins[j].start(); - - for(j = 0; j < tCnt; j++) { - try { - ins[j].join(); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - for(i = 0, j = 0; i < g; i++, j++) - ins[j] = new Insert(i, sortLength, g, false); - - for(j = 0; j < g; j++) ins[j].start(); - - for(j = 0; j < g; j++) { - try { - ins[j].join(); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - - tCnt = (tCnt+1)/2; - Reversal[] revs = new Reversal[tCnt]; - - int i = g, j = 0; - for(; i+g < sortLength; i += 2*g, j++) - revs[j] = new Reversal(i, i+g); - revs[j] = new Reversal(i, sortLength); - - for(j = 0; j < tCnt; j++) revs[j].start(); - - for(j = 0; j < tCnt; j++) { - try { - revs[j].join(); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } -} \ No newline at end of file diff --git a/src/sorts/concurrent/OptimizedOddEvenMergeSort.java b/src/sorts/concurrent/OptimizedOddEvenMergeSort.java deleted file mode 100644 index 0b497428..00000000 --- a/src/sorts/concurrent/OptimizedOddEvenMergeSort.java +++ /dev/null @@ -1,115 +0,0 @@ -package sorts.concurrent; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class OptimizedOddEvenMergeSort extends Sort { - public OptimizedOddEvenMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Optimized Odd-Even Merge"); - this.setRunAllSortsName("Optimized Odd-Even Merge Sort"); - this.setRunSortName("Optimized Odd-Even Mergesort"); - this.setCategory("Concurrent Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void compSwap(int[] array, int a, int b) { - if(Reads.compareIndices(array, a, b, 0.5, true) == 1) - Writes.swap(array, a, b, 0.5, true, false); - } - - private void compRange(int[] array, int a, int m, int s) { - for(int i = s; a+i < m; i++) - this.compSwap(array, a+i, m+i); - } - - private void compRangeExtd(int[] array, int a, int m, int p) { - int l = m-a; - - if(l > p) { - int i = a, j, d = l-p; - - for(j = 0; j < d; j++, i++) this.compSwap(array, i, i+p); - for(j = 0; j < p-d; j++, i++) this.compSwap(array, i, i+l); - for(j = 0; j < d; j++, i++) this.compSwap(array, i+d, i+l); - } - else this.compRange(array, a, m, 0); - } - - private void merge(int[] array, int a, int b) { - int m, s = (b-a)%2; - - a -= s; - m = (a+b)/2; - this.compRange(array, a, m, s); - - int l = b-a; - if(l < 4) return; - - int p; - for(p = 1; 2*p < l; p *= 2); - - while(p > 0) { - int i = a+p; - - while(i + 2*p <= m) { - this.compRange(array, i, i+p, 0); - i += 2*p; - } - this.compRangeExtd(array, i, m, p); - i = 2*m - i; - - while(i < b-p) { - this.compRange(array, i, i+p, 0); - i += 2*p; - } - p /= 2; - } - } - - private void mergeSort(int[] array, int a, int b) { - int m = (a+b)/2; - - if(m-a > 1) this.mergeSort(array, a, m); - if(b-m > 1) this.mergeSort(array, m, b); - - this.merge(array, a, b); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.mergeSort(array, 0, sortLength); - } -} \ No newline at end of file diff --git a/src/sorts/distribute/DivisorSort.java b/src/sorts/distribute/DivisorSort.java deleted file mode 100644 index 902ddb0d..00000000 --- a/src/sorts/distribute/DivisorSort.java +++ /dev/null @@ -1,92 +0,0 @@ -package sorts.distribute; - -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class DivisorSort extends Sort { - public DivisorSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Divisor"); - //this.setRunAllID("Most Significant Digit Radix Sort"); - this.setRunAllSortsName("Divisor Sort"); - this.setRunSortName("Divisor Sort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void safePush(ArrayList> aList, int index, int value) { - while (aList.size() <= index) { - aList.add(new ArrayList<>()); - } - Writes.arrayListAdd(aList.get(index), value, true, 1); - } - - private void divisorLoop(int[] array, int start, int length, int base, int log) { - int divisor = (int)Math.pow(base, log); - ArrayList> buckets = new ArrayList<>(); - - for (int i = start; i < start + length; i++) { - Highlights.markArray(1, i); - safePush(buckets, (array[i] - start) / divisor, array[i]); - } - - int current = start; - for (int i = 0; i < buckets.size(); i++) { - int size = buckets.get(i).size(); - for (int j = 0; j < size; j++) { - Writes.write(array, current + j, buckets.get(i).get(j), 1, true, false); - } - if (size > 1) { - divisorLoop(array, current, size, base, log / 2); - } - current += size; - } - - for (ArrayList bucket : buckets) { - Writes.deleteArrayList(bucket); - } - } - - @Override - public void runSort(int[] array, int sortLength, int base) throws Exception { - this.setRunAllSortsName("Divisor Sort, Base " + base); - - int highestLog = Reads.analyzeMaxCeilingLog(array, sortLength, base, 0.5, true); - - divisorLoop(array, 0, sortLength, base, highestLog / 2); - } -} \ No newline at end of file diff --git a/src/sorts/distribute/FeatureSort.java b/src/sorts/distribute/FeatureSort.java deleted file mode 100644 index 56bdebc5..00000000 --- a/src/sorts/distribute/FeatureSort.java +++ /dev/null @@ -1,268 +0,0 @@ -package sorts.distribute; - -import main.ArrayVisualizer; -import sorts.templates.Sort; -import java.util.ArrayList; - - -/* -Copyright (c) 2020-2021 thatsOven - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -final public class FeatureSort extends Sort { - public FeatureSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Feature"); - this.setRunAllSortsName("Feature Sort"); - this.setRunSortName("Feature Sort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public void arrayListSwap(ArrayList arr, int a, int b, int start) { - int temp = arr.get(a); - arr.set(a, arr.get(b)); - arr.set(b, temp); - Highlights.markArray(0, start+a); - Highlights.markArray(1, start+b); - Writes.changeAuxWrites(2); - Delays.sleep(1); - Highlights.clearAllMarks(); - } - - public void arrayListWrite(ArrayList arr, int at, int value, int pos) { - arr.set(at, value); - Writes.changeAuxWrites(1); - Highlights.markArray(1, pos+at); - Delays.sleep(1); - Highlights.clearAllMarks(); - } - - public void arrayListReversal(ArrayList array, int start, int length, int pos) { - Writes.changeReversals(1); - - for(int i = start; i < start + ((length - start + 1) / 2); i++) { - this.arrayListSwap(array, i, start + length - i, pos); - } - } - - private void mergeUp(ArrayList array, int leftStart, int rightStart, int end, int[] copied, int start) { - for (int i = 0; i < rightStart - leftStart; i++) { - Highlights.markArray(1, i + leftStart); - Writes.write(copied, i, array.get(i + leftStart), 1, false, false); - } - - int left = leftStart; - int right = rightStart; - for(int nxt = 0; nxt < end - leftStart; nxt++){ - if(left >= rightStart && right >= end) break; - - Highlights.markArray(1, nxt + leftStart); - Highlights.markArray(2, right); - - if(left < rightStart && right >= end){ - Highlights.clearMark(2); - this.arrayListWrite(array, nxt + leftStart, copied[(left++) - leftStart], start+leftStart); - } - else if(left >= rightStart && right < end){ - Highlights.clearMark(1); - break; - } - else if(Reads.compareValues(copied[left - leftStart], array.get(right)) <= 0){ - this.arrayListWrite(array, nxt + leftStart, copied[(left++) - leftStart], start+leftStart); - } - else { - this.arrayListWrite(array, nxt + leftStart, array.get(right++), start+leftStart); - } - } - - Highlights.clearAllMarks(); - - } - - private void mergeDown(ArrayList array, int leftStart, int rightStart, int end, int[] copied, int start) { - for (int i = 0; i < end - rightStart; i++) { - Highlights.markArray(1, i + rightStart); - Writes.write(copied, i, array.get(i + rightStart), 1, false, false); - } - - int left = rightStart - 1; - int right = end; - for (int nxt = end - leftStart - 1; nxt >= 0; nxt--) { - if (left <= leftStart && right <= rightStart) break; - - Highlights.markArray(1, leftStart + nxt); - Highlights.markArray(2, (int)Math.max(left, 0)); - - if (left < leftStart && right >= leftStart) { - Highlights.clearMark(2); - this.arrayListWrite(array, leftStart + nxt, copied[(right--) - rightStart - 1], start+leftStart); - } - else if ((left >= leftStart && right < leftStart) || right < rightStart + 1) { - Highlights.clearMark(1); - break; - } - else if (Reads.compareValues(array.get(left), copied[right - rightStart - 1]) <= 0) { - this.arrayListWrite(array, leftStart + nxt, copied[(right--) - rightStart - 1], start+leftStart); - } - else { - this.arrayListWrite(array, leftStart + nxt, array.get(left--), start+leftStart); - } - } - - Highlights.clearAllMarks(); - } - - private void merge(ArrayList array, int leftStart, int rightStart, int end, int[] aux, int start) { - if (end - rightStart < rightStart - leftStart) { - mergeDown(array, leftStart, rightStart, end, aux, start); - } else { - mergeUp(array, leftStart, rightStart, end, aux, start); - } - } - - private boolean compare(int a, int b) { - return Reads.compareValues(a, b) <= 0; - } - - private int identifyRun(ArrayList array, int index, int maxIndex, int start) { - int startIndex = index; - - Highlights.markArray(1, start+index); - if (index >= maxIndex) { - return -1; - } - - boolean cmp = compare(array.get(index), array.get(index + 1)); - index++; - Highlights.markArray(1, start+index); - - while (index < maxIndex) { - Delays.sleep(1); - boolean checkCmp = compare(array.get(index), array.get(index + 1)); - if (checkCmp != cmp) { - break; - } - index++; - Highlights.markArray(1, start+index); - } - Delays.sleep(1); - if (cmp == false) { - this.arrayListReversal(array, startIndex, index, start); - } - if (index >= maxIndex) { - return -1; - } - return index + 1; - } - - private ArrayList findRuns(ArrayList array, int maxIndex, int start) { - ArrayList runs = new ArrayList<>(); - - int lastRun = 0; - while (lastRun != -1) { - Writes.arrayListAdd(runs, lastRun); - Writes.mockWrite(runs.size(), runs.size() - 1, lastRun, 0); - lastRun = identifyRun(array, lastRun, maxIndex, start); - } - - return runs; - } - - private void pdMergeSort(ArrayList array, int length, int start, int[] aux) { - ArrayList runs = findRuns(array, length - 1, start); - - while (runs.size() > 1) { - for (int i = 0; i < runs.size() - 1; i += 2) { - int end = i + 2 >= runs.size() ? length : (runs.get(i + 2)); - merge(array, runs.get(i), runs.get(i + 1), end, aux, start); - } - for (int i = 1; i < runs.size(); i++) { - Writes.arrayListRemoveAt(runs, i); - } - } - - Writes.deleteArrayList(runs); - } - - public void insertionSort(ArrayList arr, int a, int b, int start) { - for (int i = a + 1; i < b; i++) { - int key = arr.get(i); - int j = i-1; - - while (j >= a && Reads.compareValues(key, arr.get(j)) < 0) { - Highlights.markArray(0, start+j); - this.arrayListWrite(arr, j+1, arr.get(j), start); - j--; - } - this.arrayListWrite(arr, j+1, key, start); - } - Highlights.clearAllMarks(); - } - - public void sortSubList(ArrayList subList, int start, int[] mainArray) { - int l = subList.size(); - if (l > 1) { - if (l <= 16) { - this.insertionSort(subList, 0, l, start); - } else { - this.pdMergeSort(subList, l, start, mainArray); - } - } - } - - public void featureSort(int[] array, int currentLength) { - double max = Reads.analyzeMax(array, currentLength, 0.25, true); - @SuppressWarnings("unchecked") - ArrayList[] pos = new ArrayList[currentLength]; - double posConstant = max / (currentLength + 4); - for (int i = 0; i < currentLength; i++) { - pos[i] = new ArrayList<>(); - } - for (int i = 0; i < currentLength; i++) { - Highlights.markArray(0, i); - int idx = (int)(array[i] * posConstant); - Writes.arrayListAdd(pos[idx], array[i], true, 1); - Writes.changeAuxWrites(1); - } - Highlights.clearAllMarks(); - for (int i = 0; i < pos.length; i++) { - Highlights.markArray(0, i); - Delays.sleep(1); - this.sortSubList(pos[i], i, array); - Highlights.clearAllMarks(); - } - Highlights.clearAllMarks(); - Writes.transcribe(array, pos, 0, true, false); - Writes.deleteExternalArray(pos); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.featureSort(array, currentLength); - } -} \ No newline at end of file diff --git a/src/sorts/distribute/InPlaceMSDRadixSort.java b/src/sorts/distribute/InPlaceMSDRadixSort.java deleted file mode 100644 index f86c9b76..00000000 --- a/src/sorts/distribute/InPlaceMSDRadixSort.java +++ /dev/null @@ -1,88 +0,0 @@ -package sorts.distribute; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class InPlaceMSDRadixSort extends Sort { - public InPlaceMSDRadixSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("In-Place MSD Radix"); - this.setRunAllSortsName("In-Place MSD Radix Sort, Base 4"); - this.setRunSortName("In-Place MSD Radixsort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void radixMSD(int[] array, int length, int min, int max, int radix, int pow, double sleep) { - if(min >= max || pow < 0) - return; - - Highlights.markArray(3, max - 1); - Highlights.markArray(4, min); - - int[] indices = new int[radix]; - Writes.changeAllocAmount(indices.length); - for (int i = 0; i < radix; i++) { - indices[i] = min; - } - - for (int i = min; i < max; i++) { - Highlights.markArray(1, i); - int temp = array[i]; - int digit = Reads.getDigit(temp, pow, radix); - for (int j = radix - 1; j > digit; j--) { - if (indices[j] != indices[j - 1]) - Writes.write(array, indices[j], array[indices[j - 1]], sleep, true, false); - Writes.write(indices, j, indices[j] + 1, 0, false, true); - } - Writes.write(array, indices[digit], temp, sleep, true, false); - Writes.write(indices, digit, indices[digit] + 1, 0, false, true); - } - - for (int i = 0; i < radix; i++) { - int subMin = i == 0 ? min : indices[i - 1]; - this.radixMSD(array, length, subMin, indices[i], radix, pow - 1, sleep); - } - - Writes.changeAllocAmount(-indices.length); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - int highestpower = Reads.analyzeMaxLog(array, sortLength, bucketCount, 0.5, true); - - radixMSD(array, sortLength, 0, sortLength, bucketCount, highestpower, 1); - } -} \ No newline at end of file diff --git a/src/sorts/distribute/LMSDRadixSort.java b/src/sorts/distribute/LMSDRadixSort.java deleted file mode 100644 index 51a12f0f..00000000 --- a/src/sorts/distribute/LMSDRadixSort.java +++ /dev/null @@ -1,103 +0,0 @@ -package sorts.distribute; - -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* -L/MSD Radix Sort Sort 2021 Copyright (C) thatsOven -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -thanks to Tanoshi, that came up with the idea too, and made me make a Java port of the algorithm -*/ - -final public class LMSDRadixSort extends Sort { - - public LMSDRadixSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("L/MSD Radix"); - this.setRunAllSortsName("L/MSD Radix Sort"); - this.setRunSortName("Least/Most Significant Digit Radix Sort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - int base; - - public ArrayList[] radixSort(int[] array, int start, int end, int place) { - @SuppressWarnings("unchecked") - ArrayList[] registers = new ArrayList[this.base]; - - for(int i = 0; i < this.base; i++) registers[i] = new ArrayList<>(); - - for (int i = start; i < end; i++) { - Highlights.markArray(1, i); - int digit = Reads.getDigit(array[i], place, this.base); - Writes.arrayListAdd(registers[digit], array[i]); - - Writes.mockWrite(end - start, digit, array[i], 1); - } - - Highlights.clearAllMarks(); - - int counter = start; - for (int i = 0; i < this.base; i++) { - for (int j = 0; j < registers[i].size(); j++) { - Writes.write(array, counter++, registers[i].get(j), 1, true, false); - } - } - - return registers; - } - - - public void lmsdRadixSort(int[] array, int mina, int maxa, int place, int maxPlace) { - if (maxPlace < place || maxa - mina <= 1) return; - - ArrayList[] registers = this.radixSort(array, mina, maxa, place); - Writes.deleteExternalArray(registers); - - if (place != maxPlace) { - registers = this.radixSort(array, mina, maxa, maxPlace); - - int sum = 0; - - for (int i = 0; i < registers.length; i++) { - this.lmsdRadixSort(array, sum + mina, sum + mina + registers[i].size(), place + 1, maxPlace - 1); - - sum += registers[i].size(); - Writes.arrayListClear(registers[i]); - Writes.changeAllocAmount(-registers[i].size()); - } - - Writes.deleteExternalArray(registers); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) throws Exception { - this.setRunAllSortsName("Least/Most Significant Digit Radix Sort, Base " + bucketCount); - this.base = bucketCount; - - int highestpower = Reads.analyzeMaxLog(array, currentLength, bucketCount, 0.5, true); - - this.lmsdRadixSort(array, 0, currentLength, 0, highestpower); - - } -} \ No newline at end of file diff --git a/src/sorts/distribute/OptimizedIndexSort.java b/src/sorts/distribute/OptimizedIndexSort.java deleted file mode 100644 index a6c680b5..00000000 --- a/src/sorts/distribute/OptimizedIndexSort.java +++ /dev/null @@ -1,69 +0,0 @@ -package sorts.distribute; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020-2021 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class OptimizedIndexSort extends Sort { - public OptimizedIndexSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Optimized Index"); - this.setRunAllSortsName("Optimized Index Sort"); - this.setRunSortName("Optimized Indexsort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - int min = Reads.analyzeMin(array, sortLength, 0.5, true); - - for (int i = 0; i < sortLength; i++) { - Highlights.markArray(2, i); - int current = array[i]; - int cmpCount = 0; - while (Reads.compareValues(i, current - min) != 0 && cmpCount < sortLength) { - int tmp = array[current - min]; - Writes.write(array, current - min, current, 0.5, true, false); - current = tmp; - cmpCount++; - } - if (cmpCount >= sortLength - 1) break; - if (cmpCount > 0) - Writes.write(array, i, current, 0.5, true, false); - Delays.sleep(0.5); - Highlights.clearMark(1); - } - } -} \ No newline at end of file diff --git a/src/sorts/distribute/OptimizedPigeonholeSort.java b/src/sorts/distribute/OptimizedPigeonholeSort.java deleted file mode 100644 index 0bb95a91..00000000 --- a/src/sorts/distribute/OptimizedPigeonholeSort.java +++ /dev/null @@ -1,84 +0,0 @@ -package sorts.distribute; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class OptimizedPigeonholeSort extends Sort { - public OptimizedPigeonholeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Optimized Pigeonhole"); - this.setRunAllSortsName("Optimized Pigeonhole Sort"); - this.setRunSortName("Optimized Pigeonhole Sort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - - for(int i = 0; i < sortLength; i++) { - if(array[i] < min) { - min = array[i]; - } - if(array[i] > max) { - max = array[i]; - } - } - - int mi = min; - int size = max - mi + 1; - int[] holes = Writes.createExternalArray(size); - - for(int x = 0; x < sortLength; x++) { - Writes.write(holes, array[x] - mi, holes[array[x] - mi] + 1, 1, false, true); - Highlights.markArray(1, x); - } - - int j = 0; - - for(int count = 0; count < size; count++) { - for (int i = 0; i < holes[count]; i++) { - Writes.write(array, j, count + mi, 1, false, false); - - Highlights.markArray(1, j); - j++; - } - } - - Writes.deleteExternalArray(holes); - } -} \ No newline at end of file diff --git a/src/sorts/distribute/QuickBinaryRadixSort.java b/src/sorts/distribute/QuickBinaryRadixSort.java deleted file mode 100644 index e922b216..00000000 --- a/src/sorts/distribute/QuickBinaryRadixSort.java +++ /dev/null @@ -1,132 +0,0 @@ -package sorts.distribute; - -import sorts.templates.Sort; -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2020 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class QuickBinaryRadixSort extends Sort { - public QuickBinaryRadixSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Quick Binary Radix"); - this.setRunAllSortsName("Quick Binary Radix Sort"); - this.setRunSortName("Quick Binary Radix Sort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public int partition(int[] array, int a, int b, int bit) { - int i = a - 1; - int j = b; - - while(true) { - i++; - while(i < b && !Reads.getBit(array[i], bit)) { - Highlights.markArray(1, i); - Delays.sleep(0.5); - i++; - } - - j--; - while(j >= a && Reads.getBit(array[j], bit)) { - Highlights.markArray(2, j); - Delays.sleep(0.5); - j--; - } - - if(i < j) Writes.swap(array, i, j, 1, true, false); - else return i; - } - } - - private void radixLSD(int[] array, int a, int b, int p, int bit) { - int m = p; - - for(int i = a; i < b; i++) { - if(!Reads.getBit(array[i], bit)) m++; - Highlights.markArray(1, i); - Highlights.markArray(2, m); - Delays.sleep(0.5); - } - - for(int i = a; i < b; i++) { - if(Reads.getBit(array[i], bit)) - Writes.swap(array, i, m++, 0.5, true, false); - else - Writes.swap(array, i, p++, 0.5, true, false); - } - } - - private void radixLSDSort(int[] array, int a, int b, int p, int maxBit) { - int pow = 0, length = b-a; - - while(pow < maxBit) { - this.radixLSD(array, a, b, p, pow++); - - if(pow >= maxBit) { - for(int i = 0; i < length; i++) - Writes.swap(array, a+i, p+i, 0.5, true, false); - return; - } - else this.radixLSD(array, p, p+length, a, pow++); - } - } - - private void quickRadixSort(int[] array, int a, int b, int maxBit) { - int start = a, end = b; - while(maxBit >= 0) { - int p = this.partition(array, start, end, maxBit); - - int left = p-start; - int right = end-p; - - if(left < right) { - this.radixLSDSort(array, start, p, p, maxBit); - start = p; - } - else { - this.radixLSDSort(array, p, end, p-right, maxBit); - end = p; - } - Highlights.clearMark(2); - - maxBit--; - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int maxBit = Reads.analyzeBit(array, length); - this.quickRadixSort(array, 0, length, maxBit); - } -} \ No newline at end of file diff --git a/src/sorts/distribute/SkaSort.java b/src/sorts/distribute/SkaSort.java deleted file mode 100644 index 9a3b6932..00000000 --- a/src/sorts/distribute/SkaSort.java +++ /dev/null @@ -1,207 +0,0 @@ -package sorts.distribute; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -// Copyright Malte Skarupke 2016. -// Distributed under the Boost Software License, Version 1.0. -// (See http://www.boost.org/LICENSE_1_0.txt) - - -final class PartitionInfo { - private int count; - private int offset; - private int next_offset; - - public PartitionInfo() { - this.setCount(0); - } - - public int getCount() { - return this.count; - } - - public void setCount(int count) { - this.count = count; - } - - public void incrementCount() { - ++this.count; - } - - public int getOffset() { - return this.offset; - } - - public void setOffset(int offset) { - this.offset = offset; - } - - public int getNextOffset() { - return this.next_offset; - } - - public void setNextOffset(int next_offset) { - this.next_offset = next_offset; - } -} - -public class SkaSort extends Sort { - final private static int StdSortThreshold = 128; - final private static int AmericanFlagSortThreshold = 1024; - - public SkaSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.enableSort(false); - this.setSortListName("Ska"); - this.setRunAllSortsName("Ska Sort"); - this.setRunSortName("Skasort"); - this.setCategory("Distribution Sorts"); - this.setComparisonBased(false); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - /* - - template - inline void unroll_loop_four_times(It begin, size_t iteration_count, Func && to_call) - { - size_t loop_count = iteration_count / 4; - size_t remainder_count = iteration_count - loop_count * 4; - for (; loop_count > 0; --loop_count) - { - to_call(begin); - ++begin; - to_call(begin); - ++begin; - to_call(begin); - ++begin; - to_call(begin); - ++begin; - } - switch(remainder_count) - { - case 3: - to_call(begin); - ++begin; - case 2: - to_call(begin); - ++begin; - case 1: - to_call(begin); - } - } - - template - inline It custom_std_partition(It begin, It end, F && func) - { - for (;; ++begin) - { - if (begin == end) - return end; - if (!func(*begin)) - break; - } - It it = begin; - for(++it; it != end; ++it) - { - if (!func(*it)) - continue; - - std::iter_swap(begin, it); - ++begin; - } - return begin; - } - - private void ska_byte_sort(int[] array, int begin, int end) { - PartitionInfo partitions[] = new PartitionInfo[256]; - for (int it = begin; it != end; ++it) { - partitions[array[it]].incrementCount(); - } - int remaining_partitions[] = new int[256]; - int total = 0; - int num_partitions = 0; - for (int i = 0; i < 256; ++i) { - int count = partitions[i].getCount(); - if (count != 0){ - partitions[i].setOffset(total); - total += count; - remaining_partitions[num_partitions] = i; - ++num_partitions; - } - partitions[i].setNextOffset(total); - } - for (int last_remaining = remaining_partitions[num_partitions], int end_partition = remaining_partitions[1]; last_remaining > end_partition;) { - last_remaining = custom_std_partition(remaining_partitions, last_remaining, [&](uint8_t partition) - { - size_t & begin_offset = partitions[partition].offset; - size_t & end_offset = partitions[partition].next_offset; - if (begin_offset == end_offset) - return false; - - unroll_loop_four_times(begin + begin_offset, end_offset - begin_offset, [partitions = partitions, begin, &extract_key, sort_data](It it) - { - uint8_t this_partition = current_byte(extract_key(*it), sort_data); - size_t offset = partitions[this_partition].offset++; - std::iter_swap(it, begin + offset); - }); - return begin_offset != end_offset; - }); - } - if (Offset + 1 != NumBytes || next_sort) - { - for (int it = remaining_partitions + num_partitions; it != remaining_partitions; --it) - { - int partition = partitions[it - 1]; - int start_offset = (partition == 0 ? 0 : partitions[partition - 1].next_offset); - int end_offset = partitions[partition].next_offset; - int partition_begin = begin + start_offset; - int partition_end = begin + end_offset; - int num_elements = end_offset - start_offset; - if (!StdSortIfLessThanThreshold(array, partition_begin, partition_end, num_elements)) { - this.sort(array, partition_begin, partition_end, num_elements); - } - } - } - } - - private boolean StdSortIfLessThanThreshold(int[] array, int begin, int end, int num_elements) { - if (num_elements <= 1) - return true; - if (num_elements >= StdSortThreshold) - return false; - BranchedPDQSort pdqSort = new BranchedPDQSort(Delays, Highlights, Reads, Writes); - pdqSort.customSort(array, begin, end); - return true; - } - - private void sort(int[] array, int begin, int end, int num_elements) { - if (num_elements < AmericanFlagSortThreshold) { - AmericanFlagSort flagSort = new AmericanFlagSort(Delays, Highlights, Reads, Writes); - flagSort.runSort(array, num_elements, 128); - } - else { - this.ska_byte_sort(array, begin, end); - } - } - - private void inplace_radix_sort(int[] array, int begin, int end) { - this.sort(array, begin, end, end - begin); - } - - private void ska_sort(int[] array, int begin, int end) { - this.inplace_radix_sort(array, begin, end); - } -*/ - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - //this.ska_sort(array, 0, length); - } -} \ No newline at end of file diff --git a/src/sorts/distribute/SliceBogoSort.java b/src/sorts/distribute/SliceBogoSort.java deleted file mode 100644 index ccde6143..00000000 --- a/src/sorts/distribute/SliceBogoSort.java +++ /dev/null @@ -1,40 +0,0 @@ -package sorts.distribute; - -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; - -/** - * Slice Bogosort repeatedly shuffles random ranges of the array until it is sorted. - */ -public final class SliceBogoSort extends BogoSorting { - public SliceBogoSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Slice Bogo"); - this.setRunAllSortsName("Slice Bogo Sort"); - this.setRunSortName("Slice Bogosort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(10); - this.setBogoSort(true); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - while (!this.isArraySorted(array, length)) { - int index1 = BogoSorting.randInt(0, length), - index2 = BogoSorting.randInt(0, length); - - Highlights.markArray(3, index1); - Highlights.markArray(4, index2); - - if (index1 < index2) - this.bogoSwap(array, index1, index2+1, false); - else - this.bogoSwap(array, index2, index1+1, false); - } - } -} diff --git a/src/sorts/exchange/AwkwardSort.java b/src/sorts/exchange/AwkwardSort.java deleted file mode 100644 index 8483c495..00000000 --- a/src/sorts/exchange/AwkwardSort.java +++ /dev/null @@ -1,54 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author aphitorite - * - */ -public final class AwkwardSort extends Sort { - - public AwkwardSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Awkward"); - setRunAllSortsName("Awkward Sort"); - setRunSortName("Awkward Sort"); - setCategory("Impractical Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(4096); - setBogoSort(false); - - } - - private void awkward(int[] arr, int l, int pos) { - if (l == 1) { - return; - } - awkward(arr, l / 2, pos); - awkward(arr, l / 2 + l % 2, pos + l / 2); - - for (int i = 0; i < l / 2; i++) { - int a = pos + i; - int b = pos + l / 2 + l % 2 + i; - - if (this.Reads.compareIndices(arr, a, b, 0.02D, true) == 1) { - this.Writes.swap(arr, a, b, 0.02D, true, false); - } - } - awkward(arr, l / 2 + l % 2, pos + l / 4); - - awkward(arr, l / 2, pos); - awkward(arr, l / 2 + l % 2, pos + l / 2); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - awkward(array, sortLength, 0); - - } - -} diff --git a/src/sorts/exchange/ChinottoSort.java b/src/sorts/exchange/ChinottoSort.java deleted file mode 100644 index ed643ea5..00000000 --- a/src/sorts/exchange/ChinottoSort.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author yuji - * @author McDude_73 - * - */ -public final class ChinottoSort extends Sort { - - /** - * @param arrayVisualizer - */ - public ChinottoSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Chinotto"); - setRunAllSortsName("Chinotto Sort"); - setRunSortName("Chinottosort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - @Override - public void runSort(int[] array, int length, int bucketCount) throws Exception { - boolean done = false; - int gap = 1; - - while (!done) { - int i = 0; - done = true; - while (i + gap < length) { - if (this.Reads.compareValues(array[i], array[i + gap]) == 1) { - done = false; - this.Writes.multiSwap(array, i, i + gap, 0.2D, true, false); - gap++; - } else if (gap >= 2) { - gap--; - } - - i++; - } - while (i - gap > 0) { - if (this.Reads.compareValues(array[i - gap], array[i]) == 1) { - done = false; - this.Writes.multiSwap(array, i, i - gap, 0.2D, true, false); - gap++; - } else if (gap >= 2) { - gap--; - } - - i--; - } - } - - } - -} diff --git a/src/sorts/exchange/CircleMergeSort.java b/src/sorts/exchange/CircleMergeSort.java deleted file mode 100644 index 0ad3a1e3..00000000 --- a/src/sorts/exchange/CircleMergeSort.java +++ /dev/null @@ -1,45 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.IterativeCircleSorting; - -/* - * -Copyright (c) rosettacode.org. -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.2 -or any later version published by the Free Software Foundation; -with no Invariant Sections, no Front-Cover Texts, and no Back-Cover -Texts. A copy of the license is included in the section entitled "GNU -Free Documentation License". - * - */ - -final public class CircleMergeSort extends IterativeCircleSorting { - public CircleMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Circle Merge"); - this.setRunAllSortsName("Circle Merge Sort"); - this.setRunSortName("Circle Mergesort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.end = sortLength; - int n = 1; - for(; n <= sortLength; n*=2) { - int numberOfSwaps = 0; - do { - numberOfSwaps = this.circleSortRoutine(array, n, 0.2); - } while (numberOfSwaps != 0); - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/CocktailGrateSort.java b/src/sorts/exchange/CocktailGrateSort.java deleted file mode 100644 index 7416e475..00000000 --- a/src/sorts/exchange/CocktailGrateSort.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author McDude_73 - * @author EilrahcF - * @implNote This sorting algorithm is bad for arrays, but good for linked - * lists. - * - */ -public final class CocktailGrateSort extends Sort { - - /** - * @param arrayVisualizer - */ - public CocktailGrateSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Cocktail Grate"); - setRunAllSortsName("Cocktail Grate Sort"); - setRunSortName("Cocktail Gratesort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(512); - setBogoSort(false); - - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - boolean sorted = false; - while (!sorted) { - sorted = true; - int i; - for (i = 0; i < currentLength - 1; i++) { - for (int j = currentLength - 1; j > i; j--) { - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, j); - this.Delays.sleep(0.25D); - if (this.Reads.compareValues(array[i], array[j]) > 0) { - sorted = false; - this.Writes.swap(array, i, j, 0.1D, true, false); - break; - } - } - } - if (sorted) - break; - for (i = 0; i < currentLength - 1; i++) { - for (int j = i + 1; j < currentLength; j++) { - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, j); - this.Delays.sleep(0.25D); - if (this.Reads.compareValues(array[i], array[j]) > 0) { - this.Writes.swap(array, i, j, 0.1D, true, false); - break; - } - } - } - } - - } - -} diff --git a/src/sorts/exchange/DandelionSort.java b/src/sorts/exchange/DandelionSort.java deleted file mode 100644 index 9c03854c..00000000 --- a/src/sorts/exchange/DandelionSort.java +++ /dev/null @@ -1,49 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author yuji - * @author McDude_73 - * - */ -public final class DandelionSort extends Sort { - - public DandelionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Dandelion"); - setRunAllSortsName("Dandelion Sort"); - setRunSortName("Dandelion Sort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - for (int b = 0; b < sortLength; ) { - this.Highlights.markArray(1, b); - int pointer = b; - boolean anyswap = false; - - while (pointer < sortLength - 1 && this.Reads.compareIndices(array, pointer + 1, pointer, 0.25D, true) < 0) { - this.Writes.swap(array, pointer, pointer + 1, 0.5D, true, false); - anyswap = true; - pointer++; - } - - if (anyswap) { - if (b > 0) b--; continue; - } b++; - } - - - } - -} diff --git a/src/sorts/exchange/FibonacciGnomeSort.java b/src/sorts/exchange/FibonacciGnomeSort.java deleted file mode 100644 index f7f0cdc0..00000000 --- a/src/sorts/exchange/FibonacciGnomeSort.java +++ /dev/null @@ -1,84 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - - -/** - * @author mingyue12 - * - */ -public final class FibonacciGnomeSort extends Sort { - - public FibonacciGnomeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Fibonacci Gnome"); - this.setRunAllSortsName("Fibonacci Gnome Sort"); - this.setRunSortName("Fibonacci Gnome Sort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public int fibonacciSearch(int[] array, int start, int end, int item) { - int fibM2 = 0; - int fibM1 = 1; - int fibM = 1; - while (fibM <= end - start) { - fibM2 = fibM1; - fibM1 = fibM; - fibM = fibM2 + fibM1; - } - - int offset = start - 1; - - while (fibM > 1) { - - int i = Math.min(offset + fibM2, end); - - Highlights.markArray(1, offset + 1); - Highlights.markArray(2, i); - - if (Reads.compareValues(array[i], item) <= 0) { - fibM = fibM1; - fibM1 = fibM2; - fibM2 = fibM - fibM1; - offset = i; - } else { - fibM = fibM2; - fibM1 -= fibM2; - fibM2 = fibM - fibM1; - } - Delays.sleep(0.6); - } - int position = ++offset; - if (Reads.compareValues(array[position], item) <= 0) { - ++position; - } - return position; - } - - public void fibonacciGnomeSort(int[] array, int length) { - for (int i = 1; i < length; i++) { - int tmp = array[i]; - int position = this.fibonacciSearch(array, 0, i - 1, tmp); - int j = i; - while (j > position) { - Writes.swap(array, j, j - 1, 0, true, false); - j--; - } - - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - fibonacciGnomeSort(array, sortLength); - - } - -} diff --git a/src/sorts/exchange/FireSort.java b/src/sorts/exchange/FireSort.java deleted file mode 100644 index 620eb6c4..00000000 --- a/src/sorts/exchange/FireSort.java +++ /dev/null @@ -1,129 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -Fire Sort is an impractical variant of Gnome Sort that forces a worst case. - -Consider that the equation S = 0.5N^2 - 0.5N represents the number of swaps -needed, variable S, for the Gnome process to reverse any list of length N -values. Fire abuses this case by tracking the number of swaps that have -been made. When this count reaches T, an incrementing check number, then it -changes this limit by N. The Gnome process will continue, but in reverse. -Once the swap tracking reaches the new T value, the limit changes by N, and -the Gnome direction reverses again. - -There are some additional situations that this algorithm could face. If the -process target reaches either bound of the list, an internal verification -system will run starting from the left. If the list is sorted, then there's -nothing more the algorithm needs to do. If it is not, the system will run -again for a reversed order. When it finds the list is sorted backward, the -limit trigger will iterate, and the Gnome direction will twist immediately. -If it is not, the verification system will fail out, the target will move -to the opposite side of the list, and continue sorting as normal. - -Reversing a list of N values with Fire Sort will do S = 0.125N^3 + 0.5N^2 -swaps, which is (0.25N(N + 4))/(N - 1) times more swaps than Gnome Sort. - -*/ -final public class FireSort extends Sort { - public FireSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Fire"); - this.setRunAllSortsName("Fire Sort"); - this.setRunSortName("Firesort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int i = 1; - int twistcheck = 0; - int twistwait = 0; - int twist = -1; - int testi = 1; - boolean testpass = false; - boolean testreverse = false; - boolean anyswaps = false; - while (!testpass) { - if (twistwait < 1) { - twistcheck += currentLength; - twistwait = twistcheck; - twist *= -1; - } else { - twistwait--; - } - anyswaps = false; - while (i + 1 <= currentLength && i >= 1 && !anyswaps) { - if (Reads.compareValues(array[i - 1], array[i]) * twist > 0) { - Writes.swap(array, i - 1, i, 0.005, true, false); - i -= twist; - anyswaps = true; - } else { - i += twist; - } - } - if (i < 1) { - i = currentLength - 1; - testi = 1; - testpass = true; - while (testi != currentLength && testpass) { - if (Reads.compareValues(array[testi - 1], array[testi]) <= 0) { - testi++; - } else { - testpass = false; - testi = 1; - testreverse = true; - while (testi != currentLength && testreverse) { - if (Reads.compareValues(array[testi - 1], array[testi]) >= 0) { - testi++; - } else { - testreverse = false; - } - } - } - } - if (testreverse) { - i = 1; - twistwait = 0; - } - } - if (i + 1 > currentLength) { - i = 1; - testi = 1; - testpass = true; - while (testi != currentLength && testpass) { - if (Reads.compareValues(array[testi - 1], array[testi]) <= 0) { - testi++; - } else { - testpass = false; - testi = 1; - testreverse = true; - while (testi != currentLength && testreverse) { - if (Reads.compareValues(array[testi - 1], array[testi]) >= 0) { - testi++; - } else { - testreverse = false; - } - } - } - } - if (testreverse) { - i = currentLength - 1; - twistwait = 0; - } - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/FloatSort.java b/src/sorts/exchange/FloatSort.java deleted file mode 100644 index e737e448..00000000 --- a/src/sorts/exchange/FloatSort.java +++ /dev/null @@ -1,69 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author Lancewer - * @author McDude_73 - * - */ -public final class FloatSort extends Sort { - - public FloatSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Float"); - setRunAllSortsName("Float Sort"); - setRunSortName("Float Sort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(8192); - setBogoSort(false); - - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - boolean sorted = false; - while (!sorted) { - int h = 0; - sorted = true; - for (int g = length - 1; g > 0; g--) { - int i = h; - int j = h + 1; - - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, j); - - while (i >= 0 && this.Reads.compareValues(array[i], array[j]) > 0) { - this.Writes.swap(array, i, j, 0.5D, true, false); - sorted = false; - i--; - j--; - } - - this.Delays.sleep(0.25D); - - if (i >= 0) { - i++; - j++; - while (j < length && this.Reads.compareValues(array[i], array[j]) > 0) { - this.Writes.swap(array, i, j, 0.5D, true, false); - sorted = false; - i++; - j++; - } - - this.Delays.sleep(0.25D); - } - - h++; - } - } - - } - -} diff --git a/src/sorts/exchange/GambitGnomeSort.java b/src/sorts/exchange/GambitGnomeSort.java deleted file mode 100644 index f8d3d521..00000000 --- a/src/sorts/exchange/GambitGnomeSort.java +++ /dev/null @@ -1,67 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -public final class GambitGnomeSort extends Sort { - - public GambitGnomeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Gambit Gnome"); - setRunAllSortsName("Gambit Gnome Sort"); - setRunSortName("Gambit Gnomesort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - } - - private int binSearch(int[] array, int begin, int end, int target) { - while (true) { - int delta = end - begin; - if (delta <= 0) - break; - int p = begin + delta / 2; - if (this.Reads.compareIndices(array, p, target, 0.5D, true) == 0) - return p; - - if (this.Reads.compareIndices(array, p, target, 0.5D, true) > 0) { - end = p; - continue; - } - begin = p + 1; - } - return end; - } - - private void binInsert(int[] array, int len, int start, int end) { - int offset = 1; - for (; offset * offset < len; offset *= 2) - ; - - for (int bStart = 0, bEnd = end, i = start + offset; i < end; i++) { - int target = binSearch(array, bStart, bEnd, i); - - int tmp = array[i]; - int j = i; - while (j > target && array[j] >= tmp) { - this.Writes.swap(array, j - 1, j, 0.125D, true, false); - j--; - } - - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - binInsert(array, sortLength, 0, sortLength); - Highlights.clearAllMarks(); - OptimizedGnomeSort ins = new OptimizedGnomeSort(arrayVisualizer); - ins.customSort(array, 0, sortLength, 0.1D); - - } - -} diff --git a/src/sorts/exchange/GnomeWeaveHighSort.java b/src/sorts/exchange/GnomeWeaveHighSort.java deleted file mode 100644 index 7c56cc31..00000000 --- a/src/sorts/exchange/GnomeWeaveHighSort.java +++ /dev/null @@ -1,91 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -Gnome Weave by Highest Prime is a reversal of Gnome Weave by Lowest Prime. - -The prime check runs to the first result in Lowest Prime, but Highest Prime -runs it to the last result. - -Because the sorting algorithm divides by prime numbers over and over again, -list lengths with recurrent factor trees cause it to act accordingly. Also, -if the length is a prime number itself, it will resort to plain OptiGnome. -Try lengths like 1365, 2310, or 4199, and it will appear more diverse. - -*/ -final public class GnomeWeaveHighSort extends Sort { - public GnomeWeaveHighSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Gnome Weave (High Prime)"); - this.setRunAllSortsName("Gnome Weave Sort (High Prime)"); - this.setRunSortName("Gnome Weave (High Prime)"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int gap = currentLength; - int icheck = 1; - int i = 1; - int bound = 1; - int primetesti = 2; - double primetestrunning = 1.0; - boolean primetest = false; - boolean finalgap = false; - while (!finalgap) { - i = icheck; - bound = icheck; - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - while ((i - 1) + gap < currentLength) { - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - if (Reads.compareValues(array[i - 1], array[(i - 1) + gap]) > 0) { - Writes.swap(array, i - 1, (i - 1) + gap, 0.25, true, false); - if (i - gap > 0) { - i -= gap; - } - } else { - bound += gap; - i = bound; - } - } - if (gap == 1) { - finalgap = true; - } - if (icheck + 1 > gap && !finalgap) { - primetestrunning = gap; - while (primetestrunning != 1) { - primetest = false; - primetesti = 2; - while (!primetest) { - if (Math.floor(primetestrunning / primetesti) == primetestrunning / primetesti) { - primetestrunning = primetestrunning / primetesti; - primetest = true; - } else { - primetesti++; - } - } - } - gap = gap / primetesti; - icheck = 1; - } else { - icheck++; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/GnomeWeaveLowSort.java b/src/sorts/exchange/GnomeWeaveLowSort.java deleted file mode 100644 index d580e4a8..00000000 --- a/src/sorts/exchange/GnomeWeaveLowSort.java +++ /dev/null @@ -1,108 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -Gnome Weave by Lowest Prime is a mix of OptiGnome Sort and prime numbers. - -The sorting begins with setting up a gap, G. Any items a multiple of G away -from a target item, T, are compared, starting with items T and T + G. After -swapping them as needed, if an item exists at T + 2G, then T + G and T + 2G -are compared. If T + 2G is less than T + G, these two items will swap. If -this new T + G is also less than T, these two swap as well. If the upper -item in either case is greater than the other, no swap is needed and the -sort will skip forward to check for T + 3G. When the next T + XG item does -not exist, the target changes by 1, and so on until T is G - 1. - -Upon reaching the last unique target value, the gap value is tested for the -smallest possible prime number, P, it can evenly divide by. The next value -is then set to G/P, the target resets to the first value, and the sorting -continues. This repeats until G is 1, and after this, the sort is complete. - -The way I coded the prime check in the original Scratch project as well as -in the ArrayV port is a bit crude, because composite numbers are also being -checked for in this gap division. However, I get away with it since running -possible divisions that all occur evenly would attempt the prime factors of -a composite number before the composite number itself. - -Because the sorting algorithm divides by prime numbers over and over again, -list lengths with recurrent factor trees cause it to act accordingly. Also, -if the length is a prime number itself, it will resort to plain OptiGnome. -Try lengths like 1365, 2310, or 4199, and it will appear more diverse. - -*/ -final public class GnomeWeaveLowSort extends Sort { - public GnomeWeaveLowSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Gnome Weave (Low Prime)"); - this.setRunAllSortsName("Gnome Weave Sort (Low Prime)"); - this.setRunSortName("Gnome Weave (Low Prime)"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int gap = currentLength; - int icheck = 1; - int i = 1; - int bound = 1; - int primetesti = 2; - double primetestrunning = 1.0; - boolean primetest = false; - boolean finalgap = false; - while (!finalgap) { - i = icheck; - bound = icheck; - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - while ((i - 1) + gap < currentLength) { - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - if (Reads.compareValues(array[i - 1], array[(i - 1) + gap]) > 0) { - Writes.swap(array, i - 1, (i - 1) + gap, 0.25, true, false); - if (i - gap > 0) { - i -= gap; - } - } else { - bound += gap; - i = bound; - } - } - if (gap == 1) { - finalgap = true; - } - if (icheck + 1 > gap && !finalgap) { - primetestrunning = gap; - while (primetestrunning == gap) { - primetest = false; - primetesti = 2; - while (!primetest) { - if (Math.floor(primetestrunning / primetesti) == primetestrunning / primetesti) { - primetestrunning = primetestrunning / primetesti; - primetest = true; - } else { - primetesti++; - } - } - } - gap = gap / primetesti; - icheck = 1; - } else { - icheck++; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/GrateSort.java b/src/sorts/exchange/GrateSort.java deleted file mode 100644 index c5eac1fc..00000000 --- a/src/sorts/exchange/GrateSort.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author McDude_73 - * @author EilrahcF - * @implNote This sorting algorithm is bad for arrays, but good for linked - * lists. - * - */ -public final class GrateSort extends Sort { - - /** - * @param arrayVisualizer - */ - public GrateSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Grate"); - setRunAllSortsName("Grate Sort"); - setRunSortName("Gratesort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(512); - setBogoSort(false); - - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) throws Exception { - boolean sorted = false; - while (!sorted) { - sorted = true; - for (int i = 0; i < currentLength - 1; i++) { - for (int j = currentLength - 1; j > i; j--) { - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, j); - this.Delays.sleep(0.25D); - if (this.Reads.compareValues(array[i], array[j]) > 0) { - sorted = false; - this.Writes.swap(array, i, j, 0.1D, true, false); - break; - } - } - } - } - - } - -} diff --git a/src/sorts/exchange/HeadPullSort.java b/src/sorts/exchange/HeadPullSort.java deleted file mode 100644 index c8f54456..00000000 --- a/src/sorts/exchange/HeadPullSort.java +++ /dev/null @@ -1,72 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -U8y3zJTNmM2cVMy2zJLMlMyvQcy4zIHNhVnMts2MzJ4gzLbNg82QzZXMq0HMuM2EzYjMolfMuM2b -zYdBzLXMj8yqWcy2zJHNjMypzKIgzLfNm8yWRsy4zIzMs8yuUsy4zIfMscyiT8y4zYrMhM2FzZVN -zLfNncyeIMy3zYPMvcyzTcy3zJvMrUXMt8yAzLEhzLXMhcymzLogzLfMjsyjScy1zYrNk8ypIMy3 -zJDMnc2WQcy4zILNhsylTMy2zIrMjs2VzK9SzLfNoMyKzJ1FzLfMk8ylQcy2zInNnc2NzKZEzLfM -ic2azJ5ZzLXMicyNzKogzLfMjMySzY1XzLfMi8y6Qcy1zJTNgsyuUsy2zL/MmE7Mt8yHzY5FzLXM -k0TMtsyLzL3MmCDMtMyOzL7MsVnMtsyRzKPMrE/MuMyEzYTMoVXMt82YzZfMvCDMtcyPzIjMmVTM -tMy/zY5IzLTMg8yQzZTMskHMtcyRzIDMnsycVMy3zZDMjs2ZIMy0zIjMu0XMuM2EzIXMqMy7Vsy1 -zYvMoUXMtsyKzZxOzLTNks2bzK4gzLXNoMyvTcy1zYPNhsydWcy4zJDMhs2cIMy0zYTMpcyfT8y2 -zYvMoc2HV8y0zJLMvcy5Tsy1zZvNl8yWIMy1zYrMl03MtsyOzLBFzLXMm82azKlOzLjMklTMuMyB -zYZBzLjNhM2ZTMy0zInNlSDMtcyUzZjNmknMtc2LzL7Mp07MuMybzLvMu1PMtsySzJfMn0HMuM2M -zJDMu07MtcyHzIzNnMyxScy0zZ3Ml1TMuMyAzLDMqlnMtcy9zZMgzLjMgMyszJZJzLjMh8yYU8y0 -zZLNms2NIMy3zaDMu0LMt8yPzLDMo0XMuMyUzZLMoc2ZWcy1zInMp0/Mts2AzZ3Mnk7MtMyOzZDM -rETMts2QzZogzLTMgcy5Tcy4zYLNlVnMt82BzL/MuyDMts2BzIvNnMylQ8y4zYLMh8yjzJlPzLjM -vsywzLJOzLjMhsyLzLLMoFTMtcy/zYXMr1LMt8yQzKdPzLjMjsy8TMy2zYHMo8ylIcy1zZfMkc2N -IMy2zYPMn8ydVMy3zL/Nlcy7SMy4zL7MiMyxQcy4zYPMn8yuVMy1zJPNiM2UJ8y0zIrMlM2ZzLFT -zLfMjc2CzJ/MqyDMtcyazKPNjUjMt8yMzKnNjU/Mt8yRzZzNh1fMuMyBzZLNhSDMt82YzJPNiM2Z -Scy3zIvNoM2cIMy2zL7MnUXMtsyOzJDMosypTsy3zYvMmMyhRMy0zIXNjc2ORcy4zZ3Mv8yWRMy1 -zJXMq8ykIMy2zI7Nnc2VVcy3zL/NksyeUMy1zITMg8ysIMy2zIHMgMydzKRIzLTMvcy6Rcy0zZvN -m8y6Usy4zZjNksyxzZxFzLfMksyrIMy3zIjMvs2NScy4zZvNhMyyzKVOzLjMgcyezKEgzLfMh8yr -zLlUzLjMjc2dzLxIzLbMlM2EzJ9FzLTMisyDzKHNhSDMtcyKzLJGzLXNl8yOzZXNmUnMuMyGzLnM -nVLMt8ybzJrNmsyeU8y3zIrNlVTMuMy9zILNh8yeIMy3zYDMkcyqUMy4zL3Mqc2HTMy4zL7Nis2Z -Qcy1zYvNnMywQ8y2zYHMkM2FRcy2zJLMjSHMt8yTzZfMncywCgogLSBUaGUgTWFkaG91c2UgQ0VP - -*/ -final public class HeadPullSort extends Sort { - public HeadPullSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Head Pull"); - this.setRunAllSortsName("Head Pull Sort"); - this.setRunSortName("Head Pull Sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(32); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int i = 1; - int verifyi = 1; - int pull = 1; - i = 1; - while (i + 1 <= currentLength) { - Highlights.markArray(1, i - 1); - Highlights.markArray(2, i); - Delays.sleep(0.1); - if (Reads.compareValues(array[i - 1], array[i]) > 0) { - pull = i; - while (pull > 0) { - Writes.swap(array, pull - 1, pull, 0.1, true, false); - pull--; - } - i = 1; - } else { - i++; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/IndexQuickSort.java b/src/sorts/exchange/IndexQuickSort.java deleted file mode 100644 index f25305d4..00000000 --- a/src/sorts/exchange/IndexQuickSort.java +++ /dev/null @@ -1,137 +0,0 @@ -package sorts.exchange; - -import java.util.Random; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -The MIT License (MIT) - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -final public class IndexQuickSort extends Sort { - public IndexQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Index Quick"); - this.setRunAllSortsName("Index Quick Sort"); - this.setRunSortName("Index Quicksort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void indexSort(int[] array, int[] idx, int a, int b) { - while(a < b) { - Highlights.markArray(2, a); - - if(Reads.compareOriginalValues(a, idx[a]) != 0) { - int t = array[a]; - int i = a, nxt = idx[a]; - - do { - Writes.write(array, i, array[nxt], 0, true, false); - Writes.write(idx, i, i, 0.5, false, true); - - i = nxt; - nxt = idx[nxt]; - } - while(Reads.compareOriginalValues(nxt, a) != 0); - - Writes.write(array, i, t, 0, true, false); - Writes.write(idx, i, i, 0.5, false, true); - } - a++; - } - } - - private int partition(int[] array, int[] idx, int a, int b) { - int c0 = a, c1 = c0, i; - - Random r = new Random(); - int m = a + r.nextInt(b-a); - - Highlights.markArray(2, m); - for(i = a; i < m; i++) { - Highlights.markArray(1, i); - Delays.sleep(0.25); - - if(Reads.compareValues(array[i], array[m]) <= 0) - c1++; - } - i++; - c1++; - for(; i < b; i++) { - Highlights.markArray(1, i); - Delays.sleep(0.25); - - if(Reads.compareValues(array[i], array[m]) < 0) - c1++; - } - - int p = c1-1; - - for(i = a; i < m; i++) { - Highlights.markArray(1, i); - - if(Reads.compareValues(array[i], array[m]) <= 0) - Writes.write(idx, c0++, i, 0.25, false, true); - - else Writes.write(idx, c1++, i, 0.25, false, true); - } - Highlights.markArray(1, i); - Writes.write(idx, p, i++, 0.25, false, true); - - for(; i < b; i++) { - Highlights.markArray(1, i); - - if(Reads.compareValues(array[i], array[m]) < 0) - Writes.write(idx, c0++, i, 0.25, false, true); - - else Writes.write(idx, c1++, i, 0.25, false, true); - } - - this.indexSort(array, idx, a, b); - return p; - } - - private void sort(int[] array, int[] idx, int a, int b) { - if(b-a < 2) return; - - int p = this.partition(array, idx, a, b); - this.sort(array, idx, a, p); - this.sort(array, idx, p+1, b); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int[] idx = Writes.createExternalArray(length); - this.sort(array, idx, 0, length); - Writes.deleteExternalArray(idx); - } -} \ No newline at end of file diff --git a/src/sorts/exchange/IterativeQuickSort.java b/src/sorts/exchange/IterativeQuickSort.java deleted file mode 100644 index 9ce569dd..00000000 --- a/src/sorts/exchange/IterativeQuickSort.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author McDude_73 - * - */ -public final class IterativeQuickSort extends Sort { - - /** - * @param arrayVisualizer - */ - public IterativeQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Iterative Quick"); - setRunAllSortsName("Iterative Quick Sort"); - setRunSortName("Iterative Quicksort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - private int partition(int[] array, int lowValue, int highValue) { - int pivot = array[highValue]; - - int i = lowValue - 1; - for (int j = lowValue; j <= highValue - 1; j++) { - if (this.Reads.compareValues(array[j], pivot) <= 0) { - i++; - this.Writes.swap(array, i, j, 1.0D, true, false); - } - } - this.Writes.swap(array, i + 1, highValue, 1.0D, true, false); - return i + 1; - } - - private void quickSort(int[] array, int startIndex, int endIndex) { - int len = endIndex - startIndex + 1; - int[] stack = new int[len]; - Writes.changeAllocAmount(len); - int top = -1; - - this.Writes.write(stack, ++top, startIndex, 0.0D, true, true); - this.Writes.write(stack, ++top, endIndex, 0.0D, true, true); - - while (top >= 0) { - endIndex = stack[top--]; - startIndex = stack[top--]; - - int p = partition(array, startIndex, endIndex); - - if (this.Reads.compareValues(p - 1, startIndex) == 1) { - this.Writes.write(stack, ++top, startIndex, 0.0D, false, true); - this.Writes.write(stack, ++top, p - 1, 0.0D, false, true); - } - - if (this.Reads.compareValues(p + 1, endIndex) == -1) { - this.Writes.write(stack, ++top, p + 1, 0.0D, false, true); - this.Writes.write(stack, ++top, endIndex, 0.0D, false, true); - } - } - Writes.changeAllocAmount(-len); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - quickSort(array, 0, sortLength - 1); - - } - -} diff --git a/src/sorts/exchange/LLQuickSortMiddlePivot.java b/src/sorts/exchange/LLQuickSortMiddlePivot.java deleted file mode 100644 index 67880e36..00000000 --- a/src/sorts/exchange/LLQuickSortMiddlePivot.java +++ /dev/null @@ -1,69 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class LLQuickSortMiddlePivot extends Sort { - public LLQuickSortMiddlePivot(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Left/Left Quick (Middle Pivot)"); - this.setRunAllSortsName("Quick Sort, Left/Left Pointers (Middle Pivot)"); - this.setRunSortName("Left/Left Quicksort (Middle Pivot)"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int partition(int[] array, int a, int b) { - int i = a, j = i, m = (a+b)/2; - - Highlights.markArray(3, m); - while(j < m) { - Highlights.clearMark(1); - Highlights.markArray(2, j); - Delays.sleep(0.5); - - if(Reads.compareValues(array[j], array[m]) <= 0) - Writes.swap(array, i++, j, 1, true, false); - - j++; - } - - Writes.swap(array, i, m, 1, true, false); - j = m+1; - m = i++; - - Highlights.markArray(3, m); - while(j < b) { - Highlights.clearMark(1); - Highlights.markArray(2, j); - Delays.sleep(0.5); - - if(Reads.compareValues(array[j], array[m]) < 0) - Writes.swap(array, i++, j, 1, true, false); - - j++; - } - - Writes.swap(array, --i, m, 1, true, false); - return i; - } - - private void quickSort(int[] array, int a, int b) { - if(b-a > 1) { - int p = this.partition(array, a, b); - this.quickSort(array, a, p); - this.quickSort(array, p+1, b); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.quickSort(array, 0, currentLength); - } -} \ No newline at end of file diff --git a/src/sorts/exchange/LazyStableQuickSort.java b/src/sorts/exchange/LazyStableQuickSort.java deleted file mode 100644 index a868d527..00000000 --- a/src/sorts/exchange/LazyStableQuickSort.java +++ /dev/null @@ -1,161 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.insert.BinaryDoubleInsertionSort; -import sorts.insert.InsertionSort; -import sorts.merge.ReverseLazyStableSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020-2021 Gaming32 (Josiah Glosson) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class LazyStableQuickSort extends Sort { - ReverseLazyStableSort rotater; - InsertionSort inserter; - BinaryDoubleInsertionSort fallback; - - public LazyStableQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Lazy Stable Quick"); - this.setRunAllSortsName("Lazy Stable Quick Sort"); - this.setRunSortName("Lazy Stable Quicksort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int log2(int x) { - int n = 1; - while (1 << n < x) n++; - if (1 << n > x) n--; - return n; - } - - private int findPivot(int[] array, int start, int mid, int end) { - if (Reads.compareIndices(array, start, mid, 0.5, true) < 0) { - if (Reads.compareIndices(array, mid, end, 0.5, true) < 0) { - return mid; - } else if (Reads.compareIndices(array, start, end, 0.5, true) < 0) { - return end; - } - return start; - } else { - if (Reads.compareIndices(array, mid, end, 0.5, true) > 0) { - return mid; - } else if (Reads.compareIndices(array, start, end, 0.5, true) < 0) { - return start; - } - return end; - } - } - - private int stablePartition(int[] array, int start, int end) { - int mid = start + (end - start) / 2; - int pivotPos = findPivot(array, start, mid, end - 1); - while (true) { - int pivot = array[pivotPos]; - - int ltLeft = start; - int runstart = start; - int runsize = 0; - int equalCount = 0; - for (int i = start; i < end; i++) { - Highlights.markArray(1, i); - Delays.sleep(0.5); - int comp = Reads.compareValues(array[i], pivot); - if (comp < 0) { - runsize++; - continue; - } else if (comp == 0) { - equalCount++; - } - if (runsize > 0 && runstart > start) { - rotater.rotateSmart(array, runstart, ltLeft, runsize); - } - ltLeft += runsize; - runstart = i + 1; - runsize = 0; - } - - if (equalCount == end - start) return -1; - - // Necessary if the run is at the end - if (runsize > 0) { - rotater.rotateSmart(array, runstart, ltLeft, runsize); - ltLeft += runsize; - } - - if (ltLeft == start) { - pivotPos++; - if (pivotPos == end) { - pivotPos = start; - } - while (Reads.compareValueIndex(array, pivot, pivotPos, 1, true) == 0) { - pivotPos++; - if (pivotPos == end) { - pivotPos = start; - } - } - continue; - } - - return ltLeft; - } - } - - private void stableQuickSort(int [] array, int start, int end, int depth) { - while (end - start > 16) { - if (depth == 0) { - fallback.customDoubleInsert(array, start, end, 1); - return; - } - int pivotIndex = this.stablePartition(array, start, end); - if (pivotIndex == -1) return; - int left = pivotIndex - start, right = end - pivotIndex; - if (left > right) { - this.stableQuickSort(array, pivotIndex, end, --depth); - end = pivotIndex; - } else { - this.stableQuickSort(array, start, pivotIndex, --depth); - start = pivotIndex; - } - } - inserter.customInsertSort(array, start, end, 1, false); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - rotater = new ReverseLazyStableSort(arrayVisualizer); - inserter = new InsertionSort(arrayVisualizer); - fallback = new BinaryDoubleInsertionSort(arrayVisualizer); - this.stableQuickSort(array, 0, length, 2 * log2(length)); - } -} \ No newline at end of file diff --git a/src/sorts/exchange/LinkedIterativeQuickSort.java b/src/sorts/exchange/LinkedIterativeQuickSort.java deleted file mode 100644 index c0e9c74d..00000000 --- a/src/sorts/exchange/LinkedIterativeQuickSort.java +++ /dev/null @@ -1,96 +0,0 @@ -package sorts.exchange; - -import java.util.LinkedList; -import java.util.Queue; -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author aphitorite - * - */ -public final class LinkedIterativeQuickSort extends Sort { - - public LinkedIterativeQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Linked Iterative Quick"); - setRunAllSortsName("Linked Iterative Quick Sort, Left/Right Pointers"); - setRunSortName("Linked Iterative Left/Right Quicksort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - private class Task { - int p; - int r; - - public Task(int p, int r) { - this.p = p; - this.r = r; - } - } - - private void quickSort(int[] a, int p, int r) { - Queue tasks = new LinkedList<>(); - tasks.add(new Task(p, r)); - - while (!tasks.isEmpty()) { - Task task = tasks.remove(); - - int i = task.p; - int j = task.r; - int pivot = task.p + (task.r - task.p) / 2; - int x = a[pivot]; - - this.Highlights.markArray(3, pivot); - - while (i <= j) { - while (this.Reads.compareValues(a[i], x) == -1) { - i++; - this.Highlights.markArray(1, i); - this.Delays.sleep(0.5D); - } - while (this.Reads.compareValues(a[j], x) == 1) { - j--; - this.Highlights.markArray(2, j); - this.Delays.sleep(0.5D); - } - - if (i <= j) { - - if (i == pivot) { - this.Highlights.markArray(3, j); - } - if (j == pivot) { - this.Highlights.markArray(3, i); - } - - this.Writes.swap(a, i, j, 1.0D, true, false); - - i++; - j--; - } - } - - if (task.p < j) { - tasks.add(new Task(task.p, j)); - } - if (i < task.r) { - tasks.add(new Task(i, task.r)); - } - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - quickSort(array, 0, sortLength - 1); - - } - -} diff --git a/src/sorts/exchange/MarkovSort.java b/src/sorts/exchange/MarkovSort.java deleted file mode 100644 index 1575f00b..00000000 --- a/src/sorts/exchange/MarkovSort.java +++ /dev/null @@ -1,44 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.BogoSorting; - -/** - * Markov Sort is like Gnome Sort, but the next element to be inserted - * randomly walks within the sorted section until it is in the correct position. - * - * @author invented by Blasterfreund - * @author implemented in Java by Sam Walko (Anonymous0726) - * @author refactored by EmeraldBlock - */ -final public class MarkovSort extends BogoSorting { - public MarkovSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Markov"); - this.setRunAllSortsName("Markov Sort"); - this.setRunSortName("Markov sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(true); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - for (int i = 0; i < length-1; ++i) { - int walk = i+1; - while ( - (walk==0 ? false : Reads.compareIndices(array, walk-1, walk, this.delay, true)>0) - || (walk>i ? false : Reads.compareIndices(array, walk, walk+1, this.delay, true)>0) - ) { - int c = (walk==0 || walk<=i && BogoSorting.randBoolean()) ? 1 : -1; - Writes.swap(array, walk, walk+c, this.delay, true, false); - walk += c; - } - } - } -} diff --git a/src/sorts/exchange/MeanQuickSort.java b/src/sorts/exchange/MeanQuickSort.java deleted file mode 100644 index 7c7d40fe..00000000 --- a/src/sorts/exchange/MeanQuickSort.java +++ /dev/null @@ -1,159 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License -Copyright (c) 2020 Gaming32 -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class MeanQuickSort extends Sort { - public MeanQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Mean Quick"); - this.setRunAllSortsName("Mean Quick Sort"); - this.setRunSortName("Mean Quick Sort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int compareIntDouble(int left, double right) { - Reads.addComparison(); - - int cmpVal = 0; - - Writes.startLap(); - - if(left > right) cmpVal = 1; - else if(left < right) cmpVal = -1; - else cmpVal = 0; - - Writes.stopLap(); - - return cmpVal; - } - - private void partition(int[] array, int start, int end, int sum) { - int left = start; - int right = end; - Highlights.markArray(1, left); - Highlights.markArray(2, right); - - int count = right - left + 1; - if (count <= 1) { - return; - } - - double mean = (double)sum / (double)count; - - int lsum = 0; - int rsum = 0; - - while (left <= right) { - // while (this.compareIntDouble(array[right], mean) >= 0) { - // rsum += array[right]; - // right--; - // Delays.sleep(0.5); - // Highlights.markArray(4, right); - // } - - // if (left > right) { - // break; - // } - - // if (this.compareIntDouble(array[left], mean) >= 0) { - // Writes.swap(array, left, right, 1, false, false); - // rsum += array[right]; - // right--; - // Highlights.markArray(4, right); - // } - // Reads.addComparison(); - - // if (left > right || left >= highestEnd) { - // break; - // } - - // lsum += array[left]; - // left++; - // Highlights.markArray(3, left); - while (compareIntDouble(array[left], mean) == -1) { - lsum += array[left]; - left++; - Highlights.markArray(1, left); - Delays.sleep(0.5); - } - while (compareIntDouble(array[right], mean) == 1) { - rsum += array[right]; - right--; - Highlights.markArray(2, right); - Delays.sleep(0.5); - } - - if (left <= right) { - Writes.swap(array, left, right, 1, true, false); - - lsum += array[left]; - rsum += array[right]; - left++; - right--; - } - } - - // Highlights.clearAllMarks(); - // partition(array, start, left + 1, lsum, highestEnd); - // partition(array, left, end, rsum, highestEnd); - if (start < right) { - partition(array, start, right, lsum); - } - if (left < end) { - partition(array, left, end, rsum); - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - int sum = 0; - for (int i = 0; i < sortLength; i++) { - Highlights.markArray(1, i); - Writes.startLap(); - sum += array[i]; - Writes.stopLap(); - Delays.sleep(0.5); - } - Highlights.clearMark(1); - - partition(array, 0, sortLength - 1, sum); - - // for (int i = 1; i < sortLength; i++) { - // int j = i; - // while (j > 0 && Reads.compareIndices(array, j, j - 1, 0.25, true) == -1) { - // Writes.swap(array, j, j - 1, 0.25, true, false); - // j--; - // } - // } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/MerryGoRoundSort.java b/src/sorts/exchange/MerryGoRoundSort.java deleted file mode 100644 index 321f35f6..00000000 --- a/src/sorts/exchange/MerryGoRoundSort.java +++ /dev/null @@ -1,71 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -*/ -final public class MerryGoRoundSort extends Sort { - public MerryGoRoundSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Merry-Go-Round"); - this.setRunAllSortsName("Merry-Go-Round Sort"); - this.setRunSortName("Merry-Go-Round Sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(false); - } - @Override - public void runSort(int[] seats, int time, int nausea) { - int im = 1; - int very = 1; - int dizzy = 1; - boolean can_someone_please = false; - boolean stop_the_ride = false; - while (!stop_the_ride) { - im = very; - can_someone_please = false; - while (im + 1 <= time) { - Highlights.markArray(1, im - 1); - Highlights.markArray(2, im); - Delays.sleep(0.001); - if (Reads.compareValues(seats[im - 1], seats[im]) > 0) { - can_someone_please = true; - dizzy = im; - while (dizzy + 1 <= time) { - Writes.swap(seats, dizzy - 1, dizzy, 0.001, true, false); - dizzy += 2; - } - if (im > 1) { - im--; - } - } else { - im += 2; - } - } - if (!can_someone_please) { - very = 1; - stop_the_ride = true; - while (very != time && stop_the_ride) { - Highlights.markArray(1, very - 1); - Highlights.markArray(2, very); - Delays.sleep(0.001); - if (Reads.compareValues(seats[very - 1], seats[very]) <= 0) { - very++; - } else { - stop_the_ride = false; - } - } - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/NapoleonSort.java b/src/sorts/exchange/NapoleonSort.java deleted file mode 100644 index f0850aff..00000000 --- a/src/sorts/exchange/NapoleonSort.java +++ /dev/null @@ -1,161 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class NapoleonSort extends Sort { - public NapoleonSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Napoleon"); - this.setRunAllSortsName("Napoleon Sort"); - this.setRunSortName("Napoleon sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(8); - this.setBogoSort(false); - } - - private void tilsit(int[] array, int currentLen) { - for(int i = 0, j = currentLen - 1; i < currentLen/2; i++, j--) { - Highlights.markArray(1, i); - Highlights.markArray(2, j); - Delays.sleep(0.01); - if(Reads.compareIndices(array, i, j, 0.01, true) > 0) - Writes.swap(array, i, j, 0.01, true, false); - } - } - - private void napoleon(int[] array, int end) { - int lo = 0; - int hi = end; - - int prev = array[0]; - boolean goSmaller = true; - boolean noneFound = false; - - while(hi > lo) { - if(goSmaller) { - int next = lookEast(array, prev, lo+1, hi); - if(next == lo) { // No smaller elements - if(noneFound) { - lo++; - hi--; - } - prev = noneFound ? array[lo] : array[hi]; - goSmaller = noneFound; - noneFound = !noneFound; - } else if(next == hi) { // Next smaller element already at end - prev = array[hi]; - conquer(array, hi, lo); - noneFound = false; - } else { // Next smaller element elsewhere - prev = array[next]; - conquer(array, next, hi); - noneFound = false; - goSmaller = false; - } - } else { - int next = lookWest(array, prev, hi-1, lo); - if(next == hi) { // No larger elements - if(noneFound) { - lo++; - hi--; - } - prev = array[lo]; - goSmaller = true; - noneFound = !noneFound; - } else if(next == lo) { // Next larger element already at start - prev = array[lo]; - conquer(array, lo, hi); - noneFound = false; - } else { // Next larger element elsewhere - prev = array[next]; - conquer(array, next, lo); - noneFound = false; - goSmaller = true; - } - } - } - - } - - private int lookEast(int[] array, int prev, int start, int end) { - for(int i = start; i <= end; i++) { - if(Reads.compareValues(array[i], prev) < 0) - return i; - } - return start - 1; - } - - private int lookWest(int[] array, int prev, int start, int end) { - for(int i = start; i >= end; i--) { - if(Reads.compareValues(array[i], prev) > 0) - return i; - } - return start + 1; - } - - private void conquer(int[] array, int index, int target) { - int blockSize = 1; - while(index + blockSize - 1 < target) { - int marchTo = recruit(array, array[index], index+blockSize, target); - int spaceBetween = marchTo - index - blockSize + 1; - march(array, index, blockSize, spaceBetween); - index += spaceBetween; - blockSize++; - } - while(index - blockSize + 1 > target) { - int marchTo = recruit(array, array[index], index-blockSize, target); - int spaceBetween = index - blockSize - marchTo + 1; - march(array, marchTo, spaceBetween, blockSize); - index -= spaceBetween; - blockSize++; - } - } - - private int recruit(int[] array, int identicalTo, int start, int end) { - if(start= end; i--) { - if(Reads.compareValues(array[i], identicalTo) == 0) - return i + 1; - } - return end; - } - - private void march(int[] array, int index, int len1, int len2) { - while(len1 != 0 && len2 != 0) { - if(len1 <= len2) { - attack(array, index, index+len1, len1); - index += len1; - len2 -= len1; - } else { - attack(array, index + len1, index + len1 - len2, len2); - len1 -= len2; - } - } - } - - private void attack(int[] array, int startA, int startB, int swapsLeft) { - while(swapsLeft != 0) { - Writes.swap(array, startA++, startB++, 1, true, false); - swapsLeft--; - } - } - - @Override - public void runSort(int[] array, int currentLen, int bucketCount) { - tilsit(array, currentLen); - Highlights.clearAllMarks(); - napoleon(array, currentLen - 1); - } -} \ No newline at end of file diff --git a/src/sorts/exchange/OddEvenWeaveHighSort.java b/src/sorts/exchange/OddEvenWeaveHighSort.java deleted file mode 100644 index 50abf3fc..00000000 --- a/src/sorts/exchange/OddEvenWeaveHighSort.java +++ /dev/null @@ -1,129 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -*/ -final public class OddEvenWeaveHighSort extends Sort { - public OddEvenWeaveHighSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Odd-Even Weave (High Prime)"); - this.setRunAllSortsName("Odd-Even Weave Sort (High Prime)"); - this.setRunSortName("Odd-Even Weave (High Prime)"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int check = 1; - int lastbound = 2; - int lastmove = currentLength; - int move = currentLength; - int noswapsfor = 0; - int gap = currentLength; - int primetesti = 2; - int i = 1; - int boundi = 1; - double primetestrunning = 1.0; - boolean primetest = false; - boolean anyswaps = false; - boolean testpass = false; - boolean visualaesthetic = true; - while (!testpass) { - i = check; - anyswaps = false; - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - while ((i - 1) + gap < currentLength) { - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - if (Reads.compareValues(array[i - 1], array[(i - 1) + gap]) > 0) { - Writes.swap(array, i - 1, (i - 1) + gap, 0.25, true, false); - anyswaps = true; - } - i += move; - } - if (!anyswaps && gap != 1) { - noswapsfor++; - if (noswapsfor == move) { - noswapsfor = 0; - lastmove = move; - primetestrunning = move; - if (!visualaesthetic) { - while (primetestrunning != 1) { - primetest = false; - primetesti = 2; - while (!primetest) { - if (Math.floor(primetestrunning / primetesti) == primetestrunning / primetesti) { - primetestrunning = primetestrunning / primetesti; - primetest = true; - } else { - primetesti++; - } - } - } - move = move / primetesti; - } - visualaesthetic = false; - if (move != 1) { - primetestrunning = move; - while (primetestrunning != 1) { - primetest = false; - primetesti = 2; - while (!primetest) { - if (Math.floor(primetestrunning / primetesti) == primetestrunning / primetesti) { - primetestrunning = primetestrunning / primetesti; - primetest = true; - } else { - primetesti++; - } - } - } - gap = move / primetesti; - } else { - move = lastmove; - gap = 1; - } - check = 0; - } - } else { - noswapsfor = 0; - } - if (gap == 1) { - if (lastbound > 1) { - boundi = lastbound - 1; - } else { - boundi = 1; - } - testpass = true; - while (boundi < currentLength && testpass) { - Highlights.markArray(1, boundi - 1); - Highlights.markArray(2, boundi); - Delays.sleep(0.25); - if (Reads.compareValues(array[boundi - 1], array[boundi]) <= 0) { - boundi++; - } else { - testpass = false; - lastbound = boundi; - check = boundi; - } - } - } else { - check = (check % move) + 1; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/OddEvenWeaveLowSort.java b/src/sorts/exchange/OddEvenWeaveLowSort.java deleted file mode 100644 index 8425c922..00000000 --- a/src/sorts/exchange/OddEvenWeaveLowSort.java +++ /dev/null @@ -1,129 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -*/ -final public class OddEvenWeaveLowSort extends Sort { - public OddEvenWeaveLowSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Odd-Even Weave (Low Prime)"); - this.setRunAllSortsName("Odd-Even Weave Sort (Low Prime)"); - this.setRunSortName("Odd-Even Weave (Low Prime)"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int check = 1; - int lastbound = 2; - int lastmove = currentLength; - int move = currentLength; - int noswapsfor = 0; - int gap = currentLength; - int primetesti = 2; - int i = 1; - int boundi = 1; - double primetestrunning = 1.0; - boolean primetest = false; - boolean anyswaps = false; - boolean testpass = false; - boolean visualaesthetic = true; - while (!testpass) { - i = check; - anyswaps = false; - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - while ((i - 1) + gap < currentLength) { - Highlights.markArray(1, i - 1); - Highlights.markArray(2, (i - 1) + gap); - Delays.sleep(0.25); - if (Reads.compareValues(array[i - 1], array[(i - 1) + gap]) > 0) { - Writes.swap(array, i - 1, (i - 1) + gap, 0.25, true, false); - anyswaps = true; - } - i += move; - } - if (!anyswaps && gap != 1) { - noswapsfor++; - if (noswapsfor == move) { - noswapsfor = 0; - lastmove = move; - primetestrunning = move; - if (!visualaesthetic) { - while (primetestrunning == move) { - primetest = false; - primetesti = 2; - while (!primetest) { - if (Math.floor(primetestrunning / primetesti) == primetestrunning / primetesti) { - primetestrunning = primetestrunning / primetesti; - primetest = true; - } else { - primetesti++; - } - } - } - move = move / primetesti; - } - visualaesthetic = false; - if (move != 1) { - primetestrunning = move; - while (primetestrunning == move) { - primetest = false; - primetesti = 2; - while (!primetest) { - if (Math.floor(primetestrunning / primetesti) == primetestrunning / primetesti) { - primetestrunning = primetestrunning / primetesti; - primetest = true; - } else { - primetesti++; - } - } - } - gap = move / primetesti; - } else { - move = lastmove; - gap = 1; - } - check = 0; - } - } else { - noswapsfor = 0; - } - if (gap == 1) { - if (lastbound > 1) { - boundi = lastbound - 1; - } else { - boundi = 1; - } - testpass = true; - while (boundi < currentLength && testpass) { - Highlights.markArray(1, boundi - 1); - Highlights.markArray(2, boundi); - Delays.sleep(0.25); - if (Reads.compareValues(array[boundi - 1], array[boundi]) <= 0) { - boundi++; - } else { - testpass = false; - lastbound = boundi; - check = boundi; - } - } - } else { - check = (check % move) + 1; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/PatternDefeatingGnomeSort.java b/src/sorts/exchange/PatternDefeatingGnomeSort.java deleted file mode 100644 index ef9a0931..00000000 --- a/src/sorts/exchange/PatternDefeatingGnomeSort.java +++ /dev/null @@ -1,53 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author Yuri-chan2007 - * - */ -public final class PatternDefeatingGnomeSort extends Sort { - - public PatternDefeatingGnomeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Pattern-Defeating Gnome"); - this.setRunAllSortsName("Pattern-Defeating Gnome Sort"); - this.setRunSortName("Pattern-Defeating Gnomesort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public void gnomeSort(int[] array, int a, int b, double sleep, boolean auxwrite) { - int i = a + 1; - if(Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { - while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; - Writes.reversal(array, a, i - 1, sleep, true, auxwrite); - } - else while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; - - Highlights.clearMark(2); - - while(i < b) { - - int pos = i; - while(pos > a && Reads.compareValues(array[pos - 1], array[pos]) > 0){ - Writes.swap(array, pos - 1, pos, sleep, true, auxwrite); - pos--; - } - i++; - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - gnomeSort(array, 0, sortLength, 1.0D, false); - - } - -} diff --git a/src/sorts/exchange/PseudoHeapSort.java b/src/sorts/exchange/PseudoHeapSort.java deleted file mode 100644 index e6a34926..00000000 --- a/src/sorts/exchange/PseudoHeapSort.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author yuji - * @author fungamer2 - * - */ -public final class PseudoHeapSort extends Sort { - - /** - * @param arrayVisualizer - */ - public PseudoHeapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Iterative Pseudo-Heap"); - setRunAllSortsName("Iterative Pseudo-Heap Sort"); - setRunSortName("Iterative Pseudo-Heapsort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - private boolean sift_down(int[] array, int start, int length, int root) { - boolean swapped = false; - int j = root; - while (2 * j < length) { - int k = 2 * j; - if (k < length && this.Reads.compareValues(array[start + k - 1], array[start + k]) == 1) { - k++; - } - if (this.Reads.compareIndices(array, start + j - 1, start + k - 1, 1.0D, true) == 1) { - this.Writes.swap(array, start + j - 1, start + k - 1, 1.0D, true, false); - j = k; - swapped = true; - continue; - } - break; - } - return swapped; - } - - private boolean sift(int[] array, int start, int end) { - return sift_down(array, start, end - start + 1, 1); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - boolean swapped = true; - while (swapped) { - swapped = false; - for (int i = length - 2; i >= 0; i--) { - if (sift(array, i, length)) - swapped = true; - } - } - - } - -} diff --git a/src/sorts/exchange/ReflectionSort.java b/src/sorts/exchange/ReflectionSort.java deleted file mode 100644 index 2fa58185..00000000 --- a/src/sorts/exchange/ReflectionSort.java +++ /dev/null @@ -1,70 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -Reflection Sort is an algorithm developed with unwritten impracticalities. - -Reflection Sort starts running a Cocktail Shaker. When a swap is found, the -target position is then set to a reflection across the length of the list. -Upon reaching either bound of the list, exactly like Cocktail Shaker Sort, -the search direction is turned opposite, and the swap hunt restarts. This -continues until a sweep in descending order can be made without any swaps. - -*/ -final public class ReflectionSort extends Sort { - public ReflectionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Reflection"); - this.setRunAllSortsName("Reflection Sort"); - this.setRunSortName("Reflection Sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(2048); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - boolean anyswap = true; - int i = 0; - while(anyswap) { - i = 0; - anyswap = false; - while(i < currentLength) { - Highlights.markArray(1, i); - Highlights.markArray(2, i + 1); - Delays.sleep(0.125); - if(Reads.compareValues(array[i], array[i + 1]) > 0) { - Writes.swap(array, i, i + 1, 0.125, true, false); - i = (currentLength - 1) - i; - anyswap = true; - } else { - i++; - } - } - i = currentLength; - anyswap = false; - while (i > 1) { - Highlights.markArray(1, i - 1); - Highlights.markArray(2, i); - Delays.sleep(0.125); - if(Reads.compareValues(array[i - 1], array[i]) > 0) { - Writes.swap(array, i - 1, i, 0.125, true, false); - i = (currentLength - 1) - i; - anyswap = true; - } else { - i--; - } - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/ReverseBubbleSort.java b/src/sorts/exchange/ReverseBubbleSort.java deleted file mode 100644 index f4d9099f..00000000 --- a/src/sorts/exchange/ReverseBubbleSort.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author mingyue12 - * - */ -public final class ReverseBubbleSort extends Sort { - - /** - * @param arrayVisualizer - */ - public ReverseBubbleSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Reverse Bubble"); - this.setRunAllSortsName("Reverse Bubble Sort"); - this.setRunSortName("Reverse Bubblesort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - // TODO Auto-generated method stub - - for(int i = 0; i < sortLength - 1; i++) { - boolean sorted = true; - for(int j = sortLength - 1; j > i; j--) { - if(Reads.compareIndices(array, j - 1, j, 0.05, true) == 1){ - Writes.swap(array, j - 1, j, 0.075, true, false); - sorted = false; - } - } - if(sorted) break; - } - - } - -} diff --git a/src/sorts/exchange/ReverseGnomeSort.java b/src/sorts/exchange/ReverseGnomeSort.java deleted file mode 100644 index e93d171b..00000000 --- a/src/sorts/exchange/ReverseGnomeSort.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* -* -MIT License -Copyright (c) 2021 mingyue12 -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -* -*/ - -/** - * This is the reversed variant of Optimized Gnomesort. - * @author mingyue12 - * - */ -public final class ReverseGnomeSort extends Sort { - - /** - * @param arrayVisualizer - */ - public ReverseGnomeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Reverse Gnome"); - this.setRunAllSortsName("Reverse Gnome Sort"); - this.setRunSortName("Reverse Gnomesort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - - } - private void reverseGnomeSort(int[] array, int lowerBound, int upperBound, double sleep) { - int pos = lowerBound; - - while(pos < upperBound && Reads.compareValues(array[pos], array[pos + 1]) == 1) { - Writes.swap(array, pos, pos + 1, sleep, true, false); - pos++; - } - } - public void customSort(int[] array, int low, int high, double sleep) { - for(int i = high; i >= low; i--) { - reverseGnomeSort(array, i, high, sleep); - } - } - - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - // TODO Auto-generated method stub - for(int i = sortLength - 1; i >= 0; i--) { - reverseGnomeSort(array, i, sortLength - 1, 0.05); - } - - } - -} diff --git a/src/sorts/exchange/ReverseGrateSort.java b/src/sorts/exchange/ReverseGrateSort.java deleted file mode 100644 index 761a73dc..00000000 --- a/src/sorts/exchange/ReverseGrateSort.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author McDude_73 - * @author EilrahcF - * @implNote This sorting algorithm is bad for arrays, but good for linked - * lists. - * - */ -public final class ReverseGrateSort extends Sort { - - /** - * @param arrayVisualizer - */ - public ReverseGrateSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Reverse Grate"); - setRunAllSortsName("Reverse Grate Sort"); - setRunSortName("Reverse Gratesort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(512); - setBogoSort(false); - - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - boolean sorted = false; - while (!sorted) { - sorted = true; - for (int i = 0; i < currentLength - 1; i++) { - for (int j = i + 1; j < currentLength; j++) { - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, j); - this.Delays.sleep(0.25D); - if (this.Reads.compareValues(array[i], array[j]) > 0) { - sorted = false; - this.Writes.swap(array, i, j, 0.1D, true, false); - break; - } - } - } - } - - } - -} diff --git a/src/sorts/exchange/SafeBogoSort.java b/src/sorts/exchange/SafeBogoSort.java deleted file mode 100644 index 0fe04e3a..00000000 --- a/src/sorts/exchange/SafeBogoSort.java +++ /dev/null @@ -1,66 +0,0 @@ -package sorts.exchange; - -import java.util.Random; - -import sorts.templates.Sort; -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class SafeBogoSort extends Sort { - public SafeBogoSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Safe Bogo"); - this.setRunAllSortsName("Safe Bogo Sort"); - this.setRunSortName("Safe Bogosort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(false); - } - - private int findLastSorted(int[] array, int length) { - int i = 1; - for(; i < length && Reads.compareValues(array[i-1], array[i]) <= 0; i++); - return i-1; - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - Random r = new Random(); - int p = this.findLastSorted(array, length); - - while(p < length-1) { - Writes.swap(array, p, p + r.nextInt(length-p), 0, true, false); - p = this.findLastSorted(array, length); - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/SplitCenterSort.java b/src/sorts/exchange/SplitCenterSort.java deleted file mode 100644 index f89a7630..00000000 --- a/src/sorts/exchange/SplitCenterSort.java +++ /dev/null @@ -1,46 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -*/ -final public class SplitCenterSort extends Sort { - public SplitCenterSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Split Center"); - this.setRunAllSortsName("Split Center Sort"); - this.setRunSortName("Split Center Sort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int way = 1; - int i = 1; - for (int r = 1; r < currentLength; r++) { - i = (int) Math.floor(currentLength / 2); - i -= way; - while (i <= currentLength && i >= 1) { - Highlights.markArray(1, i - 1); - Highlights.markArray(2, i); - Delays.sleep(0.005); - if (Reads.compareValues(array[i - 1], array[i]) > 0) { - Writes.swap(array, i - 1, i, 0.005, true, false); - } - i += way; - } - way *= -1; - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/StableQuickSortMiddlePivot.java b/src/sorts/exchange/StableQuickSortMiddlePivot.java deleted file mode 100644 index 84688372..00000000 --- a/src/sorts/exchange/StableQuickSortMiddlePivot.java +++ /dev/null @@ -1,116 +0,0 @@ -package sorts.exchange; - -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2017 Rodney Shaghoulian -Copyright (c) 2020 Josiah Glosson - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class StableQuickSortMiddlePivot extends Sort { - public StableQuickSortMiddlePivot(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stable Quick (Middle Pivot)"); - this.setRunAllSortsName("Stable Quick Sort (Middle Pivot)"); - this.setRunSortName("Stable Quicksort (Middle Pivot)"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - // Author: Rodney Shaghoulian - // Github: github.com/RodneyShag - - // Author: Josiah Glosson - // Github: github.com/gaming32 - - private void copy(ArrayList list, int [] array, int startIndex) { - for (int num : list) { - Writes.write(array, startIndex++, num, 0.25, false, false); - Highlights.markArray(1, startIndex); - } - } - - /* Partition/Quicksort "Stable Sort" version using O(n) space */ - private int stablePartition(int[] array, int start, int end) { - int pivot = start + (end - start) / 2; - int pivotValue = array[pivot]; - Highlights.markArray(3, start); - Highlights.markArray(4, pivot); - - ArrayList leftList = new ArrayList<>(); - ArrayList rightList = new ArrayList<>(); - - for (int i = start ; i <= end; i++) { - Highlights.markArray(1, i); - if (i == pivot) continue; - - if (Reads.compareValues(array[i], pivotValue) == -1) { - Writes.mockWrite(end - start, leftList.size(), array[i], 0.25); - Writes.arrayListAdd(leftList, array[i]); - } - else { - Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); - Writes.arrayListAdd(rightList, array[i]); - } - } - - /* Recreate array */ - this.copy(leftList, array, start); - - int newPivotIndex = start + leftList.size(); - - Writes.write(array, newPivotIndex, pivotValue, 0.25, false, false); - Highlights.markArray(1, newPivotIndex); - - this.copy(rightList, array, newPivotIndex + 1); - - Writes.deleteArrayList(leftList); - Writes.deleteArrayList(rightList); - - return newPivotIndex; - } - - private void stableQuickSort(int [] array, int start, int end) { - if (start < end) { - int pivotIndex = this.stablePartition(array, start, end); - this.stableQuickSort(array, start, pivotIndex - 1); - this.stableQuickSort(array, pivotIndex + 1, end); - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.stableQuickSort(array, 0, length - 1); - } -} \ No newline at end of file diff --git a/src/sorts/exchange/StableStoogeSort.java b/src/sorts/exchange/StableStoogeSort.java deleted file mode 100644 index 1ba24e6d..00000000 --- a/src/sorts/exchange/StableStoogeSort.java +++ /dev/null @@ -1,39 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class StableStoogeSort extends Sort { - public StableStoogeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stable Stooge"); - this.setRunAllSortsName("Stable Stooge Sort"); - this.setRunSortName("Stable Stoogesort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(false); - } - - private void stableStooge(int[] array, int start, int end) { - if (end - start + 1 == 2) { - if (Reads.compareIndices(array, start, end, 0.0025, true) == 1) { - Writes.swap(array, start, end, 0.005, true, false); - } - } else if (end - start + 1 > 2) { - int third = (end - start + 1) / 3; - stableStooge(array, start, end - third); - stableStooge(array, start + third, end); - stableStooge(array, start, end - third); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - stableStooge(array, 0, currentLength - 1); - } -} \ No newline at end of file diff --git a/src/sorts/exchange/StacklessQuickSort.java b/src/sorts/exchange/StacklessQuickSort.java deleted file mode 100644 index f7ef9efb..00000000 --- a/src/sorts/exchange/StacklessQuickSort.java +++ /dev/null @@ -1,156 +0,0 @@ -package sorts.exchange; - -import sorts.templates.Sort; -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class StacklessQuickSort extends Sort { - public StacklessQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stackless Quick"); - this.setRunAllSortsName("Stackless Quick Sort"); - this.setRunSortName("Stackless Quicksort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void medianOfThree(int[] array, int a, int b) { - int m = a+(b-1-a)/2; - - if(Reads.compareIndices(array, a, m, 1, true) == 1) - Writes.swap(array, a, m, 1, true, false); - - if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { - Writes.swap(array, m, b-1, 1, true, false); - - if(Reads.compareIndices(array, a, m, 1, true) == 1) - return; - } - - Writes.swap(array, a, m, 1, true, false); - } - - private int partition(int[] array, int a, int b) { - int i = a, j = b; - - this.medianOfThree(array, a, b); - Highlights.markArray(3, a); - - do { - do { - i++; - Highlights.markArray(1, i); - Delays.sleep(0.5); - } - while(i < j && Reads.compareIndices(array, i, a, 0, false) < 0); - - do { - j--; - Highlights.markArray(2, j); - Delays.sleep(0.5); - } - while(j >= i && Reads.compareIndices(array, j, a, 0, false) >= 0); - - if(i < j) Writes.swap(array, i, j, 1, true, false); - else { - Writes.swap(array, a, j, 1, true, false); - Highlights.clearMark(3); - return j; - } - } - while(true); - } - - private int leftBinSearch(int[] array, int a, int b, int p) { - while(a < b) { - int m = a+(b-a)/2; - - if(Reads.compareIndices(array, p, m, 0.5, true) <= 0) - b = m; - else - a = m+1; - } - - return a; - } - - private void quickSort(int[] array, int a, int b) { - int max = array[a]; - - for(int i = a+1; i < b; i++) { - Highlights.markArray(1, i); - Delays.sleep(0.5); - - if(Reads.compareValues(array[i], max) > 0) max = array[i]; - } - for(int i = b-1; i >= 0; i--) { - Highlights.markArray(1, i); - Delays.sleep(0.5); - - if(Reads.compareValues(array[i], max) == 0) - Writes.swap(array, i, --b, 1, true, false); - } - - int b1 = b; - - do { - while(b1-a > 2) { - int p = this.partition(array, a, b1); - Writes.swap(array, p, b, 1, true, false); - - b1 = p; - } - - if(b1-a == 2 && Reads.compareIndices(array, a, a+1, 0.5, true) == 1) - Writes.swap(array, a, a+1, 1, true, false); - - a = b1+1; - if(a >= b) { - if(a-1 < b) Writes.swap(array, a-1, b, 1, true, false); - return; - } - - b1 = this.leftBinSearch(array, a, b, a-1); - Writes.swap(array, a-1, b, 1, true, false); - - while(a < b1 && Reads.compareIndices(array, a-1, a, 0.5, true) == 0) a++; - } - while(true); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.quickSort(array, 0, length); - } -} \ No newline at end of file diff --git a/src/sorts/exchange/StupidFireSort.java b/src/sorts/exchange/StupidFireSort.java deleted file mode 100644 index fafccf94..00000000 --- a/src/sorts/exchange/StupidFireSort.java +++ /dev/null @@ -1,118 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -Stupid Fire Sort is a variant of Fire Sort, in turn variant to Gnome Sort. - -Where Fire Sort increments the swap check value by the length of the list, -Stupid Fire Sort only changes it by 1. This tiny difference lands the total -number of needed swaps, variable S, to reverse a list of N count values at -an unimaginable S = 0.125N^4 - 0.25N^3 + 1.125N^2 - N. Supposing we use 128 -items, that's over a hundred times worse than regular Fire Sort, and four -thousand times worse than Gnome Sort! Now that's impractical! - -RE8gTk9UIFVTRSBUSElTIFNPUlQsIEVWRVIh - -*/ -final public class StupidFireSort extends Sort { - public StupidFireSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Stupid Fire"); - this.setRunAllSortsName("Stupid Fire Sort"); - this.setRunSortName("Stupid Firesort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(128); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int i = 1; - int twistcheck = 0; - int twistwait = 0; - int twist = -1; - int testi = 1; - boolean testpass = false; - boolean testreverse = false; - boolean anyswaps = false; - while (!testpass) { - if (twistwait < 1) { - twistcheck++; - twistwait = twistcheck; - twist *= -1; - } else { - twistwait--; - } - anyswaps = false; - while (i + 1 <= currentLength && i >= 1 && !anyswaps) { - if (Reads.compareValues(array[i - 1], array[i]) * twist > 0) { - Writes.swap(array, i - 1, i, 0.001, true, false); - i -= twist; - anyswaps = true; - } else { - i += twist; - } - } - if (i < 1) { - i = currentLength - 1; - testi = 1; - testpass = true; - while (testi != currentLength && testpass) { - if (Reads.compareValues(array[testi - 1], array[testi]) <= 0) { - testi++; - } else { - testpass = false; - testi = 1; - testreverse = true; - while (testi != currentLength && testreverse) { - if (Reads.compareValues(array[testi - 1], array[testi]) >= 0) { - testi++; - } else { - testreverse = false; - } - } - } - } - if (testreverse) { - i = 1; - twistwait = 0; - } - } - if (i + 1 > currentLength) { - i = 1; - testi = 1; - testpass = true; - while (testi != currentLength && testpass) { - if (Reads.compareValues(array[testi - 1], array[testi]) <= 0) { - testi++; - } else { - testpass = false; - testi = 1; - testreverse = true; - while (testi != currentLength && testreverse) { - if (Reads.compareValues(array[testi - 1], array[testi]) >= 0) { - testi++; - } else { - testreverse = false; - } - } - } - } - if (testreverse) { - i = currentLength - 1; - twistwait = 0; - } - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/SwapMapSort.java b/src/sorts/exchange/SwapMapSort.java deleted file mode 100644 index f6806a95..00000000 --- a/src/sorts/exchange/SwapMapSort.java +++ /dev/null @@ -1,72 +0,0 @@ -package sorts.exchange; - -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class SwapMapSort extends Sort { - public SwapMapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Swap Map"); - this.setRunAllSortsName("Swap Map Sort"); - this.setRunSortName("Swap Map Sort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - ArrayList map = new ArrayList<>(); - - while (true) { - for (int i = 0; i < sortLength - 1; i++) { - if (Reads.compareIndices(array, i, i + 1, 0.001, true) == 1) { - Writes.arrayListAdd(map, i); - Writes.mockWrite(map.size(), map.size() - 1, i, 0); - } - } - - if (map.size() == 0) { - break; - } - - for (int i = 0; i < map.size(); i++) { - Writes.swap(array, map.get(i), map.get(i) + 1, 0.01, true, false); - } - Writes.arrayListClear(map); - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/TernarySlowSort.java b/src/sorts/exchange/TernarySlowSort.java deleted file mode 100644 index 2d2f3eee..00000000 --- a/src/sorts/exchange/TernarySlowSort.java +++ /dev/null @@ -1,62 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author fungamer2 - * - */ -public final class TernarySlowSort extends Sort { - - public TernarySlowSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Ternary Slow"); - setRunAllSortsName("Ternary Slow Sort"); - setRunSortName("Ternary Slowsort"); - setCategory("Impractical Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(512); - setBogoSort(false); - - } - - private void compareSwap(int[] array, int start, int end, int sleep) { - if (this.Reads.compareValues(array[start], array[end]) == 1) { - this.Writes.swap(array, start, end, sleep, true, false); - } - this.Highlights.markArray(1, start); - this.Highlights.markArray(2, end); - this.Delays.sleep(sleep); - } - - public void ternarySlowSort(int[] array, int start, int end) { - if (end - start + 1 == 2) { - compareSwap(array, start, end, 1); - } else if (end - start + 1 > 2) { - int third = (end - start + 1) / 3; - int mid1 = start + third; - int mid2 = start + 2 * third; - - ternarySlowSort(array, start, mid1 - 1); - ternarySlowSort(array, mid1, mid2 - 1); - ternarySlowSort(array, mid2 - 1, end); - - compareSwap(array, mid1 - 1, end, 1); - compareSwap(array, mid1 - 1, mid2 - 1, 1); - compareSwap(array, mid2 - 1, end, 1); - - ternarySlowSort(array, start, end - 1); - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - ternarySlowSort(array, 0, sortLength - 1); - - } - -} diff --git a/src/sorts/exchange/TriSearchGnomeSort.java b/src/sorts/exchange/TriSearchGnomeSort.java deleted file mode 100644 index 23c072f5..00000000 --- a/src/sorts/exchange/TriSearchGnomeSort.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author thatsOven - for the TriSearch algorithm - * @author mingyue12 - for the rest of this sorting algorithm - * - */ -public final class TriSearchGnomeSort extends Sort { - - /** - * @param arrayVisualizer - */ - public TriSearchGnomeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("TriSearch Gnome"); - this.setRunAllSortsName("TriSearch Gnome Sort"); - this.setRunSortName("TriSearch Gnomesort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public int triSearch(int[] arr, int l, int h, int val, double sleep) { - int mid = l + ((h-l) / 2); - Highlights.markArray(0, l); - Highlights.markArray(1, h); - Highlights.markArray(2, mid); - Delays.sleep(sleep); - if (Reads.compareValues(val, arr[l]) < 0) { - return l; - } else { - if (Reads.compareValues(val, arr[h]) < 0) { - if (Reads.compareValues(val, arr[mid]) < 0) { - return this.triSearch(arr, l+1, mid-1, val, sleep); - } else { - return this.triSearch(arr, mid+1, h-1, val, sleep); - } - } else { - return h+1; - } - } - } - public void triGnomeSort(int[] array, int start, int end, double compSleep, double writeSleep) { - for (int i = start+1; i < end; i++) { - int num = array[i]; - int lo = start; - - lo = this.triSearch(array, start, i-1, num, compSleep); - Highlights.clearAllMarks(); - int j = i ; - while(j>lo) { - Writes.swap(array, j, j - 1, writeSleep, true, false); - j--; - } - Highlights.clearAllMarks(); - - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount){ - triGnomeSort(array, 0, length, 40, 1); - - } - -} diff --git a/src/sorts/exchange/WiggleSort.java b/src/sorts/exchange/WiggleSort.java deleted file mode 100644 index f0d374b8..00000000 --- a/src/sorts/exchange/WiggleSort.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * - */ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author McDude_73 - * @author aphitorite - * @author EilrahcF - * - */ -public final class WiggleSort extends Sort { - - /** - * @param arrayVisualizer - */ - public WiggleSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Wiggle"); - setRunAllSortsName("Wiggle Sort"); - setRunSortName("Wigglesort"); - setCategory("Exchange Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - private void wiggleSort(int[] array, int arrLen, int start, int end) { - if (end - start < 2) - return; - int leftPoint = start; - int rightPoint = end; - - int midPoint = (leftPoint + rightPoint) / 2; - - boolean startLeft = true; - int j = midPoint; - - for (int i = leftPoint; i < midPoint; i++) { - for (int k = midPoint; k < end; k++) { - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, j); - if (this.Reads.compareValues(array[i], array[j]) >= 0) { - this.Writes.swap(array, i, j, 1.0D, true, false); - } else { - this.Delays.sleep(0.025D); - } - - if (startLeft) { - j++; - } else { - j--; - } - - } - if (startLeft) { - j--; - startLeft = false; - } else { - - j++; - startLeft = true; - } - } - - wiggleSort(array, arrLen, start, midPoint); - wiggleSort(array, arrLen, midPoint, end); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) throws Exception { - wiggleSort(array, length, 0, length); - - } - -} diff --git a/src/sorts/exchange/XSort.java b/src/sorts/exchange/XSort.java deleted file mode 100644 index 706402a1..00000000 --- a/src/sorts/exchange/XSort.java +++ /dev/null @@ -1,66 +0,0 @@ -package sorts.exchange; -import main.ArrayVisualizer; -import sorts.templates.Sort; -/* - -PORTED TO ARRAYV BY PCBOYGAMES - ------------------------------- -- SORTING ALGORITHM MADHOUSE - ------------------------------- - -*/ -final public class XSort extends Sort { - public XSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("X Pattern"); - this.setRunAllSortsName("X Pattern Sort"); - this.setRunSortName("X Pattern Sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(false); - } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int gap = currentLength; - int sortbase = 1; - int i = 1; - int xleft = 1; - int xright = 1; - boolean anyswaps = false; - boolean testpass = false; - while (!testpass) { - anyswaps = false; - i = 1; - while ((i - 1) + gap <= currentLength) { - if (Reads.compareValues(array[i - 1], array[(i - 1) + gap]) > 0) { - Writes.swap(array, i - 1, (i - 1) + gap, 0.001, true, false); - anyswaps = true; - xleft = i + 1; - xright = i + gap - 1; - if (gap != 1) { - for (int r = 0; r < gap - 1; r++) { - if (Reads.compareValues(array[xleft - 1], array[xright - 1]) > 0) { - Writes.swap(array, xleft - 1, xright - 1, 0.001, true, false); - } - xleft++; - xright--; - } - } - } - i++; - } - if (gap == 1 && !anyswaps) { - testpass = true; - } else { - if (gap != 1 && !anyswaps) { - gap--; - } - } - } - } -} \ No newline at end of file diff --git a/src/sorts/exchange/ooPQuicksort.java b/src/sorts/exchange/ooPQuicksort.java deleted file mode 100644 index d4daa1aa..00000000 --- a/src/sorts/exchange/ooPQuicksort.java +++ /dev/null @@ -1,174 +0,0 @@ -package sorts.exchange; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class ooPQuicksort extends Sort { - - public ooPQuicksort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("OopsQuick"); - this.setRunAllSortsName("Out of Place Stable QuickSort (by Control)"); - this.setRunSortName("Out of Place Stable Quicksort"); - this.setCategory("Exchange Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - // Based on Ideas by Scandum and Control - private void ooPquickSort(int[] array, int[] swap, int start, int end, boolean forwards, boolean fromSwap) { - - int a = start; - int e = end; - int c = start + (end - start + 1) / 2; - int b = start + (c - start + 1) / 2; - int d = c + (end - c + 1) / 2; - int temp = 0; - - if (end - start > 10) { - if (array[a] > array[b]) { - temp = a; - a = b; - b = temp; - } - Highlights.markArray(1, a); - Highlights.markArray(2, b); - Delays.sleep(0.25); - if (array[c] > array[d]) { - temp = c; - c = d; - d = temp; - } - Highlights.markArray(1, c); - Highlights.markArray(2, d); - Delays.sleep(0.25); - if (array[b] > array[d]) { - temp = b; - b = d; - d = temp; - } - Highlights.markArray(1, b); - Highlights.markArray(2, d); - Delays.sleep(0.25); - if (array[a] > array[c]) { - temp = a; - a = c; - c = temp; - } - Highlights.markArray(1, a); - Highlights.markArray(2, c); - Delays.sleep(0.25); - if (array[c] > array[e]) { - temp = c; - c = e; - e = temp; - } - Highlights.markArray(1, c); - Highlights.markArray(2, e); - Delays.sleep(0.25); - if (array[b] > array[c]) { - temp = b; - b = c; - c = temp; - } - Highlights.markArray(1, b); - Highlights.markArray(2, c); - Delays.sleep(0.25); - } - - int pivotpos = array[c]; - Highlights.markArray(1, pivotpos); - - int pivot = array[pivotpos]; - - int leftswappointer = start; - Highlights.markArray(1, leftswappointer); - int rightswappointer = end; - Highlights.markArray(1, rightswappointer); - - Writes.visualClear(array, pivotpos); - - if (forwards) { - int pointer = start; - Highlights.markArray(1, pointer); - while ((leftswappointer < rightswappointer)) { - if (pointer == pivotpos) { - pointer++; - } - if (Reads.compareValues(array[pointer], pivot) < 0) { - Writes.write(swap, leftswappointer, array[pointer], 0.05, false, fromSwap); - leftswappointer++; - } else if (Reads.compareValues(array[pointer], pivot) > 0) { - Writes.write(swap, rightswappointer, array[pointer], 0.05, false, fromSwap); - rightswappointer--; - } else if (Reads.compareValues(pointer, pivotpos) < 0) { - Writes.write(swap, leftswappointer, array[pointer], 0.05, false, fromSwap); - leftswappointer++; - } else { - Writes.write(swap, rightswappointer, array[pointer], 0.05, false, fromSwap); - rightswappointer--; - } - Writes.visualClear(array, pointer); - pointer++; - Highlights.markArray(1, pointer); - Highlights.markArray(2, leftswappointer); - Highlights.markArray(3, rightswappointer); - Delays.sleep(0.25); - } - } else if (!forwards) { - int pointer = end; - Highlights.markArray(1, pointer); - while ((leftswappointer < rightswappointer)) { - if (pointer == pivotpos) { - pointer--; - } - if (Reads.compareValues(array[pointer], pivot) < 0) { - Writes.write(swap, leftswappointer, array[pointer], 0.05, false, fromSwap); - leftswappointer++; - } else if (Reads.compareValues(array[pointer], pivot) > 0) { - Writes.write(swap, rightswappointer, array[pointer], 0.05, false, fromSwap); - rightswappointer--; - } else if (Reads.compareValues(pointer, pivotpos) > 0) { - Writes.write(swap, leftswappointer, array[pointer], 0.05, false, fromSwap); - leftswappointer++; - } else { - Writes.write(swap, rightswappointer, array[pointer], 0.05, false, fromSwap); - rightswappointer--; - } - Writes.visualClear(array, pointer); - pointer--; - Highlights.markArray(1, pointer); - Highlights.markArray(2, leftswappointer); - Highlights.markArray(3, rightswappointer); - Delays.sleep(0.25); - } - } - - if (!fromSwap) { - Writes.write(array, rightswappointer, pivot, 0.05, true, false); - } else { - Writes.write(swap, rightswappointer, pivot, 0.05, true, false); - } - - // recursively calls itself - if (end - leftswappointer >= 1) { - ooPquickSort(swap, array, leftswappointer + 1, end, false, !fromSwap); - } - if (rightswappointer - start >= 1) { - ooPquickSort(swap, array, start, rightswappointer - 1, true, !fromSwap); - } - - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int[] swaparray = Writes.createExternalArray(currentLength); - this.ooPquickSort(array, swaparray, 0, currentLength - 1, true, false); - Writes.deleteExternalArray(swaparray); - } -} diff --git a/src/sorts/hybrid/BaseNMergeSort.java b/src/sorts/hybrid/BaseNMergeSort.java deleted file mode 100644 index a4abc867..00000000 --- a/src/sorts/hybrid/BaseNMergeSort.java +++ /dev/null @@ -1,220 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class BaseNMergeSort extends Sort { - int[] tmp; - - private InsertionSort insertSorter; - - public BaseNMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Base-N Merge"); - this.setRunAllSortsName("Base-N Merge Sort, 4 Bases"); - this.setRunSortName("Base-N Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(true); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - this.setQuestion("Enter the number of bases for this sort:", 4); - } - - private int[] copyStarts(int[] starts, int baseCount) { - int[] copy = new int[baseCount]; - Writes.changeAllocAmount(copy.length); - for (int i = 0; i < baseCount; i++) { - copy[i] = starts[i]; - Writes.write(copy, i, starts[i], 0, false, true); - } - return copy; - } - - private void highlightMerge(int[] starts, int[] copiedStarts, int end, int baseCount) { - for (int i = 0; i < baseCount; i++) { - int startEnd = i == baseCount - 1 ? end : starts[i + 1]; - if (copiedStarts[i] < startEnd) { - Highlights.markArray(i + 1, copiedStarts[i]); - } - else { - Highlights.clearMark(i + 1); - } - } - } - - private void merge(int[] array, int[] starts, int end, int baseCount) { - int[] copiedStarts = copyStarts(starts, baseCount); - - int length = end - starts[0]; - - for (int nxt = 0; nxt < length; nxt++) { - highlightMerge(starts, copiedStarts, end, baseCount); - int minValue = Integer.MAX_VALUE; - int minIndex = 0; - for (int i = 0; i < baseCount; i++) { - int startEnd = i == baseCount - 1 ? end : starts[i + 1]; - if (copiedStarts[i] >= startEnd) { - continue; - } - if (Reads.compareValues(array[copiedStarts[i]], minValue) == -1) { - minValue = array[copiedStarts[i]]; - minIndex = i; - } - } - Writes.write(tmp, nxt, minValue, 1, false, true); - Writes.write(copiedStarts, minIndex, copiedStarts[minIndex] + 1, 0, false, true); - } - Highlights.clearAllMarks(); - - for(int i = 0; i < length; i++){ - Writes.write(array, starts[0] + i, tmp[i], 1, true, false); - } - - Writes.changeAllocAmount(-copiedStarts.length); - } - - private void mergeRun(int[] array, int[] starts, int end, int baseCount) { - if (end - starts[0] < baseCount) { - insertSorter.customInsertSort(array, starts[0], end, 1, false); - Writes.deleteExternalArray(starts); - return; - } - - for (int i = 0; i < baseCount; i++) { - int[] subStarts = calculateStarts(starts[i], starts[1] - starts[0], baseCount); - int startEnd = i == baseCount - 1 ? end : starts[i + 1]; - mergeRun(array, subStarts, startEnd, baseCount); - } - - merge(array, starts, end, baseCount); - - Writes.changeAllocAmount(-starts.length); - } - - private int[] calculateStarts(int start, int length, int baseCount) { - int[] starts = new int[baseCount]; - Writes.changeAllocAmount(starts.length); - int size = length / baseCount; - int current = start; - - for (int i = 0; i < baseCount; i++) { - Writes.write(starts, i, current, 0, false, true); - current += size; - } - - return starts; - } - - private double logBase(int value, int base) { - double result; - Writes.startLap(); - result = Math.log(value) / Math.log(base); - Writes.stopLap(); - return result; - } - - // Copied from MergeSorting.java:52 - // Used for merging wrong powers - private void mergeBase2(int[] array, int start, int mid, int end) { - int length = end - start; - - int low = start; - int high = mid; - - for(int nxt = 0; nxt < length; nxt++){ - if(low >= mid && high >= end) break; - - Highlights.markArray(1, low); - Highlights.markArray(2, high); - - if(low < mid && high >= end){ - Highlights.clearMark(2); - Writes.write(tmp, nxt, array[low++], 1, false, true); - } - else if(low >= mid && high < end){ - Highlights.clearMark(1); - Writes.write(tmp, nxt, array[high++], 1, false, true); - } - else if(Reads.compareValues(array[low], array[high]) == -1){ - Writes.write(tmp, nxt, array[low++], 1, false, true); - } - else{ - Writes.write(tmp, nxt, array[high++], 1, false, true); - } - } - Highlights.clearMark(2); - - for(int i = 0; i < length; i++){ - Writes.write(array, start + i, tmp[i], 1, true, false); - } - } - - private void baseNMerge(int[] array, int length, int baseCount) { - boolean useBinary = false; - double logBaseCount = logBase(baseCount, 2); - if (Math.pow(2, logBaseCount) == Math.pow(2, (int)logBaseCount)) { - useBinary = true; - } - - int start = 0; - - int lengthBase = useBinary ? 2 : baseCount; - double logLength = logBase(length, lengthBase); - if (Math.pow(lengthBase, (int)logLength) < Math.pow(lengthBase, logLength)) { - start = (int)(length - Math.pow(lengthBase, (int)logLength)); - } - - int[] starts = calculateStarts(start, length - start, baseCount); - - mergeRun(array, starts, length, baseCount); - - if (start > 0) { - baseNMerge(array, start, baseCount); - mergeBase2(array, 0, start, length); - } - } - - @Override - public void runSort(int[] array, int length, int baseCount) throws Exception { - this.setRunAllSortsName("Base-N Merge Sort, " + baseCount + " Bases"); - - insertSorter = new InsertionSort(arrayVisualizer); - - tmp = Writes.createExternalArray(length); - - baseNMerge(array, length, baseCount); - - Writes.deleteExternalArray(tmp); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/BinaryPDMergeSort.java b/src/sorts/hybrid/BinaryPDMergeSort.java deleted file mode 100644 index 2022cd8d..00000000 --- a/src/sorts/hybrid/BinaryPDMergeSort.java +++ /dev/null @@ -1,93 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2021 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -public class BinaryPDMergeSort extends OptimizedPDMergeSort { - public BinaryPDMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Binary Pattern-Defeating Merge"); - this.setRunAllSortsName("Binary Pattern-Defeating Merge Sort"); - this.setRunSortName("Binary Pattern-Defeating Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int monoboundLeft(int[] array, int start, int end, int value) { - int top, mid; - - top = end - start; - - while (top > 1) { - mid = top / 2; - - if (Reads.compareValueIndex(array, value, end - mid, 0.5, true) <= 0) { - end -= mid; - } - top -= mid; - } - - if (Reads.compareValueIndex(array, value, end - 1, 0.5, true) <= 0) { - return end - 1; - } - return end; - } - - private int monoboundRight(int[] array, int start, int end, int value) { - int top, mid; - - top = end - start; - - while (top > 1) { - mid = top / 2; - - if (Reads.compareIndexValue(array, start + mid, value, 0.5, true) <= 0) { - start += mid; - } - top -= mid; - } - - if (Reads.compareIndexValue(array, start, value, 0.5, true) <= 0) { - return start + 1; - } - return start; - } - - protected void merge(int[] array, int start, int mid, int end) { - start = monoboundRight(array, start, mid, array[mid]); - if (start == mid) return; - end = monoboundLeft(array, mid, end, array[mid - 1]); - super.merge(array, start, mid, end); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/BlockSelectionMergeSort.java b/src/sorts/hybrid/BlockSelectionMergeSort.java deleted file mode 100644 index 4e883c6c..00000000 --- a/src/sorts/hybrid/BlockSelectionMergeSort.java +++ /dev/null @@ -1,130 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.merge.ReverseLazyStableSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class BlockSelectionMergeSort extends Sort { - private BinaryInsertionSort binaryInserter; - private ReverseLazyStableSort extraMerger; - - public BlockSelectionMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Block Selection Merge"); - this.setRunAllSortsName("Block Selection Merge Sort"); - this.setRunSortName("Block Selection Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public void swapBlocks(int[] array, int left, int right, int length, double sleep) { - for (int i = 0; i < length; i++) { - Writes.swap(array, left + i, right + i, sleep, true, false); - } - } - - public void blockSelection(int[] array, int start, int end, int blockSize, double compSleep, double writeSleep) { - for (int i = start; i < end - blockSize; i += blockSize) { - int lowestindex = i; - - for (int j = i + blockSize; j < end; j += blockSize) { - Highlights.markArray(2, j); - Delays.sleep(compSleep); - - if (Reads.compareValues(array[j], array[lowestindex]) == -1){ - lowestindex = j; - Highlights.markArray(1, lowestindex); - Delays.sleep(compSleep); - } - } - if (lowestindex > i) - swapBlocks(array, i, lowestindex, blockSize, writeSleep); - Delays.sleep(0.5); - } - } - - private void merge(int[] array, int start, int end) { - int blockSize = (end - start) / 16; - while (blockSize >= 4) { - blockSelection(array, start, end, blockSize, 0.01, 0.5); - blockSize /= 8; - } - binaryInserter.customBinaryInsert(array, start, end, 0.333); - } - - private void mergeRun(int[] array, int start, int mid, int end, int minSize) { - if(start == mid) return; - - if (end - start == minSize) { - binaryInserter.customBinaryInsert(array, start, end, 0.333); - return; - } - - mergeRun(array, start, (mid+start)/2, mid, minSize); - mergeRun(array, mid, (mid+end)/2, end, minSize); - - merge(array, start, end); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - binaryInserter = new BinaryInsertionSort(arrayVisualizer); - extraMerger = new ReverseLazyStableSort(arrayVisualizer); - - Writes.startLap(); - int minSize = (int)(Math.log(length) / Math.log(2)) / 3 + 2; - minSize = (int)Math.pow(2, minSize); - Writes.stopLap(); - if (length <= minSize) { - binaryInserter.customBinaryInsert(array, 0, length, 0.333); - return; - } - - Writes.startLap(); - int useLength = (int)Math.pow(2, Math.floor(Math.log(length) / Math.log(2))); - Writes.stopLap(); - - int start = length - useLength; - int end = length; - int mid = start + ((end - start) / 2); - - mergeRun(array, start, mid, end, minSize); - if (length > useLength) { - runSort(array, length - useLength, bucketCount); - extraMerger.merge(array, 0, length - useLength, end); - } - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/BubbleMergeSort.java b/src/sorts/hybrid/BubbleMergeSort.java deleted file mode 100644 index 6578ffa8..00000000 --- a/src/sorts/hybrid/BubbleMergeSort.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * - */ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.templates.Sort; -import sorts.templates.TimSorting; - -/** - * @author mingyue12 - * - */ -public class BubbleMergeSort extends Sort { - - /* - * TimSort cannot be simply written off as an abstract class, as it creates an instance of itself - * in order to track its state. Plus, it contains both instance and static methods, requiring even - * more refactoring, which would be just doing unnecessary busy work. Instead of what we've done for - * the rest of the algorithms, we'll favor composition over inheritance here and pass "util" objects - * to it. - */ - private TimSorting timSortInstance; - - /** - * @param arrayVisualizer - */ - public BubbleMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Bubble Merge"); - this.setRunAllSortsName("Bubble Merge Sort"); - this.setRunSortName("Bubble Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void bubbleSort(int[] a, int start, int end) { - for(int i = end - 1; i > start; i--) { - for (int j = start; j sortLength) { - bubbleSort(array, i, sortLength); - } - this.timSortInstance = new TimSorting(array, sortLength, this.arrayVisualizer); - TimSorting.sort(this.timSortInstance, array, sortLength); - } - - } - -} diff --git a/src/sorts/hybrid/BubblescanQuickSort.java b/src/sorts/hybrid/BubblescanQuickSort.java deleted file mode 100644 index 0707ac78..00000000 --- a/src/sorts/hybrid/BubblescanQuickSort.java +++ /dev/null @@ -1,101 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.select.MaxHeapSort; -import sorts.templates.Sort; - -/** - * - * @author aphitorite - * @author thatsOven - */ -public final class BubblescanQuickSort extends Sort { - - public BubblescanQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Bubblescan Quick"); - this.setRunAllSortsName("Bubblescan Quick Sort"); - this.setRunSortName("Bubblescan Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - private InsertionSort insertSorter; - private MaxHeapSort heapSorter; - - private int partition(int[] array, int a, int b, int val) { - int i = a, j = b - 1; - while (i <= j) { - while (this.Reads.compareValues(array[i], val) < 0) { - i++; - this.Highlights.markArray(1, i); - this.Delays.sleep(0.5D); - } - while (this.Reads.compareValues(array[j], val) > 0) { - j--; - this.Highlights.markArray(2, j); - this.Delays.sleep(0.5D); - } - - if (i <= j) this.Writes.swap(array, i++, j--, 1.0D, true, false); - - } - return i; - } - - private void sort(int[] array, int a, int b, int depthLimit) { - int end = b, length = b - a; - - while (length > 16) { - if (depthLimit == 0) { - this.heapSorter.customHeapSort(array, a, end, 1.0D); - - return; - } - double sum = 0.0D; - boolean swapped = false; - - for (int i = a + 1; i < end; i++) { - this.Highlights.markArray(1, i - 1); - this.Highlights.markArray(2, i); - this.Delays.sleep(0.25D); - - if (this.Reads.compareValues(array[i - 1], array[i]) == 1) { - this.Writes.swap(array, i - 1, i, 0.5D, false, false); - swapped = true; - } - - sum += array[i - 1]; - } - - if (!swapped) - return; - int p = partition(array, a, end - 1, (int)(sum / (length - 1))); - depthLimit--; - sort(array, p, end - 1, depthLimit); - - end = p; - length = end - a; - } - - this.Highlights.clearMark(2); - this.insertSorter.customInsertSort(array, a, end, 0.5D, false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - // TODO Auto-generated method stub - this.insertSorter = new InsertionSort(this.arrayVisualizer); - this.heapSorter = new MaxHeapSort(this.arrayVisualizer); - sort(array, 0, sortLength, 2 * (int)(Math.log(sortLength) / Math.log(2.0D))); - - - } - -} diff --git a/src/sorts/hybrid/BufferedBlockSelectionMergeSort.java b/src/sorts/hybrid/BufferedBlockSelectionMergeSort.java deleted file mode 100644 index ad465c61..00000000 --- a/src/sorts/hybrid/BufferedBlockSelectionMergeSort.java +++ /dev/null @@ -1,129 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.templates.Sort; -import sorts.insert.BinaryInsertionSort; -import java.util.Arrays; - -/* - * -MIT License - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class BufferedBlockSelectionMergeSort extends Sort { - public BufferedBlockSelectionMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Buffered Block Selection Merge"); - this.setRunAllSortsName("Buffered Block Selection Merge Sort"); - this.setRunSortName("Buffered Block Selection Merge Sort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int sqrt(int n) { - return (int)Math.sqrt(n-1)+1; - } - - private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); - } - - private boolean blockLesser(int[] array, int a, int b, int bLen) { - int cmp = Reads.compareValues(array[a], array[b]); - return cmp < 0 || (cmp == 0 && Reads.compareValues(array[a+bLen-1], array[b+bLen-1]) < 0); - } - private void mergeAboveBW(int[] array, int a1, int b1, int a, int b) { - int p = (b1--)+(b--)-a; - - while(b >= a && b1 >= a1) { - if(Reads.compareValues(array[b], array[b1]) >= 0) - Writes.swap(array, --p, b--, 1, true, false); - else - Writes.swap(array, --p, b1--, 1, true, false); - } - while(b >= a) Writes.swap(array, --p, b--, 1, true, false); - } - private void mergeBW(int[] array, int a, int m, int b, int p) { - int pLen = b-m; - this.multiSwap(array, m, p, pLen); - - int i = pLen-1, j = m-1, k = b-1; - - while(i >= 0 && j >= a) { - if(Reads.compareValues(array[p+i], array[j]) >= 0) - Writes.swap(array, k--, p+(i--), 1, true, false); - else - Writes.swap(array, k--, j--, 1, true, false); - } - while(i >= 0) Writes.swap(array, k--, p+(i--), 1, true, false); - } - private void inPlaceMergeUnstable(int[] array, int a, int m, int b) { - int bLen = this.sqrt(b-a), a1 = a+(m-a-1)%bLen+1, b1 = b-(b-m)%bLen; - - this.multiSwap(array, a1, this.blockLesser(array, m-bLen, b1-bLen, bLen) ? b1-bLen : m-bLen, bLen); - - for(a1 += bLen; a1 < b1; a1 += bLen) { - int min = a1; - - for(int i = a1+bLen; i < b1; i += bLen) - if(this.blockLesser(array, i, min, bLen)) min = i; - - if(min > a1) this.multiSwap(array, min, a1, bLen); - this.mergeAboveBW(array, a, a1-bLen, a1, a1+bLen); - } - this.mergeAboveBW(array, a, a1-bLen, a1, b); - - BinaryInsertionSort smallSort = new BinaryInsertionSort(this.arrayVisualizer); - smallSort.customBinaryInsert(array, b-bLen, b, 0.25); - - this.mergeBW(array, a+bLen, b-bLen, b, a); - smallSort.customBinaryInsert(array, a, a+bLen, 0.25); - } - - private void mergeSort(int[] array, int a, int b) { - if(b-a < 32) { - BinaryInsertionSort smallSort = new BinaryInsertionSort(this.arrayVisualizer); - smallSort.customBinaryInsert(array, a, b, 0.25); - - return; - } - int m = (a+b)/2; - - this.mergeSort(array, a, m); - this.mergeSort(array, m, b); - this.inPlaceMergeUnstable(array, a, m, b); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.mergeSort(array, 0, length); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/BufferedMergeSort.java b/src/sorts/hybrid/BufferedMergeSort.java deleted file mode 100644 index 10a62c99..00000000 --- a/src/sorts/hybrid/BufferedMergeSort.java +++ /dev/null @@ -1,149 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.merge.ReverseLazyStableSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class BufferedMergeSort extends Sort { - private BinaryInsertionSort binaryInserter; - private ReverseLazyStableSort finalMerger; - private BlockSelectionMergeSort blockSelector; - - public BufferedMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Buffered Merge"); - this.setRunAllSortsName("Buffered Merge Sort"); - this.setRunSortName("Buffered Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private static double log2(double value) { - return Math.log(value) / Math.log(2); - } - - private static int getBufferSize(int length) { - return (int)Math.pow(2, Math.ceil(log2((int)log2(length)))) * 2; - } - - private void mergeUnderBuffer(int[] array, int bufferSize, int start, int mid, int end) { - int bufferPointer = 0; - int left = start, right = mid; - - while (left < mid && right < end) { - if (Reads.compareIndices(array, left, right, 0, true) <= 0) { - Writes.swap(array, bufferPointer, left, 0.25, true, false); - left++; - } - else { - Writes.swap(array, bufferPointer, right, 0.25, true, false); - right++; - } - bufferPointer++; - } - - while (left < mid) { - Writes.swap(array, bufferPointer, left, 0.25, true, false); - left++; - bufferPointer++; - } - while (right < end) { - Writes.swap(array, bufferPointer, right, 0.25, true, false); - right++; - bufferPointer++; - } - - for (int i = 0; i < end - start; i++) { - Writes.swap(array, i, start + i, 0.5, true, false); - } - } - - private void mergeOverBuffer(int[] array, int bufferSize, int start, int mid, int end) { - int blockSize = bufferSize / 2; - blockSelector.blockSelection(array, start, end, blockSize, 0.025, 1); - - int checkStart = start; - while (checkStart < end - blockSize) { - if (Reads.compareIndices(array, checkStart + blockSize - 1, checkStart + blockSize, 1, true) == 1) { - mergeUnderBuffer(array, bufferSize, checkStart, checkStart + blockSize, checkStart + bufferSize); - } - checkStart += blockSize; - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - binaryInserter = new BinaryInsertionSort(arrayVisualizer); - finalMerger = new ReverseLazyStableSort(arrayVisualizer); - blockSelector = new BlockSelectionMergeSort(arrayVisualizer); - - int bufferSize = BufferedMergeSort.getBufferSize(sortLength); - int length = sortLength - ((sortLength - bufferSize) % (bufferSize / 2)); - if (bufferSize * 2 >= length) { - binaryInserter.customBinaryInsert(array, 0, sortLength, 0.333); - return; - } - - for (int i = bufferSize; i < length - 1; i += 2) { - if (Reads.compareIndices(array, i, i + 1, 0.5, true) == 1) { - Writes.swap(array, i, i + 1, 0.5, true, false); - } - } - - for (int gap = 4; gap <= bufferSize; gap *= 2) { - for (int i = bufferSize; i + gap <= length; i += gap) { - mergeUnderBuffer(array, bufferSize, i, i + gap / 2, i + gap); - } - } - - for (int gap = bufferSize * 2; gap / 2 <= length; gap *= 2) { - int i; - for (i = bufferSize; i + gap <= length; i += gap) { - mergeOverBuffer(array, bufferSize, i, i + gap / 2, i + gap); - } - if (i + gap > length) { - mergeOverBuffer(array, bufferSize, i, i + gap / 2, length); - } - } - - runSort(array, bufferSize, bucketCount); - finalMerger.merge(array, 0, bufferSize, length); - if (sortLength - length > 0) { - binaryInserter.customBinaryInsert(array, length, sortLength, 0.333); - finalMerger.merge(array, 0, length, sortLength); - } - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/ImprovedWeaveMergeSort.java b/src/sorts/hybrid/ImprovedWeaveMergeSort.java deleted file mode 100644 index 670e8c7c..00000000 --- a/src/sorts/hybrid/ImprovedWeaveMergeSort.java +++ /dev/null @@ -1,88 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.templates.Sort; -import sorts.insert.InsertionSort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class ImprovedWeaveMergeSort extends Sort { - public ImprovedWeaveMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Improved Weave Merge"); - this.setRunAllSortsName("Improved Weave Merge Sort"); - this.setRunSortName("Improved Weave Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private InsertionSort sort; - - public static int getMaxBit(int n) { - int i; - for(i = 0; (1 << i) <= n; i++); - return i - 1; - } - - //will fail for b-a < 2 - private void weaveMerge(int[] array, int a, int b) { - int n = b-a, m = (n+1)/2; - - for(int j = 1<<(getMaxBit(n-1)-1); j >= 1; j >>= 1) { - int s = m > j ? 1 : 0; - for(int i = a+m+(1-s)*(j<<1); i+j <= b; i += j<<2) - for(int k = 0; k < j; k++) - Writes.swap(array, i-j+k, i+k, 1, true, false); - m -= s*j; - } - - Highlights.clearMark(2); - this.sort.customInsertSort(array, a, b, 0.2, false); - } - - private void weaveMergeSort(int[] array, int a, int b) { - if(b-a > 2) { - int m = a+(b-a+1)/2; - this.weaveMergeSort(array, a, m); - if(b-a > 3) - this.weaveMergeSort(array, m, b); - } - this.weaveMerge(array, a, b); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.sort = new InsertionSort(this.arrayVisualizer); - this.weaveMergeSort(array, 0, currentLength); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/IntroPseudoHeapSort.java b/src/sorts/hybrid/IntroPseudoHeapSort.java deleted file mode 100644 index e275cd88..00000000 --- a/src/sorts/hybrid/IntroPseudoHeapSort.java +++ /dev/null @@ -1,76 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; - -/** - * @author mingyue12 - * - */ -public final class IntroPseudoHeapSort extends Sort { - - - public IntroPseudoHeapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Iterative Intro Pseudo-Heap"); - setRunAllSortsName("Iterative Introspective Pseudo-Heap Sort"); - setRunSortName("Iterative Introspective Pseudo-Heapsort"); - setCategory("Hybrid Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - private boolean sift_down(int[] array, int start, int length, int root) { - boolean swapped = false; - int j = root; - while (2 * j < length) { - int k = 2 * j; - if (k < length && this.Reads.compareValues(array[start + k - 1], array[start + k]) == 1) { - k++; - } - if (this.Reads.compareIndices(array, start + j - 1, start + k - 1, 1.0D, true) == 1) { - this.Writes.swap(array, start + j - 1, start + k - 1, 1.0D, true, false); - j = k; - swapped = true; - continue; - } - break; - } - return swapped; - } - - private boolean sift(int[] array, int start, int end) { - return sift_down(array, start, end - start + 1, 1); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int threshold = 0, n = 1; - for(; n < length; n*=2, threshold++); - - threshold /= 2; - int iterations = 0; - boolean swapped = true; - while (swapped) { - swapped = false; - iterations++; - if(iterations >= threshold) { - InsertionSort ins = new InsertionSort(arrayVisualizer); - ins.customInsertSort(array, 0, length, 0.5, false); - break; - } - for (int i = length - 2; i >= 0; i--) { - if (sift(array, i, length)) - swapped = true; - } - } - - } - -} diff --git a/src/sorts/hybrid/LAQuickSort.java b/src/sorts/hybrid/LAQuickSort.java deleted file mode 100644 index 3cfbd564..00000000 --- a/src/sorts/hybrid/LAQuickSort.java +++ /dev/null @@ -1,182 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.UnstableInsertionSort; -import sorts.select.PoplarHeapSort; -import sorts.templates.Sort; - -/* -Logarithmic Average QuickSort 2020 Copyright (C) thatsOven -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -final public class LAQuickSort extends Sort { - PoplarHeapSort heapSorter; - UnstableInsertionSort insertSorter; - - public LAQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Logarithmic Average Quick"); - this.setRunAllSortsName("Logarithmic Average QuickSort"); - this.setRunSortName("Logarithmic Average QuickSort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public int partition(int[] array, int a, int b, int p) { - int i = a - 1; - int j = b; - Highlights.markArray(3, p); - - while(true) { - i++; - while(i < b && Reads.compareIndices(array, i, p, 0, false) == -1) { - Highlights.markArray(1, i); - Delays.sleep(0.25); - i++; - } - j--; - while(j >= a && Reads.compareIndices(array, j, p, 0, false) == 1) { - Highlights.markArray(2, j); - Delays.sleep(0.25); - j--; - } - if(i < j) Writes.swap(array, i, j, 1, true, false); - else return j; - } - } - - public int ghostPartition(int[] array, int a, int b, int val) { - int i = a; - int j = b - 1; - while (i <= j) { - while (Reads.compareValues(array[i], val) < 0) { - i++; - } - while (Reads.compareValues(array[j], val) > 0) { - j--; - } - if (i <= j) { - Writes.swap(array, i++, j--, 1, true, false); - } - } - Highlights.clearAllMarks(); - return i; - } - - public int log2(int N) { - int result = (int)(Math.log(N) / Math.log(2)); - return result; - } - - private void medianOfThree(int[] array, int a, int b) { - int m = a+(b-1-a)/2; - - if(Reads.compareIndices(array, a, m, 1, true) == 1) - Writes.swap(array, a, m, 1, true, false); - - if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { - Writes.swap(array, m, b-1, 1, true, false); - - if(Reads.compareIndices(array, a, m, 1, true) == 1) - return; - } - - Writes.swap(array, a, m, 1, true, false); - } - - public int logarithmicAverage(int[] arr, int low, int high) { - int sum = 0; - int counter = 0; - int qta = this.log2(high-low); - if (2 > qta) { - qta = 2; - } - for (int i = low; i < high; i += ((high-low) / qta)) { - Highlights.markArray(0, i); - Delays.sleep(1); - sum += arr[i]; - counter++; - } - Highlights.clearAllMarks(); - sum = sum / counter; - return sum; - } - - public boolean getSortedRuns(int[] array, int start, int end) { - Highlights.clearAllMarks(); - boolean reverseSorted = true; - boolean sorted = true; - int comp; - - for (int i = start; i < end-1; i++) { - comp = Reads.compareIndices(array, i, i+1, 0.5, true); - if (comp > 0) sorted = false; - else reverseSorted = false; - if ((!reverseSorted) && (!sorted)) return false; - } - - if (reverseSorted && !sorted) { - Writes.reversal(array, start, end-1, 1, true, false); - sorted = true; - } - - return sorted; - } - - public void quickSort(int[] arr, int low, int high, int depthLimit, int backPivot, boolean logAvg, int equalPivotCount) { - if (this.getSortedRuns(arr, low, high)) return; - if (high-low > 16) { - int pi = low, pivot = low; - if (!logAvg) { - this.medianOfThree(arr, low, high); - pi = this.partition(arr, low, high, low); - int left = pi-low; - int right = high-(pi+1); - if ((left == 0 || right == 0) || (left/right >= 16 || right/left >= 16)) logAvg = true; - else { - Writes.swap(arr, low, pi, 1, true, false); - pivot = arr[pi]; - } - } - if (logAvg) { - pivot = this.logarithmicAverage(arr, low, high); - pi = this.ghostPartition(arr, low, high, pivot); - } - if (backPivot == pivot) equalPivotCount++; - if (depthLimit == 0 || equalPivotCount > 4){ - if (equalPivotCount > 4) equalPivotCount = 0; - heapSorter.heapSort(arr, low, high); - return; - } - depthLimit--; - this.quickSort(arr, low, pi, depthLimit, pivot, logAvg, equalPivotCount); - this.quickSort(arr, pi+(logAvg ? 0 : 1), high, depthLimit, pivot, logAvg, equalPivotCount); - } else { - insertSorter.unstableInsertionSort(arr, low, high); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - heapSorter = new PoplarHeapSort(arrayVisualizer); - insertSorter = new UnstableInsertionSort(arrayVisualizer); - - this.quickSort(array, 0, currentLength, 2*log2(currentLength), array[1], false, 0); - } -} diff --git a/src/sorts/hybrid/LazierSort.java b/src/sorts/hybrid/LazierSort.java deleted file mode 100644 index fd26e3d5..00000000 --- a/src/sorts/hybrid/LazierSort.java +++ /dev/null @@ -1,380 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.select.MaxHeapSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class LazierSort extends Sort { - public LazierSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Lazier Stable"); - this.setRunAllSortsName("Lazier Stable Sort"); - this.setRunSortName("Lazier Sort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private static int cbrt(int n) { - int r = 1; - for(; r*r*r < n; r++); - return r; - } - - private void shift(int[] array, int a, int m, int b) { - while(m < b) Writes.swap(array, a++, m++, 1, true, false); - } - - private void shiftBW(int[] array, int a, int m, int b) { - while(m > a) Writes.swap(array, --b, --m, 1, true, false); - } - - private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); - } - - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; - - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); - b -= r; - m -= r; - l -= r; - } - else { - this.multiSwap(array, a, m, l); - a += l; - m += l; - r -= l; - } - } - } - - private void insertTo(int[] array, int a, int b) { - Highlights.clearMark(2); - int temp = array[a]; - while(a > b) Writes.write(array, a, array[(a--)-1], 0.5, true, false); - Writes.write(array, b, temp, 0.5, true, false); - } - - private int leftBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) <= 0) - b = m; - else - a = m+1; - } - - return a; - } - - private int rightBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) < 0) - b = m; - else - a = m+1; - } - - return a; - } - - private int leftExpSearch(int[] array, int a, int b, int val) { - int i = 1; - while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) > 0) i *= 2; - - return this.leftBinSearch(array, a+i/2, Math.min(b, a-1+i), val); - } - - private int findKeys(int[] array, int a, int b, int n) { - int nKeys = 1, p = a, pEnd = a+nKeys; - - Highlights.clearMark(2); - for(int i = pEnd; i < b && nKeys < n; i++) { - Highlights.markArray(1, i); - Delays.sleep(1); - int loc = this.leftBinSearch(array, p, pEnd, array[i]); - - if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { - this.rotate(array, p, pEnd, i); - int inc = i-pEnd; - loc += inc; - p += inc; - pEnd += inc; - - this.insertTo(array, pEnd, loc); - nKeys++; - pEnd++; - } - } - this.rotate(array, a, p, pEnd); - return nKeys; - } - - private void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) - this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); - } - - public void inPlaceMerge(int[] array, int a, int m, int b) { - int i = a, j = m, k; - - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) > 0) { - k = this.leftExpSearch(array, j+1, b, array[i]); - this.rotate(array, i, j, k); - - i += k-j; - j = k; - } - else i++; - } - } - - private void lazierBlockMerge(int[] array, int a, int m, int b, int bLen) { - while(m-bLen >= a) { - this.inPlaceMerge(array, m-bLen, m, b); - m -= bLen; - } - this.inPlaceMerge(array, a, m, b); - } - - private void inPlaceMergeSort(int[] array, int a, int b) { - int len = b-a, i, j; - - for(j = len; j >= 32; j = (j+1)/2); - - for(i = a; i+j <= b; i += j) - this.binaryInsertion(array, i, i+j); - this.binaryInsertion(array, i, b); - - for(; j < len; j *= 2) { - for(i = a; i + 2*j <= b; i += 2*j) - this.inPlaceMerge(array, i, i+j, i+2*j); - - if(i + j < b) - this.inPlaceMerge(array, i, i+j, b); - } - } - - private void lazierBlockMergeSort(int[] array, int a, int b, int keys) { - int a1 = a+keys, b1 = b, - len = b-a1, i, j; - - for(j = len; j >= 32; j = (j+1)/2); - - //insertion - for(i = a1; i+j <= b; i += j) - this.binaryInsertion(array, i, i+j); - this.binaryInsertion(array, i, b); - - //build blocks - if(keys >= 2*j) { - for(i = a1; i+2*j <= b; i += 2*j) - this.mergeTo(array, i, i+j, i+2*j, i-2*j); - - if(i+j < b) this.mergeTo(array, i, i+j, b, i-2*j); - else this.shift(array, i-2*j, i, b); - - j *= 2; - a1 -= j; - b1 -= j; - - while(a1-j >= a) { - for(i = a1; i+2*j <= b1; i += 2*j) - this.mergeTo(array, i, i+j, i+2*j, i-j); - - if(i+j < b1) this.mergeTo(array, i, i+j, b1, i-j); - else this.shift(array, i-j, i, b1); - - a1 -= j; - b1 -= j; - j *= 2; - } - - for(i = a1; i+2*j <= b1; i += 2*j); - if(i+j < b1) this.mergeToBW(array, i, i+j, b1, b); - else this.shiftBW(array, i, b1, b); - - for(; i > a1; i -= 2*j) this.mergeToBW(array, i-2*j, i-j, i, i+j); - - a1 += j; - j *= 2; - } - - int c = 1; - for(; j < len; j *= 2) { - while((c*c*c)/(2*j) < (2*j)) c++; - - for(i = a1; i + 2*j <= b; i += 2*j) - this.lazierBlockMerge(array, i, i+j, i+2*j, c); - - if(i + j < b) - this.lazierBlockMerge(array, i, i+j, b, c); - } - - //redist buffer - MaxHeapSort heapSort = new MaxHeapSort(this.arrayVisualizer); - heapSort.customHeapSort(array, a, a1, 1); - this.inPlaceMerge(array, a, a1, b); - } - - private void mergeTo(int[] array, int a, int m, int b, int p) { - int i = a, j = m; - - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) <= 0) - Writes.swap(array, p++, i++, 1, true, false); - - else Writes.swap(array, p++, j++, 1, true, false); - } - if(p < i) while(i < m) Writes.swap(array, p++, i++, 1, true, false); - while(j < b) Writes.swap(array, p++, j++, 1, true, false); - } - - private void mergeToBW(int[] array, int a, int m, int b, int p) { - int i = m-1, j = b-1; p--; - - while(i >= a && j >= m) { - if(Reads.compareValues(array[i], array[j]) > 0) - Writes.swap(array, p--, i--, 1, true, false); - - else Writes.swap(array, p--, j--, 1, true, false); - } - if(p > j) while(j >= m) Writes.swap(array, p--, j--, 1, true, false); - while(i >= a) Writes.swap(array, p--, i--, 1, true, false); - } - - private void mergeFW(int[] array, int a, int p, int m, int b) { - int i = a, j = m, k = p; - - while(j < b) { - while(i < p && Reads.compareValues(array[i], array[j]) <= 0) - Writes.swap(array, k++, i++, 1, true, false); - if(i == p) return; - - int n = this.leftExpSearch(array, j+1, b, array[i]); - while(j < n) Writes.swap(array, k++, j++, 1, true, false); - } - while(i < p) Writes.swap(array, k++, i++, 1, true, false); - } - - protected void lazierSort(int[] array, int a, int b) { - int len = b-a; - - //build blocks dies when length is too small (< 65) - if(len <= 64) { - this.binaryInsertion(array, a, b); - return; - } - - int bLen, mRun; - for(bLen = 1; (bLen*bLen*bLen)/len < len; bLen *= 2); - for(mRun = 1; (mRun*mRun*mRun)/len < len; mRun++); - - mRun = (16*mRun) / bLen; - bLen = (bLen*mRun) / 16; - - int keys = this.findKeys(array, a, b, bLen); - - if(keys < bLen) { - if(keys == 1) return; - else if(keys <= cbrt(len)) this.inPlaceMergeSort(array, a, b); - else this.lazierBlockMergeSort(array, a, b, keys); - return; - } - - int a1 = a+bLen, b1 = b, i, j = mRun; - - //insertion - for(i = a1; i+j <= b; i += j) - this.binaryInsertion(array, i, i+j); - this.binaryInsertion(array, i, b); - - //build blocks - for(i = a1; i+2*j <= b; i += 2*j) - this.mergeTo(array, i, i+j, i+2*j, i-2*j); - - if(i+j < b) this.mergeTo(array, i, i+j, b, i-2*j); - else this.shift(array, i-2*j, i, b); - - j *= 2; - a1 -= j; - b1 -= j; - - while(a1 > a) { - for(i = a1; i+2*j <= b1; i += 2*j) - this.mergeTo(array, i, i+j, i+2*j, i-j); - - if(i+j < b1) this.mergeTo(array, i, i+j, b1, i-j); - else this.shift(array, i-j, i, b1); - - a1 -= j; - b1 -= j; - j *= 2; - } - - //do that merge thing - for(i = a; i+bLen < b1; i += bLen); - this.shiftBW(array, i, b1, b); - - b1 = i+bLen; - i -= bLen; - - while(i >= a) { - this.mergeFW(array, i, i+bLen, b1, b); - - i -= bLen; - b1 -= bLen; - } - - //redist buffer - a1 = a+bLen; - MaxHeapSort heapSort = new MaxHeapSort(this.arrayVisualizer); - heapSort.customHeapSort(array, a, a1, 1); - this.inPlaceMerge(array, a, a1, b); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.lazierSort(array, 0, currentLength); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/MedianOfSixteenAdaptiveQuickSort.java b/src/sorts/hybrid/MedianOfSixteenAdaptiveQuickSort.java deleted file mode 100644 index f491dda9..00000000 --- a/src/sorts/hybrid/MedianOfSixteenAdaptiveQuickSort.java +++ /dev/null @@ -1,217 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.UnstableInsertionSort; -import sorts.select.MaxHeapSort; -import sorts.templates.Sort; - -/* -Copyright (c) 2020-2021 thatsOven -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -*/ - -final public class MedianOfSixteenAdaptiveQuickSort extends Sort { - MaxHeapSort heapSorter; - UnstableInsertionSort insertSorter; - - public MedianOfSixteenAdaptiveQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Median-of-16 Adaptive Quick"); - this.setRunAllSortsName("Median-Of-16 Adaptive QuickSort"); - this.setRunSortName("Median-Of-16 Adaptive QuickSort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - int[] medianOfSixteenSwaps = new int[] { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 1, 3, 5, 7, 9, 11, 13, 15, 2, 4, 6, 8, 10, 12, 14, 16, - 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16, - 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, - 6, 11, 7, 10, 4, 13, 14, 15, 8, 12, 2, 3, 5, 9, - 2, 5, 8, 14, 3, 9, 12, 15, 6, 7, 10, 11, - 3, 5, 12, 14, 4, 9, 8, 13, - 7, 9, 11, 13, 4, 6, 8, 10, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 7, 8, 9, 10 - }; - - int incs[] = {48, 21, 7, 3, 1}; - - public int log2(int N) { - int result = (int)(Math.log(N) / Math.log(2)); - return result; - } - - private void shellSort(int[] array, int lo, int hi) { - Highlights.clearAllMarks(); - - for (int k = 0; k < this.incs.length; k++) { - for (int h = this.incs[k], i = h + lo; i < hi; i++) - { - int v = array[i]; - int j = i; - - while (j >= h + lo && Reads.compareValues(array[j-h], v) == 1) - { - Highlights.markArray(1, j); - - Writes.write(array, j, array[j - h], 1, true, false); - j -= h; - } - Writes.write(array, j, v, 0.5, true, false); - } - } - Highlights.clearAllMarks(); - } - - public int partition(int[] array, int a, int b, int p) { - int i = a - 1; - int j = b; - Highlights.markArray(3, p); - - while(true) { - i++; - while(i < b && Reads.compareIndices(array, i, p, 0, false) == -1) { - Highlights.markArray(1, i); - Delays.sleep(0.25); - i++; - } - j--; - while(j >= a && Reads.compareIndices(array, j, p, 0, false) == 1) { - Highlights.markArray(2, j); - Delays.sleep(0.25); - j--; - } - if(i < j) Writes.swap(array, i, j, 1, true, false); - else return j; - } - } - - private void medianOfThree(int[] array, int a, int b) { - int m = a+(b-1-a)/2; - - if(Reads.compareIndices(array, a, m, 1, true) == 1) - Writes.swap(array, a, m, 1, true, false); - - if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { - Writes.swap(array, m, b-1, 1, true, false); - - if(Reads.compareIndices(array, a, m, 1, true) == 1) - return; - } - - Writes.swap(array, a, m, 1, true, false); - } - - private void compNSwap(int[] array, int a, int b, int gap, int start) { - if (Reads.compareIndices(array, start+(a*gap), start+(b*gap), 2, true) > 0) { - Writes.swap(array, start+(a*gap), start+(b*gap), 2, true, false); - } - } - - private void medianOfSixteen(int[] array, int a, int b) { - int gap = (b - 1 - a) / 16; - - for (int i = 0; i < this.medianOfSixteenSwaps.length; i += 2) - this.compNSwap(array, this.medianOfSixteenSwaps[i], this.medianOfSixteenSwaps[i+1], gap, a); - - Writes.swap(array, a, a + (8 * gap), 1, true, false); - } - - public boolean getSortedRuns(int[] array, int a, int b) { - Highlights.clearAllMarks(); - boolean reverseSorted = true; - boolean sorted = true; - int comp; - - for (int i = a; i < b-1; i++) { - comp = Reads.compareIndices(array, i, i+1, 0.5, true); - if (comp > 0) sorted = false; - else reverseSorted = false; - if ((!reverseSorted) && (!sorted)) return false; - } - - if (reverseSorted && !sorted) { - Writes.reversal(array, a, b-1, 1, true, false); - sorted = true; - } - - return sorted; - } - - public void quickSort(int[] array, int a, int b, int depth, boolean unbalanced) { - while (b - a > 32) { - if (this.getSortedRuns(array, a, b)) return; - if (depth == 0){ - heapSorter.customHeapSort(array, a, b, 1); - return; - } - - int p; - if (!unbalanced) { - this.medianOfThree(array, a, b); - p = this.partition(array, a, b, a); - } else p = a; - - int left = p - a; - int right = b - (p + 1); - if ((left == 0 || right == 0) || (left/right >= 16 || right/left >= 16) || unbalanced) { - if (b - a > 80) { - Writes.swap(array, a, p, 1, true, false); - if (left < right) { - this.quickSort(array, a, p, depth - 1, true); - a = p; - } else { - this.quickSort(array, p + 1, b, depth - 1, true); - b = p; - } - this.medianOfSixteen(array, a, b); - p = this.partition(array, a + 1, b, a); - } else { - this.shellSort(array, a, b); - return; - } - } - - Writes.swap(array, a, p, 1, true, false); - - depth--; - - this.quickSort(array, p+1, b, depth, false); - b = p; - } - insertSorter.unstableInsertionSort(array, a, b); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - heapSorter = new MaxHeapSort(arrayVisualizer); - insertSorter = new UnstableInsertionSort(arrayVisualizer); - - this.quickSort(array, 0, currentLength, 2*log2(currentLength), false); - } -} diff --git a/src/sorts/hybrid/OOPBufferedMergeSort.java b/src/sorts/hybrid/OOPBufferedMergeSort.java deleted file mode 100644 index bdec3962..00000000 --- a/src/sorts/hybrid/OOPBufferedMergeSort.java +++ /dev/null @@ -1,195 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.merge.ReverseLazyStableSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class OOPBufferedMergeSort extends Sort { - private BinaryInsertionSort binaryInserter; - private ReverseLazyStableSort finalMerger; - - private int[] buffer; - - public OOPBufferedMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Out-of-Place Buffered Merge"); - this.setRunAllSortsName("Out-of-Place Buffered Merge Sort"); - this.setRunSortName("Out-of-Place Buffered Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private static double log2(double value) { - return Math.log(value) / Math.log(2); - } - - private static int getBufferSize(int length) { - return (int)Math.pow(2, Math.ceil(log2((int)log2(length)))) * 2; - } - - private void mergeUnderBuffer(int[] array, int bufferSize, int start, int mid, int end) { - int bufferPointer = 0; - int left = start, right = mid; - - while (left < mid && right < end) { - if (Reads.compareIndices(array, left, right, 0, true) <= 0) { - Highlights.markArray(2, left); - Writes.write(this.buffer, bufferPointer, array[left], 0.25, true, true); - left++; - } - else { - Highlights.markArray(2, right); - Writes.write(this.buffer, bufferPointer, array[right], 0.25, true, true); - right++; - } - bufferPointer++; - } - - while (left < mid) { - Highlights.markArray(2, left); - Writes.write(this.buffer, bufferPointer, array[left], 0.25, true, true); - left++; - bufferPointer++; - } - while (right < end) { - Highlights.markArray(2, right); - Writes.write(this.buffer, bufferPointer, array[right], 0.25, true, true); - right++; - bufferPointer++; - } - - for (int i = 0; i < end - start; i++) { - Highlights.markArray(2, i); - Writes.write(array, start + i, this.buffer[i], 0.5, true, false); - } - } - - private void blockCopy(int array[], int start, int end) { - int blockSize = end - start; - for (int i = end - 1; i >= start; i--) { - Writes.write(array, i, array[i - blockSize], 0.125, true, false); - } - } - - private void blockCopyFromBuffer(int array[], int start, int end) { - for (int i = end - 1; i >= start; i--) { - Highlights.markArray(2, i - start); - Writes.write(array, i, buffer[i - start], 0.125, true, false); - } - Highlights.clearMark(2); - } - - private void blockInsertionSort(int[] array, int start, int mid, int end, int blockSize) { - for (int i = mid; i < end; i += blockSize) { - int key = array[i]; - int j = i - blockSize; - - if (Reads.compareValues(key, array[j]) >= 0) { - continue; - } - - for (int k = i; k < i + blockSize; k++) { - Highlights.markArray(2, k); - Writes.write(buffer, k - i, array[k], 0.5, true, true); - } - Highlights.clearMark(2); - - blockCopy(array, j + blockSize, j + 2 * blockSize); - j -= blockSize; - - while (j >= start && Reads.compareValues(key, array[j]) < 0) { - blockCopy(array, j + blockSize, j + 2 * blockSize); - j -= blockSize; - } - blockCopyFromBuffer(array, j + blockSize, j + 2 * blockSize); - } - } - - private void mergeOverBuffer(int[] array, int bufferSize, int start, int mid, int end) { - int blockSize = bufferSize / 2; - blockInsertionSort(array, start, mid, end, blockSize); - - int checkStart = start; - while (checkStart < end - blockSize) { - if (Reads.compareIndices(array, checkStart + blockSize - 1, checkStart + blockSize, 1, true) == 1) { - mergeUnderBuffer(array, bufferSize, checkStart, checkStart + blockSize, checkStart + bufferSize); - } - checkStart += blockSize; - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - binaryInserter = new BinaryInsertionSort(arrayVisualizer); - finalMerger = new ReverseLazyStableSort(arrayVisualizer); - - int bufferSize = OOPBufferedMergeSort.getBufferSize(sortLength); - int length = sortLength - ((sortLength - bufferSize) % (bufferSize / 2)); - if (bufferSize * 2 >= length) { - binaryInserter.customBinaryInsert(array, 0, sortLength, 0.333); - return; - } - this.buffer = Writes.createExternalArray(bufferSize); - - for (int i = 0; i < length - 1; i += 2) { - if (Reads.compareIndices(array, i, i + 1, 0.5, true) == 1) { - Writes.swap(array, i, i + 1, 0.5, true, false); - } - } - - for (int gap = 4; gap <= bufferSize; gap *= 2) { - for (int i = 0; i + gap <= length; i += gap) { - mergeUnderBuffer(array, bufferSize, i, i + gap / 2, i + gap); - } - } - - for (int gap = bufferSize * 2; gap / 2 <= length; gap *= 2) { - int i; - for (i = 0; i + gap <= length; i += gap) { - mergeOverBuffer(array, bufferSize, i, i + gap / 2, i + gap); - } - if (i + gap > length) { - mergeOverBuffer(array, bufferSize, i, i + gap / 2, length); - } - } - - if (sortLength - length > 0) { - binaryInserter.customBinaryInsert(array, length, sortLength, 0.333); - finalMerger.merge(array, 0, length, sortLength); - } - Writes.deleteExternalArray(this.buffer); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/OptimizedPDMergeSort.java b/src/sorts/hybrid/OptimizedPDMergeSort.java deleted file mode 100644 index 7a29c09a..00000000 --- a/src/sorts/hybrid/OptimizedPDMergeSort.java +++ /dev/null @@ -1,122 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.merge.PDMergeSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2021 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -public class OptimizedPDMergeSort extends PDMergeSort { - final static int MIN_RUN_SIZE = 16; - - public OptimizedPDMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Optimized Pattern-Defeating Merge"); - this.setRunAllSortsName("Optimized Pattern-Defeating Merge Sort"); - this.setRunSortName("Optimized Pattern-Defeating Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void insertSort(int[] array, int start, int mid, int end) { - int pos; - int cur; - for (int i = mid; i < end; i++) { - cur = array[i]; - pos = i - 1; - while (pos >= start && Reads.compareValues(array[pos], cur) > 0) { - Writes.write(array, pos + 1, array[pos], 0.5, true, false); - pos--; - } - Writes.write(array, pos + 1, cur, 0.5, true, false); - } - } - - protected int identifyRun(int[] array, int index, int maxIndex) { - int startIndex = index; - - Highlights.markArray(1, index); - if (index >= maxIndex) { - return -1; - } - - boolean cmp = compare(array[index], array[index + 1]); - index++; - Highlights.markArray(1, index); - - while (index < maxIndex) { - Delays.sleep(1); - boolean checkCmp = compare(array[index], array[index + 1]); - if (checkCmp != cmp) { - break; - } - index++; - Highlights.markArray(1, index); - } - Delays.sleep(1); - - if (!cmp) { - // arrayVisualizer.setHeading("PDMerge -- Reversing Run"); - Writes.reversal(array, startIndex, index, 1, true, false); - Highlights.clearMark(2); - // arrayVisualizer.setHeading("PDMerge -- Finding Runs"); - } - int length = index - startIndex + 1; - if (length < MIN_RUN_SIZE) { - int end = startIndex + MIN_RUN_SIZE; - if (end > maxIndex + 1) { - end = maxIndex + 1; - } - insertSort(array, startIndex, index + 1, end); - return end > maxIndex ? -1 : end; - } - if (index >= maxIndex) { - return -1; - } - return index + 1; - } - - protected int[] findRuns(int[] array, int maxIndex) { - int[] runs = Writes.createExternalArray(maxIndex / MIN_RUN_SIZE + 2); - runCount = 0; - - int lastRun = 0; - while (lastRun != -1) { - Writes.write(runs, runCount++, lastRun, 0.5, true, true); - int newRun = identifyRun(array, lastRun, maxIndex); - lastRun = newRun; - } - - return runs; - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/PDLaziestSort.java b/src/sorts/hybrid/PDLaziestSort.java deleted file mode 100644 index 5b952202..00000000 --- a/src/sorts/hybrid/PDLaziestSort.java +++ /dev/null @@ -1,112 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.templates.Sort; -import utils.IndexedRotations; - -/** - * @author Yuri-chan2007 - * - */ -public final class PDLaziestSort extends Sort { - - public PDLaziestSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Pattern-Defeating Laziest Stable"); - this.setRunAllSortsName("Pattern-Defeating Laziest Stable Sort"); - this.setRunSortName("Pattern-Defeating Laziest Sort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { - int i = a + 1; - if(Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { - while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; - Writes.reversal(array, a, i - 1, sleep, true, auxwrite); - } - else while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; - - Highlights.clearMark(2); - - while(i < b) { - int current = array[i]; - int pos = i - 1; - while(pos >= a && Reads.compareValues(array[pos], current) > 0){ - Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); - pos--; - } - Writes.write(array, pos + 1, current, sleep, true, auxwrite); - - i++; - } - } - - private void rotate(int[] array, int a, int m, int b) { - IndexedRotations.cycleReverse(array, a, m, b, 1.0, true, false); - } - - private int leftBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; - - if(Reads.compareValues(val, array[m]) <= 0) - b = m; - else - a = m+1; - } - - return a; - } - - private int leftExpSearch(int[] array, int a, int b, int val) { - int i = 1; - while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) > 0) i *= 2; - - return this.leftBinSearch(array, a+i/2, Math.min(b, a-1+i), val); - } - - private void inPlaceMerge(int[] array, int a, int m, int b) { - int i = a, j = m, k; - - while(i < j && j < b){ - if(Reads.compareValues(array[i], array[j]) == 1) { - k = this.leftExpSearch(array, j+1, b, array[i]); - this.rotate(array, i, j, k); - - i += k-j; - j = k; - } - else i++; - } - } - - protected void laziestStableSort(int[] array, int start, int end) { - int len = end - start; - if(len <= 16) { - insertionSort(array, start, end, 0.5, false); - return; - } - int i, blockLen = Math.max(16, (int)Math.sqrt(len)); - for(i = start; i+2*blockLen < end; i+=blockLen) { - insertionSort(array, i, i + blockLen, 0.5, false); - } - insertionSort(array, i, end, 0.5, false); - while(i-blockLen >= start) { - this.inPlaceMerge(array, i-blockLen, i, end); - i-=blockLen; - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - this.laziestStableSort(array, 0, sortLength); - - } - -} diff --git a/src/sorts/hybrid/PairwiseCircleSort.java b/src/sorts/hybrid/PairwiseCircleSort.java deleted file mode 100644 index 0b0ee13b..00000000 --- a/src/sorts/hybrid/PairwiseCircleSort.java +++ /dev/null @@ -1,90 +0,0 @@ -package sorts.hybrid; - -import sorts.templates.Sort; -import sorts.insert.InsertionSort; - -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2020 yuji - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class PairwiseCircleSort extends Sort { - public PairwiseCircleSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Pairwise-Circle"); - this.setRunAllSortsName("Pairwise-Circle Sort"); - this.setRunSortName("Pairwise-Circle Sort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void pairs(int[] array, int left, int right, int gap) { - if(left+gap >= right) return; - int a = left; - while(a + gap <= right) { - if(Reads.compareIndices(array, a, a+gap, 1, true) == 1) { - Writes.swap(array, a, a+gap, 1, true, false); - } - a += gap*2; - } - this.pairs(array, left, right, gap*2); - this.pairs(array, left+gap, right, gap*2); - } - - private void circle(int[] array, int left, int right) { - int a = left; - int b = right; - while(a < b) { - if(Reads.compareIndices(array, a, b, 1, true) == 1) { - Writes.swap(array, a, b, 1, true, false); - } - a++; - b--; - } - } - - private void pairCircle(int[] array, int left, int right) { - if(left >= right) return; - int mid = (left + right) / 2; - this.pairs(array, left, right, 1); - this.circle(array, left, right); - this.pairCircle(array, left, mid); - this.pairCircle(array, mid+1, right); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.pairCircle(array, 0, length-1); - InsertionSort sort = new InsertionSort(this.arrayVisualizer); - sort.customInsertSort(array, 0, length, 0.1, false); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/PlasmaSort.java b/src/sorts/hybrid/PlasmaSort.java deleted file mode 100644 index 32ae0129..00000000 --- a/src/sorts/hybrid/PlasmaSort.java +++ /dev/null @@ -1,305 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.insert.InsertionSort; -import sorts.merge.ReverseLazyStableSort; -import sorts.templates.Sort; -import utils.Highlights; -import utils.Rotations; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class PlasmaSort extends Sort { - int[] keys; - - private InsertionSort insertSorter; - private LazierSort finalMerger; - - public PlasmaSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Plasma"); - this.setRunAllSortsName("Plasma Sort"); - this.setRunSortName("Plasmasort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void rotate(int[] array, int pos, int lenA, int lenB) { - Rotations.holyGriesMills(array, pos, lenA, lenB, 1, true, false); - } - - private int collectKeys(int[] array, int start, int keyCount, int end) { - int minbound = start; - int compindex = start + 1; - int lastGood = compindex; - int badCount = 0; - int count; - for (count = 1; count < keyCount - start; count++) { - Highlights.markArray(3, compindex); - int num = array[compindex]; - int l = minbound, h = lastGood; - int lastBad = badCount; - - while (l < h) { - int m = l + ((h - l) / 2); // avoid int overflow! - Highlights.markArray(2, m); - - Delays.sleep(0.01); - - int comp = Reads.compareValues(num, array[m]); - - if (comp < 0) { - h = m; - } - else if (comp == 0) { - badCount++; - break; - } - else { - l = m + 1; - } - } - - if (badCount > 0) { - if (badCount > lastBad) { - Delays.sleep(0.2); - count--; - compindex++; - if (compindex >= end) { - break; - } - continue; - } - rotate(array, minbound, lastGood - minbound, badCount); - minbound += badCount; - lastGood = compindex; - l += badCount; - badCount = 0; - } - - // item has to go into position lo - int j = compindex - 1; - - while (j >= l) - { - Writes.write(array, j + 1, array[j], 1, true, false); - j--; - } - Writes.write(array, l, num, 1, true, false); - - Highlights.clearAllMarks(); - compindex++; - lastGood++; - - if (compindex >= end) { - break; - } - } - - Highlights.clearMark(4); - if (minbound != start) { - rotate(array, start, minbound - start, count); - } - return count; - } - - private static int getBufferSize(int length) { - int size; - for (size = 1; size * size < length; size *= 2); - return size; - } - - private static int getKeySize(int bufferSize, int length) { - return length / bufferSize; - } - - private void mergeUnderBuffer(int[] array, int bufferSize, int start, int mid, int end, boolean rightPriority) { - if (rightPriority) { - rotate(array, start, mid - start, end - mid); - } - for (int i = 0; i < mid - start; i++) { - Writes.swap(array, i, start + i, 0.5, true, false); - } - - int bufferPointer = 0; - int left = start, right = mid; - - while (left < right && right < end) { - if (Reads.compareIndices(array, bufferPointer, right, 0.1, true) <= 0) { - Writes.swap(array, bufferPointer++, left++, 0.25, true, false); - } - else { - Writes.swap(array, left++, right++, 0.25, true, false); - } - } - - while (left < right) { - Writes.swap(array, bufferPointer++, left++, 0.25, true, false); - } - } - - public void blockSwap(int[] array, int a, int b, int len) { - for (int i = 0; i < len; i++) { - Writes.swap(array, a + i, b + i, 1, true, false); - } - } - - // public void blockSelection(int[] array, int start, int end, int blockSize) { - // for (int i = start; i < end - blockSize; i += blockSize) { - // int lowestindex = i; - // int lowestkey = (lowestindex - start) / blockSize; - - // for (int j = i + blockSize; j < end; j += blockSize) { - // int jkey = (j - start) / blockSize; - // Highlights.markArray(2, j); - // Delays.sleep(0.5); - - // int comp = Reads.compareValues(array[j], array[lowestindex]); - // if (comp == -1 || (comp == 0 && Reads.compareOriginalIndices(keys, jkey, lowestkey, 0.25, true) == -1)) { - // lowestindex = j; - // lowestkey = jkey; - // Highlights.markArray(1, lowestindex); - // Delays.sleep(0.5); - // } - // } - // if (lowestindex > i) { - // blockSwap(array, i, lowestindex, blockSize); - // Writes.swap(keys, (i - start) / blockSize, lowestkey, 1, true, true); - // } - // } - // } - - private void mergeOverBuffer(int[] array, int bufferSize, int start, int mid, int end, int keySize) { - resetKeys(keySize); - int midKey = keys[keySize / 2]; - int blockSize = bufferSize; - // blockSelection(array, start, end, blockSize); - - int i; - for (i = start; i < end - blockSize; i += blockSize) { - int ikey = (i - start) / blockSize; - int lowestindex = i; - int lowestkey = ikey; - - for (int j = i + blockSize; j < end; j += blockSize) { - int jkey = (j - start) / blockSize; - Highlights.markArray(2, j); - Delays.sleep(0.5); - - int comp = Reads.compareValues(array[j], array[lowestindex]); - if (comp == -1 || (comp == 0 && Reads.compareOriginalIndices(keys, jkey, lowestkey, 0.25, true) == -1)) { - lowestindex = j; - lowestkey = jkey; - Highlights.markArray(1, lowestindex); - Delays.sleep(0.5); - } - } - if (lowestindex > i) { - blockSwap(array, i, lowestindex, blockSize); - Writes.swap(keys, (i - start) / blockSize, lowestkey, 1, true, true); - } - if (ikey > 0) { - if (Reads.compareIndices(array, i - 1, i, 0.5, true) > 0) { - int keyIndex = (i - start) / blockSize; - mergeUnderBuffer(array, bufferSize, i - blockSize, i, i + blockSize, keys[keyIndex - 1] > midKey && keys[keyIndex - 1] > keys[keyIndex]); - } - } - } - int keyIndex = keySize - 1; - mergeUnderBuffer(array, bufferSize, i - blockSize, i, i + blockSize, keys[keyIndex - 1] > midKey && keys[keyIndex - 1] > keys[keyIndex]); - - // int checkStart = start; - // while (checkStart < end - blockSize) { - // if (Reads.compareIndices(array, checkStart + blockSize - 1, checkStart + blockSize, 1, true) == 1) { - // int keyIndex = (checkStart - start) / blockSize; - // // int keyIndex2 = (checkStart + blockSize - start) / blockSize; - // // Highlights.markArray(1, keyIndex); - // mergeUnderBuffer(array, bufferSize, checkStart, checkStart + blockSize, checkStart + 2 * blockSize, Reads.compareOriginalValues(keys[keyIndex], keys[keyIndex + 1]) == 1); - // } - // checkStart += blockSize; - // } - } - - private void resetKeys(int count) { - for (int i = 0; i < count; i++) { - Writes.write(keys, i, i, 0.5, true, true); - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - insertSorter = new InsertionSort(arrayVisualizer); - finalMerger = new LazierSort(arrayVisualizer); - - if (sortLength < 24) { - insertSorter.customInsertSort(array, 0, sortLength, 0.333, false); - return; - } - int bufferSize = PlasmaSort.getBufferSize(sortLength); - collectKeys(array, 0, bufferSize, sortLength); - - int i; - for (i = bufferSize + 1; i < sortLength; i += 2) { - if (Reads.compareIndices(array, i - 1, i, 0.5, true) == 1) { - Writes.swap(array, i - 1, i, 0.5, true, false); - } - } - - int gap; - for (gap = 2; gap < bufferSize * 2; gap *= 2) { - for (i = bufferSize; i + 2 * gap <= sortLength; i += 2 * gap) { - mergeUnderBuffer(array, bufferSize, i, i + gap, i + 2 * gap, false); - } - if (i + gap < sortLength) { - mergeUnderBuffer(array, bufferSize, i, i + gap, sortLength, false); - } - } - - int keyCount = PlasmaSort.getKeySize(bufferSize, sortLength); - keys = Writes.createExternalArray(keyCount); - for (; gap <= sortLength - bufferSize; gap *= 2) { - int keySize = 2 * gap / bufferSize; - for (i = bufferSize; i + 2 * gap <= sortLength; i += 2 * gap) { - mergeOverBuffer(array, bufferSize, i, i + gap, i + 2 * gap, keySize); - } - if (i + gap < sortLength) { - mergeOverBuffer(array, bufferSize, i, i + gap, sortLength, keySize); - } - } - - Writes.deleteExternalArray(keys); - // runSort(array, bufferSize, bucketCount); - // finalMerger.inPlaceMerge(array, 0, bufferSize, sortLength); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/QuarterMergeSort.java b/src/sorts/hybrid/QuarterMergeSort.java deleted file mode 100644 index a6bfedae..00000000 --- a/src/sorts/hybrid/QuarterMergeSort.java +++ /dev/null @@ -1,140 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.merge.BlockSwapMergeSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class QuarterMergeSort extends Sort { - private BinaryInsertionSort binaryInserter; - private BlockSwapMergeSort finalMerger; - - public QuarterMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Quarter Merge"); - this.setRunAllSortsName("Quarter Merge Sort"); - this.setRunSortName("Quarter Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void blockSwap(int[] array, int a, int b, int size) { - for (int i = 0; i < size; i++) { - Writes.swap(array, a + i, b + i, 1, true, false); - } - } - - private void merge(int[] array, int bufferSize, int start, int mid, int end) { - blockSwap(array, 0, start, mid - start); - - int bufferPointer = 0; - int left = start, right = mid; - - while (left < right && right < end) { - if (Reads.compareIndices(array, bufferPointer, right, 0.5, true) <= 0) { - Writes.swap(array, bufferPointer++, left++, 0.5, true, false); - } - else { - Writes.swap(array, left++, right++, 0.5, true, false); - } - } - - while (left < right) { - Writes.swap(array, bufferPointer++, left++, 0.5, true, false); - } - } - - private int pow2lte(int value) { - int val; - for (val = 1; val <= value; val <<= 1); - return val >> 1; - } - - public void quarterMergeSort(int[] array, int length) { - if (finalMerger == null) { - binaryInserter = new BinaryInsertionSort(arrayVisualizer); - finalMerger = new BlockSwapMergeSort(arrayVisualizer); - } - - if (length <= 32) { - binaryInserter.customBinaryInsert(array, 0, length, 0.333); - return; - } - int quarterSize = length / 4; - int useLength = quarterSize * 4; - - for (int i = quarterSize; i < useLength - 1; i += 2) { - if (Reads.compareIndices(array, i, i + 1, 0.5, true) == 1) { - Writes.swap(array, i, i + 1, 0.5, true, false); - } - } - - int subStart, subEnd = useLength, subLength = useLength - quarterSize; - int gap; - for (int parlen = subLength; parlen >= 2; parlen = subEnd - quarterSize) { - subLength = pow2lte(parlen); - subStart = subEnd - subLength; - - for (gap = 4; gap <= subLength; gap *= 2) { - for (int i = subStart; i + gap <= subEnd; i += gap) { - merge(array, quarterSize, i, i + gap / 2, i + gap); - } - } - if (parlen != useLength - quarterSize) { - merge(array, quarterSize, subStart, subEnd, useLength); - } - subEnd = subStart; - } - - int extra = length - useLength; - if (extra > 0) { - if (extra > 1 && Reads.compareIndices(array, length - 2, length - 1, 0.5, true) == 1) { - Writes.swap(array, length - 2, length - 1, 0.5, true, false); - } - finalMerger.multiSwapMerge(array, quarterSize, useLength, length); - } - - quarterMergeSort(array, quarterSize); - finalMerger.multiSwapMerge(array, 0, quarterSize, length); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - binaryInserter = new BinaryInsertionSort(arrayVisualizer); - finalMerger = new BlockSwapMergeSort(arrayVisualizer); - - this.quarterMergeSort(array, sortLength); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/QuickSPSort.java b/src/sorts/hybrid/QuickSPSort.java deleted file mode 100644 index 0162b1f7..00000000 --- a/src/sorts/hybrid/QuickSPSort.java +++ /dev/null @@ -1,73 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.templates.GrailSorting; - -final public class QuickSPSort extends GrailSorting { - public QuickSPSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Quick Sandpaper"); - this.setRunAllSortsName("Quick Sandpaper Sort"); - this.setRunSortName("Quick Sandpapersort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void compSwap(int[] array, int a, int b) { - a--; b--; - if (Reads.compareIndices(array, a, b, 0.0125, true) > 0) { - Writes.swap(array, a, b, 0.0125, true, false); - } - } - - private void ipMerge(int[] array, int a, int m, int b) { - int len1 = m - a, len2 = b - m; - this.grailMergeWithoutBuffer(array, a, len1, len2); - } - - private void quickSPSort2(int[] array, int l, int r) { - if (r - l < 12) { - for (int i = l; i <= r; i++) { - for (int j = i; j <= r; j++) { - compSwap(array, i, j); - } - } - } - else { - int rb, min, j; - rb = l + (int)Math.ceil(Math.sqrt(1 + (r - l))); - for (int i = l; i <= rb; i++) { - for (j = i; j <= r; j++) { - compSwap(array, i, j); - } - } - min = array[rb]; - Highlights.markArray(2, rb); - j = 1 + rb; - for (int i = 1 + rb; i <= r; i++) { - Highlights.markArray(1, i - 1); - Delays.sleep(0.0125); - if (Reads.compareValues(array[i - 1], min) < 0) { - min = array[i - 1]; - Highlights.markArray(2, i - 1); - j++; - Writes.swap(array, i - 1, j - 1, 0.125, true, false); - } - } - Writes.reversal(array, rb, j - 1, 1, true, false); - quickSPSort2(array, 1 + j, r); - ipMerge(array, rb, j, r); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - quickSPSort2(array, 1, currentLength); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/SimpleHybridQuickSort.java b/src/sorts/hybrid/SimpleHybridQuickSort.java deleted file mode 100644 index 4d4ae86f..00000000 --- a/src/sorts/hybrid/SimpleHybridQuickSort.java +++ /dev/null @@ -1,118 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.select.PoplarHeapSort; -import sorts.templates.Sort; - -/** - * @author Yuri-chan2007 - * - */ -public final class SimpleHybridQuickSort extends Sort { - - public SimpleHybridQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Simple Hybrid Quick"); - this.setRunAllSortsName("Simple Hybrid Quick Sort"); - this.setRunSortName("Simple Hybrid Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - PoplarHeapSort heapSorter; - InsertionSort insertSorter; - - private int medianOfThree(int[] array, int a, int m, int b) { - if (Reads.compareValues(array[m], array[a]) > 0) { - if (Reads.compareValues(array[m], array[b]) < 0) - return m; - - if (Reads.compareValues(array[a], array[b]) > 0) - return a; - - else - return b; - } else { - if (Reads.compareValues(array[m], array[b]) > 0) - return m; - - if (Reads.compareValues(array[a], array[b]) < 0) - return a; - - else - return b; - } - } - - private int ninther(int[] array, int a, int b) { - int s = (b - a) / 9; - - int a1 = this.medianOfThree(array, a, a + s, a + 2 * s); - int m1 = this.medianOfThree(array, a + 3 * s, a + 4 * s, a + 5 * s); - int b1 = this.medianOfThree(array, a + 6 * s, a + 7 * s, a + 8 * s); - - return this.medianOfThree(array, a1, m1, b1); - } - - private int medianOfThreeNinthers(int[] array, int a, int b) { - int s = (b - a + 2) / 3; - - int a1 = this.ninther(array, a, a + s); - int m1 = this.ninther(array, a + s, a + 2 * s); - int b1 = this.ninther(array, a + 2 * s, b); - - return this.medianOfThree(array, a1, m1, b1); - } - - private int partition(int[] array, int a, int b, int val) { - int i = a, j = b; - while (i <= j) { - while (this.Reads.compareValues(array[i], val) < 0) { - i++; - this.Highlights.markArray(1, i); - this.Delays.sleep(0.5D); - } - while (this.Reads.compareValues(array[j], val) > 0) { - j--; - this.Highlights.markArray(2, j); - this.Delays.sleep(0.5D); - } - - if (i <= j) - this.Writes.swap(array, i++, j--, 1.0D, true, false); - - } - return i; - } - - private void sort(int[] array, int a, int b, int depthLimit) { - while (b - a > 16) { - if (depthLimit == 0) { - heapSorter.heapSort(array, a, b); - return; - } - int piv = medianOfThreeNinthers(array, a, b - 1); - int p = partition(array, a, b - 1, array[piv]); - depthLimit--; - sort(array, p, b, depthLimit); - b = p; - } - - insertSorter.customInsertSort(array, a, b, 0.5D, false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - insertSorter = new InsertionSort(this.arrayVisualizer); - heapSorter = new PoplarHeapSort(arrayVisualizer); - sort(array, 0, sortLength, 2 * (int) (Math.log(sortLength) / Math.log(2.0D))); - - } - -} diff --git a/src/sorts/hybrid/StableQuarterMergeSort.java b/src/sorts/hybrid/StableQuarterMergeSort.java deleted file mode 100644 index 0650e019..00000000 --- a/src/sorts/hybrid/StableQuarterMergeSort.java +++ /dev/null @@ -1,145 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.merge.BlockSwapMergeSort; -import sorts.merge.ReverseLazyStableSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class StableQuarterMergeSort extends Sort { - ReverseLazyStableSort rotater; - QuarterMergeSort sort; - BlockSwapMergeSort fallbackSort; - - public StableQuarterMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stable Quarter Merge"); - this.setRunAllSortsName("Stable Quarter Merge Sort"); - this.setRunSortName("Stable Quarter Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(true); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int ejectDuplicates(int[] array, int start, int mid, int end) { - int minbound = start; - int compindex = start + 1; - int lastGood = compindex; - int badCount = 0; - int count; - for (count = 1; count < mid - start; count++) { - Highlights.markArray(4, compindex); - int num = array[compindex]; - int l = minbound, h = lastGood; - int lastBad = badCount; - - while (l < h) { - int m = l + ((h - l) / 2); // avoid int overflow! - Highlights.markArray(1, l); - Highlights.markArray(2, m); - Highlights.markArray(3, h); - - Delays.sleep(0.01); - - int comp = Reads.compareValues(num, array[m]); - - if (comp < 0) { - h = m; - } - else if (comp == 0) { - badCount++; - break; - } - else { - l = m + 1; - } - } - - Highlights.clearMark(3); - - if (badCount > 0) { - if (badCount > lastBad) { - Delays.sleep(0.2); - count--; - compindex++; - if (compindex >= end) { - break; - } - continue; - } - rotater.rotateCommon(array, lastGood, minbound, badCount, 0.1, false); - minbound += badCount; - lastGood = compindex; - l += badCount; - badCount = 0; - } - - // item has to go into position lo - int j = compindex - 1; - - while (j >= l) - { - Writes.write(array, j + 1, array[j], 0.1, true, false); - j--; - } - Writes.write(array, l, num, 0.1, true, false); - - Highlights.clearAllMarks(); - compindex++; - lastGood++; - - if (compindex >= end) { - break; - } - } - - Highlights.clearMark(4); - if (minbound != start) { - rotater.rotateSmart(array, minbound, start, count); - } - return count; - } - - @Override - public void runSort(int[] array, int length, int baseCount) throws Exception { - rotater = new ReverseLazyStableSort(arrayVisualizer); - sort = new QuarterMergeSort(arrayVisualizer); - fallbackSort = new BlockSwapMergeSort(arrayVisualizer); - - int required = length / 4; - if (ejectDuplicates(array, 0, required, length) < required) - fallbackSort.multiSwapMergeSort(array, 0, length); - else - sort.quarterMergeSort(array, length); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/StacklessTimSort.java b/src/sorts/hybrid/StacklessTimSort.java deleted file mode 100644 index 397c8088..00000000 --- a/src/sorts/hybrid/StacklessTimSort.java +++ /dev/null @@ -1,306 +0,0 @@ -package sorts.hybrid; - -import sorts.insert.BinaryInsertionSort; -import sorts.templates.Sort; -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class StacklessTimSort extends Sort { - public StacklessTimSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stackless Tim"); - this.setRunAllSortsName("Stackless Tim Sort"); - this.setRunSortName("Stackless Timsort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private final int M = 7; - - private int highlight = 0; - - private int leftBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; - Highlights.markArray(2, this.highlight+m); - Delays.sleep(0.5); - - if(Reads.compareValues(val, array[m]) <= 0) - b = m; - else - a = m+1; - } - - return a; - } - - private int rightBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; - Highlights.markArray(2, this.highlight+m); - Delays.sleep(0.5); - - if(Reads.compareValues(val, array[m]) < 0) - b = m; - else - a = m+1; - } - - return a; - } - - private int leftExpSearch(int[] array, int a, int b, int val) { - int i = 1; - while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) > 0) i *= 2; - - return this.leftBinSearch(array, a+i/2, Math.min(b, a-1+i), val); - } - - private int rightExpSearch(int[] array, int a, int b, int val) { - int i = 1; - while(b-i >= a && Reads.compareValues(val, array[b-i]) < 0) i *= 2; - - return this.rightBinSearch(array, Math.max(a, b-i+1), b-i/2, val); - } - - private int leftBoundSearch(int[] array, int a, int b, int val) { - int i = 1; - while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) >= 0) i *= 2; - - return this.rightBinSearch(array, a+i/2, Math.min(b, a-1+i), val); - } - - private int rightBoundSearch(int[] array, int a, int b, int val) { - int i = 1; - while(b-i >= a && Reads.compareValues(val, array[b-i]) <= 0) i *= 2; - - return this.leftBinSearch(array, Math.max(a, b-i+1), b-i/2, val); - } - - private void insertTo(int[] array, int a, int b) { - Highlights.clearMark(2); - - if(a > b) { - int temp = array[a]; - - do Writes.write(array, a, array[--a], 0.25, true, false); - while(a > b); - - Writes.write(array, b, temp, 0.25, true, false); - } - } - - private void buildRuns(int[] array, int a, int b, int mRun) { - int i = a+1, j = a; - - while(i < b) { - if(Reads.compareIndices(array, i-1, i++, 1, true) == 1) { - while(i < b && Reads.compareIndices(array, i-1, i, 1, true) == 1) i++; - Writes.reversal(array, j, i-1, 1, true, false); - } - else while(i < b && Reads.compareIndices(array, i-1, i, 1, true) <= 0) i++; - - if(i < b) j = i - (i-j-1)%mRun - 1; - - while(i-j < mRun && i < b) { - this.insertTo(array, i, this.rightBinSearch(array, j, i, array[i])); - i++; - } - j = i++; - } - } - - //galloping mode code refactored from TimSorting.java - private void mergeFW(int[] array, int[] tmp, int a, int m, int b) { - int len1 = m-a, t = a; - Highlights.clearMark(2); - Writes.arraycopy(array, a, tmp, 0, len1, 1, true, true); - - int i = 0, mGallop = M, l = 0, r = 0; - - while(true) { - do { - if(Reads.compareValues(tmp[i], array[m]) <= 0) { - Writes.write(array, a++, tmp[i++], 1, true, false); - l++; - r = 0; - - if(i == len1) return; - } - else { - Highlights.markArray(2, m); - Writes.write(array, a++, array[m++], 1, true, false); - r++; - l = 0; - - if(m == b) { - while(i < len1) Writes.write(array, a++, tmp[i++], 1, true, false); - return; - } - } - } - while((l | r) < mGallop); - - do { - l = this.leftExpSearch(array, m, b, tmp[i])-m; - - for(int j = 0; j < l; j++) - Writes.write(array, a++, array[m++], 1, true, false); - Writes.write(array, a++, tmp[i++], 1, true, false); - - if(i == len1) return; - - else if(m == b) { - while(i < len1) Writes.write(array, a++, tmp[i++], 1, true, false); - return; - } - - this.highlight = t; - r = this.leftBoundSearch(tmp, i, len1, array[m])-i; - this.highlight = 0; - - for(int j = 0; j < r; j++) - Writes.write(array, a++, tmp[i++], 1, true, false); - Writes.write(array, a++, array[m++], 1, true, false); - - if(i == len1) return; - - else if(m == b) { - while(i < len1) Writes.write(array, a++, tmp[i++], 1, true, false); - return; - } - - mGallop--; - } - while((l | r) >= M); - - if(mGallop < 0) mGallop = 0; - mGallop += 2; - } - } - private void mergeBW(int[] array, int[] tmp, int a, int m, int b) { - int len2 = b-m, t = a; - Highlights.clearMark(2); - Writes.arraycopy(array, m, tmp, 0, len2, 1, true, true); - - int i = len2-1, mGallop = M, l = 0, r = 0; - m--; - - while(true) { - do { - if(Reads.compareValues(tmp[i], array[m]) >= 0) { - Writes.write(array, --b, tmp[i--], 1, true, false); - l++; - r = 0; - - if(i < 0) return; - } - else { - Highlights.markArray(2, m); - Writes.write(array, --b, array[m--], 1, true, false); - r++; - l = 0; - - if(m < a) { - while(i >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); - return; - } - } - } - while((l | r) < mGallop); - - do { - l = (m+1)-this.rightExpSearch(array, a, m+1, tmp[i]); - - for(int j = 0; j < l; j++) - Writes.write(array, --b, array[m--], 1, true, false); - Writes.write(array, --b, tmp[i--], 1, true, false); - - if(i < 0) return; - - else if(m < a) { - while(i >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); - return; - } - - this.highlight = t; - r = (i+1)-this.rightBoundSearch(tmp, 0, i+1, array[m]); - this.highlight = 0; - - for(int j = 0; j < r; j++) - Writes.write(array, --b, tmp[i--], 1, true, false); - Writes.write(array, --b, array[m--], 1, true, false); - - if(i < 0) return; - - else if(m < a) { - while(i >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); - return; - } - } - while((l | r) >= M); - - if(mGallop < 0) mGallop = 0; - mGallop += 2; - } - } - - private void smartMerge(int[] array, int[] tmp, int a, int m, int b) { - if(Reads.compareValues(array[m-1], array[m]) <= 0) return; - - a = this.leftBoundSearch(array, a, m, array[m]); - b = this.rightBoundSearch(array, m, b, array[m-1]); - - if(b-m < m-a) this.mergeBW(array, tmp, a, m, b); - else this.mergeFW(array, tmp, a, m, b); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int[] tmp = Writes.createExternalArray(length/2); - - int mRun = length; - for(; mRun >= 32; mRun = (mRun+1)/2); - - this.buildRuns(array, 0, length, mRun); - - for(int i, j = mRun; j < length; j *= 2) { - for(i = 0; i+2*j <= length; i += 2*j) - this.smartMerge(array, tmp, i, i+j, i+2*j); - - if(i+j < length) this.smartMerge(array, tmp, i, i+j, length); - } - Writes.deleteExternalArray(tmp); - } -} \ No newline at end of file diff --git a/src/sorts/hybrid/StupidQuickSort.java b/src/sorts/hybrid/StupidQuickSort.java deleted file mode 100644 index 5c5683a5..00000000 --- a/src/sorts/hybrid/StupidQuickSort.java +++ /dev/null @@ -1,90 +0,0 @@ -package sorts.hybrid; - -import sorts.templates.Sort; -import sorts.insert.InsertionSort; -import main.ArrayVisualizer; - -/* - * -MIT License -Copyright (c) 2020 fungamer2 & EilrahcF -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class StupidQuickSort extends Sort { - - public StupidQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stupid Quick"); - this.setRunAllSortsName("Stupid Quick Sort"); - this.setRunSortName("Stupid Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int times = (int)Math.sqrt(length); - for (int count = 0; count < times; count++) { - int i = 0; - int j = length - 1; - - int pivotPos = (int)(Math.random() * length); - int pivot = array[pivotPos]; - - while (i < j) { - while (Reads.compareValues(array[i], pivot) == -1){ - i++; - Highlights.markArray(1, i); - Delays.sleep(1); - } - while (Reads.compareValues(array[j], pivot) == 1){ - j--; - Highlights.markArray(2, j); - Delays.sleep(1); - } - - if (i < j) { - // Follow the pivot and highlight it. - if(i == pivotPos) { - Highlights.markArray(3, j); - } - if(j == pivotPos) { - Highlights.markArray(3, i); - } - - Writes.swap(array, i, j, 1, true, false); - - i++; - j--; - } - } - } - - Highlights.clearMark(2); - Highlights.clearMark(3); - InsertionSort insertSorter = new InsertionSort(arrayVisualizer); - insertSorter.customInsertSort(array, 0, length, 0.4, false); - } -} diff --git a/src/sorts/hybrid/SwapMergeSort.java b/src/sorts/hybrid/SwapMergeSort.java deleted file mode 100644 index ef0097ee..00000000 --- a/src/sorts/hybrid/SwapMergeSort.java +++ /dev/null @@ -1,108 +0,0 @@ -package sorts.hybrid; - -import main.ArrayVisualizer; -import sorts.insert.BinaryInsertionSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class SwapMergeSort extends Sort { - private BinaryInsertionSort binaryInserter; - - public SwapMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("SwapMerge"); - this.setRunAllSortsName("SwapMerge Sort"); - this.setRunSortName("SwapMergeSort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void moveDown(int[] array, int start, int dest) { - for (int i = dest; i < start; i++) { - Writes.swap(array, i, start, 0.025, true, false); - } - } - - private void merge(int[] array, int leftStart, int rightStart, int end) { - int left = leftStart; - int right = rightStart; - - while (left < right) { - if (left >= end || right >= end) { - break; - } - else if (Reads.compareValues(array[left], array[right]) <= 0) { - left += 1; - } - else { - moveDown(array, right, left); - left += 1; - right += 1; - } - } - } - - private void mergeRun(int[] array, int start, int mid, int end) { - if(start == mid) return; - - mergeRun(array, start, (mid+start)/2, mid); - mergeRun(array, mid, (mid+end)/2, end); - - if(end - start < 32) { - return; - } - else if(end - start == 32) { - binaryInserter.customBinaryInsert(array, start, Math.min(array.length, end + 1), 0.333); - } - else { - merge(array, start, mid, end); - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - binaryInserter = new BinaryInsertionSort(arrayVisualizer); - - if(length < 32) { - binaryInserter.customBinaryInsert(array, 0, length, 0.333); - return; - } - - int start = 0; - int end = length; - int mid = start + ((end - start) / 2); - - mergeRun(array, start, mid, end); - } -} diff --git a/src/sorts/hybrid/ThreadedPDMergeSort.java b/src/sorts/hybrid/ThreadedPDMergeSort.java deleted file mode 100644 index 52367ad6..00000000 --- a/src/sorts/hybrid/ThreadedPDMergeSort.java +++ /dev/null @@ -1,156 +0,0 @@ -package sorts.hybrid; - -import java.util.concurrent.locks.ReentrantLock; - -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2021 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -public class ThreadedPDMergeSort extends BinaryPDMergeSort { - final int MAX_THREADS = 24; - volatile int threadCount; - volatile ReentrantLock countLock; - - public ThreadedPDMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Threaded Pattern-Defeating Merge"); - this.setRunAllSortsName("Threaded Pattern-Defeating Merge Sort"); - this.setRunSortName("Threaded Pattern-Defeating Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - protected void mergeUp(int[] array, int start, int mid, int end) { - for (int i = start; i < mid; i++) { - Highlights.markArray(1, i); - Writes.write(copied, i, array[i], 1, false, true); - } - - int bufferPointer = start; - int left = start; - int right = mid; - - while (left < right && right < end) { - Highlights.markArray(2, right); - if (Reads.compareValues(copied[bufferPointer], array[right]) <= 0) - Writes.write(array, left++, copied[bufferPointer++], 1, true, false); - else - Writes.write(array, left++, array[right++], 1, true, false); - } - Highlights.clearMark(2); - - while (left < right) - Writes.write(array, left++, copied[bufferPointer++], 0.5, true, false); - Highlights.clearAllMarks(); - } - - protected void mergeDown(int[] array, int start, int mid, int end) { - for (int i = mid; i < end; i++) { - Highlights.markArray(1, i); - Writes.write(copied, i, array[i], 1, false, true); - } - - int bufferPointer = end - 1; - int left = mid - 1; - int right = end - 1; - - while (right > left && left >= start) { - Highlights.markArray(2, left); - if (Reads.compareValues(copied[bufferPointer], array[left]) >= 0) - Writes.write(array, right--, copied[bufferPointer--], 1, true, false); - else - Writes.write(array, right--, array[left--], 1, true, false); - } - Highlights.clearMark(2); - - while (left < right) - Writes.write(array, right--, copied[bufferPointer--], 0.5, true, false); - Highlights.clearAllMarks(); - } - - protected void merge(int[] array, int start, int mid, int end) { - countLock.lock(); - if (threadCount < MAX_THREADS) { - threadCount++; - new Thread() { - @Override - public void run() { - ThreadedPDMergeSort.super.merge(array, start, mid, end); - countLock.lock(); - threadCount--; - synchronized (countLock) { - countLock.notify(); - } - countLock.unlock(); - } - }.start(); - countLock.unlock(); - return; - } - countLock.unlock(); - super.merge(array, start, mid, end); - } - - public void runSort(int[] array, int length, int bucketCount) { - threadCount = 0; - countLock = new ReentrantLock(); - - int[] runs = findRuns(array, length - 1); - copied = Writes.createExternalArray(length); - - // arrayVisualizer.setHeading("PDMerge -- Merging Runs"); - while (runCount > 1) { - for (int i = 0; i < runCount - 1; i += 2) { - int end = i + 2 >= runCount ? length : (runs[i + 2]); - merge(array, runs[i], runs[i + 1], end); - } - while (threadCount > 0) { - synchronized (countLock) { - try { - countLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - for (int i = 1, j = 2; i < runCount; i++, j+=2, runCount--) { - Writes.write(runs, i, runs[j], 0.5, true, true); - } - } - - // arrayVisualizer.setHeading("Pattern-Defeating Mergesort"); - - Writes.deleteExternalArray(runs); - Writes.deleteExternalArray(copied); - } -} \ No newline at end of file diff --git a/src/sorts/insert/AdaptiveBinaryInsertionSort.java b/src/sorts/insert/AdaptiveBinaryInsertionSort.java deleted file mode 100644 index 566cba1f..00000000 --- a/src/sorts/insert/AdaptiveBinaryInsertionSort.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * - */ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author PiotrGrochowski - * - */ -public final class AdaptiveBinaryInsertionSort extends Sort { - - /** - * @param arrayVisualizer - */ - public AdaptiveBinaryInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Adaptive Binary Insert"); - this.setRunAllSortsName("Adaptive Binary Insertion Sort"); - this.setRunSortName("Adaptive Binary Insertsort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - protected void abinaryinsert(int[] array, int start, int end, double sleep) { - int count = 0; - for (int i = start + 1; i < end; i++) { - int num = array[i]; - int v = (2*count / (i - start)) + 1; //I'VE SOLVED IT!! - int lo = Math.max(i - v, start), hi = i; - while ((lo >= start) && (Reads.compareValues(array[lo], num) == 1)){ - lo -= v; - hi -= v; - } - lo++; - if (lo < start){ - lo = start; - } - while (lo < hi) { - int mid = lo + ((hi - lo) / 2); // avoid int overflow! - Highlights.markArray(2, mid); - - Delays.sleep(sleep); - - if (Reads.compareValues(num, array[mid]) < 0) { // do NOT move equal elements to right of inserted element; this maintains stability! - hi = mid; - } - else { - lo = mid + 1; - } - } - - // item has to go into position lo - count += (i - lo); - - int j = i - 1; - - if (j >= lo){ - while (j >= lo) - { - Writes.write(array, j + 1, array[j], sleep, true, false); - j--; - } - Writes.write(array, lo, num, sleep, true, false); - } - - Highlights.clearAllMarks(); - } - } - - public void customSort(int[] array, int start, int end) { - this.abinaryinsert(array, start, end, 1); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - this.abinaryinsert(array, 0, sortLength, 0.0875); - } - -} diff --git a/src/sorts/insert/AdaptiveInsertionSort.java b/src/sorts/insert/AdaptiveInsertionSort.java deleted file mode 100644 index 76622a84..00000000 --- a/src/sorts/insert/AdaptiveInsertionSort.java +++ /dev/null @@ -1,79 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class AdaptiveInsertionSort extends Sort { - public AdaptiveInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Adaptive Insertion"); - this.setRunAllSortsName("Adaptive Insertion Sort"); - this.setRunSortName("Adaptive Insertsort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int findRun(int[] array, int a, int b, double sleep, boolean auxwrite) { - int i = a + 1; - if(Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { - while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; - Writes.reversal(array, a, i - 1, sleep, true, false); - } - else while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; - Highlights.clearMark(2); - return i; - } - - public void moveFront(int[] array, int a, int m, int b, double sleep, boolean auxwrite) { - int mini = m; - int minv = array[mini]; - Highlights.markArray(2, mini); - for (int i = m + 1; i < b; i++) { - if (Reads.compareIndexValue(array, i, minv, sleep, true) < 0) { - mini = i; - minv = array[i]; - Highlights.markArray(2, mini); - } - } - Highlights.clearMark(2); - m--; - while (mini > m) { - Writes.write(array, mini, array[mini - 1], sleep, true, false); - mini--; - } - --a; - while(mini > a && Reads.compareValues(array[mini], minv) > 0) { - Writes.write(array, mini + 1, array[mini], sleep, true, auxwrite); - mini--; - } - Writes.write(array, mini + 1, minv, sleep, true, auxwrite); - } - - public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { - int i = findRun(array, a, b, sleep, auxwrite); - if (i < b) { - moveFront(array, a, i++, b, sleep, auxwrite); - while(i < b) { - int current = array[i]; - int pos = i - 1; - while(Reads.compareValues(array[pos], current) > 0) { - Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); - pos--; - } - Writes.write(array, pos + 1, current, sleep, true, auxwrite); - i++; - } - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - insertionSort(array, 0, currentLength, 1, false); - } -} \ No newline at end of file diff --git a/src/sorts/insert/BidirectionalInsertionSort.java b/src/sorts/insert/BidirectionalInsertionSort.java deleted file mode 100644 index b43396bd..00000000 --- a/src/sorts/insert/BidirectionalInsertionSort.java +++ /dev/null @@ -1,97 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 (Josiah Glosson) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class BidirectionalInsertionSort extends Sort { - public BidirectionalInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Bidirectional Insertion"); - this.setRunAllSortsName("Bidirectional Insertion Sort"); - this.setRunSortName("Bidirectional Insertsort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - protected void insertFw(int[] array, int i, int current, double sleep, boolean auxwrite) { - int pos = i - 1; - while(Reads.compareValues(array[pos], current) > 0){ - Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); - pos--; - } - Writes.write(array, pos + 1, current, sleep, true, auxwrite); - } - - protected void insertBw(int[] array, int i, int current, double sleep, boolean auxwrite) { - int pos = i - 1; - while(Reads.compareValues(array[pos], current) <= 0){ - Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); - pos--; - } - Writes.write(array, pos + 1, current, sleep, true, auxwrite); - } - - public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { - boolean dir = true; - for (int i = a + 1; i < b; i++) { - int current = array[i]; - if (dir) { - if (Reads.compareValues(current, array[a]) < 0) { - Writes.reversal(array, a, i - 1, sleep, true, auxwrite); - dir = !dir; - Highlights.clearMark(2); - } else { - insertFw(array, i, current, sleep, auxwrite); - } - } else { - if (Reads.compareValues(current, array[a]) >= 0) { - Writes.reversal(array, a, i - 1, sleep, true, auxwrite); - dir = !dir; - Highlights.clearMark(2); - } else { - insertBw(array, i, current, sleep, auxwrite); - } - } - } - if (!dir) { - Writes.reversal(array, a, b - 1, sleep, true, auxwrite); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - insertionSort(array, 0, currentLength, 0.015, false); - } -} \ No newline at end of file diff --git a/src/sorts/insert/CiuraCocktailShellSort.java b/src/sorts/insert/CiuraCocktailShellSort.java deleted file mode 100644 index 9dd7f3a1..00000000 --- a/src/sorts/insert/CiuraCocktailShellSort.java +++ /dev/null @@ -1,92 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author fungamer2 - * - */ - -public final class CiuraCocktailShellSort extends Sort { - - /** - * @param arrayVisualizer - */ - public CiuraCocktailShellSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Cocktail Shell (Ciura Gaps)"); - this.setRunAllSortsName("Cocktail Shell Sort (Ciura Gaps)"); - this.setRunSortName("Cocktail Shellsort (Ciura Gaps)"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - int[] gaps = {1, 4, 10, 23, 57, 132, 301, 701}; - - private int ciura(int n) { - if (n <= gaps.length) { - return gaps[n - 1]; - } - return (int)Math.pow(2.25, n); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - int gap = 1; - int k; - for (k = 1; gap < sortLength; k++) { - gap = ciura(k); - } - - boolean dir = true; - while (--k >= 1) { - gap = ciura(k); - if (dir) { - for (int i = gap; i < sortLength; i++) { - int tmp = array[i]; - int j = i; - while (j >= gap && Reads.compareValues(array[j - gap], tmp) == 1) { - Highlights.markArray(2, j - gap); - Writes.write(array, j, array[j - gap], 0.7, true, false); - j -= gap; - } - - if (j - gap >= 0) { - Highlights.markArray(2, j - gap); - } else { - Highlights.clearMark(2); - } - - Writes.write(array, j, tmp, 0.7, true, false); - } - } else { - for (int i = sortLength - gap; i >= 0; i--) { - int tmp = array[i]; - int j = i; - while (j < sortLength - gap && Reads.compareValues(array[j + gap], tmp) == -1) { - Highlights.markArray(2, j + gap); - Writes.write(array, j, array[j + gap], 0.7, true, false); - j += gap; - } - - if (j + gap < sortLength) { - Highlights.markArray(2, j + gap); - } else { - Highlights.clearMark(2); - } - - Writes.write(array, j, tmp, 0.7, true, false); - } - } - dir = !dir; - } - - } - -} diff --git a/src/sorts/insert/CocktailShellSort.java b/src/sorts/insert/CocktailShellSort.java deleted file mode 100644 index 2ee3586a..00000000 --- a/src/sorts/insert/CocktailShellSort.java +++ /dev/null @@ -1,77 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author fungamer2 - * - */ -public final class CocktailShellSort extends Sort { - - /** - * @param arrayVisualizer - */ - public CocktailShellSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Cocktail Shell"); - this.setRunAllSortsName("Cocktail Shell Sort"); - this.setRunSortName("Cocktail Shellsort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - int gap = sortLength / 2; - boolean dir = true; - while (gap >= 1) { - if (dir) { - for (int i = gap; i < sortLength; i++) { - int tmp = array[i]; - int j = i; - while (j >= gap && Reads.compareValues(array[j - gap], tmp) == 1) { - Highlights.markArray(2, j - gap); - Writes.write(array, j, array[j - gap], 0.7, true, false); - j -= gap; - } - - if (j - gap >= 0) { - Highlights.markArray(2, j - gap); - } else { - Highlights.clearMark(2); - } - - Writes.write(array, j, tmp, 0.7, true, false); - } - } else { - for (int i = sortLength - gap; i >= 0; i--) { - int tmp = array[i]; - int j = i; - while (j < sortLength - gap && this.Reads.compareValues(array[j + gap], tmp) == -1) { - Highlights.markArray(2, j + gap); - Writes.write(array, j, array[j + gap], 0.7, true, false); - j += gap; - } - - if (j + gap < sortLength) { - Highlights.markArray(2, j + gap); - } else { - Highlights.clearMark(2); - } - - Writes.write(array, j, tmp, 0.7, true, false); - } - } - gap /= 2; - dir = !dir; - } - - } - -} diff --git a/src/sorts/insert/FibonacciInsertionSort.java b/src/sorts/insert/FibonacciInsertionSort.java deleted file mode 100644 index eb9d09da..00000000 --- a/src/sorts/insert/FibonacciInsertionSort.java +++ /dev/null @@ -1,99 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License -Copyright (c) 2020 fungamer2 -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class FibonacciInsertionSort extends Sort { - - public FibonacciInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Fibonacci Insertion"); - this.setRunAllSortsName("Fibonacci Insertion Sort"); - this.setRunSortName("Fibonacci Insertion Sort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public void fibonacciInsertionSort(int[] array, int length) { - for (int i = 1; i < length; i++) { - int tmp = array[i]; - int position = this.fibonacciSearch(array, 0, i - 1, tmp); - int j = i - 1; - while (j >= position) { - Writes.write(array, j + 1, array[j--], 0.15, true, false); - } - Writes.write(array, j + 1, tmp, 0.15, true, false); - } - } - - public int fibonacciSearch(int[] array, int start, int end, int item) { - int fibM2 = 0; - int fibM1 = 1; - int fibM = 1; - while (fibM <= end - start) { - fibM2 = fibM1; - fibM1 = fibM; - fibM = fibM2 + fibM1; - } - - int offset = start - 1; - - while (fibM > 1) { - - int i = Math.min(offset + fibM2, end); - - Highlights.markArray(1, offset + 1); - Highlights.markArray(2, i); - - if (Reads.compareValues(array[i], item) <= 0) { - fibM = fibM1; - fibM1 = fibM2; - fibM2 = fibM - fibM1; - offset = i; - } else { - fibM = fibM2; - fibM1 -= fibM2; - fibM2 = fibM - fibM1; - } - Delays.sleep(0.6); - } - int position = ++offset; - if (Reads.compareValues(array[position], item) <= 0) { - ++position; - } - return position; - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.fibonacciInsertionSort(array, length); - } -} \ No newline at end of file diff --git a/src/sorts/insert/GambitInsertionSort.java b/src/sorts/insert/GambitInsertionSort.java deleted file mode 100644 index 47556cd8..00000000 --- a/src/sorts/insert/GambitInsertionSort.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * - */ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.insert.InsertionSort; -import sorts.templates.Sort; - -/** - * @author MP - * @author McDude_73 - * @author EilrahcF - * - */ -public final class GambitInsertionSort extends Sort { - - /** - * @param arrayVisualizer - */ - public GambitInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Gambit Insertion"); - setRunAllSortsName("Gambit Insertion Sort"); - setRunSortName("Gambit Insertsort"); - setCategory("Insertion Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(false); - setUnreasonableLimit(0); - setBogoSort(false); - - } - - private int binSearch(int[] array, int begin, int end, int target) { - while (true) { - int delta = end - begin; - if (delta <= 0) - break; - int p = begin + delta / 2; - if (this.Reads.compareIndices(array, p, target, 0.5D, true) == 0) - return p; - - if (this.Reads.compareIndices(array, p, target, 0.5D, true) > 0) { - end = p; - continue; - } - begin = p + 1; - } - return end; - } - - private void binInsert(int[] array, int len, int start, int end) { - int offset = 1; - for (; offset * offset < len; offset *= 2) - ; - - for (int bStart = 0, bEnd = end, i = start + offset; i < end; i++) { - int target = binSearch(array, bStart, bEnd, i); - - int tmp = array[i]; - int j = i - 1; - while (j >= target && array[j] > tmp) { - this.Writes.write(array, j + 1, array[j], 0.125D, true, false); - j--; - } - array[j + 1] = tmp; - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - binInsert(array, sortLength, 0, sortLength); - Highlights.clearAllMarks(); - InsertionSort ins = new InsertionSort(arrayVisualizer); - ins.customInsertSort(array, 0, sortLength, 0.1D, true); - - } - -} diff --git a/src/sorts/insert/PatternDefeatingInsertionSort.java b/src/sorts/insert/PatternDefeatingInsertionSort.java deleted file mode 100644 index 34206e80..00000000 --- a/src/sorts/insert/PatternDefeatingInsertionSort.java +++ /dev/null @@ -1,49 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class PatternDefeatingInsertionSort extends Sort { - public PatternDefeatingInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Pattern-Defeating Insertion"); - this.setRunAllSortsName("Pattern-Defeating Insertion Sort"); - this.setRunSortName("Pattern-Defeating Insertsort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { - int i = a + 1; - if(Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { - while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; - Writes.reversal(array, a, i - 1, sleep, true, auxwrite); - } - else while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; - - Highlights.clearMark(2); - - while(i < b) { - int current = array[i]; - int pos = i - 1; - while(pos >= a && Reads.compareValues(array[pos], current) > 0){ - Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); - pos--; - } - Writes.write(array, pos + 1, current, sleep, true, auxwrite); - - i++; - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - insertionSort(array, 0, currentLength, 1, false); - } -} \ No newline at end of file diff --git a/src/sorts/insert/RendezvousSort.java b/src/sorts/insert/RendezvousSort.java deleted file mode 100644 index c919a4bb..00000000 --- a/src/sorts/insert/RendezvousSort.java +++ /dev/null @@ -1,74 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class RendezvousSort extends Sort { - public RendezvousSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Rendezvous"); - this.setRunAllSortsName("Lancewer's Rendezvous Sort"); - this.setRunSortName("Lancewer's Rendezvous Sort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(4096); - this.setBogoSort(false); - } - - public void rendezvousSort(int[] array, int length){ - int len = length; - int i, j, ticker, f, gap; - while (len >= 1) { - i = 0; - j = len; - - while (length >= j) { - ticker = i; - f = 0; - - while (!(i < 1 || !(Reads.compareIndices(array, j, i, 0.01, true) < 0))) { - Writes.swap(array, i, j, 1, true, false); - f = 1; - gap = 1 + (j - i); - i -= gap; - j -= gap; - } - - i++; - j++; - - if (f == 1){ - len /= 0.25; - i = 0; - j = len; - } - } - - len /= 8; - } - i = 0; - j = 1; - - while (length >= j) { - ticker = i; - - while (!(i < 0 || !(Reads.compareIndices(array, j, i, 0.01, true) < 0))){ - Writes.swap(array, i, j, 1, true, false); - i--; - j--; - } - - i = ticker + 1; - j = ticker + 2; - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.rendezvousSort(array, length - 1); - } -} \ No newline at end of file diff --git a/src/sorts/insert/ReverseInsertionSort.java b/src/sorts/insert/ReverseInsertionSort.java deleted file mode 100644 index 575b31ff..00000000 --- a/src/sorts/insert/ReverseInsertionSort.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * - */ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author McDude73 - * - */ -public final class ReverseInsertionSort extends Sort { - - /** - * @param arrayVisualizer - */ - public ReverseInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Reverse Insertion"); - this.setRunAllSortsName("Reverse Insertion Sort"); - this.setRunSortName("Reverse Insertsort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) throws Exception { - // TODO Auto-generated method stub - for (int i = length - 1; i >= 0; i--) { - int current = array[i]; - int pos = i + 1; - - while (pos <= length - 1 && Reads.compareValues(array[pos], current) < 0) { - Writes.write(array, pos - 1, array[pos], 0.015D, true, false); - pos++; - } - Writes.write(array, pos - 1, current, 0.015D, true, false); - } - } - -} diff --git a/src/sorts/insert/RoomSort.java b/src/sorts/insert/RoomSort.java deleted file mode 100644 index ff592728..00000000 --- a/src/sorts/insert/RoomSort.java +++ /dev/null @@ -1,76 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RoomSort extends Sort { - double delay = 0.015; - InsertionSort insertionSort; - - public RoomSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Room"); - this.setRunAllSortsName("Room Sort"); - this.setRunSortName("Roomsort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public void insertTo(int[] array, int a, int b) { - int val = array[a]; - a--; - while (a >= b && Reads.compareValues(array[a], val) > 0) { - Writes.write(array, a + 1, array[a], delay, true, false); - a--; - } - Writes.write(array, a + 1, val, delay, true, false); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - insertionSort = new InsertionSort(arrayVisualizer); - int roomLen = (int)Math.sqrt(currentLength) + 1; - - int end, i; - for (end = currentLength; end > roomLen; end -= roomLen) { - Highlights.clearAllMarks(); - insertionSort.customInsertSort(array, 0, roomLen, delay, false); - for (i = roomLen; i < end; i++) { - insertTo(array, i, i - roomLen); - } - } - insertionSort.customInsertSort(array, 0, end, delay, false); - } -} \ No newline at end of file diff --git a/src/sorts/insert/ShuffledTreeSort.java b/src/sorts/insert/ShuffledTreeSort.java deleted file mode 100644 index 34ea4b99..00000000 --- a/src/sorts/insert/ShuffledTreeSort.java +++ /dev/null @@ -1,132 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -import java.util.Random; - -/* - * -MIT License - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class ShuffledTreeSort extends Sort { - public ShuffledTreeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Shuffled Tree"); - this.setRunAllSortsName("Shuffled Tree Sort"); - this.setRunSortName("Shuffled Treesort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int idx; - - private void stableSwap(int[] array, int[] keys, int a, int b) { - Writes.swap(array, a, b, 0, true, false); - Writes.swap(keys, a, b, 1, false, true); - } - - private void traverse(int[] array, int[] keys, int[] lower, int[] upper, int r) { - Highlights.markArray(2, r); - Delays.sleep(1); - - if(lower[r] != 0) this.traverse(array, keys, lower, upper, lower[r]); - - Writes.write(keys, this.idx++, r, 1, true, true); - - if(upper[r] != 0) this.traverse(array, keys, lower, upper, upper[r]); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int[] keys = Writes.createExternalArray(currentLength); - for(int i = 0; i < currentLength; i++) - Writes.write(keys, i, i, 1, true, true); - - Random random = new Random(); - for(int i = 0; i < currentLength; i++){ - int r = random.nextInt(currentLength - i) + i; - this.stableSwap(array, keys, i, r); - } - - int[] lower = Writes.createExternalArray(currentLength); - int[] upper = Writes.createExternalArray(currentLength); - int[] next; - - for(int i = 1; i < currentLength; i++) { - Highlights.markArray(2, i); - int c = 0; - - while(true) { - Highlights.markArray(1, c); - Delays.sleep(0.5); - - int cmp = Reads.compareValues(array[i], array[c]); - next = (cmp < 0 || (cmp == 0 && Reads.compareOriginalValues(keys[i], keys[c]) < 0)) ? lower : upper; - - if(next[c] == 0) { - Writes.write(next, c, i, 0, false, true); - break; - } - else c = next[c]; - } - } - Highlights.clearMark(2); - - this.idx = 0; - this.traverse(array, keys, lower, upper, 0); - - for(int i = 0; i < currentLength-1; i++) { - Highlights.markArray(2, i); - - if(Reads.compareOriginalValues(i, keys[i]) != 0) { - int t = array[i]; - int j = i, k = keys[i]; - - do { - Writes.write(array, j, array[k], 1, true, false); - Writes.write(keys, j, j, 1, true, true); - - j = k; - k = keys[k]; - } - while(Reads.compareOriginalValues(k, i) != 0); - - Writes.write(array, j, t, 1, true, false); - Writes.write(keys, j, j, 1, true, true); - } - } - - Writes.deleteExternalArray(lower); - Writes.deleteExternalArray(upper); - Writes.deleteExternalArray(keys); - } -} \ No newline at end of file diff --git a/src/sorts/insert/StableHanoiSort.java b/src/sorts/insert/StableHanoiSort.java deleted file mode 100644 index 4844e2d5..00000000 --- a/src/sorts/insert/StableHanoiSort.java +++ /dev/null @@ -1,335 +0,0 @@ -package sorts.insert; - -import java.util.Stack; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * A stable variant of Hanoi Sort. - * For more information on this type of sort, see Javadoc on {@link HanoiSort}. - * - * @author Sam Walko (Anonymous0726) - */ -final public class StableHanoiSort extends Sort { - // main array - private int[] array; - // Length of the array - private int length; - // Auxiliary stacks from the classic Tower of Hanoi problem - private Stack stack2, stack3; - // sp is a "stack pointer" for the main array (which isn't actually a stack) - private int sp; - // Where the unsorted portion of the main array begins - private int unsorted; - // These are used in determining end conditions for the hanoi function - private int target; - private int targetMoves; - - public StableHanoiSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stable Hanoi"); - this.setRunAllSortsName("Stable Hanoi Sort"); - this.setRunSortName("Stable Hanoi sort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(32); - this.setBogoSort(false); - } - - /** - * Moves an element (or group of identical elements) from the unsorted portion - * of the main array into stack2, without disturbing previously-moved elements' - * reverse-stable pattern, using the hanoi function. - */ - private void removeFromMainStack() { - Highlights.markArray(1, sp); - target = array[sp]; - - int moves = hanoi(2, true, 1); - int height = getHeight(moves + 1); - targetMoves = moves; - - Highlights.clearAllMarks(); - Highlights.markArray(1, sp); - - if(height % 2 == 1) { // Odd height case: moved to stack3 - unsorted += moveFromMain(stack2, false); - hanoi(3, false, 2); - } else { // Even height case: moved to main stack - // Moving to stack3 in this manner allows us to keep stability - hanoi(1, false, 2); - hanoi(2, false, 2); - unsorted += moveFromMain(stack2, false); - hanoi(3, true, 2); - } - } - - /** - * Stably moves all of the elements, currently in order on stack2, back to - * the main array using the hanoi function. Stability achieved by moving - * each disk, which is initially reverse-stable, an odd number of times. - */ - private void returnToMainStack() { - int moves = hanoi(2, true, 3); - int height = getHeight(moves + 1); - boolean oddHeight = height % 2 == 1; - targetMoves = moves; - - if(oddHeight) { // Odd height case: moved to stack3 - hanoi(3, false, 2); // All disks have moved an even number of times - } else { // Even height case: moved to main stack - targetMoves /= 2; - hanoi(1, false, 2); - hanoi(3, false, 2); - oddHeight = true; - // At this point, all disks but the greatest has moved a multiple of four times - // (an even number), and the greatest disk has moved once (an odd number). - } - // In both cases, there is now an odd number of disks, - // each moved an even number of times, on stack2 - while(!stack2.isEmpty()) { - targetMoves /= 2; // Rounds down to correct integer - hanoi(2, !oddHeight, 2); // Move all but the new largest element to stack3 - moveToMain(stack2); // Move the new smallest element to the main stack - hanoi(3, oddHeight, 2); // Move stack3 back to stack2 - oddHeight = !oddHeight; // Change height's odd parity - } - } - - /** - * Iteratively moves elements around the stacks according to the - * Tower of Hanoi problem. Recursion cannot be used because in many - * cases we do not know the initial recursion depth. - * - * @param startStack Which stack we wish to move a tower from - * @param goRight Whether the smallest disk should go right on the pegs - * (1->2, 2->3, 3->1) or left (1->3, 2->1, 3->2) - * @param endCon Used to determine when to end this function - * @return The number of moves performed - */ - private int hanoi(int startStack, boolean goRight, int endCon) { - int moves = 0; - int minPoleLoc = startStack; - - if(!endConMet(endCon, moves)) { - moves++; - switch(minPoleLoc) { - case 1: - if(goRight) { - moveFromMain(stack2, true); - minPoleLoc = 2; - } else { - moveFromMain(stack3, true); - minPoleLoc = 3; - } break; - case 2: - if(goRight) { - moveBetweenStacks(stack2, stack3); - minPoleLoc = 3; - } else { - moveToMain(stack2); - minPoleLoc = 1; - } break; - case 3: - if(goRight) { - moveToMain(stack3); - minPoleLoc = 1; - } else { - moveBetweenStacks(stack3, stack2); - minPoleLoc = 2; - } break; - } - } - - while(!endConMet(endCon, moves)) { - moves += 2; - switch(minPoleLoc) { - case 1: - if(!stack2.isEmpty() && - (stack3.isEmpty() || Reads.compareValues(stack2.peek(), stack3.peek()) < 0)) - moveBetweenStacks(stack2, stack3); - else - moveBetweenStacks(stack3, stack2); - if(goRight) { - moveFromMain(stack2, true); - minPoleLoc = 2; - } else { - moveFromMain(stack3, true); - minPoleLoc = 3; - } break; - case 2: - if(stack3.isEmpty() || - (sp < unsorted && Reads.compareValues(array[sp], stack3.peek()) < 0)) - moveFromMain(stack3, true); - else - moveToMain(stack3); - if(goRight) { - moveBetweenStacks(stack2, stack3); - minPoleLoc = 3; - } else { - moveToMain(stack2); - minPoleLoc = 1; - } break; - case 3: - if(stack2.isEmpty() || - (sp < unsorted && Reads.compareValues(array[sp], stack2.peek()) < 0)) - moveFromMain(stack2, true); - else - moveToMain(stack2); - if(goRight) { - moveToMain(stack3); - minPoleLoc = 1; - } else { - moveBetweenStacks(stack3, stack2); - minPoleLoc = 2; - } break; - } - } - - return moves; - } - - /** - * Determines whether or not the hanoi function should end now - * - * @param endCon Which ending condition is required for the hanoi function to end - * @param moves the moves completed by the hanoi function so far - * @return Whether or not the end condition has been met - */ - private boolean endConMet(int endCon, int moves) { - if(!validNumberMoves(moves)) - return false; - switch (endCon) { - case 1: return (stack2.isEmpty() || Reads.compareValues(target, stack2.peek()) <= 0); - case 2: return moves == targetMoves; - case 3: return stack2.isEmpty(); - default: throw new IllegalArgumentException(); - } - } - - /** - * @param moves The number of moves completed so far - * @return If the moves is of the form (2^n)-1 - */ - private boolean validNumberMoves(int moves) { - if(moves == 0) - return true; - if(moves % 2 == 0) - return false; - return validNumberMoves(moves/2); - } - - /** - * Figures out the height of the pyramid moved based on number of moves - * - * @param movesPlus1 The number of moves performed, plus one - * @return The height of the pyramid moved (equal to log_2(moves + 1)) - */ - private int getHeight(int movesPlus1) { - if(movesPlus1 == 1) - return 0; - return getHeight(movesPlus1 / 2) + 1; - } - - /** - * Moves an element from the main array to another stack, - * then moves any consecutive duplicates of that element with it - * - * @param stack The stack to move the element(s) from the main array to - * @param checkUnsorted Whether or not it is safe to remove elements in - * the unsorted portion of the main array - * @return duplicates The number of consecutive identical elements - * that were popped off the main array in the current "move" - */ - private int moveFromMain(Stack stack, boolean checkUnsorted) { - int duplicates = 1; - // Move element - Writes.changeAuxWrites(1); - Writes.startLap(); - stack.push(array[sp]); - Writes.stopLap(); - sp++; - Highlights.markArray(1, sp); - Delays.sleep(0.25); - // Move any duplicates (endOnLength indicates the relevant portion of - // the main stack is "empty") - boolean endOnLength = (sp >= length) || (checkUnsorted && sp >= unsorted); - while(!endOnLength && Reads.compareValues(array[sp], stack.peek()) == 0) { - duplicates++; - Writes.changeAuxWrites(1); - Writes.startLap(); - stack.push(array[sp]); - Writes.stopLap(); - sp++; - Highlights.markArray(1, sp); - Delays.sleep(0.25); - endOnLength = (sp >= length) || (checkUnsorted && sp >= unsorted); - } - return duplicates; - } - - /** - * Moves an element to the main array from another stack, - * then moves any consecutive duplicates of that element with it - * - * @param stack The stack to move the element(s) to the main array from - */ - private void moveToMain(Stack stack) { - // Move element - sp--; - Highlights.markArray(1, sp); - Writes.write(array, sp, stack.pop(), 0.25, false, false); - // Move any duplicates - while(!stack.isEmpty() && Reads.compareValues(stack.peek(), array[sp]) == 0) { - sp--; - Highlights.markArray(1, sp); - Writes.write(array, sp, stack.pop(), 0.25, false, false); - } - } - - /** - * Moves an element from one stack to another stack, - * then moves any consecutive duplicates of that element with it - * - * @param from the stack to move the element(s) from - * @param to the stack to move the element(s) to - */ - private void moveBetweenStacks(Stack from, Stack to) { - // Move element - Writes.changeAuxWrites(1); - Writes.startLap(); - to.push(from.pop()); - Writes.stopLap(); - Delays.sleep(0.25); - // Move any duplicates - while(!from.isEmpty() && Reads.compareValues(from.peek(), to.peek()) == 0) { - Writes.changeAuxWrites(1); - Writes.startLap(); - to.push(from.pop()); - Writes.stopLap(); - Delays.sleep(0.25); - } - } - - - @Override - public void runSort(int[] array, int length, int bucketCount) { - // Initialize local variables - this.array = array; - this.length = length; - stack2 = new Stack(); - stack3 = new Stack(); - sp = 0; - unsorted = 0; - - while(unsorted < length) - removeFromMainStack(); - - returnToMainStack(); - } -} diff --git a/src/sorts/insert/TriSearchInsertionSort.java b/src/sorts/insert/TriSearchInsertionSort.java deleted file mode 100644 index 3ce66c8a..00000000 --- a/src/sorts/insert/TriSearchInsertionSort.java +++ /dev/null @@ -1,85 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* -TriSearch Insertion Sort 2020 Copyright (C) thatsOven -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -final public class TriSearchInsertionSort extends Sort { - public TriSearchInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("TriSearch Insertion"); - this.setRunAllSortsName("thatsOven's TriSearch Insertion Sort"); - this.setRunSortName("thatsOven's TriSearch Insertion Sort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public int triSearch(int[] arr, int l, int h, int val, double sleep) { - int mid = l + ((h-l) / 2); - Highlights.markArray(0, l); - Highlights.markArray(1, h); - Highlights.markArray(2, mid); - Delays.sleep(sleep); - if (Reads.compareValues(val, arr[l]) < 0) { - return l; - } else { - if (Reads.compareValues(val, arr[h]) < 0) { - if (Reads.compareValues(val, arr[mid]) < 0) { - return this.triSearch(arr, l+1, mid-1, val, sleep); - } else { - return this.triSearch(arr, mid+1, h-1, val, sleep); - } - } else { - return h+1; - } - } - } - - public void triInsertSort(int[] array, int start, int end, double compSleep, double writeSleep) { - for (int i = start+1; i < end; i++) { - int num = array[i]; - int lo = start; - - lo = this.triSearch(array, start, i-1, num, compSleep); - Highlights.clearAllMarks(); - - int j = i - 1; - - while (j >= lo) - { - Writes.write(array, j + 1, array[j], writeSleep, true, false); - j--; - } - Writes.write(array, lo, num, writeSleep, true, false); - - Highlights.clearAllMarks(); - } - } - - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.triInsertSort(array, 0, currentLength, 40, 1); - } -} \ No newline at end of file diff --git a/src/sorts/insert/UnstableInsertionSort.java b/src/sorts/insert/UnstableInsertionSort.java deleted file mode 100644 index d0aa50af..00000000 --- a/src/sorts/insert/UnstableInsertionSort.java +++ /dev/null @@ -1,41 +0,0 @@ -package sorts.insert; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - - -final public class UnstableInsertionSort extends Sort { - public UnstableInsertionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Unstable Insertion"); - this.setRunAllSortsName("Unstable Insertion Sort"); - this.setRunSortName("Unstable Insertion Sort"); - this.setCategory("Insertion Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public void unstableInsertionSort(int[] array, int start, int end) { - for (int i = start + 1; i < end; ++i) { - if (Reads.compareIndices(array, i, start, 1, true) < 0) { - Writes.swap(array, i, start, 1, true, false); - } - int tmp = array[i]; - int j = i - 1; - for (; Reads.compareValues(array[j], tmp) > 0; --j) { - Writes.write(array, j+1, array[j], 1, true, false); - } - Writes.write(array, j+1, tmp, 1, true, false); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.unstableInsertionSort(array, 0, currentLength); - } -} diff --git a/src/sorts/merge/IndexMergeSort.java b/src/sorts/merge/IndexMergeSort.java deleted file mode 100644 index 5de88f55..00000000 --- a/src/sorts/merge/IndexMergeSort.java +++ /dev/null @@ -1,113 +0,0 @@ -package sorts.merge; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -The MIT License (MIT) - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -final public class IndexMergeSort extends Sort { - public IndexMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Index Merge"); - this.setRunAllSortsName("Index Merge Sort"); - this.setRunSortName("Index Mergesort"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void indexSort(int[] array, int[] idx, int a, int b) { - while(a < b) { - Highlights.markArray(2, a); - - if(Reads.compareOriginalValues(a, idx[a]) != 0) { - int t = array[a]; - int i = a, nxt = idx[a]; - - do { - Writes.write(array, i, array[nxt], 0, true, false); - Writes.write(idx, i, i, 0.5, false, true); - - i = nxt; - nxt = idx[nxt]; - } - while(Reads.compareOriginalValues(nxt, a) != 0); - - Writes.write(array, i, t, 0, true, false); - Writes.write(idx, i, i, 0.5, false, true); - } - a++; - } - } - - private void merge(int[] array, int[] idx, int a, int m, int b) { - int i = a, j = m, c = a; - Highlights.clearAllMarks(); - - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) <= 0) { - Highlights.markArray(1, i); - Writes.write(idx, c++, i++, 0.5, false, true); - } - else { - Highlights.markArray(2, j); - Writes.write(idx, c++, j++, 0.5, false, true); - } - } - - while(i < m) { - Highlights.markArray(1, i); - Writes.write(idx, c++, i++, 0.5, false, true); - } - while(j < b) { - Highlights.markArray(2, j); - Writes.write(idx, c++, j++, 0.5, false, true); - } - - this.indexSort(array, idx, a, b); - } - - private void sort(int[] array, int[] idx, int a, int b) { - if(b-a < 2) return; - - int m = (a+b)/2; - this.sort(array, idx, a, m); - this.sort(array, idx, m, b); - this.merge(array, idx, a, m, b); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int[] idx = Writes.createExternalArray(length); - this.sort(array, idx, 0, length); - Writes.deleteExternalArray(idx); - } -} \ No newline at end of file diff --git a/src/sorts/merge/ModuloMergeSort.java b/src/sorts/merge/ModuloMergeSort.java deleted file mode 100644 index e6152a64..00000000 --- a/src/sorts/merge/ModuloMergeSort.java +++ /dev/null @@ -1,70 +0,0 @@ -package sorts.merge; - -import java.lang.Math; -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class ModuloMergeSort extends Sort { - public ModuloMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Modulo Merge"); - this.setRunAllSortsName("Modulo Merge Sort"); - this.setRunSortName("Modulo Merge Sort"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void merge(int[] array, int start, int mid, int end, int maxEl) { - int left = start; - int right = mid + 1; - int finalSpot = start; - - Highlights.clearAllMarks(); - - while (left <= mid && right <= end) { - Highlights.markArray(0, left); - Highlights.markArray(1, right); - Delays.sleep(1); - - if (Reads.compareValues(array[left] % maxEl, array[right] % maxEl) <= 0) { - Writes.write(array, finalSpot, array[finalSpot] + (array[left++] % maxEl) * maxEl, 1, true, false); - } else { - Writes.write(array, finalSpot, array[finalSpot] + (array[right++] % maxEl) * maxEl, 1, true, false); - } - finalSpot++; - } - - Highlights.clearAllMarks(); - - while (left <= mid) { - Writes.write(array, finalSpot, array[finalSpot++] + (array[left++] % maxEl) * maxEl, 1, true, false); - } - while (right <= end) { - Writes.write(array, finalSpot, array[finalSpot++] + (array[right++] % maxEl) * maxEl, 1, true, false); - } - - for (int i = start; i <= end; i++) { - Writes.write(array, i, array[i] / maxEl, 1, true, false); - } - } - - public void mergeSort(int[] array, int start, int end, int maxEl) { - if (start < end) { - int mid = start + ((end - start) / 2); - this.mergeSort(array, start, mid, maxEl); - this.mergeSort(array, mid + 1, end, maxEl); - this.merge(array, start, mid, end, maxEl); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.mergeSort(array, 0, currentLength - 1, Reads.analyzeMax(array, currentLength, 0.5, true) + 1); - } -} \ No newline at end of file diff --git a/src/sorts/merge/NaturalMergeSort.java b/src/sorts/merge/NaturalMergeSort.java deleted file mode 100644 index 1ad212c0..00000000 --- a/src/sorts/merge/NaturalMergeSort.java +++ /dev/null @@ -1,79 +0,0 @@ -package sorts.merge; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class NaturalMergeSort extends Sort { - int[] merged; - - public NaturalMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Natural Merge"); - this.setRunAllSortsName("Natural Merge Sort"); - this.setRunSortName("Natural Merge Sort"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void merge(int[] arr, int left, int right, int stop) { - boolean first = true; - int index = 0; - int start = 0; - int origRight = right; - int origLeft = left; - while (left < origRight && right < stop) - if (Reads.compareIndices(arr, left, right, 1, true) == 1) { - first = false; - Writes.write(merged, index++, arr[right++], 0, false, true); - } else - if (first) { - start++; - index++; - left++; - } else - Writes.write(merged, index++, arr[left++], 0, false, true); - while (left < origRight) - Writes.write(merged, index++, arr[left++], 0, false, true); - Highlights.clearMark(2); - for (int i = start; i < index; i++) - Writes.write(arr, i + origLeft, merged[i], 1, true, false); - } - - @Override - public void runSort(int[] arr, int length, int bucketCount) { - merged = Writes.createExternalArray(length); - boolean done = false; - int start = 0; - int stop = length - 1; - while (!done) { - int prev = 0; - int left = -1; - done = true; - for (int i = start; i < stop; i++) - if (Reads.compareIndices(arr, i, i + 1, 1, true) == 1) { - if (left == -1) { - left = prev; - prev = i + 1; - } else { - merge(arr, left, prev, i + 1); - if (done) - start = i; - prev = i + 1; - left = -1; - done = false; - } - } - if (left != -1) { - merge(arr, left, prev, length); - done = false; - stop = left; - } - } - Writes.deleteExternalArray(merged); - } -} \ No newline at end of file diff --git a/src/sorts/merge/OptimizedPancakeSort.java b/src/sorts/merge/OptimizedPancakeSort.java deleted file mode 100644 index 69248544..00000000 --- a/src/sorts/merge/OptimizedPancakeSort.java +++ /dev/null @@ -1,132 +0,0 @@ -package sorts.merge; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -The MIT License (MIT) - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -final public class OptimizedPancakeSort extends Sort { - public OptimizedPancakeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Optimized Pancake"); - this.setRunAllSortsName("Optimized Pancake Sort"); - this.setRunSortName("Optimized Pancake Sort"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - //special thanks to Anonymous0726 !!! - - private void flip(int[] array, int idx) { - Writes.reversal(array, 0, idx, 0.1, true, false); - } - - private void cursedRotate(int[] array, int a, int m, int b) { - this.flip(array, a-1); - this.flip(array, m-1); - this.flip(array, b-1); - this.flip(array, b-m+a-1); - } - - private int binarySearch(int[] array, int a, int b, int value, boolean left) { - while(a < b) { - int m = a+(b-a)/2; - - boolean comp = left ? Reads.compareValues(value, array[m]) <= 0 - : Reads.compareValues(value, array[m]) < 0; - - if(comp) b = m; - else a = m+1; - } - - return a; - } - - private void pancakeMerge(int[] array, int m, int b) { - int m1, m2, m3; - - if(m >= b-m) { - m1 = m/2; - m2 = this.binarySearch(array, m, b, array[m1], false); - m3 = m1+(m2-m); - } - else { - m2 = m+(b-m)/2; - m1 = this.binarySearch(array, 0, m, array[m2], true); - m3 = (m2++)-(m-m1); - } - this.cursedRotate(array, m1, m, m2); - - if(m1 > 0 && m3 > m1) this.pancakeMerge(array, m1, m3); - - m3++; - if(m2 > m3 && b > m2) { - this.cursedRotate(array, 0, m3, b); - this.pancakeMerge(array, m2-m3, b-m3); - this.cursedRotate(array, 0, b-m3, b); - } - } - - private void pancakeMergeSort(int[] array, int n) { - if(n > 1) { - if(Reads.compareIndices(array, 0, 1, 0, true) <= 0) { - int i = 2; - for(; i < n && Reads.compareIndices(array, i-1, i, 0, true) <= 0; i++); - - if(i == n) return; - } - else { - int i = 2; - for(; i < n && Reads.compareIndices(array, i-1, i, 0, true) > 0; i++); - - if(i == n) { - this.flip(array, n-1); - return; - } - } - - int m = n/2; - - this.pancakeMergeSort(array, m); - this.cursedRotate(array, 0, m, n); - m = n-m; - - this.pancakeMergeSort(array, m); - this.pancakeMerge(array, m, n); - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.pancakeMergeSort(array, length); - } -} \ No newline at end of file diff --git a/src/sorts/merge/OutOfPlaceWeaveMergeSort.java b/src/sorts/merge/OutOfPlaceWeaveMergeSort.java deleted file mode 100644 index e4f83eda..00000000 --- a/src/sorts/merge/OutOfPlaceWeaveMergeSort.java +++ /dev/null @@ -1,109 +0,0 @@ -package sorts.merge; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class OutOfPlaceWeaveMergeSort extends Sort { - - public OutOfPlaceWeaveMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Out-of-Place Weave Merge"); - this.setRunAllSortsName("Out-of-Place Weave Merge (by Control)"); - this.setRunSortName("Out-of-Place Weave Merge"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - - //Implemented by Control - //Looks like weave merge, but it really is a normal merge. - //Why? you might ask... - - - //stats: - //best case: θ(n*log(n)) - //average case: θ(n*log(n)) - //worst case: θ(n*log(n)) - //extra memory: θ(n) - //Stable: Yes - - - private void weave(int[] array, int[] aux, int start, int end) { - - for(int i = 0; i<=end-start; i+=2){ - Writes.write(array, start+i, aux[start+i/2], 0.25, true, false); - } - - for(int i = 1; i<=end-start; i+=2){ - Writes.write(array, start+i, aux[start/2+i/2+end/2+1], 0.25, true, false); - } - - } - - private void merge(int[] array, int[] aux, int start, int end) { - - int i = start; - int j = start+1; - int pointer = start; - - while(i <= end && j <= end){ - - if(Reads.compareValues(array[i],array[j])>0){ - Writes.write(aux, pointer, array[j], 0.05, true, true); - j += 2; - }else{ - Writes.write(aux, pointer, array[i], 0.05, true, true); - i += 2; - } - pointer++; - } - - int k; - - if(i < j) {k = i;} - else {k = j;} - - while(k<=end){ - Writes.write(aux, pointer, array[k], 0.05, true, true); - k += 2; - pointer++; - } - } - - - public void controller(int[] array, int[] aux, int start, int end){ - if(end-start>=2){ - controller(array, aux, start, (end+start-1)/2); - controller(array, aux, (end+start+1)/2, end); - } - weave(array, aux, start, end); - merge(array, aux, start, end); - } - - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - - - int [] swaparray = Writes.createExternalArray(currentLength); - for(int i = 0; i= rightStart && right >= end) break; - - Highlights.markArray(1, nxt + leftStart); - Highlights.markArray(2, right); - - if(left < rightStart && right >= end){ - Highlights.clearMark(2); - Writes.write(array, nxt + leftStart, copied[(left++) - leftStart], 1, false, false); - } - else if(left >= rightStart && right < end){ - Highlights.clearMark(1); - Writes.write(array, nxt + leftStart, array[right++], 1, false, false); - } - else if(Reads.compareValues(copied[left - leftStart], array[right]) <= 0){ - Writes.write(array, nxt + leftStart, copied[(left++) - leftStart], 1, false, false); - } - else{ - Writes.write(array, nxt + leftStart, array[right++], 1, false, false); - } - } - - Highlights.clearAllMarks(); - - } - - private void mergeRun(int[] array, int[] copied, int start, int mid, int end) { - if(start == mid) return; - - mergeRun(array, copied, start, (mid+start)/2, mid); - mergeRun(array, copied, mid, (mid+end)/2, end); - - merge(array, copied, start, mid, end); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int[] copied = Writes.createExternalArray(length/2); - int start = 0; - int end = length; - int mid = start + ((end - start) / 2); - - mergeRun(array, copied, start, mid, end); - Writes.deleteExternalArray(copied); - } -} \ No newline at end of file diff --git a/src/sorts/merge/ReverseLazyStableSort.java b/src/sorts/merge/ReverseLazyStableSort.java deleted file mode 100644 index f41eec8c..00000000 --- a/src/sorts/merge/ReverseLazyStableSort.java +++ /dev/null @@ -1,204 +0,0 @@ -package sorts.merge; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class ReverseLazyStableSort extends Sort { - private double sleep = 0.5; - private boolean auxarr = false; - - public ReverseLazyStableSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Reverse Lazy Stable"); - this.setRunAllSortsName("Reverse Lazy Stable Sort"); - this.setRunSortName("Reverse Lazy Stable Sort"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void rotateLeft(int[] array, int start, int dest, int size) { - int amount = start - dest; - if (size > 1) { - while (amount >= size) { - for (int i = start; i > start - size; i--) { - Writes.swap(array, i - 1, i + size - 1, sleep, !auxarr, auxarr); - } - start -= size; - amount -= size; - } - Highlights.clearMark(2); - if (amount > 0) { - rotateSmart(array, start, dest, size / 2); - rotateSmart(array, start + size / 2, dest + size / 2, size - (size / 2)); - } - } - else { - int tmp = array[start]; - for (int i = start; i > dest; i--) { - Writes.write(array, i, array[i - 1], sleep, !auxarr, auxarr); - } - Writes.write(array, dest, tmp, sleep, !auxarr, auxarr); - } - } - - private int rotateRight(int[] array, int start, int dest, int size) { - int amount = dest - start; - int moved = 0; - if (size > 1) { - while (amount >= size) { - for (int i = start; i < start + size; i++) { - Writes.swap(array, i, i + size, 1, true, false); - } - start += size; - amount -= size; - moved += size; - } - Highlights.clearMark(2); - } - else { - int tmp = array[start]; - for (int i = start; i < dest; i++) { - Writes.write(array, i, array[i + 1], sleep, !auxarr, auxarr); - } - Writes.write(array, dest, tmp, sleep, !auxarr, auxarr); - moved += dest - start; - } - return moved; - } - - public void rotateSmart(int[] array, int start, int dest, int size) { - if (size > start - dest) { - int startDest = start - dest; - int moved = rotateRight(array, dest, start + size - startDest, startDest); - size -= moved; - dest = dest + moved; - start = dest + startDest; - } - if (size > 0) { - rotateLeft(array, start, dest, size); - } - } - - public void rotateCommon(int[] array, int start, int dest, int size, double sleep, boolean auxWrite) { - double tsleep = this.sleep; - boolean tauxarr = this.auxarr; - this.sleep = sleep; - this.auxarr = auxWrite; - if (start > dest) { - this.rotateSmart(array, start, dest, size); - } - else { - this.rotateSmart(array, start + size, start, dest - (start + size)); - } - this.sleep = tsleep; - this.auxarr = tauxarr; - } - - // Copied from BinaryInsertionSorting.java (and slightly modified) - private int binSearch(int[] array, int start, int i, int num) { - int lo = start, hi = i; - - while (lo < hi) { - int mid = lo + ((hi - lo) / 2); // avoid int overflow! - Highlights.markArray(1, lo); - Highlights.markArray(2, mid); - Highlights.markArray(3, hi); - - Delays.sleep(0.2); - - if (Reads.compareValues(num, array[mid]) < 0) { // do NOT move equal elements to right of inserted element; this maintains stability! - hi = mid; - } - else { - lo = mid + 1; - } - } - - Highlights.clearAllMarks(); - return lo; - } - - public void merge(int[] array, int start, int mid, int end) { - int binSearchThreshold = 2; - for (int len = mid - start; len >= 1; len /= 2) { - binSearchThreshold++; - } - while (start < mid && mid < end) { - if (Reads.compareIndices(array, start, mid, 0.2, true) == -1) { - start++; - // if (Reads.compareIndices(array, start, mid, 0.2, true) == -1) { - // start = binSearch(array, start + 1, mid, array[mid]); - // } - int i; - for (i = 0; i < binSearchThreshold; i++) { - if (Reads.compareIndices(array, start, mid, 0.2, true) == -1) - start++; - else break; - } - if (i == binSearchThreshold) { - start = binSearch(array, start, mid, array[mid]); - } - } - if (start >= mid) - break; - - int size = binSearch(array, mid, end, array[start]) - mid; - rotateSmart(array, mid, start, size); - - start += size + 1; - mid += size; - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - for (int i = 0; i < length - 1; i += 2) { - if (Reads.compareIndices(array, i, i + 1, 0.5, true) == 1) { - Writes.swap(array, i, i + 1, 0, true, false); - } - } - - int gap; - for (gap = 4; gap <= length; gap *= 2) { - for (int i = 0; i + gap <= length; i += gap) { - merge(array, i, i + gap / 2, i + gap); - } - } - - if (length - gap / 2 > 0) { - merge(array, 0, gap / 2, length); - } - } -} diff --git a/src/sorts/merge/Split16Merge.java b/src/sorts/merge/Split16Merge.java deleted file mode 100644 index f765af10..00000000 --- a/src/sorts/merge/Split16Merge.java +++ /dev/null @@ -1,103 +0,0 @@ -package sorts.merge; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class Split16Merge extends Sort { - public Split16Merge(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Split-16 Merge"); - this.setRunAllSortsName("Split-16 Merge Sort"); - this.setRunSortName("Split-16 Mergesort"); - this.setCategory("Merge Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - int[] medianOfSixteenSwaps = new int[] { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 1, 3, 5, 7, 9, 11, 13, 15, 2, 4, 6, 8, 10, 12, 14, 16, - 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16, - 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, - 6, 11, 7, 10, 4, 13, 14, 15, 8, 12, 2, 3, 5, 9, - 2, 5, 8, 14, 3, 9, 12, 15, 6, 7, 10, 11, - 3, 5, 12, 14, 4, 9, 8, 13, - 7, 9, 11, 13, 4, 6, 8, 10, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 7, 8, 9, 10 - }; - - private void compSwap1(int[] array, int a, int b) { - if (Reads.compareIndices(array, a, b, 1, true) > 0) { - Writes.swap(array, a, b, 0.5, true, false); - } - } - - private void compSwap2(int[] array, int a, int b, int gap, int start) { - if (Reads.compareIndices(array, start+(a*gap), start+(b*gap), 1, true) > 0) { - Writes.swap(array, start+(a*gap), start+(b*gap), 0.5, true, false); - } - } - - private void medianOfSixteen(int[] array, int a, int gap) { - for (int i = 0; i < this.medianOfSixteenSwaps.length; i += 2) - compSwap2(array, this.medianOfSixteenSwaps[i] - 1, this.medianOfSixteenSwaps[i+1] - 1, gap, a); - } - - private void merge(int[] array, int start, int size) { - int gap = size / 16; - for (int i = 0; i < gap; i++) { - medianOfSixteen(array, start + i, gap); - } - for (int subgap = gap / 2; subgap > 0; subgap /= 2) { - for (int i = 0; i < size - subgap; i++) { - compSwap1(array, start + i, start + i + subgap); - } - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - for (int i = 0; i < length - 15; i += 16) { - this.medianOfSixteen(array, i, 1); - } - - int gap; - for (gap = 32; gap <= length; gap *= 2) { - for (int i = 0; i + gap <= length; i += gap) { - merge(array, i, gap); - } - } - } -} diff --git a/src/sorts/misc/StalinSort.java b/src/sorts/misc/StalinSort.java deleted file mode 100644 index fec1af19..00000000 --- a/src/sorts/misc/StalinSort.java +++ /dev/null @@ -1,32 +0,0 @@ -package sorts.misc; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class StalinSort extends Sort { - public StalinSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stalin"); - this.setRunAllSortsName("Stalin Sort"); - this.setRunSortName("Stalinsort"); - this.setCategory("Impractical Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - for (int i = 1; i < currentLength; i++) { - Highlights.markArray(1, i); - Delays.sleep(0.5); - if (Reads.compareValues(array[i - 1], array[i]) > 0) { - Writes.write(array, i, array[i - 1], 0.5, true, false); - } - } - } -} diff --git a/src/sorts/quick/CubeRootQuickSort.java b/src/sorts/quick/CubeRootQuickSort.java deleted file mode 100644 index 98867834..00000000 --- a/src/sorts/quick/CubeRootQuickSort.java +++ /dev/null @@ -1,61 +0,0 @@ -package sorts.quick; - -import static java.lang.Math.cbrt; -import main.ArrayVisualizer; -import sorts.templates.Sort; - -public class CubeRootQuickSort extends Sort { - private static double DELAY = 0.2; - public CubeRootQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Cube Root Quick"); - this.setRunAllSortsName("Cube Root Quick Sort"); - this.setRunSortName("Cube Root Quick Sort"); - this.setCategory("Quick Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void sort(int[] arr, int start, int stop) { - int len = stop - start; - if (len >= 2) { - int root = (int) cbrt(len); - int newStart = start + root; - this.sort(arr, start, newStart); - int[] pivots = new int[root]; - Writes.changeAllocAmount(pivots.length); - for (int i = 0; i < root; i++) - Writes.write(pivots, i, i + start, 0, false, true); - for (int i = newStart; i < stop; i++) { - int left = 0, right = root; - while (left < right) { - int mid = (right - left) / 2 + left; - if (Reads.compareIndices(arr, pivots[mid], i, DELAY, true) == 1) - right = mid; - else - left = mid + 1; - } - int pos = i; - for (int j = root - 1; j >= left; j--) { - Writes.swap(arr, pivots[j] + 1, pos, DELAY, true, false); - Writes.swap(arr, pos = pivots[j], pivots[j] + 1, DELAY, true, false); - Writes.write(pivots, j, pivots[j] + 1, 0, false, true); - } - } - this.sort(arr, start, pivots[0]); - for (int i = 1; i < root; i++) - this.sort(arr, pivots[i - 1] + 1, pivots[i]); - this.sort(arr, pivots[root - 1] + 1, stop); - Writes.changeAllocAmount(-pivots.length); - } - } - - @Override - public void runSort(int[] arr, int length, int buckets) { - this.sort(arr, 0, length); - } -} \ No newline at end of file diff --git a/src/sorts/select/AnarchySort.java b/src/sorts/select/AnarchySort.java deleted file mode 100644 index 4fc5c804..00000000 --- a/src/sorts/select/AnarchySort.java +++ /dev/null @@ -1,106 +0,0 @@ -package sorts.select; - -import java.util.ArrayList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -public final class AnarchySort extends Sort { - - public AnarchySort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - setSortListName("Anarchy"); - setRunAllSortsName("Anarchy Sort (By Lancewer & McDude_73)"); - setRunSortName("Anarchy Sort"); - setCategory("Selection Sorts"); - setComparisonBased(true); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(1024); - setBogoSort(false); - - } - - private boolean containsValue(ArrayList list, int value) { - for (int at = 0; at < list.size(); at++) { - this.Delays.sleep(0.001D); - this.Highlights.markArray(1, at); - - this.Writes.startLap(); - boolean comp = (((Integer) list.get(at)).intValue() == value); - this.Writes.stopLap(); - - if (comp) - return true; - } - return false; - } - - private void swapper(int[] normalArray, int[] auxiliaryArray, int pos1, int pos2) { - this.Writes.swap(auxiliaryArray, pos1, pos2, 1.75D, true, true); - this.Writes.swap(normalArray, pos1, pos2, 1.75D, true, false); - } - - private void convert(int[] array, int[] aux, int length) { - int i = 0; - int j = 0; - - while (i < length) { - if (this.Reads.compareIndices(array, j, i, 0.001D, true) < 0) { - j = i; - } - i++; - } - - this.Writes.swap(array, 0, j, 1.0D, true, true); - - for (int init = 0; init < length; init++) { - this.Writes.write(aux, init, array[init], 0.001D, true, true); - } - - ArrayList t2 = new ArrayList<>(); - int m = 0; - - while (m < length) { - i = 0; - j = 0; - while (i < length) { - if (this.Reads.compareIndices(array, i, j, 0.001D, true) <= 0 && !containsValue(t2, i)) { - j = i; - } - i++; - } - this.Writes.changeAuxWrites(1); - t2.add(Integer.valueOf(j)); - this.Highlights.markArray(1, j); - this.Delays.sleep(1.0D); - - this.Writes.write(array, j, m, 1.0D, true, false); - m++; - } - } - - private void sortMainAndAux(int[] array, int[] aux, int length) { - for (int i = 0; i < length; i++) { - while (array[i] != i) { - swapper(array, aux, i, array[i]); - this.Highlights.markArray(3, array[i]); - } - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int[] aux =Writes.createExternalArray(length); - - convert(array, aux, length); - sortMainAndAux(array, aux, length); - - for (int i = 0; i < length; i++) - this.Writes.write(array, i, aux[i], 1.0D, true, false); - Writes.deleteExternalArray(aux); - - } - -} diff --git a/src/sorts/select/BinomialHeapSort.java b/src/sorts/select/BinomialHeapSort.java deleted file mode 100644 index fad97332..00000000 --- a/src/sorts/select/BinomialHeapSort.java +++ /dev/null @@ -1,61 +0,0 @@ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -final public class BinomialHeapSort extends Sort { - public BinomialHeapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Binomial Heap"); - this.setRunAllSortsName("Binomial Heap Sort"); - this.setRunSortName("Binomial Heapsort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int maxNode, focus, index, depth; - for (index = 2; index <= length; index+=2){ - maxNode = index; - do{ - focus = maxNode; - for (depth = 1; (focus&depth) == 0; depth*=2){ - if (Reads.compareValues(array[focus-depth-1], array[maxNode-1]) > 0) - maxNode = (focus-depth); - } - if (focus != maxNode){ - Writes.swap(array, focus-1, maxNode-1, 1, true, false); - } - } while (focus != maxNode); - } - for (index = length; index > 2; index--){ - maxNode = index; - focus = index; - for (depth = 1; focus != 0; depth*=2){ - if ((focus & depth) != 0) { - if (Reads.compareValues(array[focus-1], array[maxNode-1]) > 0) - maxNode = focus; - focus -= depth; - } - } - if (maxNode != index) { - focus = index; - do{ - Writes.swap(array, focus-1, maxNode-1, 1, true, false); - focus = maxNode; - for (depth = 1; (focus&depth) == 0; depth*=2){ - if (Reads.compareValues(array[focus-depth-1], array[maxNode-1]) > 0) - maxNode = (focus-depth); - } - } while (focus != maxNode); - } - } - } -} \ No newline at end of file diff --git a/src/sorts/select/CycleSort.java b/src/sorts/select/CycleSort.java deleted file mode 100644 index 60fa7dbb..00000000 --- a/src/sorts/select/CycleSort.java +++ /dev/null @@ -1,106 +0,0 @@ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -Copyright (c) rosettacode.org -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 -or any later version published by the Free Software Foundation; -with no Invariant Sections, no Front-Cover Texts, and no Back-Cover -Texts. A copy of the license is included in the section entitled "GNU -Free Documentation License". - * - */ - -final public class CycleSort extends Sort { - public CycleSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Cycle"); - this.setRunAllSortsName("Cycle Sort"); - this.setRunSortName("Cyclesort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - for (int cycleStart = 0; cycleStart < length - 1; cycleStart++) { - int val = array[cycleStart]; - - /* - Count the number of values that are smaller - than val since cycleStart - */ - - int pos = cycleStart; - Highlights.markArray(3, pos); - - for (int i = cycleStart + 1; i < length; i++) { - Highlights.markArray(2, i); - Delays.sleep(0.01); - - if (Reads.compareValues(array[i], val) == -1) { - pos++; - Highlights.markArray(1, pos); - Delays.sleep(0.01); - } - - } - - // there aren't any - if (pos == cycleStart) { - Highlights.markArray(1, pos); - continue; - } - - // Skip duplicates - while (val == array[pos]) { - pos++; - Highlights.markArray(1, pos); - } - - // Put val into final position - int tmp = array[pos]; - Writes.write(array, pos, val, 0.02, true, false); - val = tmp; - - /* - Repeat as long as we can find values to swap - otherwise start new cycle - */ - while (pos != cycleStart) { - pos = cycleStart; - Highlights.markArray(3, pos); - - for (int i = cycleStart + 1; i < length; i++) { - Highlights.markArray(2, i); - Delays.sleep(0.01); - - if (Reads.compareValues(array[i], val) == -1) { - pos++; - Highlights.markArray(1, pos); - Delays.sleep(0.01); - } - } - - while (val == array[pos]) { - pos++; - Highlights.markArray(1, pos); - } - - tmp = array[pos]; - Writes.write(array, pos, val, 0.02, true, false); - val = tmp; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/select/DequeueSort.java b/src/sorts/select/DequeueSort.java deleted file mode 100644 index 22167873..00000000 --- a/src/sorts/select/DequeueSort.java +++ /dev/null @@ -1,118 +0,0 @@ -package sorts.select; - -import java.util.PriorityQueue; -import java.util.Comparator; -import java.util.LinkedList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -final public class DequeueSort extends Sort { - public DequeueSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Dequeue"); - this.setRunAllSortsName("Dequeue Sort"); - this.setRunSortName("Dequeuesort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void queueAddLeft(LinkedList q, int val) { - Writes.startLap(); - q.addFirst(val); - Writes.stopLap(); - } - - private void queueAddRight(LinkedList q, int val) { - Writes.startLap(); - q.addLast(val); - Writes.stopLap(); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - PriorityQueue> heap = new PriorityQueue<>(sortLength / 2, new Comparator>(){ - @Override - public int compare(LinkedList q1, LinkedList q2) { - return Reads.compareValues(q1.peek(), q2.peek()); - } - }); - - int currentValueRight = array[0]; - int currentValueLeft = array[0]; - LinkedList currentQueue = new LinkedList<>(); - this.queueAddRight(currentQueue, currentValueRight); - Writes.changeAllocAmount(1); - - int qCount = 1; - - for (int i = 1; i < sortLength; i++) { - Highlights.markArray(1, i); - Highlights.markArray(2, qCount); - if (Reads.compareValues(array[i], currentValueRight) >= 0) { - currentValueRight = array[i]; - this.queueAddRight(currentQueue, array[i]); - } - else if (Reads.compareValues(array[i], currentValueLeft) <= 0) { - currentValueLeft = array[i]; - this.queueAddLeft(currentQueue, array[i]); - } - else { - currentValueRight = array[i]; - currentValueLeft = array[i]; - heap.add(currentQueue); - currentQueue = new LinkedList<>(); - this.queueAddRight(currentQueue, array[i]); - qCount++; - } - Writes.changeAuxWrites(1); - Writes.changeAllocAmount(1); - Delays.sleep(1); - } - heap.add(currentQueue); - - int j = 0; - while (qCount > 0) { - Highlights.markArray(2, qCount); - LinkedList first = heap.poll(); - Writes.write(array, j++, first.pop(), 1, true, false); - Writes.changeAllocAmount(-1); - if (first.size() > 0) { - heap.add(first); - } - else { - qCount--; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/select/ForcedStableHeapSort.java b/src/sorts/select/ForcedStableHeapSort.java deleted file mode 100644 index b8901211..00000000 --- a/src/sorts/select/ForcedStableHeapSort.java +++ /dev/null @@ -1,76 +0,0 @@ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/** - * @author Yuri-chan2007 - * - */ -public final class ForcedStableHeapSort extends Sort { - - public ForcedStableHeapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Forced Stable Heap"); - this.setRunAllSortsName("Forced Stable Heap Sort"); - this.setRunSortName("Forced Stable Heapsort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private boolean stableComp(int[] array, int[] key, int a, int b) { - int comp = Reads.compareIndices(array, a, b, 0.0, true); - - return comp > 0 || (comp == 0 && Reads.compareOriginalIndices(key, a, b, 0.0, false) > 0); - } - - private void stableSwap(int[] array, int[] key, int a, int b) { - Writes.swap(array, a, b, 0.0, true, false); - Writes.swap(key, a, b, 1.0, false, true); - } - - private void siftDown(int[] array, int[] key, int root, int dist, int start) { - while (root <= dist / 2) { - int leaf = 2 * root; - if (leaf < dist && this.stableComp(array, key, start + leaf, start + leaf - 1)) { - leaf++; - } - if(this.stableComp(array, key, start + leaf - 1, start + root - 1)) { - this.stableSwap(array, key, start + leaf - 1, start + root - 1); - root = leaf; - } - else break; - } - } - - protected void heapify(int[] array, int[] key, int low, int high) { - int length = high - low; - for (int i = length / 2; i >= 1; i--) { - siftDown(array, key, i, length, low); - } - } - - protected void heapSort(int[] array, int[] key, int start, int length) { - heapify(array, key, start, length); - for (int i = length - start; i > 1; i--) { - this.stableSwap(array, key, start, start + i - 1); - siftDown(array, key, 1, i - 1, start); - } - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) { - int[] key = Writes.createExternalArray(sortLength); - for(int i = 0; i < sortLength; i++) - Writes.write(key, i, i, 0.5, true, true); - heapSort(array, key, 0, sortLength); - Writes.deleteExternalArray(key); - - } - -} diff --git a/src/sorts/select/HeavyHeapSort.java b/src/sorts/select/HeavyHeapSort.java deleted file mode 100644 index 6280ba12..00000000 --- a/src/sorts/select/HeavyHeapSort.java +++ /dev/null @@ -1,66 +0,0 @@ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.HeapSorting; - -/* - * -Copyright (c) rosettacode.org. -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.2 -or any later version published by the Free Software Foundation; -with no Invariant Sections, no Front-Cover Texts, and no Back-Cover -Texts. A copy of the license is included in the section entitled "GNU -Free Documentation License". - * - */ - -final public class HeavyHeapSort extends HeapSorting { - public HeavyHeapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Heavy Heap"); - this.setRunAllSortsName("Heavy Heap Sort"); - this.setRunSortName("Heavy Heapsort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void bitReversal(int[] array, int a, int b) { - int len = b-a, m = 0; - int d1 = len>>1, d2 = d1+(d1>>1); - - for(int i = 1; i < len-1; i++) { - int j = d1; - - for( - int k = i, n = d2; - (k&1) == 0; - j -= n, k >>= 1, n >>= 1 - ); - m += j; - if(m > i) Writes.swap(array, a+i, a+m, 1, true, false); - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - boolean dir = false; - for (int i = 0; i < length; i++) { - this.heapify(array, i, length, 0.002, dir); - dir = !dir; - } - Writes.changeReversals(1); - for (int i = 1, j = length - 1; i < j; i += 2, j -= 2) { - Writes.swap(array, i, j, 1, true, false); - } - bitReversal(array, 0, length); - bitReversal(array, 0, length / 2); - bitReversal(array, length / 2, length); - } -} \ No newline at end of file diff --git a/src/sorts/select/OptimizedLazyHeapSort.java b/src/sorts/select/OptimizedLazyHeapSort.java deleted file mode 100644 index d6a62b06..00000000 --- a/src/sorts/select/OptimizedLazyHeapSort.java +++ /dev/null @@ -1,100 +0,0 @@ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2021 aphitorite - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class OptimizedLazyHeapSort extends Sort { - public OptimizedLazyHeapSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Optimized Lazy Heap"); - this.setRunAllSortsName("Optimized Lazy Heap Sort"); - this.setRunSortName("Optimized Lazy Heapsort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private int findMin(int[] array, int p, int a, int b, int s) { - int min = p; - - for(int i = a; i < b; i += s) - if(Reads.compareIndices(array, i, min, 0.1, true) < 0) - min = i; - - return min; - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - int s = (int)Math.sqrt(length-1)+1; - - int f = (length-1)%s+1; - int fMin = this.findMin(array, 0, 1, f, 1); - - for(int j = f; j < length; j += s) { - int min = this.findMin(array, j, j+1, j+s, 1); - - if(j != min) Writes.swap(array, j, min, 1, true, false); - } - - for(int j = 0; j < length;) { - int min = this.findMin(array, fMin, f, length, s); - - if(min == fMin) { - if(j != min) Writes.swap(array, j, min, 1, true, false); - if(++j == f) f += s; //check for bounds if last block is < s - - fMin = this.findMin(array, j, j+1, f, 1); - } - else { - if(j == fMin) fMin = this.findMin(array, j+1, j+2, f, 1); - - int nMin = this.findMin(array, j, min+1, min+s, 1); - - if(nMin == j) Writes.swap(array, j, min, 1, true, false); - - else { - Highlights.clearMark(2); - - int t = array[j]; - Writes.write(array, j, array[min], 0.5, true, false); - Writes.write(array, min, array[nMin], 0.5, true, false); - Writes.write(array, nMin, t, 0.5, true, false); - } - - if(++j == f) f += s; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/select/QueueSort.java b/src/sorts/select/QueueSort.java deleted file mode 100644 index c4ad0f92..00000000 --- a/src/sorts/select/QueueSort.java +++ /dev/null @@ -1,105 +0,0 @@ -package sorts.select; - -import java.util.PriorityQueue; -import java.util.Comparator; -import java.util.LinkedList; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -final public class QueueSort extends Sort { - public QueueSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Queue"); - this.setRunAllSortsName("Queue Sort"); - this.setRunSortName("Queuesort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void queueAdd(LinkedList q, int val) { - Writes.startLap(); - q.add(val); - Writes.stopLap(); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - PriorityQueue> heap = new PriorityQueue<>(sortLength / 2, new Comparator>(){ - @Override - public int compare(LinkedList q1, LinkedList q2) { - return Reads.compareValues(q1.peek(), q2.peek()); - } - }); - - int currentValue = array[0]; - LinkedList currentQueue = new LinkedList<>(); - this.queueAdd(currentQueue, currentValue); - heap.add(currentQueue); - Writes.changeAllocAmount(1); - - int qCount = 1; - - for (int i = 1; i < sortLength; i++) { - Highlights.markArray(1, i); - Highlights.markArray(2, qCount); - if (Reads.compareValues(array[i], array[i - 1]) >= 0) { - this.queueAdd(currentQueue, array[i]); - } - else { - currentValue = array[i]; - currentQueue = new LinkedList<>(); - this.queueAdd(currentQueue, array[i]); - heap.add(currentQueue); - qCount++; - } - Writes.changeAuxWrites(1); - Writes.changeAllocAmount(1); - Delays.sleep(1); - } - - int j = 0; - while (qCount > 0) { - Highlights.markArray(2, qCount); - LinkedList first = heap.poll(); - Writes.write(array, j++, first.pop(), 1, true, false); - Writes.changeAllocAmount(-1); - if (first.size() > 0) { - heap.add(first); - } - else { - qCount--; - } - } - } -} \ No newline at end of file diff --git a/src/sorts/select/ReverseSelectionSort.java b/src/sorts/select/ReverseSelectionSort.java deleted file mode 100644 index 62b9fd03..00000000 --- a/src/sorts/select/ReverseSelectionSort.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * - */ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2021 mingyue12 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -/** - * @author mingyue12 - * - */ -public final class ReverseSelectionSort extends Sort { - - /** - * @param arrayVisualizer - */ - public ReverseSelectionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Reverse Selection"); - this.setRunAllSortsName("Reverse Selection Sort"); - this.setRunSortName("Reverse Selection Sort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - // TODO Auto-generated method stub - for (int i = sortLength - 1; i >= 0; i--) { - int highestindex = 0; - - for (int j = 1; j < i + 1; j++) { - Highlights.markArray(2, j); - Delays.sleep(0.01); - - if (Reads.compareValues(array[j], array[highestindex]) == 1){ - highestindex = j; - Highlights.markArray(1, highestindex); - Delays.sleep(0.01); - } - } - Writes.swap(array, i, highestindex, 0.02, true, false); - } - - } - -} diff --git a/src/sorts/select/SandpaperSort.java b/src/sorts/select/SandpaperSort.java deleted file mode 100644 index a3c09e00..00000000 --- a/src/sorts/select/SandpaperSort.java +++ /dev/null @@ -1,57 +0,0 @@ -package sorts.select; - -import main.ArrayVisualizer; -import sorts.templates.Sort; - -/* -MIT License - -Copyright (c) 2020 yuji -Copyright (c) 2021 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -final public class SandpaperSort extends Sort { - public SandpaperSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Sandpaper"); - this.setRunAllSortsName("Sandpaper Sort"); - this.setRunSortName("Sandpapersort"); - this.setCategory("Selection Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - for (int i = 0; i < currentLength - 1; i++) { - for (int j = i + 1; j < currentLength; j++) { - if (Reads.compareIndices(array, i, j, 0.05, true) > 0) { - Writes.swap(array, i, j, 0.05, true, false); - } - } - } - } -} diff --git a/src/sorts/templates/Sort.java b/src/sorts/templates/Sort.java deleted file mode 100644 index 83ea0773..00000000 --- a/src/sorts/templates/Sort.java +++ /dev/null @@ -1,148 +0,0 @@ -package sorts.templates; - -import main.ArrayVisualizer; -import utils.Delays; -import utils.Highlights; -import utils.Reads; -import utils.Writes; - -public abstract class Sort { - private boolean sortEnabled; - - private String sortListName; - private String runAllSortsName; - private String runSortName; - - private String category; - - private boolean comparisonBased; - private boolean bucketSort; - private boolean radixSort; - private boolean unreasonablySlow; - private boolean bogoSort; - - private int unreasonableLimit; - - private String question; - private int defaultAnswer; - - protected ArrayVisualizer arrayVisualizer; - - protected Delays Delays; - protected Highlights Highlights; - protected Reads Reads; - protected Writes Writes; - - protected Sort(ArrayVisualizer arrayVisualizer) { - this.enableSort(true); // If set to false, ArrayV won't load the sort - - this.setSortListName(""); // Displays in the 'Choose Sort' menu - this.setRunAllSortsName(""); // Displays during 'Run All Sorts' - this.setRunSortName(""); // Displays when a sort is picked from 'Choose Sort' - this.setCategory(""); // Shown at the top-left corner of the window - - this.setComparisonBased(true); // If set to false, sort will listed on the right side of the 'Choose Sort' menu - this.setBucketSort(false); // Slightly changes the 'Customize Sort' dialog - this.setRadixSort(false); // Also slightly changes the 'Customize Sort' dialog - - this.setUnreasonablySlow(false); // Indicates a sort is so inefficient that it will run for a very long time even after clicking 'Skip Sort' - this.setUnreasonableLimit(0); // If a sort is 'unreasonably slow', a warning will pop up if the array length is more than this number - this.setBogoSort(false); // Slightly changes the 'unreasonably slow' dialog - - this.setQuestion(null, 0); // Asks a specific question before this sort is run - - this.arrayVisualizer = arrayVisualizer; - - this.Delays = arrayVisualizer.getDelays(); - this.Highlights = arrayVisualizer.getHighlights(); - this.Reads = arrayVisualizer.getReads(); - this.Writes = arrayVisualizer.getWrites(); - } - - public boolean isSortEnabled() { - return this.sortEnabled; - } - public String getSortListName() { - return this.sortListName; - } - public String getRunAllSortsName() { - return this.runAllSortsName; - } - public String getRunSortName() { - return this.runSortName; - } - public String getCategory() { - return this.category; - } - public boolean isComparisonBased() { - return this.comparisonBased; - } - public boolean usesBuckets() { - return this.bucketSort; - } - public boolean isRadixSort() { - return this.radixSort; - } - public boolean isUnreasonablySlow() { - return this.unreasonablySlow; - } - public int getUnreasonableLimit() { - return this.unreasonableLimit; - } - public boolean isBogoSort() { - return this.bogoSort; - } - public String getQuestion() { - return this.question; - } - public int getDefaultAnswer() { - return this.defaultAnswer; - } - - protected void enableSort(boolean Bool) { - this.sortEnabled = Bool; - } - protected void setSortListName(String ID) { - this.sortListName = ID; - } - protected void setRunAllSortsName(String ID) { - this.runAllSortsName = ID; - } - protected void setRunSortName(String ID) { - this.runSortName = ID; - } - protected void setCategory(String ID) { - this.category = ID; - } - public void setComparisonBased(boolean Bool) { - this.comparisonBased = Bool; - } - public void setBucketSort(boolean Bool) { - this.bucketSort = Bool; - } - protected void setRadixSort(boolean Bool) { - this.radixSort = Bool; - } - public void setUnreasonablySlow(boolean Bool) { - this.unreasonablySlow = Bool; - } - public void setUnreasonableLimit(int number) { - this.unreasonableLimit = number; - } - protected void setBogoSort(boolean Bool) { - this.bogoSort = Bool; - } - protected void setQuestion(String question) { - this.question = question; - } - protected void setQuestion(String question, int defaultAnswer) { - this.question = question; - this.defaultAnswer = defaultAnswer; - } - - public int validateAnswer(int answer) { - return answer; - } - - public abstract void runSort(int[] array, int sortLength, int bucketCount) throws Exception; //bucketCount will be zero for comparison-based sorts -} \ No newline at end of file diff --git a/src/sorts/templates/SortComparator.java b/src/sorts/templates/SortComparator.java deleted file mode 100644 index 0c29456b..00000000 --- a/src/sorts/templates/SortComparator.java +++ /dev/null @@ -1,12 +0,0 @@ -package sorts.templates; - -import java.util.Comparator; - -final public class SortComparator implements Comparator { - public SortComparator() {} - - @Override - public int compare(Sort left, Sort right) { - return left.getSortListName().compareTo(right.getSortListName()); - } -} \ No newline at end of file diff --git a/src/test/Tester.java b/src/test/Tester.java deleted file mode 100644 index b95898f6..00000000 --- a/src/test/Tester.java +++ /dev/null @@ -1,84 +0,0 @@ -package test; - -import java.util.Arrays; - -import main.ArrayVisualizer; -import utils.Delays; -import utils.Highlights; -import utils.Reads; -import utils.Timer; -import utils.Writes; - -public class Tester { - private static Delays Delays; - private static Highlights Highlights; - private static Reads Reads; - private static Timer RealTimer; - private static Writes Writes; - - // Attempts to use insertion sort on [begin, end). Will return false if more than - // partial_insertion_sort_limit elements were moved, and abort sorting. Otherwise it will - // successfully sort and return true. - private static boolean pdqPartialInsertSort(int[] array, int begin, int end) { - if (begin == end) return true; - - int limit = 0; - for (int cur = begin + 1; cur != end; ++cur) { - if (limit > 8) return false; - - int sift = cur; - int siftMinusOne = cur - 1; - - // Compare first so we can avoid 2 moves for an element already positioned correctly. - if (Reads.compareValues(array[sift], array[siftMinusOne]) < 0) { - int tmp = array[sift]; - - do { - Writes.write(array, sift--, array[siftMinusOne], 0, false, false); - } while (sift != begin && Reads.compareValues(tmp, array[--siftMinusOne]) < 0); - - Writes.write(array, sift, tmp, 0, false, false); - limit += cur - sift; - } - } - return true; - } - - public static void main(String[] args) throws Exception { - int[] testArr = new int[32]; - for(int i = 0; i < testArr.length; i++) { - testArr[i] = i; - } - - ArrayVisualizer av = new ArrayVisualizer(); - - Delays = new Delays(av); - Delays.setSleepRatio(Double.MAX_VALUE); - - Highlights = new Highlights(av, testArr.length); - Highlights.toggleFancyFinishes(false); - - RealTimer = new Timer(av); - RealTimer.toggleRealTimer(false); - - Reads = new Reads(av); - Writes = new Writes(av); - - for(int i = 0; i < testArr.length; i++){ - Writes.swap(testArr, i, (int)(Math.random()*testArr.length), 0, false, false); - } - - System.out.println(Arrays.toString(testArr)); - - RealTimer.startLap(); - - pdqPartialInsertSort(testArr, 0, testArr.length); - - RealTimer.stopLap(); - - RealTimer.toggleRealTimer(true); - - System.out.println(Arrays.toString(testArr)); - System.out.println(RealTimer.getRealTime()); - } -} \ No newline at end of file diff --git a/src/threads/MultipleSortThread.java b/src/threads/MultipleSortThread.java deleted file mode 100644 index ccd06f10..00000000 --- a/src/threads/MultipleSortThread.java +++ /dev/null @@ -1,121 +0,0 @@ -package threads; - -import main.ArrayManager; -import main.ArrayVisualizer; -import panes.JErrorPane; -import frames.ArrayFrame; -import sorts.templates.Sort; -import utils.Delays; -import utils.Highlights; -import utils.Reads; -import utils.Sounds; -import utils.StopSort; -import utils.Timer; -import utils.Writes; - -public abstract class MultipleSortThread { - protected ArrayManager arrayManager; - protected ArrayVisualizer arrayVisualizer; - protected ArrayFrame arrayFrame; - protected Delays Delays; - protected Highlights Highlights; - protected Reads Reads; - protected Writes Writes; - protected Sounds Sounds; - protected Timer Timer; - - protected volatile int sortCount; - protected volatile int sortNumber; - - protected volatile int categoryCount; - - private int startingLength; - - public MultipleSortThread(ArrayVisualizer arrayVisualizer) { - this.arrayVisualizer = arrayVisualizer; - this.arrayManager = arrayVisualizer.getArrayManager(); - this.arrayFrame = arrayVisualizer.getArrayFrame(); - this.Delays = arrayVisualizer.getDelays(); - this.Highlights = arrayVisualizer.getHighlights(); - this.Reads = arrayVisualizer.getReads(); - this.Writes = arrayVisualizer.getWrites(); - this.Sounds = arrayVisualizer.getSounds(); - this.Timer = arrayVisualizer.getTimer(); - - this.startingLength = arrayVisualizer.getCurrentLength(); - } - - protected int calculateLength(int defaultLength) { - return (int) Math.max((defaultLength / 2048d) * this.startingLength, 2); - } - protected int calculateLengthSlow(int defaultLength, int unreasonableLimit) { - return Math.min(this.calculateLength(defaultLength), unreasonableLimit); - } - - protected double calculateSpeed(double defaultDelay, int length) { - if(length < (this.startingLength / 2)) { - return defaultDelay * Math.pow((this.startingLength / 2048d), 2); - } - else { - return defaultDelay * (this.startingLength / 2048d); - } - } - - protected synchronized void runIndividualSort(Sort sort, int bucketCount, int[] array, int defaultLength, double defaultSpeed, boolean slowSort) throws Exception { - Delays.setSleepRatio(2.5); - - int sortLength; - if(slowSort) { - sortLength = this.calculateLengthSlow(defaultLength, sort.getUnreasonableLimit()); - } - else { - sortLength = this.calculateLength(defaultLength); - } - if(sortLength != arrayVisualizer.getCurrentLength()) { - arrayFrame.setLengthSlider(sortLength); - } - - arrayManager.refreshArray(array, arrayVisualizer.getCurrentLength(), this.arrayVisualizer); - - arrayVisualizer.setHeading(sort.getRunAllSortsName() + " (Sort " + this.sortNumber + " of " + this.sortCount + ")"); - - double sortSpeed = this.calculateSpeed(defaultSpeed, arrayVisualizer.getCurrentLength()); - Delays.setSleepRatio(sortSpeed); - - Timer.enableRealTimer(); - - // arrayVisualizer.toggleVisualUpdates(true); - try { - sort.runSort(array, arrayVisualizer.getCurrentLength(), bucketCount); - } - catch (StopSort e) { } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - // arrayVisualizer.toggleVisualUpdates(false); - - arrayVisualizer.endSort(); - Thread.sleep(1000); - - this.sortNumber++; - } - - protected abstract void executeSortList(int[] array) throws Exception; - protected abstract void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception; - - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } - - public int getSortCount() { - return this.sortCount; - } - - public int getCategoryCount() { - return this.categoryCount; - } -} \ No newline at end of file diff --git a/src/threads/RunAllSorts.java b/src/threads/RunAllSorts.java deleted file mode 100644 index d6e9761e..00000000 --- a/src/threads/RunAllSorts.java +++ /dev/null @@ -1,74 +0,0 @@ -package threads; - -import java.util.ArrayList; - -import main.ArrayVisualizer; -import panes.JErrorPane; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunAllSorts { - private ArrayVisualizer arrayVisualizer; - private ArrayList allSortThreads; - - public RunAllSorts(ArrayVisualizer arrayVisualizer) { - this.arrayVisualizer = arrayVisualizer; - this.allSortThreads = new ArrayList<>(); - this.allSortThreads.add(new RunExchangeSorts(arrayVisualizer)); - this.allSortThreads.add(new RunQuickSorts(arrayVisualizer)); - this.allSortThreads.add(new RunSelectionSorts(arrayVisualizer)); - this.allSortThreads.add(new RunInsertionSorts(arrayVisualizer)); - this.allSortThreads.add(new RunMergeSorts(arrayVisualizer)); - this.allSortThreads.add(new RunDistributionSorts(arrayVisualizer)); - this.allSortThreads.add(new RunConcurrentSorts(arrayVisualizer)); - this.allSortThreads.add(new RunHybridSorts(arrayVisualizer)); - this.allSortThreads.add(new RunMiscellaneousSorts(arrayVisualizer)); - this.allSortThreads.add(new RunImpracticalSorts(arrayVisualizer)); - } - - public void reportAllSorts(int[] array) { - int totalSortCount = 0; - for(MultipleSortThread category : this.allSortThreads) { - totalSortCount += category.getSortCount(); - } - - try { - int currentSort = 1; - for(MultipleSortThread thread : this.allSortThreads) { - thread.reportAllSorts(array, currentSort, totalSortCount); - this.arrayVisualizer.getSortingThread().join(); - currentSort += thread.getCategoryCount(); - } - } catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - - this.arrayVisualizer.setCategory("Run All Sorts"); - this.arrayVisualizer.setHeading("Finished!!"); - this.arrayVisualizer.updateNow(); - } -} \ No newline at end of file diff --git a/src/threads/RunComparisonSort.java b/src/threads/RunComparisonSort.java deleted file mode 100644 index d04750d2..00000000 --- a/src/threads/RunComparisonSort.java +++ /dev/null @@ -1,177 +0,0 @@ -package threads; - -import java.lang.reflect.Constructor; - -import javax.swing.JOptionPane; - -import main.ArrayManager; -import main.ArrayVisualizer; -import panes.JEnhancedOptionPane; -import panes.JErrorPane; -import sorts.templates.Sort; -import utils.Delays; -import utils.SortingNetworkGenerator; -import utils.Sounds; -import utils.StopSort; -import utils.Timer; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunComparisonSort { - private ArrayManager arrayManager; - private ArrayVisualizer arrayVisualizer; - private Delays delayOps; - private Sounds sounds; - private Timer realTimer; - - private Object[] inputOptions; - - public RunComparisonSort(ArrayVisualizer arrayVisualizer) { - this.arrayVisualizer = arrayVisualizer; - this.arrayManager = arrayVisualizer.getArrayManager(); - this.delayOps = arrayVisualizer.getDelays(); - this.sounds = arrayVisualizer.getSounds(); - this.realTimer = arrayVisualizer.getTimer(); - - this.inputOptions = new Object[]{"Enter", "Use default"}; - } - - private int getCustomInput(String text) throws Exception { - String input = JEnhancedOptionPane.showInputDialog("Customize Sort", text, this.inputOptions); - int integer = Integer.parseInt(input); - return Math.abs(integer); - } - - public void ReportComparativeSort(int[] array, int selection) { - if(arrayVisualizer.isActive()) - return; - - //TODO: This code is bugged! It causes the program to forget the sleep ratio specified by the user! - if(delayOps.skipped()) { - delayOps.setSleepRatio(1); - delayOps.changeSkipped(false); - } - - sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try { - Class sortClass = arrayVisualizer.getComparisonSorts()[selection].sortClass; - Constructor newSort = sortClass.getConstructor(new Class[] {ArrayVisualizer.class}); - Sort sort = (Sort) newSort.newInstance(RunComparisonSort.this.arrayVisualizer); - - int extra = 0; - - if (sort.getQuestion() != null) { - try { - extra = sort.validateAnswer(getCustomInput(sort.getQuestion())); - } - catch(Exception e) { - extra = sort.getDefaultAnswer(); - } - } - - boolean goAhead; - - if(sort.isUnreasonablySlow() && arrayVisualizer.getCurrentLength() > sort.getUnreasonableLimit()) { - goAhead = false; - Object[] options = { "Let's see how bad " + sort.getRunSortName() + " is!", "Cancel" }; - - if(sort.isBogoSort()) { - int warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Even at a high speed, " - + sort.getRunSortName() + "ing " + arrayVisualizer.getCurrentLength() - + " numbers will almost certainly not finish in a reasonable amount of time. " - + "Are you sure you want to continue?", "Warning!", 2, JOptionPane.WARNING_MESSAGE, - null, options, options[1]); - if(warning == 0) goAhead = true; - else goAhead = false; - } - else { - int warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Even at a high speed, " - + sort.getRunSortName() + "ing " + arrayVisualizer.getCurrentLength() - + " numbers will not finish in a reasonable amount of time. " - + "Are you sure you want to continue?", "Warning!", 2, JOptionPane.WARNING_MESSAGE, - null, options, options[1]); - - if(warning == 0) goAhead = true; - else goAhead = false; - } - } - else { - goAhead = true; - } - - if(goAhead) { - arrayManager.toggleMutableLength(false); - arrayManager.refreshArray(array, arrayVisualizer.getCurrentLength(), arrayVisualizer); - - arrayVisualizer.setHeading(sort.getRunSortName()); - arrayVisualizer.setCategory(sort.getCategory()); - - realTimer.enableRealTimer(); - boolean antiq = arrayVisualizer.useAntiQSort(); - boolean networks = arrayVisualizer.generateSortingNetworks(); - if (antiq) - arrayVisualizer.initAntiQSort(); - else if (networks) - arrayVisualizer.getReads().networkIndices.clear(); - - try { - sort.runSort(array, arrayVisualizer.getCurrentLength(), extra); - } - catch (StopSort e) { } - catch (OutOfMemoryError e) { - JErrorPane.invokeCustomErrorMessage(sort.getRunAllSortsName() + " ran out of memory: " + e.getMessage()); - throw new RuntimeException(e); - } - - if (antiq) - arrayVisualizer.finishAntiQSort(sort.getClass().getSimpleName()); - else if (networks) - SortingNetworkGenerator.encodeNetworkAndDisplay( - sort.getClass().getSimpleName(), - arrayVisualizer.getReads().networkIndices.toArray(new Integer[] {}), - arrayVisualizer.getCurrentLength() - ); - } - else { - arrayManager.initializeArray(array); - } - } - catch(Exception e) { - JErrorPane.invokeErrorMessage(e); - } - arrayVisualizer.endSort(); - arrayManager.toggleMutableLength(true); - sounds.toggleSound(false); - } - }); - - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunConcurrentSorts.java b/src/threads/RunConcurrentSorts.java deleted file mode 100644 index 8065bb71..00000000 --- a/src/threads/RunConcurrentSorts.java +++ /dev/null @@ -1,167 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.concurrent.*; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2019 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunConcurrentSorts extends MultipleSortThread { - private Sort FoldSort; - private Sort CreaseSort; - private Sort MatrixSort; - private Sort BitonicSortRecursive; - private Sort OddEvenMergeSortRecursive; - private Sort PairwiseSortRecursive; - private Sort BoseNelsonSortRecursive; - private Sort WeaveSortRecursive; - private Sort BitonicSortIterative; - private Sort OddEvenMergeSortIterative; - private Sort PairwiseSortIterative; - private Sort BoseNelsonSortIterative; - private Sort WeaveSortIterative; - private Sort MergeExchangeSortIterative; - private Sort BitonicSortParallel; - private Sort BoseNelsonSortParallel; - private Sort DiamondSortIterative; - private Sort DiamondSortRecursive; - private Sort OddEvenMergeSortParallel; - private Sort OptimizedOddEvenMergeSort; - private Sort PairwiseMergeSortIterative; - private Sort PairwiseMergeSortRecursive; - private Sort WeaveSortParallel; - private Sort ApollyonSort; - - public RunConcurrentSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 24; - this.categoryCount = this.sortCount; - - FoldSort = new FoldSort(this.arrayVisualizer); - CreaseSort = new CreaseSort(this.arrayVisualizer); - MatrixSort = new MatrixSort(this.arrayVisualizer); - BitonicSortRecursive = new BitonicSortRecursive(this.arrayVisualizer); - OddEvenMergeSortRecursive = new OddEvenMergeSortRecursive(this.arrayVisualizer); - PairwiseSortRecursive = new PairwiseSortRecursive(this.arrayVisualizer); - BoseNelsonSortRecursive = new BoseNelsonSortRecursive(this.arrayVisualizer); - WeaveSortRecursive = new WeaveSortRecursive(this.arrayVisualizer); - BitonicSortIterative = new BitonicSortIterative(this.arrayVisualizer); - OddEvenMergeSortIterative = new OddEvenMergeSortIterative(this.arrayVisualizer); - PairwiseSortIterative = new PairwiseSortIterative(this.arrayVisualizer); - BoseNelsonSortIterative = new BoseNelsonSortIterative(this.arrayVisualizer); - WeaveSortIterative = new WeaveSortIterative(this.arrayVisualizer); - MergeExchangeSortIterative = new MergeExchangeSortIterative(this.arrayVisualizer); - BitonicSortParallel = new BitonicSortParallel(this.arrayVisualizer); - BoseNelsonSortParallel = new BoseNelsonSortParallel(this.arrayVisualizer); - DiamondSortIterative = new DiamondSortIterative(this.arrayVisualizer); - DiamondSortRecursive = new DiamondSortRecursive(this.arrayVisualizer); - OddEvenMergeSortParallel = new OddEvenMergeSortParallel(this.arrayVisualizer); - OptimizedOddEvenMergeSort = new OptimizedOddEvenMergeSort(this.arrayVisualizer); - PairwiseMergeSortIterative = new PairwiseMergeSortIterative(this.arrayVisualizer); - PairwiseMergeSortRecursive = new PairwiseMergeSortRecursive(this.arrayVisualizer); - WeaveSortParallel = new WeaveSortParallel(this.arrayVisualizer); - ApollyonSort = new ApollyonSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - // Other - RunConcurrentSorts.this.runIndividualSort(FoldSort, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(CreaseSort, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(ApollyonSort, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(MatrixSort, 0, array, 256, 0.667, false); - RunConcurrentSorts.this.runIndividualSort(OptimizedOddEvenMergeSort, 0, array, 1024, 1, false); - - // Recursive - RunConcurrentSorts.this.runIndividualSort(BitonicSortRecursive, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(OddEvenMergeSortRecursive, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(PairwiseSortRecursive, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(BoseNelsonSortRecursive, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(WeaveSortRecursive, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(DiamondSortRecursive, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(PairwiseMergeSortRecursive, 0, array, 1024, 1, false); - - // Parallel - RunConcurrentSorts.this.runIndividualSort(BitonicSortParallel, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(OddEvenMergeSortParallel, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(BoseNelsonSortParallel, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(WeaveSortParallel, 0, array, 1024, 1, false); - - // Iterative - RunConcurrentSorts.this.runIndividualSort(BitonicSortIterative, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(OddEvenMergeSortIterative, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(PairwiseSortIterative, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(BoseNelsonSortIterative, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(WeaveSortIterative, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(MergeExchangeSortIterative, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(DiamondSortIterative, 0, array, 1024, 1, false); - RunConcurrentSorts.this.runIndividualSort(PairwiseMergeSortIterative, 0, array, 1024, 1, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunConcurrentSorts.this.sortNumber = current; - RunConcurrentSorts.this.sortCount = total; - } - else { - RunConcurrentSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Concurrent Sorts"); - - RunConcurrentSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Concurrent Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunDistributionSort.java b/src/threads/RunDistributionSort.java deleted file mode 100644 index 6b84c2fd..00000000 --- a/src/threads/RunDistributionSort.java +++ /dev/null @@ -1,261 +0,0 @@ -package threads; - -import java.lang.reflect.Constructor; - -import javax.swing.JOptionPane; - -import main.ArrayManager; -import main.ArrayVisualizer; -import panes.JEnhancedOptionPane; -import panes.JErrorPane; -import sorts.templates.Sort; -import utils.Delays; -import utils.Sounds; -import utils.StopSort; -import utils.Timer; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunDistributionSort { - private ArrayManager arrayManager; - private ArrayVisualizer arrayVisualizer; - private Delays delayOps; - private Sounds sounds; - private Timer realTimer; - - private Object[] inputOptions; - - public RunDistributionSort(ArrayVisualizer arrayVisualizer) { - this.arrayVisualizer = arrayVisualizer; - this.arrayManager = arrayVisualizer.getArrayManager(); - this.delayOps = arrayVisualizer.getDelays(); - this.sounds = arrayVisualizer.getSounds(); - this.realTimer = arrayVisualizer.getTimer(); - - this.inputOptions = new Object[]{"Enter", "Use default"}; - } - - private String getTimeSortEstimate(int bucketCount) { - String timeString = ""; - String timeUnit; - - int seconds = Math.max(((arrayVisualizer.getCurrentLength() * bucketCount) / 1000), 1); - int minutes; - int hours; - long days; - - if(seconds >= 60) { - minutes = Math.round(seconds / 60); - - if(minutes >= 60) { - hours = Math.round(minutes / 60); - - if(hours >= 24) { - days = Math.round(hours / 24); - - if(days < 2) timeUnit = "day"; - else timeUnit = "days"; - - timeString = "" + arrayVisualizer.getNumberFormat().format(days) + " " + timeUnit + " "; - } - else { - if(hours < 2) timeUnit = "hour"; - else timeUnit = "hours"; - - timeString = "" + hours + " " + timeUnit + " "; - } - } - else { - if(minutes < 2) timeUnit = "minute"; - else timeUnit = "minutes"; - - timeString = "" + minutes + " " + timeUnit + " "; - } - } - else { - if(seconds < 2) timeUnit = "second"; - else timeUnit = "seconds"; - - timeString = "" + seconds + " " + timeUnit + " "; - } - - return timeString; - } - - private int getCustomInput(String text) throws Exception { - String input = JEnhancedOptionPane.showInputDialog("Customize Sort", text, this.inputOptions); - int integer = Integer.parseInt(input); - return Math.abs(integer); - } - - public void ReportDistributionSort(int[] array, int selection) { - if(arrayVisualizer.isActive()) - return; - - //TODO: This code is bugged! It causes the program to forget the sleep ratio specified by the user! - if(delayOps.skipped()) { - delayOps.setSleepRatio(1); - delayOps.changeSkipped(false); - } - - double storeVol = sounds.getVolume(); - - arrayVisualizer.setCategory("Distribution Sorts"); - - sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @SuppressWarnings("unused") - @Override - public void run(){ - try { - Class sortClass = arrayVisualizer.getDistributionSorts()[selection].sortClass; - Constructor newSort = sortClass.getConstructor(new Class[] {ArrayVisualizer.class}); - Sort sort = (Sort) newSort.newInstance(RunDistributionSort.this.arrayVisualizer); - - int bucketCount; - - if (sort.getQuestion() != null) { - try { - bucketCount = sort.validateAnswer(getCustomInput(sort.getQuestion())); - } - catch(Exception e) { - bucketCount = sort.getDefaultAnswer(); - } - } - else { - if(sort.usesBuckets()) { - if(sort.isRadixSort()) { - try { - bucketCount = RunDistributionSort.this.getCustomInput("Enter the base for this sort:"); - } - catch(Exception e) { - bucketCount = 4; - } - } - else if(sort.getRunSortName().contains("Shatter")) { - try { - bucketCount = RunDistributionSort.this.getCustomInput("Enter the size for each partition:"); - } - catch(Exception e) { - bucketCount = arrayVisualizer.getCurrentLength() / 16; - } - } - else { - try { - bucketCount = RunDistributionSort.this.getCustomInput("How many buckets will this sort use?"); - } - catch(Exception e) { - bucketCount = 16; - } - } - if(bucketCount < 2) bucketCount = 2; - } - else { - bucketCount = 0; - } - } - - arrayManager.toggleMutableLength(false); - arrayManager.refreshArray(array, arrayVisualizer.getCurrentLength(), arrayVisualizer); - - boolean goAhead; - - if(sort.isUnreasonablySlow() && arrayVisualizer.getCurrentLength() > sort.getUnreasonableLimit()) { - goAhead = false; - - if(sort.getRunSortName().equals("Timesort")) { - Object[] options = { "Continue", "Cancel" }; - - int warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Time Sort will take at least " + getTimeSortEstimate(bucketCount) - + "to complete. Once it starts, you cannot skip this sort.", "Warning!", 2, JOptionPane.WARNING_MESSAGE, - null, options, options[1]); - - if(warning == 0) goAhead = true; - else goAhead = false; - - } - else { - Object[] options = { "Let's see how bad " + sort.getRunSortName() + " is!", "Cancel" }; - - if(sort.isBogoSort()) { - int warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Even at a high speed, " - + sort.getRunSortName() + "ing " + arrayVisualizer.getCurrentLength() - + " numbers will almost certainly not finish in a reasonable amount of time. " - + "Are you sure you want to continue?", "Warning!", 2, JOptionPane.WARNING_MESSAGE, - null, options, options[1]); - if(warning == 0) goAhead = true; - else goAhead = false; - } - else { - //Currently, no distribution sort calls this message. It's here if you want to include a sort that might use it in the future. - int warning = JOptionPane.showOptionDialog(arrayVisualizer.getMainWindow(), "Even at a high speed, " - + sort.getRunSortName() + "ing " + arrayVisualizer.getCurrentLength() - + " numbers will not finish in a reasonable amount of time. " - + "Are you sure you want to continue?", "Warning!", 2, JOptionPane.WARNING_MESSAGE, - null, options, options[1]); - - if(warning == 0) goAhead = true; - else goAhead = false; - } - } - } - else { - goAhead = true; - } - - if(sort.getRunSortName().equals("In-Place LSD Radix")) { - sounds.changeVolume(0.01); // Here to protect your ears :) - } - - if(goAhead) { - arrayVisualizer.setHeading(sort.getRunSortName()); - - realTimer.enableRealTimer(); - // arrayVisualizer.toggleVisualUpdates(true); - try { - sort.runSort(array, arrayVisualizer.getCurrentLength(), bucketCount); - } - catch (StopSort e) { } - // arrayVisualizer.toggleVisualUpdates(false); - } - else { - arrayManager.initializeArray(array); - } - } - catch(Exception e) { - JErrorPane.invokeErrorMessage(e); - } - arrayVisualizer.endSort(); - arrayManager.toggleMutableLength(true); - sounds.changeVolume(storeVol); - sounds.toggleSound(false); - } - }); - - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunDistributionSorts.java b/src/threads/RunDistributionSorts.java deleted file mode 100644 index 28c4ec79..00000000 --- a/src/threads/RunDistributionSorts.java +++ /dev/null @@ -1,170 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.distribute.*; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunDistributionSorts extends MultipleSortThread { - private Sort CountingSort; - private Sort PigeonholeSort; - private Sort OptimizedPigeonholeSort; - private Sort FeatureSort; - private Sort GravitySort; - private Sort ClassicGravitySort; - private Sort StaticSort; - private Sort IndexSort; - private Sort AmericanFlagSort; - private Sort DivisorSort; - private Sort LSDRadixSort; - private Sort InPlaceLSDRadixSort; - private Sort MSDRadixSort; - private Sort InPlaceMSDRadixSort; - private Sort FlashSort; - private Sort BinaryQuickSortIterative; - private Sort BinaryQuickSortRecursive; - private Sort ShatterSort; - private Sort SimpleShatterSort; - private Sort ImmediateShatterSort; - private Sort TimeSort; - private Sort LMSDRadixSort; - private Sort OptimizedIndexSort; - private Sort QuickBinaryRadixSort; - private Sort StacklessAmericanFlagSort; - private Sort StacklessBinaryQuickSort; - - public RunDistributionSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 25; - this.categoryCount = this.sortCount; - - CountingSort = new CountingSort(this.arrayVisualizer); - PigeonholeSort = new PigeonholeSort(this.arrayVisualizer); - OptimizedPigeonholeSort = new OptimizedPigeonholeSort(this.arrayVisualizer); - FeatureSort = new FeatureSort(this.arrayVisualizer); - GravitySort = new GravitySort(this.arrayVisualizer); - ClassicGravitySort = new ClassicGravitySort(this.arrayVisualizer); - StaticSort = new StaticSort(this.arrayVisualizer); - IndexSort = new IndexSort(this.arrayVisualizer); - AmericanFlagSort = new AmericanFlagSort(this.arrayVisualizer); - DivisorSort = new DivisorSort(this.arrayVisualizer); - LSDRadixSort = new LSDRadixSort(this.arrayVisualizer); - InPlaceLSDRadixSort = new InPlaceLSDRadixSort(this.arrayVisualizer); - MSDRadixSort = new MSDRadixSort(this.arrayVisualizer); - InPlaceMSDRadixSort = new InPlaceMSDRadixSort(this.arrayVisualizer); - FlashSort = new FlashSort(this.arrayVisualizer); - BinaryQuickSortIterative = new BinaryQuickSortIterative(this.arrayVisualizer); - BinaryQuickSortRecursive = new BinaryQuickSortRecursive(this.arrayVisualizer); - ShatterSort = new ShatterSort(this.arrayVisualizer); - SimpleShatterSort = new SimpleShatterSort(this.arrayVisualizer); - ImmediateShatterSort = new ImmediateShatterSort(this.arrayVisualizer); - TimeSort = new TimeSort(this.arrayVisualizer); - LMSDRadixSort = new LMSDRadixSort(this.arrayVisualizer); - OptimizedIndexSort = new OptimizedIndexSort(this.arrayVisualizer); - QuickBinaryRadixSort = new QuickBinaryRadixSort(this.arrayVisualizer); - StacklessAmericanFlagSort = new StacklessAmericanFlagSort(this.arrayVisualizer); - StacklessBinaryQuickSort = new StacklessBinaryQuickSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunDistributionSorts.this.runIndividualSort(CountingSort, 0, array, 2048, 1.5, false); - RunDistributionSorts.this.runIndividualSort(PigeonholeSort, 0, array, 2048, 1.5, false); - RunDistributionSorts.this.runIndividualSort(OptimizedPigeonholeSort, 0, array, 2048, 1.5, false); - RunDistributionSorts.this.runIndividualSort(FeatureSort, 0, array, 2048, 0.75, false); - RunDistributionSorts.this.runIndividualSort(GravitySort, 0, array, 1024, 0.5, false); - RunDistributionSorts.this.runIndividualSort(ClassicGravitySort, 0, array, 1024, 1, false); - RunDistributionSorts.this.runIndividualSort(StaticSort, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(IndexSort, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(OptimizedIndexSort, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(AmericanFlagSort, 128, array, 2048, 0.75, false); - RunDistributionSorts.this.runIndividualSort(StacklessAmericanFlagSort, 128, array, 2048, 0.75, false); - // RunDistributionSorts.this.runIndividualSort(DivisorSort, 128, array, 2048, 0.5, false); - RunDistributionSorts.this.runIndividualSort(LSDRadixSort, 4, array, 2048, 1.5, false); - - Sounds.toggleSofterSounds(true); - RunDistributionSorts.this.runIndividualSort(InPlaceLSDRadixSort, 10, array, 2048, 1, false); - Sounds.toggleSofterSounds(false); - - RunDistributionSorts.this.runIndividualSort(MSDRadixSort, 4, array, 2048, 1.25, false); - RunDistributionSorts.this.runIndividualSort(InPlaceMSDRadixSort, 4, array, 2048, 1.25, false); - RunDistributionSorts.this.runIndividualSort(LMSDRadixSort, 4, array, 2048, 1.25, false); - RunDistributionSorts.this.runIndividualSort(FlashSort, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(BinaryQuickSortIterative, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(BinaryQuickSortRecursive, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(StacklessBinaryQuickSort, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(QuickBinaryRadixSort, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(ShatterSort, 128, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(SimpleShatterSort, 128, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(ImmediateShatterSort, 0, array, 2048, 1, false); - RunDistributionSorts.this.runIndividualSort(TimeSort, 10, array, 512, 0.05, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunDistributionSorts.this.sortNumber = current; - RunDistributionSorts.this.sortCount = total; - } - else { - RunDistributionSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Distribution Sorts"); - - RunDistributionSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Distribution Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunExchangeSorts.java b/src/threads/RunExchangeSorts.java deleted file mode 100644 index c1b6dfb4..00000000 --- a/src/threads/RunExchangeSorts.java +++ /dev/null @@ -1,238 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.exchange.*; -import sorts.templates.Sort; -import utils.Shuffles; - -/* - * -MIT License - -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunExchangeSorts extends MultipleSortThread { - private Sort UnoptimizedBubbleSort; - private Sort BubbleSort; - private Sort UnoptimizedCocktailShakerSort; - private Sort CocktailShakerSort; - private Sort OddEvenSort; - private Sort SwapMapSort; - private Sort OptimizedStoogeSort; - private Sort GnomeSort; - private Sort OptimizedGnomeSort; - private Sort BinaryGnomeSort; - private Sort CombSort; - private Sort ThreeSmoothCombSortRecursive; - private Sort ThreeSmoothCombSortIterative; - private Sort CircleSortRecursive; - private Sort CircleMergeSort; - private Sort CircleSortIterative; - private Sort LLQuickSort; - private Sort LLQuickSortMiddlePivot; - private Sort LRQuickSort; - private Sort DualPivotQuickSort; - private Sort MeanQuickSort; - private Sort StableQuickSort; - private Sort StableQuickSortMiddlePivot; - private Sort ForcedStableQuickSort; - private Sort LazyStableQuickSort; - private Sort TableSort; - private Sort OptimizedBubbleSort; - private Sort OptimizedCocktailShakerSort; - private Sort OptimizedStoogeSortStudio; - private Sort ooPQuickSort; - private Sort FunSort; - private Sort ClassicThreeSmoothCombSort; - private Sort IndexQuickSort; - private Sort LRQuickSortParallel; - private Sort ReverseBubbleSort; - private Sort ReverseGnomeSort; - private Sort StableQuickSortParallel; - private Sort StacklessQuickSort; - private Sort ThreeSmoothCombSortParallel; - private Sort ChinottoSort; - private Sort CocktailGrateSort; - private Sort GrateSort; - private Sort ReverseGrateSort; - private Sort GnomeWeaveHighSort; - private Sort GnomeWeaveLowSort; - private Sort IterativeQuickSort; - private Sort PseudoHeapSort; - private Sort SlopeSort; - private Sort TriSearchGnomeSort; - private Sort WiggleSort; - - public RunExchangeSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 49; - this.categoryCount = this.sortCount; - - UnoptimizedBubbleSort = new UnoptimizedBubbleSort(this.arrayVisualizer); - BubbleSort = new BubbleSort(this.arrayVisualizer); - OptimizedBubbleSort = new OptimizedBubbleSort(this.arrayVisualizer); - UnoptimizedCocktailShakerSort = new UnoptimizedCocktailShakerSort(this.arrayVisualizer); - CocktailShakerSort = new CocktailShakerSort(this.arrayVisualizer); - OptimizedCocktailShakerSort = new OptimizedCocktailShakerSort(this.arrayVisualizer); - OddEvenSort = new OddEvenSort(this.arrayVisualizer); - SwapMapSort = new SwapMapSort(this.arrayVisualizer); - OptimizedStoogeSort = new OptimizedStoogeSort(this.arrayVisualizer); - OptimizedStoogeSortStudio = new OptimizedStoogeSortStudio(this.arrayVisualizer); - FunSort = new FunSort(this.arrayVisualizer); - GnomeSort = new GnomeSort(this.arrayVisualizer); - OptimizedGnomeSort = new OptimizedGnomeSort(this.arrayVisualizer); - BinaryGnomeSort = new BinaryGnomeSort(this.arrayVisualizer); - CombSort = new CombSort(this.arrayVisualizer); - ThreeSmoothCombSortRecursive = new ThreeSmoothCombSortRecursive(this.arrayVisualizer); - ThreeSmoothCombSortIterative = new ThreeSmoothCombSortIterative(this.arrayVisualizer); - CircleSortRecursive = new CircleSortRecursive(this.arrayVisualizer); - CircleSortIterative = new CircleSortIterative(this.arrayVisualizer); - CircleMergeSort = new CircleMergeSort(this.arrayVisualizer); - LLQuickSort = new LLQuickSort(this.arrayVisualizer); - LLQuickSortMiddlePivot = new LLQuickSortMiddlePivot(this.arrayVisualizer); - LRQuickSort = new LRQuickSort(this.arrayVisualizer); - DualPivotQuickSort = new DualPivotQuickSort(this.arrayVisualizer); - MeanQuickSort = new MeanQuickSort(this.arrayVisualizer); - StableQuickSort = new StableQuickSort(this.arrayVisualizer); - StableQuickSortMiddlePivot = new StableQuickSortMiddlePivot(this.arrayVisualizer); - ooPQuickSort = new ooPQuicksort(this.arrayVisualizer); - ForcedStableQuickSort = new ForcedStableQuickSort(this.arrayVisualizer); - LazyStableQuickSort = new LazyStableQuickSort(this.arrayVisualizer); - TableSort = new TableSort(this.arrayVisualizer); - ClassicThreeSmoothCombSort = new ClassicThreeSmoothCombSort(this.arrayVisualizer); - IndexQuickSort = new IndexQuickSort(this.arrayVisualizer); - LRQuickSortParallel = new LRQuickSortParallel(this.arrayVisualizer); - ReverseBubbleSort = new ReverseBubbleSort(this.arrayVisualizer); - ReverseGnomeSort = new ReverseGnomeSort(this.arrayVisualizer); - StableQuickSortParallel = new StableQuickSortParallel(this.arrayVisualizer); - StacklessQuickSort = new StacklessQuickSort(this.arrayVisualizer); - ThreeSmoothCombSortParallel = new ThreeSmoothCombSortParallel(this.arrayVisualizer); - ChinottoSort = new ChinottoSort(this.arrayVisualizer); - CocktailGrateSort = new CocktailGrateSort(this.arrayVisualizer); - GrateSort = new GrateSort(this.arrayVisualizer); - ReverseGrateSort = new ReverseGrateSort(this.arrayVisualizer); - GnomeWeaveHighSort = new GnomeWeaveHighSort(this.arrayVisualizer); - GnomeWeaveLowSort = new GnomeWeaveLowSort(this.arrayVisualizer); - IterativeQuickSort = new IterativeQuickSort(this.arrayVisualizer); - PseudoHeapSort = new PseudoHeapSort(this.arrayVisualizer); - SlopeSort = new SlopeSort(this.arrayVisualizer); - TriSearchGnomeSort = new TriSearchGnomeSort(this.arrayVisualizer); - WiggleSort = new WiggleSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunExchangeSorts.this.runIndividualSort(UnoptimizedBubbleSort, 0, array, 512, 1.5, false); - RunExchangeSorts.this.runIndividualSort(BubbleSort, 0, array, 512, 1.5, false); - RunExchangeSorts.this.runIndividualSort(OptimizedBubbleSort, 0, array, 512, 1.5, false); - RunExchangeSorts.this.runIndividualSort(ReverseBubbleSort, 0, array, 512, 1.5, false); - RunExchangeSorts.this.runIndividualSort(UnoptimizedCocktailShakerSort, 0, array, 512, 1.25, false); - RunExchangeSorts.this.runIndividualSort(CocktailShakerSort, 0, array, 512, 1.25, false); - RunExchangeSorts.this.runIndividualSort(OptimizedCocktailShakerSort, 0, array, 512, 1.25, false); - RunExchangeSorts.this.runIndividualSort(ChinottoSort, 0, array, 512, 1.25, false); - RunExchangeSorts.this.runIndividualSort(WiggleSort, 0, array, 512, 1.25, false); - RunExchangeSorts.this.runIndividualSort(OddEvenSort, 0, array, 512, 1, false); - RunExchangeSorts.this.runIndividualSort(SwapMapSort, 0, array, 512, 0.125, false); - RunExchangeSorts.this.runIndividualSort(OptimizedStoogeSort, 0, array, 512, 1, false); - RunExchangeSorts.this.runIndividualSort(OptimizedStoogeSortStudio, 0, array, 512, 1, false); - RunExchangeSorts.this.runIndividualSort(GrateSort, 0, array, 64, 1, false); - RunExchangeSorts.this.runIndividualSort(ReverseGrateSort, 0, array, 128, 1, false); - RunExchangeSorts.this.runIndividualSort(CocktailGrateSort, 0, array, 128, 1.5, false); - RunExchangeSorts.this.runIndividualSort(FunSort, 0, array, 256, 2, false); - RunExchangeSorts.this.runIndividualSort(GnomeSort, 0, array, 128, 0.025, false); - RunExchangeSorts.this.runIndividualSort(OptimizedGnomeSort, 0, array, 128, 0.025, false); - RunExchangeSorts.this.runIndividualSort(BinaryGnomeSort, 0, array, 128, 0.025, false); - RunExchangeSorts.this.runIndividualSort(TriSearchGnomeSort, 0, array, 128, 1, false); - RunExchangeSorts.this.runIndividualSort(ReverseGnomeSort, 0, array, 128, 0.025, false); - RunExchangeSorts.this.runIndividualSort(GnomeWeaveHighSort, 0, array, 126, 0.025, false); - RunExchangeSorts.this.runIndividualSort(GnomeWeaveLowSort, 0, array, 126, 0.025, false); - RunExchangeSorts.this.runIndividualSort(SlopeSort, 0, array, 128, 0.025, false); - RunExchangeSorts.this.runIndividualSort(CombSort, 130, array, 1024, 1, false); - RunExchangeSorts.this.runIndividualSort(ThreeSmoothCombSortRecursive, 0, array, 1024, 1.25, false); - RunExchangeSorts.this.runIndividualSort(ThreeSmoothCombSortParallel, 0, array, 1024, 1.25, false); - RunExchangeSorts.this.runIndividualSort(ThreeSmoothCombSortIterative, 0, array, 1024, 1.25, false); - RunExchangeSorts.this.runIndividualSort(ClassicThreeSmoothCombSort, 0, array, 1024, 1.25, false); - RunExchangeSorts.this.runIndividualSort(CircleSortRecursive, 0, array, 1024, 1, false); - RunExchangeSorts.this.runIndividualSort(CircleSortIterative, 0, array, 1024, 1, false); - RunExchangeSorts.this.runIndividualSort(CircleMergeSort, 0, array, 1024, 0.75, false); - RunExchangeSorts.this.runIndividualSort(PseudoHeapSort, 0, array, 1024, 1.5, false); - RunExchangeSorts.this.runIndividualSort(LLQuickSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.5 : 5, false); - RunExchangeSorts.this.runIndividualSort(LLQuickSortMiddlePivot, 0, array, 2048, 1.5, false); - RunExchangeSorts.this.runIndividualSort(LRQuickSort, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(LRQuickSortParallel, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(DualPivotQuickSort, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(StacklessQuickSort, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(IterativeQuickSort, 0, array, 2048, 1, false); - // RunExchangeSorts.this.runIndividualSort(MeanQuickSort, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(StableQuickSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 6.5, false); - RunExchangeSorts.this.runIndividualSort(StableQuickSortMiddlePivot, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(ooPQuickSort, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(StableQuickSortParallel, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(ForcedStableQuickSort, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(LazyStableQuickSort, 0, array, 256, 0.5, false); - RunExchangeSorts.this.runIndividualSort(TableSort, 0, array, 1024, 0.75, false); - RunExchangeSorts.this.runIndividualSort(IndexQuickSort, 0, array, 1024, 0.75, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunExchangeSorts.this.sortNumber = current; - RunExchangeSorts.this.sortCount = total; - } - else { - RunExchangeSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Exchange Sorts"); - - RunExchangeSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Exchange Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} diff --git a/src/threads/RunHybridSorts.java b/src/threads/RunHybridSorts.java deleted file mode 100644 index 5097c776..00000000 --- a/src/threads/RunHybridSorts.java +++ /dev/null @@ -1,243 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; - -import sorts.hybrid.*; -import sorts.templates.Sort; -import utils.Shuffles; - -/* - * -MIT License - -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunHybridSorts extends MultipleSortThread { - private Sort HybridCombSort; - private Sort IntroCircleSortRecursive; - private Sort IntroCircleSortIterative; - private Sort PairwiseCircleSort; - private Sort QuickSPSort; - private Sort BinaryMergeSort; - private Sort MergeInsertionSort; - private Sort SwapMergeSort; - private Sort BaseNMergeSort; - private Sort WeaveMergeSort; - private Sort ImprovedWeaveMergeSort; - private Sort TimSort; - private Sort CocktailMergeSort; - private Sort LazierSort; - private Sort LaziestSort; - private Sort WikiSort; - private Sort GrailSort; - private Sort UnstableGrailSort; - private Sort SqrtSort; - private Sort KotaSort; - private Sort EctaSort; - private Sort BufferedMergeSort; - private Sort OOPBufferedMergeSort; - private Sort BlockSelectionMergeSort; - private Sort ImprovedBlockSelectionSort; - private Sort MedianMergeSort; - private Sort ThirdMergeSort; - private Sort StableThirdMergeSort; - private Sort IntroSort; - private Sort OptimizedBottomUpMergeSort; - private Sort OptimizedDualPivotQuickSort; - private Sort OptimizedWeaveMergeSort; - private Sort StupidQuickSort; - private Sort LAQuickSort; - private Sort MedianOfSixteenAdaptiveQuickSort; - private Sort StacklessHybridQuickSort; - private Sort PDQBranchedSort; - private Sort PDQBranchlessSort; - private Sort DropMergeSort; - private Sort OptimizedPDMergeSort; - private Sort BinaryPDMergeSort; - private Sort FlanSort; - private Sort BubblescanQuickSort; - private Sort BufferPartitionMergeSort; - private Sort ParallelBlockMergeSort; - private Sort ParallelGrailSort; - private Sort RemiSort; - private Sort StacklessDualPivotQuickSort; - private Sort AdaptiveGrailSort; - private Sort BubbleMergeSort; - private Sort ThreadedPDMergeSort; - - public RunHybridSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 51; - this.categoryCount = this.sortCount; - - HybridCombSort = new HybridCombSort(this.arrayVisualizer); - IntroCircleSortRecursive = new IntroCircleSortRecursive(this.arrayVisualizer); - IntroCircleSortIterative = new IntroCircleSortIterative(this.arrayVisualizer); - PairwiseCircleSort = new PairwiseCircleSort(this.arrayVisualizer); - QuickSPSort = new QuickSPSort(this.arrayVisualizer); - BinaryMergeSort = new BinaryMergeSort(this.arrayVisualizer); - MergeInsertionSort = new MergeInsertionSort(this.arrayVisualizer); - SwapMergeSort = new SwapMergeSort(this.arrayVisualizer); - BaseNMergeSort = new BaseNMergeSort(this.arrayVisualizer); - WeaveMergeSort = new WeaveMergeSort(this.arrayVisualizer); - ImprovedWeaveMergeSort = new ImprovedWeaveMergeSort(this.arrayVisualizer); - TimSort = new TimSort(this.arrayVisualizer); - CocktailMergeSort = new CocktailMergeSort(this.arrayVisualizer); - OptimizedPDMergeSort = new OptimizedPDMergeSort(this.arrayVisualizer); - LazierSort = new LazierSort(this.arrayVisualizer); - LaziestSort = new LaziestSort(this.arrayVisualizer); - WikiSort = new WikiSort(this.arrayVisualizer); - GrailSort = new GrailSort(this.arrayVisualizer); - UnstableGrailSort = new UnstableGrailSort(this.arrayVisualizer); - SqrtSort = new SqrtSort(this.arrayVisualizer); - KotaSort = new KotaSort(this.arrayVisualizer); - EctaSort = new EctaSort(this.arrayVisualizer); - FlanSort = new FlanSort(this.arrayVisualizer); - BufferedMergeSort = new BufferedMergeSort(this.arrayVisualizer); - OOPBufferedMergeSort = new OOPBufferedMergeSort(this.arrayVisualizer); - BlockSelectionMergeSort = new BlockSelectionMergeSort(this.arrayVisualizer); - ImprovedBlockSelectionSort = new ImprovedBlockSelectionSort(this.arrayVisualizer); - MedianMergeSort = new MedianMergeSort(this.arrayVisualizer); - ThirdMergeSort = new QuarterMergeSort(this.arrayVisualizer); - StableThirdMergeSort = new StableQuarterMergeSort(this.arrayVisualizer); - IntroSort = new IntroSort(this.arrayVisualizer); - OptimizedBottomUpMergeSort = new OptimizedBottomUpMergeSort(this.arrayVisualizer); - OptimizedDualPivotQuickSort = new OptimizedDualPivotQuickSort(this.arrayVisualizer); - OptimizedWeaveMergeSort = new OptimizedWeaveMergeSort(this.arrayVisualizer); - StupidQuickSort = new StupidQuickSort(this.arrayVisualizer); - LAQuickSort = new LAQuickSort(this.arrayVisualizer); - MedianOfSixteenAdaptiveQuickSort = new MedianOfSixteenAdaptiveQuickSort(this.arrayVisualizer); - StacklessHybridQuickSort = new StacklessHybridQuickSort(this.arrayVisualizer); - PDQBranchedSort = new PDQBranchedSort(this.arrayVisualizer); - PDQBranchlessSort = new PDQBranchlessSort(this.arrayVisualizer); - DropMergeSort = new DropMergeSort(this.arrayVisualizer); - BubblescanQuickSort = new BubblescanQuickSort(this.arrayVisualizer); - BufferPartitionMergeSort = new BufferPartitionMergeSort(this.arrayVisualizer); - ParallelBlockMergeSort = new ParallelBlockMergeSort(this.arrayVisualizer); - ParallelGrailSort = new ParallelGrailSort(this.arrayVisualizer); - RemiSort = new RemiSort(this.arrayVisualizer); - StacklessDualPivotQuickSort = new StacklessDualPivotQuickSort(this.arrayVisualizer); - AdaptiveGrailSort = new AdaptiveGrailSort(this.arrayVisualizer); - BinaryPDMergeSort = new BinaryPDMergeSort(this.arrayVisualizer); - BubbleMergeSort = new BubbleMergeSort(this.arrayVisualizer); - ThreadedPDMergeSort = new ThreadedPDMergeSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunHybridSorts.this.runIndividualSort(HybridCombSort, 0, array, 1024, 1, false); - RunHybridSorts.this.runIndividualSort(IntroCircleSortRecursive, 0, array, 1024, 1, false); - RunHybridSorts.this.runIndividualSort(IntroCircleSortIterative, 0, array, 1024, 1, false); - RunHybridSorts.this.runIndividualSort(PairwiseCircleSort, 0, array, 1024, 1.5, false); - RunHybridSorts.this.runIndividualSort(QuickSPSort, 0, array, 512, 0.4, false); - RunHybridSorts.this.runIndividualSort(BinaryMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(MergeInsertionSort, 0, array, 2048, 1.75, false); - RunHybridSorts.this.runIndividualSort(SwapMergeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.65 : 6.5, false); - RunHybridSorts.this.runIndividualSort(BaseNMergeSort, 4, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(WeaveMergeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.65 : 6.5, false); - RunHybridSorts.this.runIndividualSort(ImprovedWeaveMergeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.65 : 6.5, false); - RunHybridSorts.this.runIndividualSort(TimSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(CocktailMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(BubbleMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(OptimizedPDMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(BinaryPDMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(ThreadedPDMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(LazierSort, 0, array, 1024, 0.4, false); - RunHybridSorts.this.runIndividualSort(LaziestSort, 0, array, 1024, 1, false); - RunHybridSorts.this.runIndividualSort(WikiSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(GrailSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(AdaptiveGrailSort, 0, array, 2048, 1, false); - // RunHybridSorts.this.runIndividualSort(HolyGrailSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(UnstableGrailSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(SqrtSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(KotaSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(EctaSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(ParallelBlockMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(ParallelGrailSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(FlanSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(RemiSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(BufferedMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(OOPBufferedMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(BlockSelectionMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(ImprovedBlockSelectionSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(MedianMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(BufferPartitionMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(ThirdMergeSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(StableThirdMergeSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(BubblescanQuickSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(IntroSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(OptimizedBottomUpMergeSort, 0, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(OptimizedDualPivotQuickSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(OptimizedWeaveMergeSort, 0, array, 1024, 0.4, false); - RunHybridSorts.this.runIndividualSort(StupidQuickSort, 0, array, 1024, 1, false); - RunHybridSorts.this.runIndividualSort(LAQuickSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(MedianOfSixteenAdaptiveQuickSort, 0, array, 1024, 0.25, false); - RunHybridSorts.this.runIndividualSort(StacklessHybridQuickSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(StacklessDualPivotQuickSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(PDQBranchedSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(PDQBranchlessSort, 0, array, 2048, 0.75, false); - RunHybridSorts.this.runIndividualSort(DropMergeSort, 0, array, 2048, 0.75, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunHybridSorts.this.sortNumber = current; - RunHybridSorts.this.sortCount = total; - } - else { - RunHybridSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Hybrid Sorts"); - - RunHybridSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Hybrid Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunImpracticalSorts.java b/src/threads/RunImpracticalSorts.java deleted file mode 100644 index b8737803..00000000 --- a/src/threads/RunImpracticalSorts.java +++ /dev/null @@ -1,225 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.select.BadSort; -import sorts.exchange.StoogeSort; -import sorts.exchange.StableStoogeSort; -import sorts.exchange.QuadStoogeSort; -import sorts.exchange.SillySort; -import sorts.exchange.SlowSort; -import sorts.exchange.SnuffleSort; -import sorts.exchange.FireSort; -import sorts.exchange.ReflectionSort; -import sorts.exchange.StupidFireSort; -import sorts.insert.HanoiSort; -import sorts.insert.StableHanoiSort; -import sorts.exchange.NapoleonSort; -import sorts.distribute.SelectionBogoSort; -import sorts.exchange.BubbleBogoSort; -import sorts.distribute.CocktailBogoSort; -import sorts.exchange.MarkovSort; -import sorts.distribute.LessBogoSort; -import sorts.exchange.ExchangeBogoSort; -import sorts.distribute.MedianQuickBogoSort; -import sorts.distribute.QuickBogoSort; -import sorts.distribute.MergeBogoSort; -import sorts.distribute.SmartGuessSort; -import sorts.distribute.BozoSort; -import sorts.distribute.DeterministicBogoSort; -import sorts.distribute.SmartBogoBogoSort; -import sorts.distribute.SliceBogoSort; -import sorts.distribute.BogoSort; -import sorts.distribute.OptimizedGuessSort; -import sorts.distribute.RandomGuessSort; -import sorts.distribute.GuessSort; -import sorts.distribute.BogoBogoSort; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunImpracticalSorts extends MultipleSortThread { - private Sort BadSort; - private Sort StoogeSort; - private Sort StableStoogeSort; - private Sort SillySort; - private Sort SlowSort; - private Sort SnuffleSort; - private Sort HanoiSort; - private Sort StableHanoiSort; - private Sort NapoleonSort; - private Sort SelectionBogoSort; - private Sort BubbleBogoSort; - private Sort CocktailBogoSort; - private Sort MarkovSort; - private Sort LessBogoSort; - private Sort ExchangeBogoSort; - private Sort MedianQuickBogoSort; - private Sort QuickBogoSort; - private Sort MergeBogoSort; - private Sort SmartGuessSort; - private Sort BozoSort; - private Sort DeterministicBogoSort; - private Sort SmartBogoBogoSort; - private Sort SliceBogoSort; - private Sort BogoSort; - private Sort OptimizedGuessSort; - private Sort RandomGuessSort; - private Sort GuessSort; - private Sort BogoBogoSort; - private Sort FireSort; - private Sort QuadStoogeSort; - private Sort ReflectionSort; - private Sort StupidFireSort; - - public RunImpracticalSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 32; - this.categoryCount = this.sortCount; - - BadSort = new BadSort(this.arrayVisualizer); - StoogeSort = new StoogeSort(this.arrayVisualizer); - StableStoogeSort = new StableStoogeSort(this.arrayVisualizer); - SillySort = new SillySort(this.arrayVisualizer); - SlowSort = new SlowSort(this.arrayVisualizer); - SnuffleSort = new SnuffleSort(this.arrayVisualizer); - HanoiSort = new HanoiSort(this.arrayVisualizer); - StableHanoiSort = new StableHanoiSort(this.arrayVisualizer); - NapoleonSort = new NapoleonSort(this.arrayVisualizer); - SelectionBogoSort = new SelectionBogoSort(this.arrayVisualizer); - BubbleBogoSort = new BubbleBogoSort(this.arrayVisualizer); - CocktailBogoSort = new CocktailBogoSort(this.arrayVisualizer); - MarkovSort = new MarkovSort(this.arrayVisualizer); - LessBogoSort = new LessBogoSort(this.arrayVisualizer); - ExchangeBogoSort = new ExchangeBogoSort(this.arrayVisualizer); - MedianQuickBogoSort = new MedianQuickBogoSort(this.arrayVisualizer); - QuickBogoSort = new QuickBogoSort(this.arrayVisualizer); - MergeBogoSort = new MergeBogoSort(this.arrayVisualizer); - SmartGuessSort = new SmartGuessSort(this.arrayVisualizer); - BozoSort = new BozoSort(this.arrayVisualizer); - DeterministicBogoSort = new DeterministicBogoSort(this.arrayVisualizer); - SmartBogoBogoSort = new SmartBogoBogoSort(this.arrayVisualizer); - SliceBogoSort = new SliceBogoSort(this.arrayVisualizer); - BogoSort = new BogoSort(this.arrayVisualizer); - OptimizedGuessSort = new OptimizedGuessSort(this.arrayVisualizer); - RandomGuessSort = new RandomGuessSort(this.arrayVisualizer); - GuessSort = new GuessSort(this.arrayVisualizer); - BogoBogoSort = new BogoBogoSort(this.arrayVisualizer); - FireSort = new FireSort(this.arrayVisualizer); - QuadStoogeSort = new QuadStoogeSort(this.arrayVisualizer); - ReflectionSort = new ReflectionSort(this.arrayVisualizer); - StupidFireSort = new StupidFireSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunImpracticalSorts.this.runIndividualSort(FireSort, 0, array, 256, 0.25, true); - RunImpracticalSorts.this.runIndividualSort(StupidFireSort, 0, array, 128, 1, true); - RunImpracticalSorts.this.runIndividualSort(ReflectionSort, 0, array, 128, 0.25, true); - RunImpracticalSorts.this.runIndividualSort(BadSort, 0, array, 64, 0.0075, true); - RunImpracticalSorts.this.runIndividualSort(StoogeSort, 0, array, 64, 0.005, true); - RunImpracticalSorts.this.runIndividualSort(StableStoogeSort, 0, array, 64, 0.005, true); - RunImpracticalSorts.this.runIndividualSort(QuadStoogeSort, 0, array, 64, 0.005, true); - RunImpracticalSorts.this.runIndividualSort(SillySort, 0, array, 64, 0.5, true); - RunImpracticalSorts.this.runIndividualSort(SlowSort, 0, array, 64, 0.5, true); - RunImpracticalSorts.this.runIndividualSort(SnuffleSort, 0, array, 64, 0.25, true); - RunImpracticalSorts.this.runIndividualSort(HanoiSort, 0, array, 8, 0.025, true); - RunImpracticalSorts.this.runIndividualSort(StableHanoiSort, 0, array, 8, 0.025, true); - RunImpracticalSorts.this.runIndividualSort(NapoleonSort, 0, array, 6, 0.005, true); - - // Bogosorts - Sounds.toggleSofterSounds(true); - // the not-bad ones - RunImpracticalSorts.this.runIndividualSort(SelectionBogoSort, 0, array, 64, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(BubbleBogoSort, 0, array, 40, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(CocktailBogoSort, 0, array, 40, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(MarkovSort, 0, array, 40, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(LessBogoSort, 0, array, 32, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(ExchangeBogoSort, 0, array, 28, 1e-9, true); - // the meh ones - RunImpracticalSorts.this.runIndividualSort(MedianQuickBogoSort, 0, array, 12, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(QuickBogoSort, 0, array, 9, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(MergeBogoSort, 0, array, 9, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(SmartGuessSort, 0, array, 8, 1e-9, true); - // the scary ones - RunImpracticalSorts.this.runIndividualSort(BozoSort, 0, array, 7, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(DeterministicBogoSort, 0, array, 7, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(SmartBogoBogoSort, 0, array, 6, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(SliceBogoSort, 0, array, 6, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(BogoSort, 0, array, 6, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(OptimizedGuessSort, 0, array, 5, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(RandomGuessSort, 0, array, 5, 1e-9, true); - RunImpracticalSorts.this.runIndividualSort(GuessSort, 0, array, 4, 1e-9, true); - // aaaaa - RunImpracticalSorts.this.runIndividualSort(BogoBogoSort, 0, array, 4, 1e-9, true); - Sounds.toggleSofterSounds(false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunImpracticalSorts.this.sortNumber = current; - RunImpracticalSorts.this.sortCount = total; - } - else { - RunImpracticalSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Impractical Sorts"); - - RunImpracticalSorts.this.executeSortList(array); - - if(runAllActive) { - Thread.sleep(3000); - } - else { - arrayVisualizer.setCategory("Run Impractical Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunInsertionSorts.java b/src/threads/RunInsertionSorts.java deleted file mode 100644 index ebefa3ce..00000000 --- a/src/threads/RunInsertionSorts.java +++ /dev/null @@ -1,160 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.insert.*; -import sorts.templates.Sort; -import utils.Shuffles; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunInsertionSorts extends MultipleSortThread { - private Sort InsertionSort; - private Sort DoubleInsertionSort; - private Sort BinaryInsertionSort; - private Sort TriSearchInsertionSort; - private Sort UnstableInsertionSort; - private Sort ShellSort; - private Sort RecursiveShellSort; - private Sort RendezvousSort; - private Sort SimplifiedLibrarySort; - private Sort PatienceSort; - private Sort ClassicTreeSort; - private Sort AATreeSort; - private Sort AVLTreeSort; - private Sort FibonacciInsertionSort; - private Sort SplaySort; - private Sort RoomSort; - private Sort LibrarySort; - private Sort CocktailShellSort; - private Sort ShellSortParallel; - private Sort ShuffledTreeSort; - private Sort TreeSort; - private Sort AdaptiveBinaryInsertionSort; - private Sort GambitInsertionSort; - private Sort ReverseInsertionSort; - - public RunInsertionSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 24; - this.categoryCount = this.sortCount; - - InsertionSort = new InsertionSort(this.arrayVisualizer); - DoubleInsertionSort = new DoubleInsertionSort(this.arrayVisualizer); - BinaryInsertionSort = new BinaryInsertionSort(this.arrayVisualizer); - TriSearchInsertionSort = new TriSearchInsertionSort(this.arrayVisualizer); - FibonacciInsertionSort = new FibonacciInsertionSort(this.arrayVisualizer); - UnstableInsertionSort = new UnstableInsertionSort(this.arrayVisualizer); - ShellSort = new ShellSort(this.arrayVisualizer); - RecursiveShellSort = new RecursiveShellSort(this.arrayVisualizer); - RendezvousSort = new RendezvousSort(this.arrayVisualizer); - RoomSort = new RoomSort(this.arrayVisualizer); - SimplifiedLibrarySort = new SimplifiedLibrarySort(this.arrayVisualizer); - PatienceSort = new PatienceSort(this.arrayVisualizer); - ClassicTreeSort = new ClassicTreeSort(this.arrayVisualizer); - AATreeSort = new AATreeSort(this.arrayVisualizer); - AVLTreeSort = new AVLTreeSort(this.arrayVisualizer); - SplaySort = new SplaySort(this.arrayVisualizer); - LibrarySort = new LibrarySort(this.arrayVisualizer); - CocktailShellSort = new CocktailShellSort(this.arrayVisualizer); - ShellSortParallel = new ShellSortParallel(this.arrayVisualizer); - ShuffledTreeSort = new ShuffledTreeSort(this.arrayVisualizer); - TreeSort = new TreeSort(this.arrayVisualizer); - AdaptiveBinaryInsertionSort = new AdaptiveBinaryInsertionSort(this.arrayVisualizer); - GambitInsertionSort = new GambitInsertionSort(this.arrayVisualizer); - ReverseInsertionSort = new ReverseInsertionSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunInsertionSorts.this.runIndividualSort(InsertionSort, 0, array, 128, 0.005, false); - RunInsertionSorts.this.runIndividualSort(ReverseInsertionSort, 0, array, 128, 0.005, false); - RunInsertionSorts.this.runIndividualSort(DoubleInsertionSort, 0, array, 128, 0.002, false); - RunInsertionSorts.this.runIndividualSort(BinaryInsertionSort, 0, array, 128, 0.025, false); - RunInsertionSorts.this.runIndividualSort(AdaptiveBinaryInsertionSort, 0, array, 128, 0.025, false); - RunInsertionSorts.this.runIndividualSort(TriSearchInsertionSort, 0, array, 128, 1, false); - RunInsertionSorts.this.runIndividualSort(FibonacciInsertionSort, 0, array, 128, 0.025, false); - RunInsertionSorts.this.runIndividualSort(GambitInsertionSort, 0, array, 128, 0.025, false); - RunInsertionSorts.this.runIndividualSort(UnstableInsertionSort, 0, array, 128, 0.2, false); - RunInsertionSorts.this.runIndividualSort(ShellSort, 0, array, 256, 0.1, false); - RunInsertionSorts.this.runIndividualSort(CocktailShellSort, 0, array, 256, 0.1, false); - RunInsertionSorts.this.runIndividualSort(RecursiveShellSort, 0, array, 256, 0.1, false); - RunInsertionSorts.this.runIndividualSort(ShellSortParallel, 0, array, 256, 0.1, false); - RunInsertionSorts.this.runIndividualSort(RendezvousSort, 0, array, 256, 0.1, false); - RunInsertionSorts.this.runIndividualSort(RoomSort, 0, array, 512, 0.05, false); - RunInsertionSorts.this.runIndividualSort(SimplifiedLibrarySort, 0, array, 2048, 1, false); - RunInsertionSorts.this.runIndividualSort(LibrarySort, 0, array, 2048, 1, false); - RunInsertionSorts.this.runIndividualSort(PatienceSort, 0, array, 2048, 1, false); - RunInsertionSorts.this.runIndividualSort(ClassicTreeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 5, false); - RunInsertionSorts.this.runIndividualSort(TreeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 5, false); - RunInsertionSorts.this.runIndividualSort(ShuffledTreeSort, 0, array, 2048, 1, false); - RunInsertionSorts.this.runIndividualSort(AATreeSort, 0, array, 2048, 1, false); - RunInsertionSorts.this.runIndividualSort(AVLTreeSort, 0, array, 2048, 1, false); - RunInsertionSorts.this.runIndividualSort(SplaySort, 0, array, 2048, 1, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunInsertionSorts.this.sortNumber = current; - RunInsertionSorts.this.sortCount = total; - } - else { - RunInsertionSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Insertion Sorts"); - - RunInsertionSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Insertion Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunMergeSorts.java b/src/threads/RunMergeSorts.java deleted file mode 100644 index d99fc91e..00000000 --- a/src/threads/RunMergeSorts.java +++ /dev/null @@ -1,164 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.merge.*; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunMergeSorts extends MultipleSortThread { - private Sort MergeSort; - private Sort BottomUpMergeSort; - private Sort PartialMergeSort; - private Sort TwinSort; - private Sort NaturalMergeSort; - private Sort PDMergeSort; - private Sort InPlaceMergeSort; - private Sort ImprovedInPlaceMergeSort; - private Sort LazyStableSort; - private Sort ReverseLazyStableSort; - private Sort ModuloMergeSort; - private Sort BlockSwapMergeSort; - private Sort RotateMergeSort; - private Sort AndreySort; - private Sort SplitSixteenMergeSort; - private Sort StrandSort; - private Sort OutOfPlaceWeaveMergeSort; - private Sort BufferedStoogeSort; - private Sort IndexMergeSort; - private Sort IterativeTopDownMergeSort; - private Sort MergeSortParallel; - private Sort NewShuffleMergeSort; - private Sort OptimizedPancakeSort; - private Sort RotateMergeSortParallel; - private Sort StacklessRotateMergeSort; - private Sort WeavedMergeSort; - - public RunMergeSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 25; - this.categoryCount = this.sortCount; - - MergeSort = new MergeSort(this.arrayVisualizer); - BottomUpMergeSort = new BottomUpMergeSort(this.arrayVisualizer); - PartialMergeSort = new PartialMergeSort(this.arrayVisualizer); - TwinSort = new TwinSort(this.arrayVisualizer); - NaturalMergeSort = new NaturalMergeSort(this.arrayVisualizer); - PDMergeSort = new PDMergeSort(this.arrayVisualizer); - InPlaceMergeSort = new InPlaceMergeSort(this.arrayVisualizer); - ImprovedInPlaceMergeSort = new ImprovedInPlaceMergeSort(this.arrayVisualizer); - OutOfPlaceWeaveMergeSort = new OutOfPlaceWeaveMergeSort(this.arrayVisualizer); - LazyStableSort = new LazyStableSort(this.arrayVisualizer); - ReverseLazyStableSort = new ReverseLazyStableSort(this.arrayVisualizer); - ModuloMergeSort = new ModuloMergeSort(this.arrayVisualizer); - BlockSwapMergeSort = new BlockSwapMergeSort(this.arrayVisualizer); - RotateMergeSort = new RotateMergeSort(this.arrayVisualizer); - AndreySort = new AndreySort(this.arrayVisualizer); - SplitSixteenMergeSort = new Split16Merge(this.arrayVisualizer); - StrandSort = new StrandSort(this.arrayVisualizer); - BufferedStoogeSort = new BufferedStoogeSort(this.arrayVisualizer); - IndexMergeSort = new IndexMergeSort(this.arrayVisualizer); - IterativeTopDownMergeSort = new IterativeTopDownMergeSort(this.arrayVisualizer); - MergeSortParallel = new MergeSortParallel(this.arrayVisualizer); - NewShuffleMergeSort = new NewShuffleMergeSort(this.arrayVisualizer); - OptimizedPancakeSort = new OptimizedPancakeSort(this.arrayVisualizer); - RotateMergeSortParallel = new RotateMergeSortParallel(this.arrayVisualizer); - StacklessRotateMergeSort = new StacklessRotateMergeSort(this.arrayVisualizer); - WeavedMergeSort = new WeavedMergeSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunMergeSorts.this.runIndividualSort(MergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(BottomUpMergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(MergeSortParallel, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(PartialMergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(IterativeTopDownMergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(WeavedMergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(TwinSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(NaturalMergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(PDMergeSort, 0, array, 2048, 1, false); - RunMergeSorts.this.runIndividualSort(InPlaceMergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(ImprovedInPlaceMergeSort, 0, array, 2048, 1.5, false); - RunMergeSorts.this.runIndividualSort(OutOfPlaceWeaveMergeSort, 0, array, 2048, 1, false); - RunMergeSorts.this.runIndividualSort(LazyStableSort, 0, array, 256, 0.2, false); - RunMergeSorts.this.runIndividualSort(ReverseLazyStableSort, 0, array, 256, 0.1, false); - RunMergeSorts.this.runIndividualSort(ModuloMergeSort, 0, array, 2048, 3, false); - RunMergeSorts.this.runIndividualSort(BlockSwapMergeSort, 0, array, 256, 0.1, false); - RunMergeSorts.this.runIndividualSort(RotateMergeSort, 0, array, 512, 0.2, false); - RunMergeSorts.this.runIndividualSort(RotateMergeSortParallel, 0, array, 512, 0.2, false); - RunMergeSorts.this.runIndividualSort(AndreySort, 0, array, 2048, 1, false); - RunMergeSorts.this.runIndividualSort(SplitSixteenMergeSort, 0, array, 512, 0.75, false); - RunMergeSorts.this.runIndividualSort(IndexMergeSort, 0, array, 2048, 1, false); - RunMergeSorts.this.runIndividualSort(NewShuffleMergeSort, 0, array, 1024, 1, false); - RunMergeSorts.this.runIndividualSort(StrandSort, 0, array, 2048, 1, false); - RunMergeSorts.this.runIndividualSort(BufferedStoogeSort, 0, array, 256, 0.2, false); - RunMergeSorts.this.runIndividualSort(OptimizedPancakeSort, 0, array, 2048, 1, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunMergeSorts.this.sortNumber = current; - RunMergeSorts.this.sortCount = total; - } - else { - RunMergeSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Merge Sorts"); - - RunMergeSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Merge Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunMiscellaneousSorts.java b/src/threads/RunMiscellaneousSorts.java deleted file mode 100644 index 9fcc05ba..00000000 --- a/src/threads/RunMiscellaneousSorts.java +++ /dev/null @@ -1,93 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.misc.*; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunMiscellaneousSorts extends MultipleSortThread { - private Sort PancakeSort; - private Sort BurntPancakeSort; - - public RunMiscellaneousSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 2; - this.categoryCount = this.sortCount; - - PancakeSort = new PancakeSort(this.arrayVisualizer); - BurntPancakeSort = new BurntPancakeSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunMiscellaneousSorts.this.runIndividualSort(PancakeSort, 0, array, 128, 0.015, false); - RunMiscellaneousSorts.this.runIndividualSort(BurntPancakeSort, 0, array, 128, 0.015, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunMiscellaneousSorts.this.sortNumber = current; - RunMiscellaneousSorts.this.sortCount = total; - } - else { - RunMiscellaneousSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Miscellaneous Sorts"); - - RunMiscellaneousSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Miscellaneous Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunQuickSorts.java b/src/threads/RunQuickSorts.java deleted file mode 100644 index 4613ccc5..00000000 --- a/src/threads/RunQuickSorts.java +++ /dev/null @@ -1,91 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.quick.*; -import sorts.templates.Sort; -import utils.Shuffles; - -/* - * -MIT License - -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunQuickSorts extends MultipleSortThread { - private Sort CubeRootQuickSort; - - public RunQuickSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 1; - this.categoryCount = this.sortCount; - - CubeRootQuickSort = new CubeRootQuickSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunQuickSorts.this.runIndividualSort(CubeRootQuickSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 6.5, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunQuickSorts.this.sortNumber = current; - RunQuickSorts.this.sortCount = total; - } - else { - RunQuickSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Quick Sorts"); - - RunQuickSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Quick Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} diff --git a/src/threads/RunScriptedSorts.java b/src/threads/RunScriptedSorts.java deleted file mode 100644 index f6cd3dac..00000000 --- a/src/threads/RunScriptedSorts.java +++ /dev/null @@ -1,122 +0,0 @@ -package threads; - -import java.io.File; - -import dialogs.RunScriptDialog; -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.templates.Sort; -import utils.MultipleScript; - -/* - * -MIT License - -Copyright (c) 2020 Gaming32 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunScriptedSorts extends MultipleSortThread { - private RunScriptDialog fileDialog; - private String currentCategory; - - public RunScriptedSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - fileDialog = new RunScriptDialog(); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - this.executeSortList(new MultipleScript.ScriptCommand[] { }, array); - } - - protected synchronized void executeSortList(MultipleScript.ScriptCommand[] commands, int[] array) throws Exception { - for (MultipleScript.ScriptCommand command : commands) { - if (command.type == MultipleScript.ScriptCommand.CommandType.SetCategory) { - String category = (String)command.argument; - RunScriptedSorts.this.currentCategory = category; - arrayVisualizer.setCategory(category); - } - else if (command.type == MultipleScript.ScriptCommand.CommandType.SortCall) { - MultipleScript.SortCallInfo info = (MultipleScript.SortCallInfo)command.argument; - RunScriptedSorts.this.runIndividualSort(info.algortitm, - info.bucketCount, - array, - info.defaultLength, - info.defaultSpeedMultiplier, - info.slowSort); - } - } - } - - @Override - public synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - File file = fileDialog.getFile(); - MultipleScript.ScriptCommand[] commands = RunScriptedSorts.this.arrayVisualizer.getScriptParser().runScript(file); - if (commands == null) - return; - - int sortCount = 0; - for (MultipleScript.ScriptCommand command : commands) { - if (command.type == MultipleScript.ScriptCommand.CommandType.SortCall) { - sortCount++; - } - } - - RunScriptedSorts.this.sortNumber = 1; - RunScriptedSorts.this.sortCount = sortCount; - RunScriptedSorts.this.categoryCount = sortCount; - - arrayManager.toggleMutableLength(false); - - RunScriptedSorts.this.currentCategory = "Scripted Sorts"; - arrayVisualizer.setCategory("Scripted Sorts"); - - RunScriptedSorts.this.executeSortList(commands, array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run " + RunScriptedSorts.this.currentCategory); - arrayVisualizer.setHeading("Done"); - arrayVisualizer.updateNow(); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/threads/RunSelectionSorts.java b/src/threads/RunSelectionSorts.java deleted file mode 100644 index 40291dbd..00000000 --- a/src/threads/RunSelectionSorts.java +++ /dev/null @@ -1,156 +0,0 @@ -package threads; - -import main.ArrayVisualizer; -import panes.JErrorPane; -import sorts.select.*; -import sorts.templates.Sort; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class RunSelectionSorts extends MultipleSortThread { - private Sort SelectionSort; - private Sort DoubleSelectionSort; - private Sort CycleSort; - private Sort MaxHeapSort; - private Sort MinHeapSort; - private Sort FlippedMinHeapSort; - private Sort BaseNMaxHeapSort; - private Sort WeakHeapSort; - private Sort TernaryHeapSort; - private Sort SmoothSort; - private Sort PoplarHeapSort; - private Sort TournamentSort; - private Sort AsynchronousSort; - private Sort QueueSort; - private Sort DequeueSort; - private Sort StableSelectionSort; - private Sort BingoSort; - private Sort ClassicTournamentSort; - private Sort ReverseSandpaperSort; - private Sort ReverseSelectionSort; - private Sort SandpaperSort; - private Sort StableCycleSort; - private Sort TriangularHeapSort; - - public RunSelectionSorts(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.sortCount = 23; - this.categoryCount = this.sortCount; - - SelectionSort = new SelectionSort(this.arrayVisualizer); - StableSelectionSort = new StableSelectionSort(this.arrayVisualizer); - DoubleSelectionSort = new DoubleSelectionSort(this.arrayVisualizer); - CycleSort = new CycleSort(this.arrayVisualizer); - MaxHeapSort = new MaxHeapSort(this.arrayVisualizer); - MinHeapSort = new MinHeapSort(this.arrayVisualizer); - FlippedMinHeapSort = new FlippedMinHeapSort(this.arrayVisualizer); - WeakHeapSort = new WeakHeapSort(this.arrayVisualizer); - TernaryHeapSort = new TernaryHeapSort(this.arrayVisualizer); - BaseNMaxHeapSort = new BaseNMaxHeapSort(this.arrayVisualizer); - SmoothSort = new SmoothSort(this.arrayVisualizer); - PoplarHeapSort = new PoplarHeapSort(this.arrayVisualizer); - TournamentSort = new TournamentSort(this.arrayVisualizer); - AsynchronousSort = new AsynchronousSort(this.arrayVisualizer); - QueueSort = new QueueSort(this.arrayVisualizer); - DequeueSort = new DequeueSort(this.arrayVisualizer); - BingoSort = new BingoSort(this.arrayVisualizer); - ClassicTournamentSort = new ClassicTournamentSort(this.arrayVisualizer); - ReverseSandpaperSort = new ReverseSandpaperSort(this.arrayVisualizer); - ReverseSelectionSort = new ReverseSelectionSort(this.arrayVisualizer); - SandpaperSort = new SandpaperSort(this.arrayVisualizer); - StableCycleSort = new StableCycleSort(this.arrayVisualizer); - TriangularHeapSort = new TriangularHeapSort(this.arrayVisualizer); - } - - @Override - protected synchronized void executeSortList(int[] array) throws Exception { - RunSelectionSorts.this.runIndividualSort(SelectionSort, 0, array, 128, 0.01, false); - RunSelectionSorts.this.runIndividualSort(ReverseSelectionSort, 0, array, 128, 0.01, false); - RunSelectionSorts.this.runIndividualSort(DoubleSelectionSort, 0, array, 128, 0.01, false); - RunSelectionSorts.this.runIndividualSort(StableSelectionSort, 0, array, 128, 0.5, false); - RunSelectionSorts.this.runIndividualSort(SandpaperSort, 0, array, 128, 0.05, false); - RunSelectionSorts.this.runIndividualSort(ReverseSandpaperSort, 0, array, 128, 0.05, false); - RunSelectionSorts.this.runIndividualSort(CycleSort, 0, array, 128, 0.01, false); - RunSelectionSorts.this.runIndividualSort(StableCycleSort, 0, array, 128, 0.01, false); - RunSelectionSorts.this.runIndividualSort(BingoSort, 0, array, 128, 0.1, false); - RunSelectionSorts.this.runIndividualSort(MaxHeapSort, 0, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(MinHeapSort, 0, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(FlippedMinHeapSort, 0, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(BaseNMaxHeapSort, 4, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(TriangularHeapSort, 0, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(WeakHeapSort, 0, array, 2048, 1, false); - RunSelectionSorts.this.runIndividualSort(TernaryHeapSort, 0, array, 2048, 1, false); - RunSelectionSorts.this.runIndividualSort(SmoothSort, 0, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(PoplarHeapSort, 0, array, 2048, 1, false); - RunSelectionSorts.this.runIndividualSort(TournamentSort, 0, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(ClassicTournamentSort, 0, array, 2048, 1.5, false); - RunSelectionSorts.this.runIndividualSort(AsynchronousSort, 0, array, 1024, 1.5, false); - RunSelectionSorts.this.runIndividualSort(QueueSort, 0, array, 2048, 1, false); - RunSelectionSorts.this.runIndividualSort(DequeueSort, 0, array, 2048, 1, false); - } - - @Override - protected synchronized void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception { - if(arrayVisualizer.isActive()) - return; - - Sounds.toggleSound(true); - arrayVisualizer.setSortingThread(new Thread() { - @Override - public void run() { - try{ - if(runAllActive) { - RunSelectionSorts.this.sortNumber = current; - RunSelectionSorts.this.sortCount = total; - } - else { - RunSelectionSorts.this.sortNumber = 1; - } - - arrayManager.toggleMutableLength(false); - - arrayVisualizer.setCategory("Selection Sorts"); - - RunSelectionSorts.this.executeSortList(array); - - if(!runAllActive) { - arrayVisualizer.setCategory("Run Selection Sorts"); - arrayVisualizer.setHeading("Done"); - } - - arrayManager.toggleMutableLength(true); - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e); - } - Sounds.toggleSound(false); - arrayVisualizer.setSortingThread(null); - } - }); - arrayVisualizer.runSortingThread(); - } -} \ No newline at end of file diff --git a/src/utils/MultipleScript.java b/src/utils/MultipleScript.java deleted file mode 100644 index 6c913393..00000000 --- a/src/utils/MultipleScript.java +++ /dev/null @@ -1,179 +0,0 @@ -package utils; - -import java.io.File; -import java.io.FileNotFoundException; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.Scanner; - -import main.ArrayVisualizer; -import main.SortAnalyzer.SortPair; -import sorts.templates.Sort; -import panes.JErrorPane; - -final public class MultipleScript { - public static class ScriptCommand { - public static enum CommandType { - SortCall, - SetCategory - } - - public CommandType type; - public Object argument; - - public ScriptCommand(CommandType type, Object argument) { - this.type = type; - this.argument = argument; - } - } - - public static class SortCallInfo { - public Sort algortitm; - public int bucketCount; - public int defaultLength; - public double defaultSpeedMultiplier; - public boolean slowSort; - - public SortCallInfo(ArrayVisualizer arrayVisualizer, Class sortClass, int bucketCount, int defaultLength, double defaultSpeedMultiplier) { - Sort inst = null; - try { - Constructor newSort = sortClass.getConstructor(new Class[] {ArrayVisualizer.class}); - inst = (Sort) newSort.newInstance(arrayVisualizer); - } - catch (Exception e) { } - algortitm = inst; - - this.bucketCount = bucketCount; - this.defaultLength = defaultLength; - this.defaultSpeedMultiplier = defaultSpeedMultiplier; - } - } - - private static String[] simpleCommandLineParse(String commandLine) { - ArrayList result = new ArrayList<>(); - - char last = ' '; - String current = ""; - boolean inBlock = false; - - for (char character : commandLine.toCharArray()) { - if (character == ' ' && !inBlock) { - if (current != "") { - result.add(current); - current = ""; - } - } - else if (character == '"' && last == ' ' && !inBlock) { - inBlock = true; - } - else if (character == ' ' && last == '"' && inBlock) { - result.add(current); - current = ""; - inBlock = false; - } - else if (character == '"' && inBlock) { } - else if (character == ' ' && last == ' ' && !inBlock) { } - else { - current += character; - } - last = character; - } - result.add(current); - - return result.toArray(new String[result.size()]); - } - - private ArrayVisualizer arrayVisualizer; - - private final Hashtable> sortNames; - - public MultipleScript(ArrayVisualizer arrayVisualizer) { - this.arrayVisualizer = arrayVisualizer; - - sortNames = new Hashtable<>(); - populateSortTable(this.arrayVisualizer.getComparisonSorts(), sortNames); - populateSortTable(this.arrayVisualizer.getDistributionSorts(), sortNames); - } - - private void populateSortTable(SortPair[] array, Hashtable> table) { - for (SortPair sort : array) { - Class sortClass = sort.sortClass; - Sort inst; - try { - Constructor newSort = sortClass.getConstructor(new Class[] {ArrayVisualizer.class}); - inst = (Sort) newSort.newInstance(this.arrayVisualizer); - } - catch (Exception e) { - continue; - } - - String[] classParts = sortClass.getName().split("\\."); - table.put(classParts[classParts.length - 1].toLowerCase(), sortClass); - table.put(inst.getSortListName().toLowerCase(), sortClass); - table.put(inst.getRunSortName().toLowerCase(), sortClass); - table.put(inst.getRunAllSortsName().toLowerCase(), sortClass); - } - } - - public ScriptCommand[] runScript(Scanner scanner) { - ArrayList result = new ArrayList<>(); - - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - String[] commands = simpleCommandLineParse(line); - if (commands.length == 0 || (commands.length == 1 && commands[0].length() == 0)) - continue; - - ScriptCommand.CommandType commandType = null; - Object argument = null; - - String commandLabel = commands[0].toLowerCase(); - if (commandLabel.compareTo("setcategory") == 0) { - commandType = ScriptCommand.CommandType.SetCategory; - argument = commands.length > 1 ? commands[1] : "Scripted Sorts"; - } - else { - String sortName = commandLabel; - if (!sortNames.containsKey(sortName)) { - continue; - } - Class sortClass = sortNames.get(sortName); - - int bucketCount = commands.length > 1 ? Integer.parseInt(commands[1]) : 0; - int defaultLength = commands.length > 2 ? Integer.parseInt(commands[2]) : 2048; - double defaultSpeedMultiplier = commands.length > 3 ? Double.parseDouble(commands[3]) : 1; - - commandType = ScriptCommand.CommandType.SortCall; - argument = new SortCallInfo(this.arrayVisualizer, sortClass, bucketCount, defaultLength, defaultSpeedMultiplier); - } - result.add(new ScriptCommand(commandType, argument)); - } - - return result.toArray(new ScriptCommand[result.size()]); - } - - public ScriptCommand[] runScript(String[] code) { - Scanner scanner = new Scanner(String.join("\n", code)); - return runScript(scanner); - } - - public ScriptCommand[] runScript(File file) { - Scanner scanner; - try { - scanner = new Scanner(file); - } - catch (FileNotFoundException e) { - JErrorPane.invokeCustomErrorMessage("The file \"" + file.getPath() + "\" does not exist"); - return null; - } - catch (NullPointerException e) { - return null; - } - return runScript(scanner); - } - - public ScriptCommand[] runScript(String path) { - return runScript(new File(path)); - } -} diff --git a/src/utils/PerlinNoise.java b/src/utils/PerlinNoise.java deleted file mode 100644 index 9eae2faf..00000000 --- a/src/utils/PerlinNoise.java +++ /dev/null @@ -1,55 +0,0 @@ -package utils; - -// MASSIVE thanks to https://github.com/keijiro/PerlinNoise -public class PerlinNoise { - final private static int[] perm = { - 151,160,137,91,90,15, - 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, - 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, - 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, - 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, - 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, - 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, - 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, - 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, - 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, - 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, - 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, - 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, - 151 - }; - - public PerlinNoise() { } - - private static float fade(float t) { - return t * t * t * (t * (t * 6 - 15) + 10); - } - - private static float grad(int hash, float x) { - return (hash & 1) == 0 ? x : -x; - } - - private static float lerp(float t, float a, float b) - { - return a + t * (b - a); - } - - public static float returnNoise(float x) { - int index = ((int) Math.floor(x)) & 0xff; - x -= Math.floor(x); - float u = fade(x); - return lerp(u, grad(perm[index], x), grad(perm[index + 1], x - 1)) * 2; - } - - public static float returnFracBrownNoise(float x, int octave) - { - float f = 0.0f; - float w = 0.5f; - for (int i = 0; i < octave; i++) { - f += w * returnNoise(x); - x *= 2.0f; - w *= 0.5f; - } - return f; - } -} \ No newline at end of file diff --git a/src/utils/SortingNetworkGenerator.java b/src/utils/SortingNetworkGenerator.java deleted file mode 100644 index 41a38968..00000000 --- a/src/utils/SortingNetworkGenerator.java +++ /dev/null @@ -1,136 +0,0 @@ -package utils; - -import java.awt.Desktop; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.lang.ProcessBuilder.Redirect; -import java.util.stream.Collectors; -import java.text.DecimalFormat; - -import javax.swing.JOptionPane; - -import frames.UtilFrame; -import panes.JErrorPane; -import resources.sorting_network_master.SortingNetworkFetcher; - -public class SortingNetworkGenerator { - static DecimalFormat formatter = new DecimalFormat(); - - static boolean hasPython = false; - static String pythonCommand = null; - - final static int LIMIT = 20000; - - static boolean verifyPythonVersion(String minVersion, String command) { - try { - ProcessBuilder builder = new ProcessBuilder(command, "-c", - String.format("import sys; print (sys.version_info >= (%s))", minVersion)); - Process p = builder.start(); - if (p.waitFor() != 0) { - return false; - } - BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); - if (r.readLine().equals("True")) { - pythonCommand = command; - return true; - } - return false; - } - catch (IOException e) { - return false; - } - catch (Exception e) { - e.printStackTrace(); - return false; - } - } - - public static boolean verifyPythonVersion() { - return (hasPython = hasPython // This caches the result if it's true - || verifyPythonVersion("3, 2, 0", "python3") - || verifyPythonVersion("3, 2, 0", "python") - || verifyPythonVersion("3, 2, 0", "py")); - } - - public static boolean verifyPythonVersionAndDialog() { - boolean hasVersion = verifyPythonVersion(); - if (!hasVersion) { - JOptionPane.showMessageDialog(null, "It appears that you do not have Python 3.2 or later installed on your computer! Please install it before using this mode.", - "Sorting Network Visualizer", JOptionPane.WARNING_MESSAGE); - } - return hasVersion; - } - - public static boolean encodeNetwork(int[] indices, String path) { - if (indices.length < 2) { - JOptionPane.showMessageDialog(null, "Sort does not compare indices; An empty sorting network cannot be generated.", - "File not saved", JOptionPane.ERROR_MESSAGE); - - return false; - } - else if (indices.length > 2*LIMIT) { - String[] options = {"Yes", "Cancel"}; - int choice = JOptionPane.showOptionDialog(null, "Sorting network is very large and exceeds the " + formatter.format(LIMIT) + " comparator limit. Generate anyway?", - "Warning!", 2, JOptionPane.WARNING_MESSAGE, null, options, options[1]); - - if (choice == 1) { - return false; - } - } - String result = indices[0] + ":" + indices[1]; - for (int i = 3; i < indices.length; i += 2) { - result += "," + indices[i - 1] + ":" + indices[i]; - } - SortingNetworkFetcher fetcher = new SortingNetworkFetcher(); - try { - ProcessBuilder builder = new ProcessBuilder(pythonCommand, "-c", - new BufferedReader(new InputStreamReader(fetcher.getStream())).lines().collect(Collectors.joining("\n")), - "--svg", path); - builder.redirectOutput(Redirect.INHERIT); - Process p = builder.start(); - BufferedWriter w = new BufferedWriter(new OutputStreamWriter(p.getOutputStream())); - w.write(result); - w.close(); - if (p.waitFor() != 0) { - BufferedReader r = new BufferedReader(new InputStreamReader(p.getErrorStream())); - JErrorPane.invokeCustomErrorMessage(r.lines().collect(Collectors.joining("\n"))); - return false; - } - } - catch (IOException e) { - JErrorPane.invokeErrorMessage(e, "Sorting Network Visualizer"); - return false; - } - catch (Exception e) { - JErrorPane.invokeErrorMessage(e, "Sorting Network Visualizer"); - return false; - } - return true; - } - - public static String encodeNetworkAndDisplay(String name, Integer[] indices, int arrayLength) { - String path = "network_" + name + "_" + arrayLength + ".svg"; - int[] indicesInt = new int[indices.length]; - for (int i = 0; i < indices.length; i++) { - indicesInt[i] = indices[i]; - } - if (!encodeNetwork(indicesInt, path)) { - return null; - } - JOptionPane.showMessageDialog(null, "Successfully saved output to file \"" + path + "\"", - "Sorting Network Visualizer", JOptionPane.INFORMATION_MESSAGE); - File file = new File(path); - Desktop desktop = Desktop.getDesktop(); - try { - desktop.open(file); - } - catch (IOException e) { - e.printStackTrace(); - } - return path; - } -} diff --git a/src/utils/Writes.java b/src/utils/Writes.java deleted file mode 100644 index 8a8ba269..00000000 --- a/src/utils/Writes.java +++ /dev/null @@ -1,476 +0,0 @@ -package utils; - -import java.util.Arrays; -import java.util.List; -import java.text.DecimalFormat; -import java.util.ArrayList; - -import main.ArrayVisualizer; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -/** - * - * @author S630690 - */ -final public class Writes { - private volatile long reversals; - private volatile long swaps; - private volatile long auxWrites; - private volatile long writes; - private volatile long allocAmount; - - private DecimalFormat formatter; - - private ArrayVisualizer ArrayVisualizer; - private Delays Delays; - private Highlights Highlights; - private Timer Timer; - - public Writes(ArrayVisualizer ArrayVisualizer) { - this.reversals = 0; - this.swaps = 0; - this.auxWrites = 0; - this.writes = 0; - this.allocAmount = 0; - - this.ArrayVisualizer = ArrayVisualizer; - this.Delays = ArrayVisualizer.getDelays(); - this.Highlights = ArrayVisualizer.getHighlights(); - this.Timer = ArrayVisualizer.getTimer(); - - this.formatter = ArrayVisualizer.getNumberFormat(); - } - - public void resetStatistics() { - this.reversals = 0; - this.swaps = 0; - this.auxWrites = 0; - this.writes = 0; - this.allocAmount = 0; - } - - public String getReversals() { - if(this.reversals < 0) { - this.reversals = Long.MIN_VALUE; - return "Over " + this.formatter.format(Long.MAX_VALUE); - } - else { - if(reversals == 1) return this.reversals + " Reversal"; - else return this.formatter.format(this.reversals) + " Reversals"; - } - } - - public String getSwaps() { - if(this.swaps < 0) { - this.swaps = Long.MIN_VALUE; - return "Over " + this.formatter.format(Long.MAX_VALUE); - } - else { - if(this.swaps == 1) return this.swaps + " Swap"; - else return this.formatter.format(this.swaps) + " Swaps"; - } - } - - public String getAuxWrites() { - if(this.auxWrites < 0) { - this.auxWrites = Long.MIN_VALUE; - return "Over " + this.formatter.format(Long.MAX_VALUE); - } - else { - if(this.auxWrites == 1) return this.auxWrites + " Write to Auxiliary Array(s)"; - else return this.formatter.format(this.auxWrites) + " Writes to Auxiliary Array(s)"; - } - } - - public String getMainWrites() { - if(this.writes < 0) { - this.writes = Long.MIN_VALUE; - return "Over " + this.formatter.format(Long.MAX_VALUE); - } - else { - if(this.writes == 1) return this.writes + " Write to Main Array"; - else return this.formatter.format(this.writes) + " Writes to Main Array"; - } - } - - public String getAllocAmount() { - if(this.allocAmount < 0) { - this.allocAmount = Long.MIN_VALUE; - return "Over " + this.formatter.format(Long.MAX_VALUE); - } - else { - if(this.allocAmount == 1) return this.allocAmount + " Item in External Arrays"; - else return this.formatter.format(this.allocAmount) + " Items in External Arrays"; - } - } - - public void changeAuxWrites(int value) { - this.auxWrites += value; - } - - public void changeWrites(int value) { - this.writes += value; - } - - public void changeAllocAmount(int value) { - this.allocAmount += value; - } - - public void clearAllocAmount() { - this.allocAmount = 0; - } - - public void changeReversals(int value) { - this.reversals += value; - } - - private void updateSwap(boolean auxwrite) { - this.swaps++; - if(auxwrite) this.auxWrites += 2; - else this.writes += 2; - } - - private void markSwap(int a, int b) { - Highlights.markArray(1, a); - Highlights.markArray(2, b); - } - - public void swap(int[] array, int a, int b, double pause, boolean mark, boolean auxwrite) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - if (!auxwrite && a >= ArrayVisualizer.getCurrentLength()) { - System.err.println("Warning: write to index " + a + ", which is out of bounds for the current length (" + ArrayVisualizer.getCurrentLength() + ")"); - } - if (!auxwrite && b >= ArrayVisualizer.getCurrentLength()) { - System.err.println("Warning: write to index " + b + ", which is out of bounds for the current length (" + ArrayVisualizer.getCurrentLength() + ")"); - } - - if(mark) this.markSwap(a, b); - - Timer.startLap("Swap"); - - int temp = array[a]; - array[a] = array[b]; - array[b] = temp; - - Timer.stopLap(); - - this.updateSwap(auxwrite); - ArrayVisualizer.updateNow(); - Delays.sleep(pause); - } - - public void multiSwap(int[] array, int pos, int to, double sleep, boolean mark, boolean auxwrite) { - if(to - pos > 0) { - for(int i = pos; i < to; i++) { - this.swap(array, i, i + 1, 0, mark, auxwrite); - Delays.sleep(sleep); - } - } - else { - for(int i = pos; i > to; i--) { - this.swap(array, i, i - 1, 0, mark, auxwrite); - Delays.sleep(sleep); - } - } - } - - public void reversal(int[] array, int start, int length, double sleep, boolean mark, boolean auxwrite) { - this.reversals++; - - for(int i = start; i < start + ((length - start + 1) / 2); i++) { - this.swap(array, i, start + length - i, sleep, mark, auxwrite); - } - } - - public void write(int[] array, int at, int equals, double pause, boolean mark, boolean auxwrite) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - if (!auxwrite && at >= ArrayVisualizer.getCurrentLength()) { - System.err.println("Warning: write to index " + at + ", which is out of bounds for the current length (" + ArrayVisualizer.getCurrentLength() + ")"); - } - - if(mark) Highlights.markArray(1, at); - - if(auxwrite) auxWrites++; - else writes++; - - Timer.startLap("Write"); - - array[at] = equals; - - Timer.stopLap(); - - ArrayVisualizer.updateNow(); - Delays.sleep(pause); - } - - public void write(T[] array, int at, T equals, double pause, boolean mark) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - if(mark) Highlights.markArray(1, at); - - auxWrites++; - - Timer.startLap("Write"); - - array[at] = equals; - - Timer.stopLap(); - - ArrayVisualizer.updateNow(); - Delays.sleep(pause); - } - - public void visualClear(int[] array, int index) { - visualClear(array, index, 0); - } - - public void visualClear(int[] array, int index, double delay) { - array[index] = -1; - } - - public void multiDimWrite(int[][] array, int x, int y, int equals, double pause, boolean mark, boolean auxwrite) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - if(mark) Highlights.markArray(1, x); - - if(auxwrite) auxWrites++; - else writes++; - - Timer.startLap(); - - array[x][y] = equals; - - Timer.stopLap(); - - ArrayVisualizer.updateNow(); - Delays.sleep(pause); - } - - public void multiDimWrite(T[][] array, int x, int y, T equals, double pause, boolean mark) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - if(mark) Highlights.markArray(1, x); - - auxWrites++; - - Timer.startLap(); - - array[x][y] = equals; - - Timer.stopLap(); - - ArrayVisualizer.updateNow(); - Delays.sleep(pause); - } - - //Simulates a write in order to better estimate time for values being written to an ArrayList - public void mockWrite(int length, int pos, int val, double pause) { - if (ArrayVisualizer.sortCanceled()) throw new StopSort(); - int[] mockArray = new int[length]; - - this.auxWrites++; - - Timer.startLap(); - - mockArray[pos] = val; - - Timer.stopLap(); - - Delays.sleep(pause); - } - - public void transcribe(int[] array, ArrayList[] registers, int start, boolean mark, boolean auxwrite) { - int total = start; - - for(int index = 0; index < registers.length; index++) { - for(int i = 0; i < registers[index].size(); i++) { - this.write(array, total++, registers[index].get(i), 0, mark, auxwrite); - if(mark) Delays.sleep(1); - } - this.arrayListClear(registers[index]); - } - } - - public void transcribeMSD(int[] array, ArrayList[] registers, int start, int min, double sleep, boolean mark, boolean auxwrite) { - int total = start; - int temp = 0; - - for(ArrayList list : registers) { - total += list.size(); - } - - for(int index = registers.length - 1; index >= 0; index--) { - for(int i = registers[index].size() - 1; i >= 0; i--) { - this.write(array, total + min - temp++ - 1, registers[index].get(i), 0, mark, auxwrite); - if(mark) Delays.sleep(sleep); - } - } - } - - public void fancyTranscribe(int[] array, int length, ArrayList[] registers, double sleep) { - int[] tempArray = this.createExternalArray(length); - boolean[] tempWrite = new boolean[length]; - int radix = registers.length; - - this.transcribe(tempArray, registers, 0, false, true); - auxWrites -= length; - - for(int i = 0; i < length; i++) { - int register = i % radix; - int pos = (register * (length / radix)) + (i / radix); - - if(!tempWrite[pos]) { - this.write(array, pos, tempArray[pos], 0, false, false); - tempWrite[pos] = true; - } - - Highlights.markArray(register, pos); - if(register == 0) Delays.sleep(sleep); - } - for(int i = 0; i < length; i++) { - if(!tempWrite[i]){ - this.write(array, i, tempArray[i], 0, false, false); - } - } - - Highlights.clearAllMarks(); - - this.deleteExternalArray(tempArray); - } - - //Methods mocking System.arraycopy (reversearraycopy is for TimSort's MergeHi and BinaryInsert, and WikiSort's Rotate) - public void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length, double sleep, boolean mark, boolean aux) { - for(int i = 0; i < length; i++) { - if(mark) { - if(aux) Highlights.markArray(1, srcPos + i); - else Highlights.markArray(1, destPos + i); - } - - //TODO: Handle order of Delays in write method better - this.write(dest, destPos + i, src[srcPos + i], sleep, false, aux); - } - } - - public int[] copyOfArray(int[] original, int newLength) { - this.allocAmount += newLength; - int[] result = Arrays.copyOf(original, newLength); - ArrayVisualizer.getArrays().add(result); - ArrayVisualizer.updateNow(); - return result; - } - - public int[] copyOfRangeArray(int[] original, int from, int to) { - this.allocAmount += to - from; - int[] result = Arrays.copyOfRange(original, from, to); - ArrayVisualizer.getArrays().add(result); - ArrayVisualizer.updateNow(); - return result; - } - - public void reversearraycopy(int[] src, int srcPos, int[] dest, int destPos, int length, double sleep, boolean mark, boolean aux) { - for(int i = length - 1; i >= 0; i--) { - if(mark) { - if(aux) Highlights.markArray(1, srcPos + i); - else Highlights.markArray(1, destPos + i); - } - - this.write(dest, destPos + i, src[srcPos + i], sleep, false, aux); - } - } - - public int[] createExternalArray(int length) { - this.allocAmount += length; - int[] result = new int[length]; - ArrayVisualizer.getArrays().add(result); - ArrayVisualizer.updateNow(); - return result; - } - - public void deleteExternalArray(int[] array) { - this.allocAmount -= array.length; - ArrayVisualizer.getArrays().remove(array); - ArrayVisualizer.updateNow(); - } - - public void deleteExternalArrays(int[]... arrays) { - this.allocAmount -= Arrays.stream(arrays).reduce(0, (a, b) -> (a + b.length), (a, b) -> a + b); - List visArrays = ArrayVisualizer.getArrays(); - Arrays.stream(arrays).forEach(visArrays::remove); - ArrayVisualizer.updateNow(); - } - - public void arrayListAdd(ArrayList aList, int value) { - allocAmount++; - aList.add(value); - } - - public void arrayListAdd(ArrayList aList, int value, boolean mockWrite, double sleep) { - allocAmount++; - aList.add(value); - if (mockWrite) { - this.mockWrite(aList.size(), aList.size() - 1, value, sleep); - } - else { - Delays.sleep(sleep); - } - } - - public void arrayListRemoveAt(ArrayList aList, int index) { - allocAmount--; - aList.remove(index); - } - - public void arrayListClear(ArrayList aList) { - allocAmount -= aList.size(); - aList.clear(); - } - - public void deleteArrayList(ArrayList aList) { - allocAmount -= aList.size(); - } - - public void deleteExternalArray(ArrayList[] array) { - for (ArrayList aList : array) { - deleteArrayList(aList); - } - } - - //TODO: These methods should be solely controlled by Timer class - public void addTime(long milliseconds) { - if(Timer.timerEnabled()) Timer.manualAddTime(milliseconds); - } - - public void setTime(long milliseconds) { - if(Timer.timerEnabled()) Timer.manualSetTime(milliseconds); - } - - public void startLap() { - if(Timer.timerEnabled()) Timer.startLap(); - } - - public void stopLap() { - if(Timer.timerEnabled()) Timer.stopLap(); - } -} \ No newline at end of file diff --git a/src/visuals/Visual.java b/src/visuals/Visual.java deleted file mode 100644 index 3945ef35..00000000 --- a/src/visuals/Visual.java +++ /dev/null @@ -1,131 +0,0 @@ -package visuals; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; - -public abstract class Visual { - protected Graphics2D mainRender; - protected Graphics2D extraRender; - - public Visual(ArrayVisualizer ArrayVisualizer) { - this.updateRender(ArrayVisualizer); - } - - public void updateRender(ArrayVisualizer ArrayVisualizer) { - this.mainRender = ArrayVisualizer.getMainRender(); - this.extraRender = ArrayVisualizer.getExtraRender(); - } - - public static Color getIntColor(int i, int length) { - return Color.getHSBColor(((float) i / length), 0.8F, 0.8F); - } - - public static void markBar(Graphics2D bar, boolean color, boolean rainbow, boolean analysis) { - if(color || rainbow) { - if(analysis) bar.setColor(Color.LIGHT_GRAY); - else bar.setColor(Color.WHITE); - } - else if(analysis) bar.setColor(Color.BLUE); - else bar.setColor(Color.RED); - } - private static void markBarFancy(Graphics2D bar, boolean color, boolean rainbow) { - if(!color && !rainbow) bar.setColor(Color.RED); - else bar.setColor(Color.BLACK); - } - - public static void lineMark(Graphics2D line, double width, boolean color, boolean analysis) { - line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); - if(color) line.setColor(Color.BLACK); - else if(analysis) line.setColor(Color.BLUE); - else line.setColor(Color.RED); - } - //TODO: Change name to markLineFancy - public static void lineFancy(Graphics2D line, double width) { - line.setColor(Color.GREEN); - line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); - } - //TODO: Change name to clearLine - public static void lineClear(Graphics2D line, boolean color, int[] array, int i, int length, double width) { - if(color) line.setColor(getIntColor(array[i], length)); - else line.setColor(Color.WHITE); - line.setStroke(new BasicStroke((float) (3f * (width / 1280f)))); - } - - public static void setRectColor(Graphics2D rect, boolean color, boolean analysis) { - if(color) rect.setColor(Color.WHITE); - else if(analysis) rect.setColor(Color.BLUE); - else rect.setColor(Color.RED); - } - - @SuppressWarnings("fallthrough") - //The longer the array length, the more bars marked. Makes the visual easier to see when bars are thinner. - public static void colorMarkedBars(int logOfLen, int index, Highlights Highlights, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled, boolean analysis) { - switch(logOfLen) { - case 15: if(Highlights.containsPosition(index - 15)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 14)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 13)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 12)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 11)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - case 14: if(Highlights.containsPosition(index - 10)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 9)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 8)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - case 13: if(Highlights.containsPosition(index - 7)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 6)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 5)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - case 12: if(Highlights.containsPosition(index - 4)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - if(Highlights.containsPosition(index - 3)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - case 11: if(Highlights.containsPosition(index - 2)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - case 10: if(Highlights.containsPosition(index - 1)) { markBar(mainRender, colorEnabled, rainbowEnabled, analysis); break; } - default: if(Highlights.containsPosition(index)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); - } - } - - @SuppressWarnings("fallthrough") - public static void drawFancyFinish(int logOfLen, int index, int position, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled) { - switch(logOfLen) { - case 15: if(index == position - 14) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 14: if(index == position - 13) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 13: if(index == position - 12) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 12: if(index == position - 11) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 11: if(index == position - 10) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 10: if(index == position - 9) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 9: if(index == position - 8) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 8: if(index == position - 7) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 7: if(index == position - 6) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 6: if(index == position - 5) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 5: if(index == position - 4) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 4: if(index == position - 3) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 3: if(index == position - 2) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - case 2: if(index == position - 1) { markBarFancy(mainRender, colorEnabled, rainbowEnabled); break; } - default: if(index == position) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - } - } - - @SuppressWarnings("fallthrough") - public static void drawFancyFinishLine(int logOfLen, int index, int position, Graphics2D mainRender, double width, boolean colorEnabled) { - switch(logOfLen) { - case 15: if(index == position - 14) { lineMark(mainRender, width, colorEnabled, false); break; } - case 14: if(index == position - 13) { lineMark(mainRender, width, colorEnabled, false); break; } - case 13: if(index == position - 12) { lineMark(mainRender, width, colorEnabled, false); break; } - case 12: if(index == position - 11) { lineMark(mainRender, width, colorEnabled, false); break; } - case 11: if(index == position - 10) { lineMark(mainRender, width, colorEnabled, false); break; } - case 10: if(index == position - 9) { lineMark(mainRender, width, colorEnabled, false); break; } - case 9: if(index == position - 8) { lineMark(mainRender, width, colorEnabled, false); break; } - case 8: if(index == position - 7) { lineMark(mainRender, width, colorEnabled, false); break; } - case 7: if(index == position - 6) { lineMark(mainRender, width, colorEnabled, false); break; } - case 6: if(index == position - 5) { lineMark(mainRender, width, colorEnabled, false); break; } - case 5: if(index == position - 4) { lineMark(mainRender, width, colorEnabled, false); break; } - case 4: if(index == position - 3) { lineMark(mainRender, width, colorEnabled, false); break; } - case 3: if(index == position - 2) { lineMark(mainRender, width, colorEnabled, false); break; } - case 2: if(index == position - 1) { lineMark(mainRender, width, colorEnabled, false); break; } - default: if(index == position) lineMark(mainRender, width, colorEnabled, false); - } - } - - public abstract void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights); -} \ No newline at end of file diff --git a/src/visuals/VisualStyles.java b/src/visuals/VisualStyles.java deleted file mode 100644 index 017a4e2d..00000000 --- a/src/visuals/VisualStyles.java +++ /dev/null @@ -1,130 +0,0 @@ -package visuals; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -public enum VisualStyles { - BARS { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[0].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - RAINBOW { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[1].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - DISP_BARS { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[2].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - COLOR_CIRCLE { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[3].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - DISP_CIRCLE { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[4].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - DISP_CHORDS { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[5].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - DISP_DOTS { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[6].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - DOTS { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[7].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - WAVE_DOTS { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[8].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - CUSTOM_IMAGE { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[9].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - SINE_WAVE { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[10].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - HOOP_STACK { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[11].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - PIXEL_MESH { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[12].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - SPIRAL { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[13].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }, - SPIRAL_DOTS { - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - ArrayVisualizer.getVisuals()[14].drawVisual(array, ArrayVisualizer, Renderer, Highlights); - } - }; - - public VisualStyles getCurrentVisual() { - return this; - } - - public abstract void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights); -} \ No newline at end of file diff --git a/src/visuals/bars/BarGraph.java b/src/visuals/bars/BarGraph.java deleted file mode 100644 index 461b4321..00000000 --- a/src/visuals/bars/BarGraph.java +++ /dev/null @@ -1,56 +0,0 @@ -package visuals.bars; - -import java.awt.Color; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -final public class BarGraph extends Visual { - - public BarGraph(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - if (width == 0) continue; - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else if(ArrayVisualizer.colorEnabled()) { - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getIndexValue(array[i]): array[i]; - this.mainRender.setColor(getIntColor(val, ArrayVisualizer.getCurrentLength())); - } - else this.mainRender.setColor(Color.WHITE); - - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getStabilityValue(array[i]): array[i]; - int y = (int) (((Renderer.getViewSize() - 20)) - (val + 1) * Renderer.getYScale()); - - this.mainRender.fillRect(j + 20, Renderer.getYOffset() + y, width, (int) ((val + 1) * Renderer.getYScale())); - j += width; - } - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - int length = Math.min(Renderer.getArrayLength(), ArrayVisualizer.getCurrentLength()); - - for(int i = 0, j = 0; i < length; i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - - if(Highlights.containsPosition(i)) { - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getStabilityValue(array[i]): array[i]; - int y = (int) (((Renderer.getViewSize() - 20)) - (val + 1) * Renderer.getYScale()); - - this.mainRender.fillRect(j + 20, Renderer.getYOffset() + y, Math.max(width, 2), (int) ((val + 1) * Renderer.getYScale())); - } - j += width; - } - if(ArrayVisualizer.externalArraysEnabled()) { - this.mainRender.setColor(Color.BLUE); - this.mainRender.fillRect(0, Renderer.getYOffset() + Renderer.getViewSize() - 20, ArrayVisualizer.currentWidth(), 1); - } - } -} \ No newline at end of file diff --git a/src/visuals/bars/DisparityBarGraph.java b/src/visuals/bars/DisparityBarGraph.java deleted file mode 100644 index e2695cc0..00000000 --- a/src/visuals/bars/DisparityBarGraph.java +++ /dev/null @@ -1,54 +0,0 @@ -package visuals.bars; - -import java.awt.Color; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -final public class DisparityBarGraph extends Visual { - - public DisparityBarGraph(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - if (width == 0) continue; - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - - else this.mainRender.setColor(Color.WHITE); - - double disp = (1 + Math.sin((Math.PI * (array[i] - i)) / ArrayVisualizer.getCurrentLength())) * 0.5; - int y = (int) (((Renderer.getViewSize() - 20)) - disp * ArrayVisualizer.getCurrentLength() * Renderer.getYScale()); - - this.mainRender.fillRect(j + 20, Renderer.getYOffset() + y, width, (int) (disp * ArrayVisualizer.getCurrentLength() * Renderer.getYScale())); - j += width; - } - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - - if(Highlights.containsPosition(i)) { - double disp = (1 + Math.sin((Math.PI * (array[i] - i)) / ArrayVisualizer.getCurrentLength())) * 0.5; - int y = (int) (((Renderer.getViewSize() - 20)) - disp * ArrayVisualizer.getCurrentLength() * Renderer.getYScale()); - - this.mainRender.fillRect(j + 20, Renderer.getYOffset() + y, Math.max(width, 2), (int) (disp * ArrayVisualizer.getCurrentLength() * Renderer.getYScale())); - } - j += width; - } - if(ArrayVisualizer.externalArraysEnabled()) { - this.mainRender.setColor(Color.BLUE); - this.mainRender.fillRect(0, Renderer.getYOffset() + Renderer.getViewSize() - 20, ArrayVisualizer.currentWidth(), 1); - } - } -} \ No newline at end of file diff --git a/src/visuals/bars/Rainbow.java b/src/visuals/bars/Rainbow.java deleted file mode 100644 index d7c20bf2..00000000 --- a/src/visuals/bars/Rainbow.java +++ /dev/null @@ -1,73 +0,0 @@ -package visuals.bars; - -import java.awt.Color; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class Rainbow extends Visual { - public Rainbow(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - if (width == 0) continue; - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - - this.mainRender.fillRect(j + 20, Renderer.getYOffset() - 20, width, (int) (Renderer.getViewSize())); - - j += width; - } - if(ArrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.LIGHT_GRAY); - else this.mainRender.setColor(Color.WHITE); - - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - - if(Highlights.containsPosition(i)) { - - this.mainRender.fillRect(j + 20, Renderer.getYOffset() - 20, Math.max(width, 2), (int) (Renderer.getViewSize())); - } - j += width; - } - if(ArrayVisualizer.externalArraysEnabled()) { - this.mainRender.setColor(Color.BLUE); - this.mainRender.fillRect(0, Renderer.getYOffset() + Renderer.getViewSize() - 20, ArrayVisualizer.currentWidth(), 1); - } - } -} \ No newline at end of file diff --git a/src/visuals/bars/SineWave.java b/src/visuals/bars/SineWave.java deleted file mode 100644 index 363a4b47..00000000 --- a/src/visuals/bars/SineWave.java +++ /dev/null @@ -1,77 +0,0 @@ -package visuals.bars; - -import java.awt.Color; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -/* - * -MIT License - -Copyright (c) 2020 MusicTheorist -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class SineWave extends Visual { - - public SineWave(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - - else this.mainRender.setColor(Color.WHITE); - - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - - int y = (int) (((Renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / Renderer.getArrayLength()))) + Renderer.halfViewSize() - 20); - this.mainRender.fillRect(j + 20, Renderer.getYOffset() + y, Math.max(width, 1), 20); - - j += width; - } - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - - if(Highlights.containsPosition(i)) { - int y = (int) (((Renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / Renderer.getArrayLength()))) + Renderer.halfViewSize() - 20); - this.mainRender.fillRect(j + 20, Renderer.getYOffset() + y, Math.max(width, 2), 20); - } - j += width; - } - if(ArrayVisualizer.externalArraysEnabled()) { - this.mainRender.setColor(Color.BLUE); - this.mainRender.fillRect(0, Renderer.getYOffset() + Renderer.getViewSize() - 20, ArrayVisualizer.currentWidth(), 1); - } - } -} \ No newline at end of file diff --git a/src/visuals/circles/ColorCircle.java b/src/visuals/circles/ColorCircle.java deleted file mode 100644 index a3d3d499..00000000 --- a/src/visuals/circles/ColorCircle.java +++ /dev/null @@ -1,104 +0,0 @@ -package visuals.circles; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Polygon; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class ColorCircle extends Visual { - - public ColorCircle(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; - - int width = ArrayVisualizer.windowWidth(); - int height = ArrayVisualizer.windowHeight(); - - int n = ArrayVisualizer.getCurrentLength(); - - double r = Math.min(width, height)/2.75; - int p = (int)(r/12); - - int[] x = new int[3]; - int[] y = new int[3]; - - int[] px = new int[3]; - int[] py = new int[3]; - - this.extraRender.setColor(Color.WHITE); - - x[0] = width/2; - y[0] = height/2; - - x[2] = width/2 + (int)(r * Math.cos(Math.PI * (2d*(n-1) / n - 0.5))); - y[2] = height/2 + (int)(r * Math.sin(Math.PI * (2d*(n-1) / n - 0.5))); - - for(int i = 0; i < n; i++) { - x[1] = x[2]; - y[1] = y[2]; - - x[2] = width/2 + (int)(r * Math.cos(Math.PI * (2d*i / n - 0.5))); - y[2] = height/2 + (int)(r * Math.sin(Math.PI * (2d*i / n - 0.5))); - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else { - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - - if(Highlights.containsPosition(i)) { - if(ArrayVisualizer.analysisEnabled()) this.extraRender.setColor(Color.LIGHT_GRAY); - else this.extraRender.setColor(Color.WHITE); - - px[0] = width/2 + (int)((r + p/4) * Math.cos(Math.PI * ((2d*i - 1) / n - 0.5))); - py[0] = height/2 + (int)((r + p/4) * Math.sin(Math.PI * ((2d*i - 1) / n - 0.5))); - - px[1] = px[0] + (int)(p * Math.cos(Math.PI * ((2d*i - 1) / n - 0.67))); - py[1] = py[0] + (int)(p * Math.sin(Math.PI * ((2d*i - 1) / n - 0.67))); - - px[2] = px[0] + (int)(p * Math.cos(Math.PI * ((2d*i - 1) / n - 0.33))); - py[2] = py[0] + (int)(p * Math.sin(Math.PI * ((2d*i - 1) / n - 0.33))); - - this.extraRender.fillPolygon(px, py, 3); - } - } - - if(x[1] != x[2] || y[1] != y[2]) this.mainRender.fillPolygon(x, y, 3); - } - } -} \ No newline at end of file diff --git a/src/visuals/circles/Spiral.java b/src/visuals/circles/Spiral.java deleted file mode 100644 index ecaec519..00000000 --- a/src/visuals/circles/Spiral.java +++ /dev/null @@ -1,93 +0,0 @@ -package visuals.circles; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Polygon; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class Spiral extends Visual { - - public Spiral(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - if(Renderer.auxActive) return; - - int width = ArrayVisualizer.windowWidth(); - int height = ArrayVisualizer.windowHeight(); - - int n = ArrayVisualizer.getCurrentLength(); - double r = Math.min(width, height)/2.5; - - this.extraRender.setStroke(ArrayVisualizer.getThickStroke()); - this.extraRender.setColor(ArrayVisualizer.getHighlightColor()); - - int[] x = {width/2, 0, 0}; - int[] y = {height/2, 0, 0}; - - double mult = (double) array[n-1] / ArrayVisualizer.getCurrentLength() - 1; - mult = 1 - mult*mult; - - x[2] = width/2 + (int)(mult * r * Math.cos(Math.PI * (2d*(n-1) / n - 0.5))); - y[2] = height/2 + (int)(mult * r * Math.sin(Math.PI * (2d*(n-1) / n - 0.5))); - - for(int i = 0; i < n; i++) { - x[1] = x[2]; - y[1] = y[2]; - - mult = (double) array[i] / ArrayVisualizer.getCurrentLength() - 1; - mult = 1 - mult*mult; - - x[2] = width/2 + (int)(mult * r * Math.cos(Math.PI * (2d*i / n - 0.5))); - y[2] = height/2 + (int)(mult * r * Math.sin(Math.PI * (2d*i / n - 0.5))); - - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else if(Highlights.containsPosition(i)) { - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - this.extraRender.drawPolygon(x, y, 3); - } - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - - else this.mainRender.setColor(Color.WHITE); - - this.mainRender.fillPolygon(x, y, 3); - } - this.extraRender.setStroke(ArrayVisualizer.getDefaultStroke()); - } -} \ No newline at end of file diff --git a/src/visuals/dots/ScatterPlot.java b/src/visuals/dots/ScatterPlot.java deleted file mode 100644 index f3c66637..00000000 --- a/src/visuals/dots/ScatterPlot.java +++ /dev/null @@ -1,120 +0,0 @@ -package visuals.dots; - -import java.awt.Color; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class ScatterPlot extends Visual { - public ScatterPlot(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - int offset = 20 + (int) (Renderer.getXScale()/2); - - if(ArrayVisualizer.linesEnabled()) { - int lastX = 0; - int lastY = (int) (((Renderer.getViewSize() - 20)) - (array[0] + 1) * Renderer.getYScale()); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - - for(int i = 1, j = (int) Renderer.getXScale(); i < Renderer.getArrayLength(); i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { - this.mainRender.setColor(Color.GREEN); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(4)); - } - else if(Highlights.containsPosition(i)) { - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(4)); - } - else if(ArrayVisualizer.colorEnabled()) { - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getIndexValue(array[i]): array[i]; - this.mainRender.setColor(getIntColor(val, ArrayVisualizer.getCurrentLength())); - } - - else this.mainRender.setColor(Color.WHITE); - - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getStabilityValue(array[i]): array[i]; - int y = (int) (((Renderer.getViewSize() - 20)) - (val + 1) * Renderer.getYScale()); - - this.mainRender.drawLine(lastX + offset, Renderer.getYOffset() + lastY, j + offset, Renderer.getYOffset() + y); - - lastX = j; - lastY = y; - - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - j += width; - } - this.mainRender.setStroke(ArrayVisualizer.getDefaultStroke()); - } - else { - int dotS = Renderer.getDotDimensions(); - - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else if(ArrayVisualizer.colorEnabled()) { - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getIndexValue(array[i]): array[i]; - this.mainRender.setColor(getIntColor(val, ArrayVisualizer.getCurrentLength())); - } - else this.mainRender.setColor(Color.WHITE); - - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getStabilityValue(array[i]): array[i]; - int y = (int) (((Renderer.getViewSize() - 20)) - (val + 1) * Renderer.getYScale()); - - this.mainRender.fillRect(j + offset, Renderer.getYOffset() + y, dotS, dotS); - - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - j += width; - } - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - if(Highlights.containsPosition(i)) { - int val = ArrayVisualizer.doingStabilityCheck() && ArrayVisualizer.colorEnabled() ? ArrayVisualizer.getStabilityValue(array[i]): array[i]; - int y = (int) (((Renderer.getViewSize() - 20)) - (val + 1) * Renderer.getYScale()); - - this.mainRender.fillRect(j + offset - (int)(1.5*dotS), Renderer.getYOffset() + y - (int)(1.5*dotS), 4*dotS, 4*dotS); - } - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - j += width; - } - } - if(ArrayVisualizer.externalArraysEnabled()) { - this.mainRender.setColor(Color.BLUE); - this.mainRender.fillRect(0, Renderer.getYOffset() + Renderer.getViewSize() - 20, ArrayVisualizer.currentWidth(), 1); - } - } -} \ No newline at end of file diff --git a/src/visuals/dots/WaveDots.java b/src/visuals/dots/WaveDots.java deleted file mode 100644 index 1779fc34..00000000 --- a/src/visuals/dots/WaveDots.java +++ /dev/null @@ -1,115 +0,0 @@ -package visuals.dots; - -import java.awt.Color; - -import main.ArrayVisualizer; -import utils.Highlights; -import utils.Renderer; -import visuals.Visual; - -/* - * -MIT License - -Copyright (c) 2019 w0rthy -Copyright (c) 2020 MusicTheorist -Copyright (c) 2021 ArrayV 4.0 Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - * - */ - -final public class WaveDots extends Visual { - public WaveDots(ArrayVisualizer ArrayVisualizer) { - super(ArrayVisualizer); - } - - @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { - int offset = 20 + (int) (Renderer.getXScale()/2); - - if(ArrayVisualizer.linesEnabled()) { - int lastX = 0; - int lastY = (int) (((Renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[0] / Renderer.getArrayLength()))) + Renderer.halfViewSize() - 20); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - - for(int i = 1, j = (int) Renderer.getXScale(); i < Renderer.getArrayLength(); i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) { - this.mainRender.setColor(Color.GREEN); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(4)); - } - else if(Highlights.containsPosition(i)) { - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(4)); - } - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i-1], ArrayVisualizer.getCurrentLength())); - - else this.mainRender.setColor(Color.WHITE); - - int y = (int) (((Renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / Renderer.getArrayLength()))) + Renderer.halfViewSize() - 20); - - this.mainRender.drawLine(lastX + offset, Renderer.getYOffset() + lastY, j + offset, Renderer.getYOffset() + y); - - lastX = j; - lastY = y; - - this.mainRender.setStroke(ArrayVisualizer.getCustomStroke(2)); - - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - j += width; - } - this.mainRender.setStroke(ArrayVisualizer.getDefaultStroke()); - } - else { - int dotS = Renderer.getDotDimensions(); - - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - if(Highlights.fancyFinishActive() && i < Highlights.getFancyFinishPosition()) - this.mainRender.setColor(Color.GREEN); - - else if(ArrayVisualizer.colorEnabled()) - this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - - else this.mainRender.setColor(Color.WHITE); - - int y = (int) (((Renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / Renderer.getArrayLength()))) + Renderer.halfViewSize() - 20); - - this.mainRender.fillRect(j + offset, Renderer.getYOffset() + y, dotS, dotS); - - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - j += width; - } - this.mainRender.setColor(ArrayVisualizer.getHighlightColor()); - - for(int i = 0, j = 0; i < Renderer.getArrayLength(); i++) { - if(Highlights.containsPosition(i)) { - int y = (int) (((Renderer.getViewSize() - 20) / 2.5) * Math.sin((2 * Math.PI * ((double) array[i] / Renderer.getArrayLength()))) + Renderer.halfViewSize() - 20); - this.mainRender.fillRect(j + offset - (int)(1.5*dotS), Renderer.getYOffset() + y - (int)(1.5*dotS), 4*dotS, 4*dotS); - } - int width = (int) (Renderer.getXScale() * (i + 1)) - j; - j += width; - } - } - if(ArrayVisualizer.externalArraysEnabled()) { - this.mainRender.setColor(Color.BLUE); - this.mainRender.fillRect(0, Renderer.getYOffset() + Renderer.getViewSize() - 20, ArrayVisualizer.currentWidth(), 1); - } - } -} \ No newline at end of file diff --git a/stable_checker.py b/stable_checker.py index 249cd449..74df769c 100644 --- a/stable_checker.py +++ b/stable_checker.py @@ -14,7 +14,7 @@ def wrap_int(cls, val, key) -> IntegerWrapper: res = cls(val) res.key = key return res - + def key_compare(self, other: IntegerWrapper) -> Literal[None, -1, 0, 1]: if self < other: return -1 @@ -25,7 +25,7 @@ def key_compare(self, other: IntegerWrapper) -> Literal[None, -1, 0, 1]: elif self.key > other.key: return 1 return 0 - + def __repr__(self) -> str: return f'{super().__repr__()}:{self.key!r}' @@ -39,7 +39,7 @@ def caller(self, *args): res = getattr(int, funcname)(self, *args) return IntegerWrapper.wrap_int(res, self.key) return caller - + __abs__ = __wrapper('abs') __add__ = __wrapper('add') __and__ = __wrapper('and') @@ -127,7 +127,7 @@ def main(colonfunc: str): print('Module', repr(module.__name__), 'has no attribute', repr(funcname)) sys.exit(1) func = getattr(module, funcname) - + result = simple_sort(func) stable = IntegerWrapper.is_sequence_stable(result) print(colonfunc, ' is', ' not' * (not stable), ' stable', sep='') diff --git a/stats-config.txt b/stats-config.txt new file mode 100644 index 00000000..cd273a8a --- /dev/null +++ b/stats-config.txt @@ -0,0 +1,18 @@ +FONT: Times New Roman * 25 +# fps +# +sort +length + +delay +vtime +stime + +comps +swaps +revs + +wmain +waux +auxlen +segments diff --git a/template.java b/template.java index 8bb2c051..1b8ee3cd 100644 --- a/template.java +++ b/template.java @@ -1,26 +1,19 @@ package sorts.category; -import main.ArrayVisualizer; -import sorts.templates.Sort; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; -final public class MySort extends Sort { +@SortMeta( + name = "My", + category = "Category Sorts" +) +public final class MySort extends Sort { public MySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("My"); - this.setRunAllSortsName("My Sort"); - this.setRunSortName("Mysort"); - this.setCategory("Category Sorts"); - this.setComparisonBased(true); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - + @Override public void runSort(int[] array, int currentLength, int bucketCount) { - } }