diff --git a/proj1b/src/deque/ArrayDeque61B.java b/proj1b/src/deque/ArrayDeque61B.java new file mode 100644 index 0000000..2b2c02c --- /dev/null +++ b/proj1b/src/deque/ArrayDeque61B.java @@ -0,0 +1,194 @@ +package deque; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ArrayDeque61B implements Deque61B { + private T[] array; + private int nextFirst; + public int nextLast; + private int size; + public int firstElementIndex; + public int lastElementIndex; + + public ArrayDeque61B() { + array = (T[]) new Object[8];; + nextFirst = 4; + nextLast = 5; + size = 0; + } + + private class ArrayDequeIterator implements Iterator { + private int wizPos; + + @Override + public boolean hasNext() { + return wizPos < size; + } + + @Override + public T next() { + int indexToReturn = wizPos; + wizPos++; + return get(indexToReturn); + } + } + + @Override + public Iterator iterator() { + return new ArrayDequeIterator(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof ArrayDeque61B otherArray) { + if (size() != otherArray.size()) return false; + + for (int i = 0; i < size(); i++) { + if (get(i) != otherArray.get(i)) return false; + } + } + return true; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("["); + int count = 0; + for (T x : this) { + stringBuilder.append(x); + count++; + if (count < size) { + stringBuilder.append(", "); + } + else { + stringBuilder.append("]"); + } + } + return stringBuilder.toString(); + } + + @Override + public void addFirst(T x) { + if (size == array.length) { + resizeUp(2); + } + array[nextFirst] = x; + firstElementIndex = nextFirst; + nextFirst = Math.floorMod(nextFirst - 1, array.length); + size++; + } + + @Override + public void addLast(T x) { + if (size == array.length) { + resizeUp(2); + } + + if (array[firstElementIndex] == null) firstElementIndex = nextLast; + + array[nextLast] = x; + lastElementIndex = nextLast; + nextLast = Math.floorMod(nextLast + 1, array.length); + size++; + } + + @Override + public List toList() { + List returnList = new ArrayList<>(); + int cur = firstElementIndex; + for (int i = 0; i < array.length; i++) { + int curIndex = Math.floorMod(cur, array.length); + if (array[curIndex] == null) break; + returnList.add(array[curIndex]); + cur++; + } + return returnList; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public int size() { + return size; + } + + @Override + public T removeFirst() { + if (array[firstElementIndex] == null) return null; + T element = array[firstElementIndex]; + array[firstElementIndex] = null; + nextFirst = firstElementIndex; + firstElementIndex = Math.floorMod(nextFirst + 1, array.length); + size--; + if(toResizeDown()) resizeDown(); + return element; + } + + @Override + public T removeLast() { + if (array[lastElementIndex] == null) return null; + T element = array[lastElementIndex]; + array[lastElementIndex] = null; + nextLast = lastElementIndex; + lastElementIndex = Math.floorMod(nextLast - 1, array.length); + size--; + if(toResizeDown()) resizeDown(); + return element; + } + + @Override + public T get(int index) { + int getIndex = Math.floorMod(firstElementIndex + index, array.length); + if (index < 0 || index >= array.length || array[getIndex] == null) return null; + return array[getIndex]; + } + + @Override + public T getRecursive(int index) { + return null; + } + + public void resizeUp(double by) { + T[] outputArray = (T[]) new Object[(int) (array.length * by)]; + for (int i = 0; i < array.length; i++) { + int newArrayIndex = Math.floorMod(i + firstElementIndex, outputArray.length); + int curArrayIndex = Math.floorMod(i + firstElementIndex, array.length); + outputArray[newArrayIndex] = array[curArrayIndex]; + lastElementIndex = newArrayIndex; + nextLast = Math.floorMod(newArrayIndex + 1, outputArray.length); + } + array = outputArray; + } + + public void resizeDown() { + T[] outputArray = (T[]) new Object[(int) (array.length * 0.5)]; + int curIndex = firstElementIndex; + int lastIndex = -1; + for (int i = 0; i < outputArray.length; i++) { + if (array[curIndex] == null) break; + if (array[curIndex] != null) outputArray[i] = array[curIndex]; + curIndex++; + if (outputArray[i] != null) lastIndex++; + } + nextFirst = Math.floorMod(-1, outputArray.length); + nextLast = Math.floorMod(lastIndex + 1, outputArray.length); + + firstElementIndex = Math.floorMod(nextFirst + 1, outputArray.length); + lastElementIndex = Math.floorMod(nextLast - 1, outputArray.length); + array = outputArray; + } + + private boolean toResizeDown() { + if (array.length >= 16) { + double ratio = (double) size / array.length; + if (ratio < 0.25) return true; + } + return false; + } +} diff --git a/proj1b/src/deque/Deque61B.java b/proj1b/src/deque/Deque61B.java index 29651a2..b54ef56 100644 --- a/proj1b/src/deque/Deque61B.java +++ b/proj1b/src/deque/Deque61B.java @@ -6,7 +6,7 @@ * Created by hug on 2/4/2017. Methods are provided in the suggested order * that they should be completed. */ -public interface Deque61B { +public interface Deque61B extends Iterable { /** * Add {@code x} to the front of the deque. Assumes {@code x} is never null. diff --git a/proj1b/src/deque/Maximizer61B.java b/proj1b/src/deque/Maximizer61B.java index 8d77ee7..f4b8526 100644 --- a/proj1b/src/deque/Maximizer61B.java +++ b/proj1b/src/deque/Maximizer61B.java @@ -10,7 +10,13 @@ public class Maximizer61B { * @return the maximum element */ public static > T max(Iterable iterable) { - return null; + T max = null; + for (T x : iterable) { + if (max == null || x.compareTo(max) > 0) { + max = x; + } + } + return max; } /** @@ -22,17 +28,23 @@ public static > T max(Iterable iterable) { * @return the maximum element according to the comparator */ public static T max(Iterable iterable, Comparator comp) { - return null; + T max = null; + for (T x : iterable) { + if (max == null || comp.compare(x, max) > 0) { + max = x; + } + } + return max; } public static void main(String[] args) { // The style checker will complain about this main method, feel free to delete. - // ArrayDeque61B ad = new ArrayDeque61B<>(); - // ad.addLast(5); - // ad.addLast(12); - // ad.addLast(17); - // ad.addLast(23); - // System.out.println(max(ad)); + ArrayDeque61B ad = new ArrayDeque61B<>(); + ad.addLast(5); + ad.addLast(12); + ad.addLast(17); + ad.addLast(23); + System.out.println(max(ad)); } } diff --git a/proj1b/tests/ArrayDeque61BTest.java b/proj1b/tests/ArrayDeque61BTest.java index f9c1d6a..e7f664e 100644 --- a/proj1b/tests/ArrayDeque61BTest.java +++ b/proj1b/tests/ArrayDeque61BTest.java @@ -1,10 +1,13 @@ import deque.ArrayDeque61B; +import deque.Deque61B; +import edu.princeton.cs.algs4.In; import jh61b.utils.Reflection; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.List; import static com.google.common.truth.Truth.assertThat; @@ -12,14 +15,250 @@ public class ArrayDeque61BTest { -// @Test -// @DisplayName("ArrayDeque61B has no fields besides backing array and primitives") -// void noNonTrivialFields() { -// List badFields = Reflection.getFields(ArrayDeque61B.class) -// .filter(f -> !(f.getType().isPrimitive() || f.getType().equals(Object[].class) || f.isSynthetic())) -// .toList(); -// -// assertWithMessage("Found fields that are not array or primitives").that(badFields).isEmpty(); -// } + @Test + @DisplayName("ArrayDeque61B has no fields besides backing array and primitives") + void noNonTrivialFields() { + List badFields = Reflection.getFields(ArrayDeque61B.class) + .filter(f -> !(f.getType().isPrimitive() || f.getType().equals(Object[].class) || f.isSynthetic())) + .toList(); + assertWithMessage("Found fields that are not array or primitives").that(badFields).isEmpty(); + } + + @Test + public void addFirstTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + lld1.addFirst(5); + lld1.addFirst(4); + lld1.addFirst(3); + lld1.addFirst(2); + lld1.addFirst(1); + + List output = new ArrayList<>(); + + for (int i = 1; i <= 8; i++) { + if (i <= 5) output.add(i); + } + + assertThat(lld1.toList()).isEqualTo(output); + } + + @Test + void addLastTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + lld1.addLast(1); + lld1.addLast(2); + lld1.addLast(3); + lld1.addLast(4); + lld1.addLast(5); + + List output = new ArrayList<>(); + for (int i = 1; i <= 8; i++) { + if (i <= 5) output.add(i); + } + assertThat(lld1.toList()).isEqualTo(output); + } + + @Test + void firstElementIndexTest() { + ArrayDeque61B lld1 = new ArrayDeque61B<>(); + lld1.addLast(5); + lld1.addLast(6); + lld1.addLast(7); + assertThat(lld1.firstElementIndex).isEqualTo(5); + lld1.addFirst(4); + assertThat(lld1.firstElementIndex).isEqualTo(4); + lld1.addLast(8); + assertThat(lld1.firstElementIndex).isEqualTo(4); + lld1.addFirst(0); + assertThat(lld1.firstElementIndex).isEqualTo(3); + } + + @Test + void getTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + assertThat(lld1.get(0)).isEqualTo(null); + + lld1.addFirst(1); + lld1.addFirst(2); + lld1.addLast(10); + + assertThat(lld1.get(0)).isEqualTo(2); + + Deque61B lld2 = new ArrayDeque61B<>(); + + lld2.addLast(10); + assertThat(lld2.get(0)).isEqualTo(10); + + lld2.addLast(100); + lld2.addLast(1000); + assertThat(lld2.get(0)).isEqualTo(10); + assertThat(lld2.get(2)).isEqualTo(1000); + } + + @Test + void sizeTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + + assertThat(lld1.size()).isEqualTo(0); + + lld1.addFirst(1); + assertThat(lld1.size()).isEqualTo(1); + + lld1.addLast(1); + assertThat(lld1.size()).isEqualTo(2); + + lld1.removeFirst(); + assertThat(lld1.size()).isEqualTo(1); + + lld1.removeLast(); + assertThat(lld1.size()).isEqualTo(0); + } + + @Test + void isEmptyTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + assertThat(lld1.isEmpty()).isTrue(); + + lld1.addFirst(10); + assertThat(lld1.isEmpty()).isFalse(); + + lld1.removeFirst(); + assertThat(lld1.isEmpty()).isTrue(); + } + + @Test + void removeFirstTest() { + ArrayDeque61B lld1 = new ArrayDeque61B<>(); + lld1.addFirst(1); + assertThat(lld1.get(0)).isEqualTo(1); + lld1.addLast(2); + lld1.addFirst(3); + lld1.removeFirst(); + assertThat(lld1.get(0)).isEqualTo(1); + assertThat(lld1.size()).isEqualTo(2); + lld1.removeFirst(); + assertThat(lld1.get(0)).isEqualTo(2); + int val = lld1.removeFirst(); + assertThat(lld1.get(0)).isEqualTo(null); + assertThat(val).isEqualTo(2); + } + + @Test + void removeLastTest() { + ArrayDeque61B lld1 = new ArrayDeque61B<>(); + lld1.addLast(1); + assertThat(lld1.get(0)).isEqualTo(1); + lld1.addLast(2); + assertThat(lld1.nextLast).isEqualTo(7); + lld1.addLast(3); + lld1.addLast(4); + lld1.addLast(5); + lld1.addLast(6); + lld1.addLast(7); + lld1.addLast(8); + assertThat(lld1.nextLast).isEqualTo(5); + + assertThat(lld1.get(7)).isEqualTo(8); + assertThat(lld1.removeLast()).isEqualTo(8); + assertThat(lld1.nextLast).isEqualTo(4); + lld1.addLast(9); + assertThat(lld1.nextLast).isEqualTo(5); + assertThat(lld1.get(7)).isEqualTo(9); + assertThat(lld1.removeLast()).isEqualTo(9); + assertThat(lld1.nextLast).isEqualTo(4); + assertThat(lld1.get(7)).isNull(); + } + + @Test + void resizeUpTest() { + ArrayDeque61B lld1 = new ArrayDeque61B<>(); + lld1.addFirst(9); + lld1.addFirst(8); + lld1.addFirst(7); + lld1.addFirst(6); + lld1.addFirst(5); + lld1.addFirst(4); + lld1.addFirst(3); + lld1.addFirst(2); + List output = new ArrayList<>(); + for (int i = 2; i < lld1.size() + 2; i++) { + output.add(i); + } + assertThat(lld1.toList()).isEqualTo(output); + lld1.addFirst(1); + lld1.removeFirst(); + assertThat(lld1.toList()).isEqualTo(output); + } + + @Test + void resizeDownTest() { + ArrayDeque61B lld1 = new ArrayDeque61B<>(); + for (int i = 0; i < 33; i++) { + lld1.addLast(i); + } + + assertThat(lld1.size()).isEqualTo(33); + + for (int i = 0; i < 30; i++) { + lld1.removeFirst(); + } + + assertThat(lld1.size()).isEqualTo(3); + } + + @Test + void iteratorTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + for (int i = 0; i < 10; i++) { + lld1.addLast(i + 1); + } + + for (Integer num : lld1) { + System.out.println(num); + } + } + + @Test + void equalsTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + Deque61B lld2 = new ArrayDeque61B<>(); + for (int i = 0; i < 10; i++) { + lld1.addLast(i + 1); + } + + assertThat(lld1.equals(lld2)).isFalse(); + + for (int i = 0; i < 10; i++) { + lld2.addLast(i + 1); + } + + assertThat(lld1.equals(lld2)).isTrue(); + + for (int i = 10; i < 50; i++) { + lld1.addLast(i); + lld2.addLast(i); + } + + assertThat(lld1.equals(lld2)).isTrue(); + for (int i = 0; i < 20; i++) { + lld1.removeFirst(); + } + assertThat(lld1.equals(lld2)).isFalse(); + + for (int i = 0; i < 20; i++) { + lld2.removeFirst(); + } + assertThat(lld1.equals(lld2)).isTrue(); + } + + @Test + void toStringTest() { + Deque61B lld1 = new ArrayDeque61B<>(); + for (int i = 0; i < 10; i++) { + lld1.addLast(i + 1); + } + + System.out.println(lld1.toString()); + } } diff --git a/proj1b/tests/Maximizer61BTest.java b/proj1b/tests/Maximizer61BTest.java index f54166b..95b487e 100644 --- a/proj1b/tests/Maximizer61BTest.java +++ b/proj1b/tests/Maximizer61BTest.java @@ -15,12 +15,12 @@ public int compare(String a, String b) { } } -// @Test -// public void basicTest() { -// ArrayDeque61B ad = new ArrayDeque61B<>(); -// ad.addFirst(""); -// ad.addFirst("2"); -// ad.addFirst("fury road"); -// assertThat(Maximizer61B.max(ad, new StringLengthComparator())).isEqualTo("fury road"); -// } + @Test + public void basicTest() { + ArrayDeque61B ad = new ArrayDeque61B<>(); + ad.addFirst(""); + ad.addFirst("2"); + ad.addFirst("fury road"); + assertThat(Maximizer61B.max(ad, new StringLengthComparator())).isEqualTo("fury road"); + } }