diff --git a/.idea/misc.xml b/.idea/misc.xml index 511c874..122ba17 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/app/bin/main/de/uni_marburg/powersort/App.class b/app/bin/main/de/uni_marburg/powersort/App.class new file mode 100644 index 0000000..2c43fac Binary files /dev/null and b/app/bin/main/de/uni_marburg/powersort/App.class differ diff --git a/app/bin/main/de/uni_marburg/powersort/ComparableTimSort.class b/app/bin/main/de/uni_marburg/powersort/ComparableTimSort.class new file mode 100644 index 0000000..9f7d58f Binary files /dev/null and b/app/bin/main/de/uni_marburg/powersort/ComparableTimSort.class differ diff --git a/app/bin/main/de/uni_marburg/powersort/PowerSort.class b/app/bin/main/de/uni_marburg/powersort/PowerSort.class new file mode 100644 index 0000000..d40d730 Binary files /dev/null and b/app/bin/main/de/uni_marburg/powersort/PowerSort.class differ diff --git a/app/bin/main/de/uni_marburg/powersort/TimSort.class b/app/bin/main/de/uni_marburg/powersort/TimSort.class new file mode 100644 index 0000000..fe86166 Binary files /dev/null and b/app/bin/main/de/uni_marburg/powersort/TimSort.class differ diff --git a/app/bin/test/de/uni_marburg/powersort/AppTest.class b/app/bin/test/de/uni_marburg/powersort/AppTest.class new file mode 100644 index 0000000..994ac66 Binary files /dev/null and b/app/bin/test/de/uni_marburg/powersort/AppTest.class differ diff --git a/app/src/main/java/de/uni_marburg/powersort/msort/IMPL_M_1.java b/app/src/main/java/de/uni_marburg/powersort/msort/IMPL_M_1.java new file mode 100644 index 0000000..0d0f25d --- /dev/null +++ b/app/src/main/java/de/uni_marburg/powersort/msort/IMPL_M_1.java @@ -0,0 +1,298 @@ +package de.uni_marburg.powersort.msort; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.IntStream; + +public class IMPL_M_1 { + + + + private IMPL_M_1() {} + + /** + * Sorts the given range, using the given workspace array slice + * for temp storage when possible. This method is designed to be + * invoked from public methods (in class Arrays) after performing + * any necessary array bounds checks and expanding parameters into + * the required forms. + * + * @param a the array to be sorted + * @param lo the index of the first element, inclusive, to be sorted + * @param hi the index of the last element, exclusive, to be sorted + * @param c the comparator to use + * @param work a workspace array (slice) + * @param workBase origin of usable space in work array + * @param workLen usable size of work array + * @since 1.8 + */ + protected static int MERGE_COST = 0; + + // Example usage +// int[] runs = new int[] {5, 3, 3, 14, 1, 2}; // example from slides +// //runs = new int[]{9, 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; +// +// ArrayList a = new ArrayList<>(IntStream.range(0, Arrays.stream(runs).sum()).boxed().collect(Collectors.toList())); +// +// System.out.println(); +// fillWithAscRunsHighToLow(a, runs); +// MERGE_COST = 0; +// System.out.println("Sorting with Powersort:"); +// powersort(a, this::extendRunIncreasingOnly); +// System.out.println("Merge cost: " + MERGE_COST); + +// runs = [5,3,3,14,1,2]; +// runs = [9,16,7,7,7,7,7,7,7,7,7,7]; +// +// a = list(range(sum(runs))); +// fill_with_asc_runs_high_to_low(a, runs); +// MERGE_COST = 0; +// System.out.println("Sorting with Powersort:"); +// powersort(a, extendRunIncreasingOnly); +// System.out.println("Merge cost: " + MERGE_COST); + + + public static void fillWithAscRunsHighToLow(List A, int[] runLengths, int runLenFactor) { + int n = A.size(); + assert IntStream.of(runLengths).sum() * runLenFactor == n; + + for (int i = 0; i < n; i++) { + A.set(i, n - i); + } + + int i = 0; + for (int l : runLengths) { + int L = l * runLenFactor; + List sublist = A.subList(i, i + L); + Collections.sort(sublist); + i += L; + } + } + + private static List merge(List run1, List run2) { + List result = new ArrayList<>(); + while (!run1.isEmpty() && !run2.isEmpty()) { + if (run1.get(0) < run2.get(0)) { + result.add(run1.remove(0)); + } else { + result.add(run2.remove(0)); + } + } + result.addAll(run1); + result.addAll(run2); + return result; + } + + private static void mergeInplace(List a, int i, int m, int j) { + System.out.printf("Merge(%d, %d, %d)%n", i, m, j); + MERGE_COST += j - i; + List sublist = merge( + new ArrayList<>(a.subList(i, m)), + new ArrayList<>(a.subList(m, j)) + ); + for (int k = 0; k < sublist.size(); k++) { + a.set(i + k, sublist.get(k)); + } + } + + static int extendRun(List a, int i) { + if (i == a.size() - 1) { + return i + 1; + } + int j = i + 1; + if (a.get(i) <= a.get(j)) { + while (j < a.size() && a.get(j - 1) <= a.get(j)) { + j++; + } + } else { + while (j < a.size() && a.get(j - 1) > a.get(j)) { + j++; + } + List sublist = a.subList(i, j); + Collections.reverse(sublist); + } + return j; + } + + private static int extendRunIncreasingOnly(List a, int i) { + if (i == a.size() - 1) { + return i + 1; + } + int j = i + 1; + while (j < a.size() && a.get(j - 1) <= a.get(j)) { + j++; + } + return j; + } + + public static int power(int[] run1, int[] run2, int n) { + int i1 = run1[0], n1 = run1[1]; + int i2 = run2[0], n2 = run2[1]; + + assert i1 >= 0; + assert i2 == i1 + n1; + assert n1 >= 1 && n2 >= 1; + assert i2 + n2 <= n; + + double a = ((i1 + n1 / 2.0d) / n); + double b = ((i2 + n2 / 2.0d) / n); + + int l = 0; + while (Math.floor(a * Math.pow(2, l)) == Math.floor(b * Math.pow(2, l))) { + l++; + } + return l; + } + + public static int powerFast(int[] run1, int[] run2, int n) { + int i1 = run1[0], n1 = run1[1]; + int i2 = run2[0], n2 = run2[1]; + + int a = 2 * i1 + n1; + int b = a + n1 + n2; + + int l = 0; + while (true) { + l++; + if (a >= n) { + assert b >= a; + a -= n; + b -= n; + } else if (b >= n) { + break; + } + assert a < b && b < n; + a <<= 1; + b <<= 1; + } + return l; + } + + public static void mergeTopmost2(List a, List runs) { + assert runs.size() >= 2; + + int[] Y = runs.get(runs.size() - 2); + int[] Z = runs.get(runs.size() - 1); + + assert Z[0] == Y[0] + Y[1]; + + mergeInplace(a, Y[0], Z[0], Z[0] + Z[1]); + + runs.set(runs.size() - 2, new int[] {Y[0], Y[1] + Z[1], Y[2]}); + runs.remove(runs.size() - 1); + } + + public static void powerSort(List a) { + int n = a.size(); + int i = 0; + List runs = new ArrayList<>(); + + int j = extendRun(a, i); + runs.add(new int[] {i, j - i, 0}); + i = j; + + while (i < n) { + j = extendRun(a, i); + int p = power(runs.get(runs.size() - 1), new int[] {i, j - i}, n); + + while (p <= runs.get(runs.size() - 1)[2]) { + mergeTopmost2(a, runs); + } + + runs.add(new int[] {i, j - i, p}); + i = j; + } + + while (runs.size() >= 2) { + mergeTopmost2(a, runs); + } + } + + /* """Fills the given array A with ascending runs of the given list of run + lengths. + More precisely, the array is first filled n, n-1, ..., 1 + and then for i=0..l-1 segments of runLengths.get(i) * runLenFactor + are sorted ascending. + The sum of all lengths in runLengths times runLenFactor should be equal to the + length of A. + """*/ + + + /* static void sort(T[] a, int lo, int hi, Comparator c, + T[] work, int workBase, int workLen) { + assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length; + }*/ +/* + public static final int MIN_MERGE=24; + public int mergeCost=0; + private final T []sortedArray; + + public PowerSort(T[] sortedArray) { + super(); + this.sortedArray = sortedArray; + } + + ArrayList run1 = new ArrayList<>(); + ArrayList run2 = new ArrayList<>(); + + private AbstractList merge(ArrayList run1, ArrayList run2) { + ArrayList result = new ArrayList<>(); + + while(run1.size() > 0 && run2.size() >0) { + if (run1.getFirst() { T[] work, int workBase, int workLen) { assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length; } -} \ No newline at end of file +} diff --git a/app/src/test/java/de/uni_marburg/powersort/msort/PowerSortTest.java b/app/src/test/java/de/uni_marburg/powersort/msort/PowerSortTest.java new file mode 100644 index 0000000..dc2bfa5 --- /dev/null +++ b/app/src/test/java/de/uni_marburg/powersort/msort/PowerSortTest.java @@ -0,0 +1,37 @@ +package de.uni_marburg.powersort.msort; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.Test; + +import static de.uni_marburg.powersort.msort.IMPL_M_1.MERGE_COST; +import static de.uni_marburg.powersort.msort.IMPL_M_1.extendRun; +import static de.uni_marburg.powersort.msort.IMPL_M_1.fillWithAscRunsHighToLow; +import static de.uni_marburg.powersort.msort.IMPL_M_1.powerSort; + +class PowerSortTest { + @Test + + public void testWithOneInputList() { + List list = new ArrayList<>(List.of(5, 2, 8, 12, 1, 6)); + extendRun(list, 0); + System.out.println(list); + // example from slides he wrote this + int[] runs = {5, 3, 3, 14, 1, 2}; + // runs = new int[]{9, 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; + + List a = new ArrayList<>(IntStream.range(0, Arrays.stream(runs).sum()).boxed().collect(Collectors.toList())); + + System.out.println(); + fillWithAscRunsHighToLow(a, runs, 1); + MERGE_COST = 0; + System.out.println("Sorting with Powersort:"); + powerSort(a); + System.out.println("Merge cost: " + MERGE_COST); + } + + } \ No newline at end of file