diff --git a/README.md b/README.md index ef6e7ae..4ae95d0 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,25 @@ -# Visualization of different sorting algorithms +

+ Visualization of different sorting algorithms

+ +

+ Insertion sort gif

## How to build executable file? -run this in an IDE's terminal +In an IDE's terminal: -``` bash +``` mvn clean package ``` -This command will create `/taget` folder and executable `fileName-version-jar-with-dependencies.jar` inside. +This command will create `/taget` folder and executable `sav-version-jar-with-dependencies.jar` inside. ## How to run? -open terminal in a folder with `.jar` file and run: +1. Build project or download latest release from release section. + +2. Open terminal in a folder with `.jar` file and run this command: -``` bash -java -jar filename.jar ``` +java -jar sav-1.0-jar-with-dependencies.jar +``` \ No newline at end of file diff --git a/assets/README-animation.gif b/assets/README-animation.gif new file mode 100644 index 0000000..28fb804 Binary files /dev/null and b/assets/README-animation.gif differ diff --git a/pom.xml b/pom.xml index 0d24cdc..fbad8cc 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,11 @@ JTerminal 1.0.2 + + org.jline + jline + 3.26.2 + diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 994514d..5e78bb3 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,7 +1,22 @@ -import ui.TestUI; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; +import ui.UI; public class Main { public static void main(String[] args) { - TestUI.start(); + UI ui; + try{ + Terminal terminal = TerminalBuilder.builder().system(true).build(); + LineReader reader = LineReaderBuilder.builder().terminal(terminal).build(); + ui = new UI(terminal, reader); + ui.start(); + + } + catch (Exception e){ + e.printStackTrace(); + } + } } diff --git a/src/main/java/algorithms/BubbleSort.java b/src/main/java/algorithms/BubbleSort.java index 78eff60..647f2c2 100644 --- a/src/main/java/algorithms/BubbleSort.java +++ b/src/main/java/algorithms/BubbleSort.java @@ -6,15 +6,14 @@ import java.util.HashSet; import java.util.Set; -public class BubbleSort extends AlgorithmSort { +public class BubbleSort extends SortingAlgorithm { public BubbleSort(ArrayList array) { super(array); } - @Override public void sort() { - int SLEEP_DURATION = 5; + int SLEEP_DURATION = 3; if (array.isEmpty()) { System.out.println("Array is empty, nothing to sort."); diff --git a/src/main/java/algorithms/InsertionSort.java b/src/main/java/algorithms/InsertionSort.java index ceb72d8..642c35d 100644 --- a/src/main/java/algorithms/InsertionSort.java +++ b/src/main/java/algorithms/InsertionSort.java @@ -6,7 +6,7 @@ import java.util.HashSet; import java.util.Set; -public class InsertionSort extends AlgorithmSort { +public class InsertionSort extends SortingAlgorithm { public InsertionSort(ArrayList array) { super(array); @@ -14,7 +14,7 @@ public InsertionSort(ArrayList array) { @Override public void sort() { - int SLEEP_DURATION = 10; + int SLEEP_DURATION = 2; Set sortedIndices = new HashSet<>(); if (array.isEmpty()) { diff --git a/src/main/java/algorithms/QuickSort.java b/src/main/java/algorithms/QuickSort.java index 3626524..795e6e9 100644 --- a/src/main/java/algorithms/QuickSort.java +++ b/src/main/java/algorithms/QuickSort.java @@ -6,7 +6,7 @@ import java.util.HashSet; import java.util.Set; -public class QuickSort extends AlgorithmSort { +public class QuickSort extends SortingAlgorithm { public QuickSort(ArrayList array) { super(array); diff --git a/src/main/java/algorithms/SelectionSort.java b/src/main/java/algorithms/SelectionSort.java index b188369..8489c1e 100644 --- a/src/main/java/algorithms/SelectionSort.java +++ b/src/main/java/algorithms/SelectionSort.java @@ -6,7 +6,7 @@ import java.util.HashSet; import java.util.Set; -public class SelectionSort extends AlgorithmSort { +public class SelectionSort extends SortingAlgorithm { public SelectionSort(ArrayList array) { super(array); diff --git a/src/main/java/algorithms/AlgorithmSort.java b/src/main/java/algorithms/SortingAlgorithm.java similarity index 65% rename from src/main/java/algorithms/AlgorithmSort.java rename to src/main/java/algorithms/SortingAlgorithm.java index 6d90ab5..75447b2 100644 --- a/src/main/java/algorithms/AlgorithmSort.java +++ b/src/main/java/algorithms/SortingAlgorithm.java @@ -1,11 +1,12 @@ package algorithms; + import java.util.ArrayList; -public abstract class AlgorithmSort { +public abstract class SortingAlgorithm { protected ArrayList array; - public AlgorithmSort(ArrayList array ){ - if(array == null){ + public SortingAlgorithm(ArrayList array) { + if (array == null) { throw new IllegalArgumentException("Array can't be empty."); } this.array = array; diff --git a/src/main/java/ui/BubbleSort.java b/src/main/java/ui/BubbleSort.java new file mode 100644 index 0000000..d7d1874 --- /dev/null +++ b/src/main/java/ui/BubbleSort.java @@ -0,0 +1,11 @@ +package ui; + +import static ui.UI.array; + +class BubbleSort { + protected static void start() { + Utils.prepareForSorting("Bubble Sort"); + new algorithms.BubbleSort(array).sort(); + Utils.sleepALittle(1000); + } +} diff --git a/src/main/java/ui/InsertionSort.java b/src/main/java/ui/InsertionSort.java new file mode 100644 index 0000000..3d2fc81 --- /dev/null +++ b/src/main/java/ui/InsertionSort.java @@ -0,0 +1,11 @@ +package ui; + +import static ui.UI.array; + +class InsertionSort { + protected static void start() { + Utils.prepareForSorting("Insertion sort"); + new algorithms.InsertionSort(array).sort(); + Utils.sleepALittle(1000); + } +} diff --git a/src/main/java/ui/Menu.java b/src/main/java/ui/Menu.java new file mode 100644 index 0000000..126ed7c --- /dev/null +++ b/src/main/java/ui/Menu.java @@ -0,0 +1,33 @@ +package ui; + +import io.github.shuoros.jterminal.JTerminal; + +import static ui.UI.reader; + +class Menu { + protected static void printOptions() { + JTerminal.clear(); + Utils.printInCenter("AWESOME algorithm visualization app", "="); + JTerminal.println(""" + \nSelect an option:\ + \n\ + \n(1)\tRun Bubble sort\ + \n(2)\tRun Insertion sort\ + \n(3)\tRun Quick sort\ + \n(4)\tRun Selection sort\ + \n(a)\tRun all\ + \n(e)\texit"""); + } + + protected static void handleOptions() { + switch (reader.readLine().trim().toLowerCase()) { + case "1" -> BubbleSort.start(); + case "2" -> InsertionSort.start(); + case "3" -> QuickSort.start(); + case "4" -> SelectionSort.start(); + case "a", "all" -> StartAllOption.start(); + case "exit", "e" -> System.exit(0); + default -> JTerminal.println("Wrong input"); + } + } +} diff --git a/src/main/java/ui/QuickSort.java b/src/main/java/ui/QuickSort.java new file mode 100644 index 0000000..3758486 --- /dev/null +++ b/src/main/java/ui/QuickSort.java @@ -0,0 +1,11 @@ +package ui; + +import static ui.UI.array; + +class QuickSort { + protected static void start() { + Utils.prepareForSorting("Quick Sort"); + new algorithms.QuickSort(array).sort(); + Utils.sleepALittle(1000); + } +} diff --git a/src/main/java/ui/SelectionSort.java b/src/main/java/ui/SelectionSort.java new file mode 100644 index 0000000..c888aac --- /dev/null +++ b/src/main/java/ui/SelectionSort.java @@ -0,0 +1,11 @@ +package ui; + +import static ui.UI.array; + +class SelectionSort { + protected static void start() { + Utils.prepareForSorting("Selection Sort"); + new algorithms.InsertionSort(array).sort(); + Utils.sleepALittle(1000); + } +} diff --git a/src/main/java/ui/StartAllOption.java b/src/main/java/ui/StartAllOption.java new file mode 100644 index 0000000..a24b1ac --- /dev/null +++ b/src/main/java/ui/StartAllOption.java @@ -0,0 +1,10 @@ +package ui; + +class StartAllOption { + protected static void start() { + BubbleSort.start(); + InsertionSort.start(); + QuickSort.start(); + SelectionSort.start(); + } +} diff --git a/src/main/java/ui/TestUI.java b/src/main/java/ui/TestUI.java deleted file mode 100644 index be6c3b8..0000000 --- a/src/main/java/ui/TestUI.java +++ /dev/null @@ -1,36 +0,0 @@ -package ui; - -import algorithms.BubbleSort; -import algorithms.InsertionSort; -import algorithms.QuickSort; -import algorithms.SelectionSort; - -import java.util.ArrayList; -import java.util.List; - -public class TestUI { - public static void start() { - - ArrayList list = new ArrayList<>(List.of( - 10, 17, 9, 19, 15, 7, 6, 4, 7, 6, - 6, 20, 17, 6, 5, 8, 8, 5, 17, 18, - 16, 17, 10, 1, 18, 4, 6, 20, 9, 14, - 7, 4, 15, 7, 6, 2, 15, 15, 3, 1, 9, - 2, 19, 8, 16, 14, 19, 5, 20, 9 - )); - BubbleSort bubbleSort = new BubbleSort(list); - //bubbleSort.sort(); - - SelectionSort selectionSort = new SelectionSort(list); - //selectionSort.sort(); - - - QuickSort quickSort = new QuickSort(list); - //quickSort.sort(); - - InsertionSort insertionSort = new InsertionSort(list); - insertionSort.sort(); - - - } -} diff --git a/src/main/java/ui/UI.java b/src/main/java/ui/UI.java new file mode 100644 index 0000000..664d344 --- /dev/null +++ b/src/main/java/ui/UI.java @@ -0,0 +1,29 @@ +package ui; + +import io.github.shuoros.jterminal.JTerminal; +import org.jline.reader.LineReader; +import org.jline.terminal.Terminal; + +import java.util.ArrayList; + +public class UI { + protected static ArrayList array; + public static Terminal terminal; + protected static LineReader reader; + + public UI(Terminal terminal, LineReader reader) { + UI.terminal = terminal; + UI.reader = reader; + array = new ArrayList<>(); + } + + public void start() { + while (true) { + Menu.printOptions(); + Menu.handleOptions(); + Utils.sleepALittle(1500); + } + } + + +} diff --git a/src/main/java/ui/Utils.java b/src/main/java/ui/Utils.java index 63c1e98..9db2825 100644 --- a/src/main/java/ui/Utils.java +++ b/src/main/java/ui/Utils.java @@ -3,9 +3,14 @@ import io.github.shuoros.jterminal.JTerminal; import java.util.ArrayList; +import java.util.Random; import java.util.Set; +import static ui.UI.array; +import static ui.UI.terminal; + public abstract class Utils { + public static int findMax(ArrayList array) { int max = 0; for (var element : array) { @@ -15,13 +20,8 @@ public static int findMax(ArrayList array) { } public static void swapHighlighted(ArrayList arr, int currentIndex, int targetIndex, Set sortedIndices, int sleepDuration) { - displayVerticalArray(arr, currentIndex, targetIndex, sortedIndices); - try { - Thread.sleep(sleepDuration); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + sleepALittle(sleepDuration); // Perform the swap int temp = arr.get(currentIndex); @@ -29,11 +29,7 @@ public static void swapHighlighted(ArrayList arr, int currentIndex, int arr.set(targetIndex, temp); displayVerticalArray(arr, currentIndex, targetIndex, sortedIndices); - try { - Thread.sleep(sleepDuration); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + sleepALittle(sleepDuration); } @@ -67,8 +63,8 @@ public static void displayVerticalArray(ArrayList arrayList, int curren } output.append("\n"); } - - System.out.print(output.toString()); + //printInCenter(output.toString(), " "); + System.out.print(output); /* Repositioning the cursor: @@ -79,6 +75,66 @@ public static void displayVerticalArray(ArrayList arrayList, int curren System.out.print("\033[" + maxHeight + "F"); // Move cursor up to the top } + /** + * Overload displayVerticalArray method to print initial unsorted array + * + * @param arrayList array to print + */ + public static void displayVerticalArray(ArrayList arrayList) { + StringBuilder output = new StringBuilder(); + + int maxHeight = findMax(arrayList); + + for (int row = maxHeight; row > 0; row--) { + output.append("\033[2K"); // Clear the whole line + for (int col = 0; col < arrayList.size(); col++) { + int element = arrayList.get(col); + if (element >= row) output.append("◼"); + else output.append(" "); + } + output.append("\n"); + } + System.out.print(output); + System.out.print("\033[" + maxHeight + "F"); // Move cursor up to the top + } + + public static void clearArrayAndFillRandomly(ArrayList array, int width, int height) { + Random r = new Random(); + array.clear(); + for (int i = 0; i < width - 1; i++) { + array.add(r.nextInt(1, (int) (height - 1))); + } + } + + public static void printInCenter(String line, String symbolForFill) { + int width = UI.terminal.getWidth(); + int padding = ((width - line.length()) / 2); + JTerminal.println(symbolForFill.repeat(Math.max(0, padding)) + line + symbolForFill.repeat(Math.max(0, padding))); + } - // fillArrayRandomlyMethod (between 1 and 100 for example) + /** + * Preparing to print a sorting animation and show unsorted array for 3 seconds + * + * @param algorithm Name of algorithm that will be printed at the top of the screen + */ + public static void prepareForSorting(String algorithm) { + clearArrayAndFillRandomly(array, terminal.getWidth(), terminal.getHeight()); + JTerminal.clear(); + printInCenter(algorithm, "="); + displayVerticalArray(array); + sleepALittle(3000); + } + + /** + * We use Thread.sleep() a lot, so let's extract it to the nice method + * + * @param sleepDuration duration of sleep in millis + */ + public static void sleepALittle(int sleepDuration) { + try { + Thread.sleep(sleepDuration); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file