diff --git a/.gitignore b/.gitignore index 4a305d7..cf74795 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Ignore Gradle project-specific cache directory .gradle - +# Igonre the .idea directory +.idea # Ignore Gradle build output directory build bin \ No newline at end of file diff --git a/clients/build.gradle b/clients/build.gradle index d80e4c6..8e4f6b7 100644 --- a/clients/build.gradle +++ b/clients/build.gradle @@ -16,6 +16,7 @@ dependencies { implementation project(':module5') implementation project(':module6') implementation project(':module7') + implementation project(':module8') implementation project(':common') testImplementation project(':common') } diff --git a/clients/src/main/java/com/hithomelabs/clients/module8/HeapSortClient.java b/clients/src/main/java/com/hithomelabs/clients/module8/HeapSortClient.java new file mode 100644 index 0000000..4534500 --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/module8/HeapSortClient.java @@ -0,0 +1,23 @@ +package com.hithomelabs.clients.module8; + +import com.hithomelabs.princeton1.common.Apple; +import com.hithomelabs.princeton1.module8.HeapSort; + +import java.util.Random; + +public class HeapSortClient { + + public static void main(String[] args) { + int size = 10; + Apple[] apples = new Apple[size]; + HeapSort heap = new HeapSort(); + + for (int i = 0; i < apples.length; i++) { + apples[i] = new Apple(new Random().nextInt(10)); + } + heap.sort(apples); + for (int i = 0; i < apples.length; i++) + System.out.println(apples[i]); + } + +} diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java index 8576647..41ecda7 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java @@ -5,100 +5,28 @@ import java.util.Iterator; import javax.annotation.Nonnull; public class ArrayQueue extends Queue{ - - // insertion from tail, removal from head - public static final int DEFAULT_CAPACITY = 10; - private int capacity; - private int tail; - private int head; - private int size; - private E[] arr; - - public ArrayQueue(){ - this(DEFAULT_CAPACITY); - } - - public ArrayQueue(int capacity){ - this.capacity = capacity; - arr = (E[]) new Object[this.capacity]; - size = 0; - } - @Override public boolean isEmpty() { - return size == 0; + return false; } @Override public E dequeue() { - if(isEmpty()) - return null; - else{ - E element = arr[head]; - // Garbage collection - arr[head] = null; - head = (head+1)%capacity; - size = size - 1; - if(capacity >= 40 && size < capacity/4){ - capacity = capacity/2; - resize(capacity, capacity*2); - } - return element; - } + return null; } @Override public void enqueue(E element) { - // We plan capacity expansion if needed - if (size == capacity){ - capacity = capacity * 2; - resize(capacity, capacity/2); - } - arr[tail] = element; - tail = (tail + 1) % capacity; - ++size; - } - - // When resize takes place always the original array is full, so copy the complete array as is - private void resize(int capacity, int oldCapacity) { - E[] resizedArr = (E[]) new Object[capacity]; - for(int i = 0; i < size; i++) { - resizedArr[i] = arr[head]; - // halving because capacity has now doubled - arr[head] = null; - head = (head + 1) % oldCapacity; - } - arr = resizedArr; - // When resizing takes place, we bring the head to 0 and the tail to size - // tail is where new inserts will be made and head will be where elements will be removed - tail = size; - head = 0; } @Override public int size() { - return size; + return 0; } @Override - @Nonnull public Iterator iterator() { - return new Iterator() { - int counter = size; - int pointer = head; - @Override - public boolean hasNext() { - return counter != 0; - } - - @Override - public E next() { - E element = arr[pointer]; - pointer = (pointer + 1)% capacity; - --counter; - return element; - } - }; + return null; } } diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java index 93b3f30..c67f138 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java @@ -5,94 +5,28 @@ import javax.annotation.Nonnull; // Concrete implementation of stack using arrays // Creating a generic stack of type E public class ArrayStack extends Stack { - - // Capacity and size are two variables, capacity determines total capacity of array, capacity defaults at 10 - // every time size == capacity, capacity = 2 * capacity - private static final int DEFAULT_CAPACITY = 10; - private int capacity; - private int size; - private E[] arr; - - public ArrayStack(int capacity){ - this.capacity = capacity; - arr = (E[]) new Object[this.capacity]; - } - - // Constructor chaining, default constructor will call parametrized constructor with default initial capacity 10 - public ArrayStack(){ - this(DEFAULT_CAPACITY); - } - @Override public boolean isEmpty() { - return size == 0; + return false; } - private void changeCapacity(int newCapacity){ - E[] resizedArr = (E[]) new Object[newCapacity]; - for (int i = 0; i < size; i++) - resizedArr[i] = arr[i]; - arr = resizedArr; - } - - private void incrementSize(){ - if (size == capacity){ - capacity = 2 * capacity; - changeCapacity(capacity); - } - } - - // Push always happens at the end of the stack - // Say the size of the stack is 1, new element gets inserted at 1 @Override public void push(E element) { - // Lazy approach, we assume size to always be lesser than capacity - incrementSize(); - arr[size++] = element; + } @Override public E pop() { - if (isEmpty()) - return null; - else{ - E e = arr[--size]; - arr[size] = null; - checkResize(); - return e; - } - } - - private void checkResize() { - if (size < capacity / 4 && capacity >= 20){ - capacity = capacity / 2; - changeCapacity(capacity); - } + return null; } @Override public int size() { - return size; + return 0; } @Override - @Nonnull public Iterator iterator() { - return new Iterator() { - - int current = 0; - - @Override - public boolean hasNext() { - return current != size; - } - - @Override - public E next() { - E element = arr[current]; - current = current + 1; - return element; - } - }; + return null; } } diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java index b7e62ff..b68b148 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java @@ -4,71 +4,28 @@ import javax.annotation.Nonnull; import java.util.Iterator; public class LinkedQueue extends Queue{ - - Node head; - Node tail; - int size; - - private class Node{ - E value; - Node next; - - Node(E value){ - this.value = value; - } - } - @Override public boolean isEmpty() { - return size==0; + return false; } @Override public E dequeue() { - if(isEmpty()) - return null; - E element = head.value; - // Only a single element is present - if (head == tail){ - tail = null; - } - head = head.next; - --size; - return element; + return null; } @Override public void enqueue(E element) { - Node newNode = new Node(element); - if(isEmpty()) - head = newNode; - else - tail.next = newNode; - tail = newNode; - ++size; + } @Override public int size() { - return size; + return 0; } @Override - @Nonnull public Iterator iterator() { - return new Iterator() { - Node current = head; - @Override - public boolean hasNext() { - return current != null; - } - - @Override - public E next() { - E element = current.value; - current = current.next; - return element; - } - }; + return null; } } diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java index 6c7c398..72259c0 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java @@ -3,70 +3,28 @@ import java.util.Iterator; // Creating a concrete linked Implementation of Stack public class LinkedStack extends Stack{ - - // No need for an explicit constructor as size will be initialized to 0 and root to null - private int size; - private Node first; - - // By default instance variables are package private - private class Node{ - E value; - Node next; - } - - // Will return true if size is 0 @Override public boolean isEmpty() { - return (this.size == 0); + return false; } - // Adds an element to the start of a linked list @Override public void push(E element) { - Node newNode = new Node(); - newNode.value = element; - newNode.next = first; - first = newNode; - this.size = this.size + 1; + } @Override public E pop() { - if (this.isEmpty()) - return null; - else{ - Node toBePopped = first; - first = first.next; - this.size = this.size - 1; - return toBePopped.value; - } + return null; } @Override public int size() { - return this.size; + return 0; } @Override public Iterator iterator() { - return new Iterator() { - - // Internal classes can access outer objects - Node current = first; - @Override - public boolean hasNext() { - return current != null; - } - - @Override - public E next() { - E element = current.value; - current = current.next; - return element; - } - }; + return null; } - - - } diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java index 647b506..86bfbbd 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java @@ -4,12 +4,11 @@ public abstract class AbstractCustomSorts { public abstract void sort(E[] arr); + // TODO: Implement this method public void exch(E[] arr, int j, int i) { - E temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; } + // TODO: Implement this method public boolean less(Comparable e1, E e2) { return e1.compareTo(e2) < 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..a4117d4 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,9 @@ package com.hithomelabs.princeton1.module5; public class Insertion extends AbstractCustomSorts { - - public void sort(E[] arr){ - if (arr == null) return; - else{ - int N = arr.length; - // * * swap arr[i] with each element greater to it's left - 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; - } - } - } - - } - + @Override + public void sort(E[] arr) { } +} 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..d483434 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,13 @@ package com.hithomelabs.princeton1.module5; - +/* + * * 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 class Selection extends AbstractCustomSorts{ + @Override + public void sort(E[] arr) { - /* - * * 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){ - 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; - } - exch(arr, i, minIndex); - } } - } 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..620accd 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java @@ -24,33 +24,10 @@ public class Shell extends AbstractCustomSorts { */ @Override public void sort(E[] arr) { - MetaData metaData = new MetaData(); - int N = arr.length; - int h = 1; - // * * Calculates the largest value of h greater than n - while (3 * h + 1 < N) { - h = 3 * h + 1; - } - while (h >= 1) { - h = hsort(arr, h, 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) { - 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); - j = j - h; - ++metadata.compares; - } - } - return h; + return 0; } /* * Sample implementation of insertion sort as h-sort of h = 1 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..380ac31 100644 --- a/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java +++ b/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java @@ -7,39 +7,6 @@ import java.util.Arrays; public class Merge extends AbstractCustomSorts { @Override public void sort(E[] arr) { - - int N = arr.length; - // * * aux is a helper array required for merge - E[] aux = Arrays.copyOf(arr, N); - mergesort(arr, aux, 0, N-1); - - } - - private void mergesort(E[] arr, E[] aux, int lo, int hi) { - - 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); - - } - - private void merge(E[] arr, E[] aux, int lo, int mid, int hi) { - - // * * 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++){ - // * 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++]; - else arr[k] = aux[j++]; - } } } 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..1483c7e 100644 --- a/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java +++ b/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java @@ -6,49 +6,6 @@ import com.hithomelabs.princeton1.module5.AbstractCustomSorts; public class Quick extends AbstractCustomSorts { @Override public void sort(E[] arr) { - int N = arr.length; - quickSort(arr, 0, N - 1); - } - - public void altSort(E[] arr) { - int N = arr.length; - altQuickSort(arr, 0, N-1); - } - - private void altQuickSort(E[] arr, int lo, int hi) { - if (lo >= hi) return; - int i = lo + 1; - int j = i; - while(j <= hi){ - if(less((Comparable) arr[j], arr[lo])){ - exch(arr, i, j); - i++; - } - j++; - } - exch(arr, i-1, lo); - altQuickSort(arr, lo, i-2); - altQuickSort(arr, i, hi); - } - - private void quickSort(E[] arr, int lo, int hi) { - - if (lo >= hi) return; - int i = lo; - int j = hi+1; - while(true){ - while(less((Comparable) arr[++i], arr[lo])){ - if(i == hi) break; - } - while(!less((Comparable) arr[--j], arr[lo])){ - if (j == lo ) break; - } - if(j<=i) break; - exch(arr, i , j); - } - exch(arr, j, lo); - quickSort(arr, lo, j-1); - quickSort(arr, j+1, hi); } } 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..3ff75b9 100644 --- a/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java +++ b/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java @@ -33,6 +33,8 @@ class QuickTest { Assertions.assertArrayEquals(sorted, arr); } + // * * Optional test for alternate sort implmentation + /* @Test @DisplayName("testing Quick sort default implementation") public void testAltSort(){ @@ -45,6 +47,8 @@ class QuickTest { Apple[] sorted = apples.toArray(new Apple[apples.size()]); Assertions.assertArrayEquals(sorted, arr); } + */ + @AfterEach diff --git a/module8/build.gradle b/module8/build.gradle new file mode 100644 index 0000000..9a03430 --- /dev/null +++ b/module8/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'java' +} + +group = 'com.hithomelabs.princeton1.module8' +version = 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' + implementation project(':module5') + testImplementation project(':common') +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/module8/src/main/java/com/hithomelabs/princeton1/module8/Heap.java b/module8/src/main/java/com/hithomelabs/princeton1/module8/Heap.java new file mode 100644 index 0000000..2a66d58 --- /dev/null +++ b/module8/src/main/java/com/hithomelabs/princeton1/module8/Heap.java @@ -0,0 +1,33 @@ +package com.hithomelabs.princeton1.module8; + +/* + * * Designing Heap as a wrapper class with static methods that perform sink and swim operations on underlying comparable[] array + * * Heap does not have any instance variables, instance variables shall be housed by, the implementation using heaps, like priority queues and heap sort + */ + +public class Heap{ + + /* + * * Sink Node T with to it's appropriate place in a Heap of size N, if it's children exist and are greater + * * Implement sink API to sink a node if it's sub-heap is not heap-order + */ + public static void sink(T[] arr, int root, int N){ + } + + // * * Swim if element is not root, and parent is lesser than node + public static void swim(T[] arr, int node, int N){ + } + + private static void exch(T[] arr, int i, int j){ + T temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + private static boolean less(T v, T w){ + if(((Comparable)v).compareTo(w) < 1 ) return true; + else return false; + } + + +} diff --git a/module8/src/main/java/com/hithomelabs/princeton1/module8/HeapSort.java b/module8/src/main/java/com/hithomelabs/princeton1/module8/HeapSort.java new file mode 100644 index 0000000..55d7b91 --- /dev/null +++ b/module8/src/main/java/com/hithomelabs/princeton1/module8/HeapSort.java @@ -0,0 +1,27 @@ +package com.hithomelabs.princeton1.module8; + +import com.hithomelabs.princeton1.module5.AbstractCustomSorts; + + +public class HeapSort extends AbstractCustomSorts { + + @Override + public void sort(E[] arr) { + int N = arr.length; + + E[] heapArr = (E[]) new Object[N+1]; + // * * to simplify we copy original array and write it to the new array starting index 1 + System.arraycopy(arr, 0, heapArr, 1, N); + // * * An array of size N holds a heap of size N-1 + coreSortingLogic(heapArr, N); + // * * Re-copying the sorted array to the original + System.arraycopy(heapArr, 1, arr, 0, N); + } + + /* + * * Implement the core sorting logic + * * P.S the provision of making the index 0 null for ease of use has already been done above + */ + private void coreSortingLogic(E[] arr, int N) { + } +} diff --git a/module8/src/test/java/com/hithomelabs/princeton1/module8/HeapSortTest.java b/module8/src/test/java/com/hithomelabs/princeton1/module8/HeapSortTest.java new file mode 100644 index 0000000..8f35154 --- /dev/null +++ b/module8/src/test/java/com/hithomelabs/princeton1/module8/HeapSortTest.java @@ -0,0 +1,51 @@ +package com.hithomelabs.princeton1.module8; + +import com.hithomelabs.princeton1.common.Apple; +import org.junit.jupiter.api.*; + +import java.util.ArrayList; +import java.util.Random; + +import static org.junit.jupiter.api.Assertions.*; + +class HeapSortTest { + + private HeapSort heap; + private ArrayList apples; + private Random random; + + @BeforeEach + void setUp() { + heap = new HeapSort(); + apples = new ArrayList(); + random = new Random(); + } + + @Test + @DisplayName("Sort a heap of a 100 random sized apples") + public void testSort(){ + for(int i = 0; i < 100; i++) + apples.add(new Apple(random.nextInt(1000))); + Apple[] arr = apples.toArray(new Apple[apples.size()]); + heap.sort(arr); + apples.sort(null); + Apple[] sorted = apples.toArray(new Apple[apples.size()]); + Assertions.assertArrayEquals(sorted, arr); + } + + @Test + @DisplayName("Sort 100 apples in descending order") + public void testSortBorder(){ + for(int i = 0; i < 100; i++) + apples.add(new Apple(100 - i)); + Apple[] arr = apples.toArray(new Apple[apples.size()]); + heap.sort(arr); + apples.sort(null); + Apple[] sorted = apples.toArray(new Apple[apples.size()]); + Assertions.assertArrayEquals(sorted, arr); + } + + @AfterEach + void tearDown() { + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f9e40b6..2348850 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,4 +17,5 @@ include 'module5' include 'module6' include 'common' include 'module7' +include 'module8'