diff --git a/clients/src/main/java/com/hithomelabs/clients/Benchmarks/BenchMark.java b/clients/src/main/java/com/hithomelabs/clients/Benchmarks/BenchMark.java new file mode 100644 index 0000000..d4dda43 --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/Benchmarks/BenchMark.java @@ -0,0 +1,57 @@ +package com.hithomelabs.clients.Benchmarks; + +import com.hithomelabs.princeton1.common.Apple; +import com.hithomelabs.princeton1.module5.MeasurableSort; +import com.hithomelabs.princeton1.module5.SortingMetaData; + +import java.util.List; +import java.util.Random; + +public class BenchMark { + + private int size; + private List> algorithms; + private Apple[] sorted; + private Apple[] reverseSorted; + private Apple[] random; + + BenchMark(int size, List> algorithms) { + this.size = size; + this.algorithms = algorithms; + sorted = new Apple[this.size]; + reverseSorted = new Apple[this.size]; + random = new Apple[this.size]; + + for (int i = 0; i < size; i++) { + sorted[i] = new Apple(i); + reverseSorted[i] = new Apple(size - i); + random[i] = new Apple(new Random().nextInt(1000)); + } + } + + public void run() { + for (MeasurableSort algo: algorithms){ + System.out.println("Input size: "+size); + System.out.println("Running "+algo.getClass()); + System.out.println("Sorting already sorted list"); + SortingMetaData metaData = new SortingMetaData(); + algo.sort(sorted.clone(),Apple.COMPARE_BY_SIZE, metaData); + System.out.println(metaData); + System.out.println("Sorting reverse sorted list"); + metaData = new SortingMetaData(); + algo.sort(reverseSorted.clone(),Apple.COMPARE_BY_SIZE, metaData); + System.out.println(metaData); + System.out.println("Sorting randomly ordered list"); + metaData = new SortingMetaData(); + algo.sort(random.clone(),Apple.COMPARE_BY_SIZE, metaData); + System.out.println(metaData); + } + } + +} + + + + + + diff --git a/clients/src/main/java/com/hithomelabs/clients/Benchmarks/BenchMarkingClient.java b/clients/src/main/java/com/hithomelabs/clients/Benchmarks/BenchMarkingClient.java new file mode 100644 index 0000000..dd3bebe --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/Benchmarks/BenchMarkingClient.java @@ -0,0 +1,37 @@ +package com.hithomelabs.clients.Benchmarks; + +import com.hithomelabs.princeton1.common.Apple; +import com.hithomelabs.princeton1.module5.Insertion; +import com.hithomelabs.princeton1.module5.MeasurableSort; +import com.hithomelabs.princeton1.module5.Selection; +import com.hithomelabs.princeton1.module5.Shell; +import com.hithomelabs.princeton1.module6.Merge; +import com.hithomelabs.princeton1.module7.Quick; + +import java.util.ArrayList; +import java.util.List; + +public class BenchMarkingClient { + + public static void main(String[] args) { + List> algorithms = new ArrayList>(); + + algorithms.add(new Selection()); + algorithms.add(new Insertion()); + algorithms.add(new Shell()); + algorithms.add(new Merge()); + algorithms.add(new Quick()); + + BenchMark b1 = new BenchMark(32, algorithms); + BenchMark b2 = new BenchMark(512, algorithms); + BenchMark b3 = new BenchMark(1024, algorithms); + BenchMark b4 = new BenchMark(4096,algorithms); + b1.run(); + b2.run(); + b3.run(); + b4.run(); + + } + + +} diff --git a/common/src/main/java/com/hithomelabs/princeton1/common/Apple.java b/common/src/main/java/com/hithomelabs/princeton1/common/Apple.java index 04edf46..a170767 100644 --- a/common/src/main/java/com/hithomelabs/princeton1/common/Apple.java +++ b/common/src/main/java/com/hithomelabs/princeton1/common/Apple.java @@ -1,9 +1,18 @@ package com.hithomelabs.princeton1.common; +import java.util.Comparator; import java.util.Objects; public class Apple implements Comparable { private int size; + public static Comparator COMPARE_BY_SIZE = new Comparator() { + @Override + public int compare(Apple a1, Apple a2) { + if(a1.size < a2.size) return -1; + else if (a1.size == (a2.size)) return 0; + else return 1; + } + }; public Apple(int size) { this.size = size; diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java deleted file mode 100644 index 647b506..0000000 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.hithomelabs.princeton1.module5; - -public abstract class AbstractCustomSorts { - - public abstract void sort(E[] arr); - - public void exch(E[] arr, int j, int i) { - E temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; - } - - public boolean less(Comparable e1, E e2) { - return e1.compareTo(e2) < 0; - } - -} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/ComparableSort.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/ComparableSort.java new file mode 100644 index 0000000..6198c51 --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/ComparableSort.java @@ -0,0 +1,17 @@ +package com.hithomelabs.princeton1.module5; + +public interface ComparableSort { + + void sort(E[] arr); + + default void exch(E[] arr, int j, int i) { + E temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + default boolean less(Comparable e1, E e2) { + return e1.compareTo(e2) < 0; + } + +} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/ComparatorComparableSort.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/ComparatorComparableSort.java new file mode 100644 index 0000000..550b5a0 --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/ComparatorComparableSort.java @@ -0,0 +1,15 @@ +package com.hithomelabs.princeton1.module5; + +import java.util.Comparator; + +public interface ComparatorComparableSort extends ComparableSort { + + public void sort(E[] arr, Comparator cmp); + + public default boolean less(E v, E w, Comparator cmp){ + if (cmp == null) + return ComparableSort.super.less((Comparable) v, w); + else + return cmp.compare(v, w) < 0; + } +} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java index 49ce313..81f15dc 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java @@ -1,23 +1,41 @@ package com.hithomelabs.princeton1.module5; -public class Insertion extends AbstractCustomSorts { +import java.util.Comparator; - public void sort(E[] arr){ +public class Insertion implements MeasurableSort { + + public void sort(E[] arr) { + coreSortLogic(arr, null, null); + + } + + private void coreSortLogic(E[] arr, Comparator cmp, SortingMetaData metaData) { if (arr == null) return; - else{ + else { int N = arr.length; // * * swap arr[i] with each element greater to it's left - for (int i = 1; i < N; i++){ + for (int i = 1; i < N; i++) { int j = i; - while(j >= 1 && less((Comparable)arr[j], arr[j-1])){ - exch(arr, j, j-1); - j = j-1; + while (j >= 1 && less(arr[j], arr[j - 1], cmp, metaData)) { + exch(arr, j, j - 1, metaData); + j = j - 1; } } } - } - + @Override + public void sort(E[] arr, Comparator cmp, SortingMetaData metaData) { + if (metaData != null) + metaData.startTime(); + coreSortLogic(arr, cmp, metaData); + if (metaData != null) + metaData.endTime(); } + @Override + public void sort(E[] arr, Comparator cmp) { + coreSortLogic(arr, cmp, null); + } +} + diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/MeasurableSort.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/MeasurableSort.java new file mode 100644 index 0000000..d30dbcf --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/MeasurableSort.java @@ -0,0 +1,22 @@ +package com.hithomelabs.princeton1.module5; + +import java.util.Comparator; + +public interface MeasurableSort extends ComparatorComparableSort { + + + default boolean less(E v, E w, Comparator cmp, SortingMetaData metaData) { + if (metaData != null) + metaData.incrementCompares(); + return ComparatorComparableSort.super.less(v, w, cmp); + } + + default void exch(E[] arr, int j, int i, SortingMetaData metaData) { + if (metaData != null) + metaData.incrementExchanges(); + ComparatorComparableSort.super.exch(arr, j, i); + } + + public void sort(E[] arr, Comparator cmp, SortingMetaData metaData); + +} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java index 3b0a0c1..01551fe 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java @@ -1,23 +1,42 @@ package com.hithomelabs.princeton1.module5; -public class Selection extends AbstractCustomSorts{ +import java.util.Comparator; + +public class Selection implements MeasurableSort { /* * * Selection sort "selects" the smallest element and swaps it with arr[0] of the array * * Then proceeds to do the same swapping arr[i] with arr[i:arr.length-1] */ public void sort(E[] arr){ + coreSortLogic(arr, null, null); + } + + private void coreSortLogic(E[] arr, Comparator cmp, SortingMetaData metaData){ if (arr == null) return; Comparable[] arr1 = (Comparable[]) arr; for(int i = 0; i < arr1.length - 1; i++){ int minIndex = i; for(int j = i+1; j < arr.length; j ++){ - if (less((Comparable) arr[j], arr[minIndex])) minIndex = j; + if (less(arr[j], arr[minIndex], cmp, metaData)) minIndex = j; } - exch(arr, i, minIndex); + exch(arr, i, minIndex, metaData); } } + @Override + public void sort(E[] arr, Comparator cmp, SortingMetaData metaData) { + if (metaData != null) + metaData.startTime(); + coreSortLogic(arr, cmp, metaData); + if (metaData != null) + metaData.endTime(); + } + + @Override + public void sort(E[] arr, Comparator cmp) { + coreSortLogic(arr, cmp, null); + } } diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java index d253056..11a9714 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java @@ -1,13 +1,9 @@ package com.hithomelabs.princeton1.module5; -public class Shell extends AbstractCustomSorts { +import java.util.ArrayList; +import java.util.Comparator; - // * * sample metadata class to compare no. of sorts and compares, shell sort vs insertion sort - private class MetaData{ - - int compares; - int swaps; - } +public class Shell implements MeasurableSort { /* * * We will be performing h sort @@ -24,7 +20,10 @@ public class Shell extends AbstractCustomSorts { */ @Override public void sort(E[] arr) { - MetaData metaData = new MetaData(); + coreSortLogic(arr,null,null); + } + + private void coreSortLogic(E[] arr, Comparator cmp, SortingMetaData metaData){ int N = arr.length; int h = 1; // * * Calculates the largest value of h greater than n @@ -32,22 +31,18 @@ public class Shell extends AbstractCustomSorts { h = 3 * h + 1; } while (h >= 1) { - h = hsort(arr, h, metaData); + h = hsort(arr, h, cmp, metaData); h = h / 3; } - System.out.println("Array sorted (shell sort) with " + metaData.compares + " compares and " + metaData.swaps + " swaps"); } - private int hsort(E[] arr, int h, MetaData metadata) { + private int hsort(E[] arr, int h, Comparator cmp, SortingMetaData metaData) { int N = arr.length; for(int i = h; i < N; i++){ int j = i; - ++metadata.compares; - while(j >= h && less((Comparable) arr[j], arr[j-h])){ - ++metadata.swaps; - exch(arr, j, j-h); + while(j >= h && less(arr[j], arr[j-h], cmp, metaData)){ + exch(arr, j, j-h, metaData); j = j - h; - ++metadata.compares; } } return h; @@ -57,10 +52,21 @@ public class Shell extends AbstractCustomSorts { * Will just be comparing the number of saps taken across both implementations */ public void insertionSort(E[] arr){ - MetaData metaData = new MetaData(); int h = 1; - h = hsort(arr, h, metaData); - System.out.println("Array sorted (insertion sort) with " + metaData.compares + " compares and " + metaData.swaps + " swaps"); + h = hsort(arr, h, null, null); } + @Override + public void sort(E[] arr, Comparator cmp, SortingMetaData metaData) { + if (metaData != null) + metaData.startTime(); + coreSortLogic(arr, cmp, metaData); + if (metaData != null) + metaData.endTime(); + } + + @Override + public void sort(E[] arr, Comparator cmp) { + coreSortLogic(arr, cmp, null); + } } diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/SortingMetaData.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/SortingMetaData.java new file mode 100644 index 0000000..23029bf --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/SortingMetaData.java @@ -0,0 +1,34 @@ +package com.hithomelabs.princeton1.module5; + +public class SortingMetaData { + + private double tick; + private double tok; + private int exchanges; + private int compares; + + public double timeElapsed(){ + return tok - tick; + } + + public void startTime(){ + tick = System.nanoTime(); + } + + public void endTime(){ + tok = System.nanoTime(); + } + + public void incrementCompares(){ + ++compares; + } + + public void incrementExchanges(){ + ++exchanges; + } + + @Override + public String toString() { + return "Time elapsed: " + this.timeElapsed() + " nano-seconds \nCompares: "+this.compares+ "\nSwaps: "+this.exchanges; + } +} diff --git a/module5/src/test/java/com/hithomelabs/princeton1/module5/SortTest.java b/module5/src/test/java/com/hithomelabs/princeton1/module5/SortTest.java index 301c6d5..1b853a2 100644 --- a/module5/src/test/java/com/hithomelabs/princeton1/module5/SortTest.java +++ b/module5/src/test/java/com/hithomelabs/princeton1/module5/SortTest.java @@ -11,7 +11,7 @@ import java.util.Random; class SortTest { private ArrayList apples; - private AbstractCustomSorts sortingAlgorithm; + private ComparableSort sortingAlgorithm; private Random random; @BeforeEach @@ -21,7 +21,7 @@ class SortTest { random = new Random(); } - private void testSort(AbstractCustomSorts sortingAlgorithm) { + private void testSort(ComparableSort sortingAlgorithm) { for (int i = 0; i < 100; i++) apples.add(new Apple(random.nextInt(100))); diff --git a/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java b/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java index 5cffa56..66fa2be 100644 --- a/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java +++ b/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java @@ -1,46 +1,73 @@ package com.hithomelabs.princeton1.module6; -import com.hithomelabs.princeton1.module5.AbstractCustomSorts; +import com.hithomelabs.princeton1.module5.ComparableSort; +import com.hithomelabs.princeton1.module5.MeasurableSort; +import com.hithomelabs.princeton1.module5.SortingMetaData; import java.util.Arrays; +import java.util.Comparator; -public class Merge extends AbstractCustomSorts { +public class Merge implements MeasurableSort { @Override public void sort(E[] arr) { + coreSortLogic(arr, null, null); + } + private void coreSortLogic(E[] arr, Comparator cmp, SortingMetaData metaData) { int N = arr.length; // * * aux is a helper array required for merge E[] aux = Arrays.copyOf(arr, N); - mergesort(arr, aux, 0, N-1); - + mergesort(arr, aux, 0, N - 1, cmp, metaData); } - private void mergesort(E[] arr, E[] aux, int lo, int hi) { + private void mergesort(E[] arr, E[] aux, int lo, int hi, Comparator cmp, SortingMetaData metaData) { if (hi <= lo) return; - int mid = lo + (hi - lo)/2; - mergesort(arr, aux, lo, mid); - mergesort(arr, aux, mid+1, hi); - merge(arr, aux, lo, mid, hi); + int mid = lo + (hi - lo) / 2; + mergesort(arr, aux, lo, mid, cmp, metaData); + mergesort(arr, aux, mid + 1, hi, cmp, metaData); + merge(arr, aux, lo, mid, hi, cmp, metaData); } - private void merge(E[] arr, E[] aux, int lo, int mid, int hi) { + private void merge(E[] arr, E[] aux, int lo, int mid, int hi, Comparator cmp, SortingMetaData metaData) { // * * creating backup of original array for (int i = lo; i <= hi; i++) aux[i] = arr[i]; int i = lo; - int j = mid+1; - for (int k = lo; k <= hi; k++){ + int j = mid + 1; + for (int k = lo; k <= hi; k++) { // * If i has already reached mid, no need to compare we insert at pointer k - if(i > mid) arr[k] = aux[j++]; - else if(j > hi) arr[k] = aux[i++]; - else if(less((Comparable) aux[i], aux[j])) arr[k] = aux[i++]; + if (i > mid) { + arr[k] = aux[j++]; + if (metaData != null) + metaData.incrementCompares(); + } else if (j > hi) { + arr[k] = aux[i++]; + if (metaData != null) + metaData.incrementCompares(); + } else if (less( aux[i], aux[j], cmp, metaData)) { + arr[k] = aux[i++]; + } else arr[k] = aux[j++]; } } + + @Override + public void sort(E[] arr, Comparator cmp, SortingMetaData metaData) { + if (metaData != null) + metaData.startTime(); + coreSortLogic(arr, cmp, metaData); + if (metaData != null) + metaData.endTime(); + } + + @Override + public void sort(E[] arr, Comparator cmp) { + coreSortLogic(arr, cmp, null); + } } diff --git a/module6/src/test/java/com/hithomelabs/princeton1/module6/MergeTest.java b/module6/src/test/java/com/hithomelabs/princeton1/module6/MergeTest.java index abf0bd5..61d1a6e 100644 --- a/module6/src/test/java/com/hithomelabs/princeton1/module6/MergeTest.java +++ b/module6/src/test/java/com/hithomelabs/princeton1/module6/MergeTest.java @@ -1,6 +1,6 @@ package com.hithomelabs.princeton1.module6; -import com.hithomelabs.princeton1.module5.AbstractCustomSorts; +import com.hithomelabs.princeton1.module5.ComparableSort; import com.hithomelabs.princeton1.common.Apple; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -14,7 +14,7 @@ import static org.junit.jupiter.api.Assertions.*; class MergeTest { - private AbstractCustomSorts sortingAlgorithm; + private ComparableSort sortingAlgorithm; private ArrayList apples; private Random random; diff --git a/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java b/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java index c3e4c40..3294ca4 100644 --- a/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java +++ b/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java @@ -1,13 +1,16 @@ package com.hithomelabs.princeton1.module7; -import com.hithomelabs.princeton1.module5.AbstractCustomSorts; +import com.hithomelabs.princeton1.module5.MeasurableSort; +import com.hithomelabs.princeton1.module5.SortingMetaData; + +import java.util.Comparator; -public class Quick extends AbstractCustomSorts { + public class Quick implements MeasurableSort { @Override public void sort(E[] arr) { int N = arr.length; - quickSort(arr, 0, N - 1); + quickSort(arr, 0, N - 1, null, null); } public void altSort(E[] arr) { @@ -31,24 +34,40 @@ public class Quick extends AbstractCustomSorts { altQuickSort(arr, i, hi); } - private void quickSort(E[] arr, int lo, int hi) { + private void quickSort(E[] arr, int lo, int hi, Comparator cmp, SortingMetaData metaData) { if (lo >= hi) return; int i = lo; int j = hi+1; while(true){ - while(less((Comparable) arr[++i], arr[lo])){ + while(less( arr[++i], arr[lo], cmp, metaData)){ if(i == hi) break; } - while(!less((Comparable) arr[--j], arr[lo])){ + while(!less(arr[--j], arr[lo], cmp, metaData)){ if (j == lo ) break; } if(j<=i) break; - exch(arr, i , j); + exch(arr, i , j, metaData); } - exch(arr, j, lo); - quickSort(arr, lo, j-1); - quickSort(arr, j+1, hi); + exch(arr, j, lo, metaData); + quickSort(arr, lo, j-1, cmp, metaData); + quickSort(arr, j+1, hi, cmp, metaData); } + + @Override + public void sort(E[] arr, Comparator cmp) { + int N = arr.length; + quickSort(arr, 0, N - 1, cmp, null); + } + + public void sort(E[] arr, Comparator cmp, SortingMetaData metaData) { + if(metaData != null){ + metaData.startTime(); + } + int N = arr.length; + quickSort(arr, 0, N - 1, cmp, metaData); + if (metaData != null) + metaData.endTime(); + } } diff --git a/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java b/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java index e252c68..e3de927 100644 --- a/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java +++ b/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java @@ -46,6 +46,18 @@ class QuickTest { Assertions.assertArrayEquals(sorted, arr); } + @Test + @DisplayName("testing Comparator sort") + public void testComparatorSort(){ + for(int i = 0; i < 100; i++) + apples.add(new Apple(random.nextInt(1000))); + Apple[] arr = apples.toArray(new Apple[apples.size()]); + quick.sort(arr, Apple.COMPARE_BY_SIZE); + apples.sort(Apple.COMPARE_BY_SIZE); + Apple[] sorted = apples.toArray(new Apple[apples.size()]); + Assertions.assertArrayEquals(sorted, arr); + } + @AfterEach void tearDown() {