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
-
-

+
+
-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.
+ * @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 extends Sort> 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 extends Sort>)sortClass);
+ }
+
+ private boolean compileSingle(Class extends Sort> 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 extends ZipEntry> 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 extends JavaFileObject> 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 extends Sort> sortClass) throws NoSuchMethodException, IllegalAccessException {
+ this(getMh(sortClass));
+ }
+
+ public MethodAnswerValidator(Sort sort) throws IllegalAccessException, NoSuchMethodException {
+ this(sort.getClass());
+ }
+
+ private static MethodHandle getMh(Class extends Sort> 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 extends Sort> constructor) throws IllegalAccessException {
+ this(LOOKUP.unreflectConstructor(constructor));
+ }
+
+ public NewSortInstance(Class extends Sort> sortClass) throws NoSuchMethodException, IllegalAccessException {
+ this(getMh(sortClass));
+ }
+
+ public NewSortInstance(Sort sort) throws IllegalAccessException, NoSuchMethodException {
+ this(sort.getClass());
+ }
+
+ private static MethodHandle getMh(Class extends Sort> 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 extends Sort> 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 extends Sort> 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 extends Sort> 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 extends Sort> sort) {
+ this(-1, sort);
+ }
+
+ public SortInfo(Sort sort) {
+ this(-1, sort);
+ }
+
+ private static String findSortCategory(Class extends Sort> 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 extends Sort> 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 extends Sort> 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 extends Sort> 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 extends Integer> c) {
+ return false;
+ }
+
+ @Override
+ public boolean addAll(int index, Collection extends Integer> 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 super Integer> 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 extends ShuffleInfo> 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("