diff --git a/src/ArrayList.java b/src/ArrayList.java new file mode 100644 index 0000000..b0225be --- /dev/null +++ b/src/ArrayList.java @@ -0,0 +1,301 @@ +/** + * ArrayList + * List that uses a built-in array to store its data + * + * @author R.J. Trenchard + * 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; + +public class ArrayList implements List { + + private static final double MAX_CAPACITY = 0.75; + private static final double MIN_CAPACITY = 0.5; + private static final int DEFAULT_BUFFER = 10; + + private E[] arrayData; + int arraySize; + + /** + * Generate an arraylist of the default buffer size + */ + public ArrayList() { + this(DEFAULT_BUFFER); + } + + /** + * Generate an array list of a specified buffer size + * @param bufsize size of the initial underlying buffer. + */ + public ArrayList(int bufsize) { + arrayData = (E[])new Object[bufsize]; + arraySize = 0; + } + + // performs resizing if too large or too small of a buffer size. + // O(n), linear progression each time we need to make new spaces. + // + // grow/shrink are included in this + + private void autoResize() { + double capacity = this.size() / (double)arrayData.length; + + // grow when we reach max capacity + if (capacity > MAX_CAPACITY) grow(); + // shrink if we're below the min capacity, but the default buffer must have a size. + else if (capacity < MIN_CAPACITY && arrayData.length > DEFAULT_BUFFER) shrink(); + } + + // general index checker + private void checkIfInRange(int i) { + if (i < 0 || i >= arraySize) { + throw new IndexOutOfBoundsException(String.format("%d is not a valid index.", i)); + } + } + + private void grow() { + // hold old data + E[] buf = arrayData; + int newLength = arrayData.length + DEFAULT_BUFFER; + + // create new array of a larger size + arrayData = (E[]) new Object[newLength]; + + this.copy(buf, arrayData); + } + + private void shrink() { + // hold old data + E[] buf = arrayData; + int newLength = arrayData.length - DEFAULT_BUFFER; + + // don't try if the new length is too small + if (newLength < DEFAULT_BUFFER) return; + + // create new array of a smaller size + arrayData = (E[]) new Object[newLength]; + + this.copy(buf, arrayData); + } + + // O(n), linear copy. + private void copy(E[] from, E[] to) { + // copy old data to new array + int shortest = Math.min(to.length, from.length); + for (int i = 0; i < shortest; i++) { + to[i] = from[i]; + } + } + + /** + * Add item to the front. + * O(n) - adding a new item to the beginning means you need to look at every element + * + * @param item the item to be added + */ + @Override + public void addFront(E item) { + add(0, item); + } + + /** + * Add item to the back. + * O(n) - would be O(1) if arrays could be expanded without copying, but no luck there. + * + * @param item the item to be added + */ + @Override + public void addBack(E item) { + add(this.size(), item); + } + + /** + * Add an item at specified index (position). + * O(n) - item added to the beginning would move the whole array. + * additionally, changes in array capacity would result in a second pass. + * + * @param i the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int i, E item) { + // special range check, add will be able to perform addBack + if (i < 0 || i > this.size()) throw new IndexOutOfBoundsException(String.format("%d is not a valid index.", i)); + + autoResize(); + + // move all from rhs of index right by one + for (int idx = this.size(); idx > i; idx--) { + arrayData[idx] = arrayData[idx-1]; + } + + // set new value and array size + arrayData[i] = item; + arraySize++; + } + + /** + * Get the item at a specified index. + * O(1) - Access is constant in an array + * + * @param i the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int i) { + checkIfInRange(i); + return arrayData[i]; + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * O(1) - access/setting is constant + * + * @param i the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int i, E item) { + checkIfInRange(i); + arrayData[i] = item; + } + + /** + * Remove item at the front of the list. + * O(n) - removing an element from the front results in moving the whole array + * + * @return the item that was removed + */ + @Override + public E removeFront() { + return remove(0); + } + + /** + * Remove item at the back of the list + * O(n) - changes in array capacity will result in copying all data + * + * @return the item that was removed + */ + @Override + public E removeBack() { + return remove(this.size()-1); + } + + /** + * Remove item from the list + * O(n) - changes in array capacity will result in copying all data + * + * @param item the item to be removed + */ + @Override + public void remove(E item) { + for (int i = 0; i < this.size(); i++) { + if (arrayData[i].equals(item)) { + remove(i); // call the integer type remove, since it will do the same thing once we find the index + return; // we probably only want to remove one item at a time + } + + } + } + + /** + * Remove item at a specified index. + * O(n) - changes in array capacity will result in copying all data + * + * @param i the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int i) { + checkIfInRange(i); + + autoResize(); + + E data = arrayData[i]; + + // shift all from rhs left to shrink, adjust array size + for (int idx = i; idx < this.size(); idx++) { + arrayData[idx] = arrayData[idx+1]; + } + arraySize--; + + return data; + } + + /** + * Checks if an item is in the list. + * O(n) - item not present will go over whole array + * + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(E item) { + for (int i = 0; i < arraySize; i++) + if (arrayData[i].equals(item)) return true; + return false; + } + + /** + * Checks if the list is empty. + * O(1) - instant access to size + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + /** + * Provides a count of the number of items in the list. + * O(1) - instant access to size + * + * @return number of items in the list + */ + @Override + public int size() { + return arraySize; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n) - by its nature + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + + E[] readOnly = arrayData.clone(); + + return new Iterator<>() { + int index = 0; + final int size = size(); + + @Override + public boolean hasNext() { + return index < size; + } + + @Override + public E next() { + if (!hasNext()) throw new IndexOutOfBoundsException(); + E value = readOnly[index]; + index++; + return value; + } + }; + } + + // for use in testing + protected int getArraySize() { + return arrayData.length; + } +} diff --git a/src/Bag.java b/src/Bag.java new file mode 100644 index 0000000..12d2092 --- /dev/null +++ b/src/Bag.java @@ -0,0 +1,26 @@ +/** + * Bag interface only supports adding and iterating. + * + * @param Type to be added + * @author R.J. Trenchard + */ + +public interface Bag extends Iterable { + /** + * Adds an item to the bag + * @param item An item of the generic type. + */ + void add(E item); + + /** + * Returns true if the bag has no items. + * @return true if empty. + */ + boolean isEmpty(); + + /** + * Gets the amount of items in the bag. + * @return size + */ + int size(); +} diff --git a/src/DequeImpl.java b/src/DequeImpl.java new file mode 100644 index 0000000..96d131b --- /dev/null +++ b/src/DequeImpl.java @@ -0,0 +1,216 @@ +/** + * Double-ended Queue implementation + * Can add and remove from both sides of the queue. + * + * @author R.J. Trenchard + * @date 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class DequeImpl implements Deque { + + private int size; + private Node head, tail; + + private class Node { + E data; + Node prev, next; + + public Node(E data) { + this(data, null, null); + } + + public Node(E data, Node prev, Node next) { + this.data = data; + this.prev = prev; + this.next = next; + } + } + + public DequeImpl() { + int size = 0; + head = tail = null; + } + + /** + * Checks if the deque is empty. + * O(1), size access is recorded during node creation/deletion + * + * @return true if the deque is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns the number of items in the deque. + * O(1), size access is constant + * + * @return number of items in the deque + */ + @Override + public int size() { + return size; + } + + /** + * Add an item to the left end of the deque. + * @param item item to be added + */ + @Override + public void pushLeft(E item) { + // case: size is 0, need to assign new head and tail + if (size == 0) { + head = tail = new Node(item); + } + + // case: size is 1, we need to decouple head and tail and make them point to each other + else if (size == 1) { + tail.prev = head = new Node(item, null, tail); + } + + // case: any other size + else { + head = head.prev = new Node(item, null, head); + } + + size++; + + } + + /** + * Add an item to the right end of the deque. + * O(1), adding right is instant + * + * @param item item to add + */ + @Override + public void pushRight(E item) { + // case: size is 0, need to assign new head and tail + if (size == 0) { + head = tail = new Node(item); + } + + // case: size is 1, adding one we need to decouple head and tail and make them point to each other + else if (size == 1) { + head.next = tail = new Node(item, head, null); + } + + // case: any other size + else { + tail = tail.next = new Node(item, tail, null); + + + } + + size++; + } + + /** + * Remove an item from the left end of the deque. + * O(1), left access is instant + * + * @return the item on the left end of the queue + */ + @Override + public E popLeft() { + if (head == null) throw new NoSuchElementException("No elements left in queue."); + + E data = head.data; + + size--; + + // case: size is 0, the resulting dequeue will be null; + if (size == 0) { + head = tail = null; + } + + // case: size is 1, head will point to tail. + else if (size == 1) { + head = tail; + + // erase references to prev/next + head.next = head.prev = null; + } + + // case: any other size + else { + // move right one node + head = head.next; + // and null its reference to the previous node + head.prev = null; + } + + return data; + } + + /** + * Remove an item from the right end of the deque. + * O(1), contrast to something like a linked list, we can instantly access the right end of a dequeue + * + * @return the item on the right end of the queue + */ + @Override + public E popRight() { + if (tail == null) throw new NoSuchElementException("No elements left in queue."); + + E data = tail.data; + + size--; + + // case: size is 0, the resulting dequeue will be null; + if (size == 0) { + head = tail = null; + } + + // case: size is 1, tail will point to head. + else if (size == 1) { + tail=head; + + // erase references to next + tail.next = tail.prev = null; + } + + // case: any other size + else { + // move head back one node + tail = tail.prev; + + tail.next = null; + } + + return data; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n), as usual, an iterator will always pass a list once and once only unless break occurs. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator<>() { + Node cur = head; + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + E data = cur.data; + cur = cur.next; + return data; + } + }; + } +} diff --git a/src/LinkedBag.java b/src/LinkedBag.java new file mode 100644 index 0000000..a07b54f --- /dev/null +++ b/src/LinkedBag.java @@ -0,0 +1,103 @@ +/** + * Linked Bag implementation + * Bag uses linked nodes to store its data + * + * @author R.J. trenchard + * 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedBag implements Bag { + + int size; + Node head, tail; + + public LinkedBag(){ + size = 0; + head = tail = null; + } + + private class Node { + E data; + + Node next; + + public Node (E data) { + this.data = data; + this.next = null; + } + } + + /** + * Adds an item to the bag + * O(1), because we keep track of the tail end, we can always add to it without searching for it. + * + * @param item An item of the generic type. + */ + @Override + public void add(E item) { + // case: Bag is empty, create head + if (this.isEmpty()) { + tail = head = new Node(item); + } + // case: bag has elements, add element to tail end + else { + tail = tail.next = new Node(item); + } + size++; + } + + + /** + * Returns true if the bag has no items. + * O(1), empty access is instant + * + * @return true if empty. + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Gets the amount of items in the bag. + * O(1), size access is instant + * + * @return size + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n), will always loop over the whole list + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator<>() { + Node cur = head; + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + + E data = cur.data; + cur = cur.next; + return data; + } + }; + } +} diff --git a/src/LinkedList.java b/src/LinkedList.java new file mode 100644 index 0000000..1be2574 --- /dev/null +++ b/src/LinkedList.java @@ -0,0 +1,291 @@ +/** + * List implementation with linked nodes + * Allows adding elements without resizing in chunks + * + * @author R.J. Trenchard + * 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedList implements List { + + Node head; + int size; + + public LinkedList() { + head = null; + size = 0; + } + + + private class Node { + Node next; + E data; + + public Node(E data) { + this(data, null); + } + + public Node(E data, Node next) { + this.data = data; + this.next = next; + } + } + + /** + * Add item to the front. + * O(1) - access to the front nodes are instant + * + * @param item the item to be added + */ + @Override + public void addFront(E item) { + add(0, item); + } + + /** + * Add item to the back. + * O(n) - need to scroll to the end node since we don't keep track of it. + * although we could and it would result in O(1) as well. + * + * @param item the item to be added + */ + @Override + public void addBack(E item) { + add(size(), item); + } + + /** + * Add an item at specified index (position). + * O(n) - if adding to the very back, you will need to scroll the whole list. + * + * @param i the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int i, E item) { + // check if in range + if (i < 0 || i > size() ) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + + size++; + + // case: size is 0/no head + if (head == null) { + head = new Node(item); + return; + } + + // case: index 0, need to reassign head + if (i == 0) { + head = new Node(item, head); + return; + } + + // case: valid index + // wind to the place we want to add. + Node cur = head; + for (int j = 0; j < i - 1; j++) { + cur = cur.next; + } + + // insert an item at this point + cur.next = new Node(item, cur.next); + + } + + /** + * Get the item at a specified index. + * O(n) - if scrolling to the very back, will need to traverse whole list + * + * @param i the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int i) { + // check if valid range + if (i < 0 || i > size() - 1) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + + Node cur = head; + + // wind to index and return that data + for (int j = 0; j < i; j++) { + cur = cur.next; + } + + return cur.data; + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * O(n) - will need to scroll to position to set it. + * + * + * @param i the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int i, E item) { + // check if valid range + if (i < 0 || i > size() - 1) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + + // wind to index, set that item. + Node cur = head; + for (int j = 0; j < i; j++) { + cur = cur.next; + } + + cur.data = item; + + } + + /** + * Remove item at the front of the list. + * O(1) - head is readily accessible. + * + * @return the item that was removed + */ + @Override + public E removeFront() { + return remove(0); + } + + /** + * Remove item at the back of the list + * O(n) - back needs to be scrolled to before removing it + * + * @return the item that was removed + */ + @Override + public E removeBack() { + return remove(size()-1); + } + + /** + * Remove item from the list + * O(n) - this implementation calls remove twice, + * but is guaranteed to pass no more than twice. + * thus is it 2n, not BigO Squared. + * + * @param item the item to be removed + */ + @Override + public void remove(E item) { + Node cur = head; + for (int i = 0; i < size(); i++) { + if (cur.data.equals(item)) { + remove(i); + return; + } + cur = cur.next; + } + } + + /** + * Remove item at a specified index. + * O(n) - need to scroll to index to find it, which may be at the end. + * + * @param i the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int i) { + // check if valid range + if (i < 0 || i > size() - 1) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + + size--; + + // case: index is at position 0, need to reassign head + if (i == 0) { + E data = head.data; + head = head.next; + return data; + } + + // case: any other index + Node cur = head, prev = cur; + for (int j = 0; j < i; j++) { + prev = cur; + cur = cur.next; + } + + E data = cur.data; + + // remove reference to current node + prev.next = cur.next; + + return data; + } + + /** + * Checks if an item is in the list. + * O(n) - may not find an item, resulting in traversing the whole list. + * + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(E item) { + Node cur = head; + for (int i = 0; i < size(); i++) { + if (cur.data.equals(item)) { + return true; + } + cur = cur.next; + } + return false; + } + + /** + * Checks if the list is empty. + * O(1), size access is instant + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Provides a count of the number of items in the list. + * O(1) - size access is instant. + * + * @return number of items in the list + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n) - traverses entire list. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator<>() { + Node cur = head; + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + E data = cur.data; + cur = cur.next; + return data; + } + }; + } +} diff --git a/src/LinkedQueue.java b/src/LinkedQueue.java new file mode 100644 index 0000000..b8670df --- /dev/null +++ b/src/LinkedQueue.java @@ -0,0 +1,129 @@ +/** + * LinkedQueue implementation + + * This queue uses linked nodes to store data, both a head and a tail + * for quick access to enqueuing to the back, and dequeuing from the front. + * + * @author R.J. Trenchard + * 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedQueue implements Queue { + + int size; + Node head, tail; + + public LinkedQueue() { + size = 0; + head = tail = null; + } + + private class Node { + E data; + + Node next; + + public Node(E data) { + this(data, null); + } + + public Node(E data, Node next) { + this.data = data; + this.next = next; + } + } + /** + * Add an item to the queue. + * O(1), adding to a queue is instant if we keep track of the head and tail. + * + * @param item the item to be added + */ + @Override + public void enqueue(E item) { + // case: size is 0, create head and tail + if (size == 0) { + head = tail = new Node(item); + } + // case: any other size, add to back + else { + tail = tail.next = new Node(item, tail); + } + + size++; + } + + /** + * Remove an item from the queue. + * O(1), dequeuing is instant and involves no loops. + * + * @return the item that was removed + */ + @Override + public E dequeue() { + // check if there's anything in the queue + if (size == 0) throw new NoSuchElementException(); + + size--; + + // dequeuing should be generally safe + E data = head.data; + head = head.next; + + return data; + } + + /** + * Checks to see if the queue is empty. + * O(1), size access is instant + * + * @return true if the queue is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns a count of the number of items in the queue. + * O(1), size access is instant + * + * @return the number of items in the queue + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n) - guaranteed to be O(n) if you iterate through the list once + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator<>() { + Node cur = head; + + @Override + public boolean hasNext() { + return !isEmpty(); + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + + E data = cur.data; + cur = cur.next; + return data; + } + }; + } +} diff --git a/src/LinkedStack.java b/src/LinkedStack.java new file mode 100644 index 0000000..f1879a9 --- /dev/null +++ b/src/LinkedStack.java @@ -0,0 +1,123 @@ +/** + * Linked Stack + * Stack that uses linked nodes to store its data + * + * @author R.J. Trenchard + * 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedStack implements Stack { + + int size; + Node tail; + + public LinkedStack() { + tail = null; + size = 0; + } + + private class Node { + E data; + + Node prev; + + public Node(E data, Node prev) { + this.data = data; + this.prev = prev; + } + } + + /** + * Add an item to the stack. + * + * @param item the item to be added + */ + @Override + public void push(E item) { + tail = new Node(item, tail); + size++; + } + + /** + * Removes the most recently added item from the stack. + * + * @return the item that was removed + */ + @Override + public E pop() { + if (tail == null) { + throw new NoSuchElementException(); + } + size--; + E data = tail.data; + tail = tail.prev; + return data; + } + + /** + * Returns the item at the top of the stack. + * Does not modify the stack or the item at the top. + * + * @return item at the top of the stack. + */ + @Override + public E peek() { + if (tail == null) { + throw new NoSuchElementException(); + } + return tail.data; + } + + /** + * Checks to see if the stack is empty. + * + * @return true if the stack is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns a count of the number of items in the stack. + * + * @return the number of items in the stack + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator<>() { + Node cur = tail; + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + E data = cur.data; + cur = cur.prev; + return data; + } + }; + } +} diff --git a/src/LinkedStackTestClient.java b/src/LinkedStackTestClient.java new file mode 100644 index 0000000..f9ffc0a --- /dev/null +++ b/src/LinkedStackTestClient.java @@ -0,0 +1,30 @@ +/** + * demos the linked stack + * + * @author R.J. Trenchard + * 2/15/2024 + */ +import java.util.Scanner; + + +public class LinkedStackTestClient { + public static void main(String[] args) { + Stack s = new LinkedStack<>(); + + Scanner in = new Scanner("to be or not to - be - - that - - - is"); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + s.push(item); + } + else if (!s.isEmpty()) { + System.out.print(s.pop() + " "); + } + } + + System.out.println("\n(" + s.size() + " left in the stack)"); + + } + +} diff --git a/src/MathSetImpl.java b/src/MathSetImpl.java new file mode 100644 index 0000000..40bc571 --- /dev/null +++ b/src/MathSetImpl.java @@ -0,0 +1,157 @@ +/** + * In progress + * + * @author R.J. Trenchard + * 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; + +public class MathSetImpl> implements MathSet { + /** + * Adds a key (item) to the set. Duplicate items + * are not added. + * + * @param key the key (item) to be added + */ + @Override + public void add(E key) { + + } + + /** + * Removes a key (item) from the set. + * + * @param key the key (item) to be removed + */ + @Override + public void remove(E key) { + + } + + /** + * Checks if a key (item) is an element in the set. + * + * @param key the key (item) to check + * @return true if the key is in the set, false otherise + */ + @Override + public boolean contains(E key) { + return false; + } + + /** + * Checks if this set is equal to another set. + * + * @param other the set to compare this set against + * @return true if this set is equal to the other set + */ + @Override + public boolean equals(MathSet other) { + return false; + } + + /** + * Checks if this set is a subset of another set. + * + * @param other the set to compare this set against + * @return true if this set is a subset of the other set + */ + @Override + public boolean isSubsetOf(MathSet other) { + return false; + } + + /** + * Checks if this set is a proper subset of another set. + * + * @param other the set to compare this set against + * @return true if this set is a proper subset of the other set + */ + @Override + public boolean isProperSubsetOf(MathSet other) { + return false; + } + + /** + * Computes the union of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the union + */ + @Override + public MathSet union(MathSet other) { + return null; + } + + /** + * Computes the intersection of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the intersection + */ + @Override + public MathSet intersection(MathSet other) { + return null; + } + + /** + * Computes the difference of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the difference + */ + @Override + public MathSet difference(MathSet other) { + return null; + } + + /** + * Computes the symmetric difference of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the symmetric difference + */ + @Override + public MathSet symmetricDifference(MathSet other) { + return null; + } + + /** + * Checks if this set is empty. + * + * @return true if this set is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return false; + } + + /** + * Returns a count of the number of keys (elements) in this set + * also known as the cardinality of the set. + * + * @return number of keys (elements) in this set. + */ + @Override + public int size() { + return 0; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return null; + } +} diff --git a/src/QueueTestClient.java b/src/QueueTestClient.java new file mode 100644 index 0000000..d8ca03d --- /dev/null +++ b/src/QueueTestClient.java @@ -0,0 +1,30 @@ +/** + * demos the queue + * + * @author R.J. Trenchard + * 2/15/2024 + */ +import java.util.Scanner; + + +public class QueueTestClient { + public static void main(String[] args) { + Queue q = new LinkedQueue<>(); + + Scanner in = new Scanner("to be or not to - be - - that - - - is"); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + q.enqueue(item); + } + else if (!q.isEmpty()) { + System.out.print(q.dequeue() + " "); + } + } + + System.out.println("\n(" + q.size() + " left in the queue)"); + + } + +} diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java new file mode 100644 index 0000000..019da2c --- /dev/null +++ b/src/ResizingArrayStack.java @@ -0,0 +1,190 @@ +/** + * Resizing Array Stack + * This stack uses a built-in array to store its data. + * + * @author R.J. Trenchard + * @date 2/15/2024 + */ + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ResizingArrayStack implements Stack { + + private static final int DEFAULT_BUFFER = 10; + private static final double MAX_CAPACITY = 0.75; + + private static final double MIN_CAPACITY = 0.5; + + private E[] stack; + private int size; + + public ResizingArrayStack() { + this.stack = (E[]) new Object[DEFAULT_BUFFER]; + this.size = 0; + } + + // for testing + protected int getArraySize() { + return stack.length; + } + + // resizes the array when capacity is overfull or underfull + private void autoResize() { + double capacity = this.size() / (double)stack.length; + + // grow when we reach max capacity + if (capacity > MAX_CAPACITY) { + grow(); + } + + // shrink if we're below the min capacity, but the default buffer must have a size. + else if (capacity < MIN_CAPACITY && stack.length > DEFAULT_BUFFER) { + shrink(); + } + } + + private void grow() { + // hold old data + E[] buf = stack; + int newLength = stack.length + DEFAULT_BUFFER; + + // create new array of a larger size + stack = (E[]) new Object[newLength]; + + this.copy(buf, stack); + } + + private void shrink() { + // hold old data + E[] buf = stack; + int newLength = stack.length - DEFAULT_BUFFER; + + // don't try if the new length is too small + if (newLength < DEFAULT_BUFFER) { + return; + } + + // create new array of a smaller size + stack = (E[]) new Object[newLength]; + + this.copy(buf, stack); + } + + // O(n), linear copy. + private void copy(E[] from, E[] to) { + // copy old data to new array + int shortest = Math.min(to.length, from.length); + for (int i = 0; i < shortest; i++) { + to[i] = from[i]; + } + } + + /** + * Add an item to the stack. + * O(n) - if the buffer is full, we need to copy the whole stack + * + * @param item the item to be added + */ + @Override + public void push(E item) { + autoResize(); + + // add item, grow size + stack[size] = item; + size++; + } + + /** + * Removes the most recently added item from the stack. + * O(n) - if the buffer is too large, need to copy array + * + * @return the item that was removed + */ + @Override + public E pop() { + if (this.isEmpty()) { + throw new NoSuchElementException(); + } + + autoResize(); + + // grab data and lower size + E data = stack[size-1]; + size--; + return data; + } + + /** + * Returns the item at the top of the stack. + * Does not modify the stack or the item at the top. + * O(1) - access to peek is instant + * + * @return item at the top of the stack. + */ + @Override + public E peek() { + if (this.isEmpty()) { + throw new NoSuchElementException(); + } + return stack[size-1]; + } + + /** + * Checks to see if the stack is empty. + * O(1) - instant access + * + * @return true if the stack is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns a count of the number of items in the stack. + * O(1) - access to size is instant + * + * @return the number of items in the stack + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n) - always n elements unless you break early. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator<>() { + int it = 0; + + final E[] readonly = stack.clone(); + + final int readonly_size = size(); + + + @Override + public boolean hasNext() { + return it < readonly_size; + } + + @Override + public E next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + E data = readonly[it]; + it++; + return data; + } + }; + } +} diff --git a/src/ResizingArrayStackTestClient.java b/src/ResizingArrayStackTestClient.java new file mode 100644 index 0000000..09d9cdb --- /dev/null +++ b/src/ResizingArrayStackTestClient.java @@ -0,0 +1,30 @@ +/** + * demos the array stack + * + * @author R.J. Trenchard + * 2/15/2024 + */ +import java.util.Scanner; + + +public class ResizingArrayStackTestClient { + public static void main(String[] args) { + Stack s = new ResizingArrayStack<>(); + + Scanner in = new Scanner("to be or not to - be - - that - - - is"); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + s.push(item); + } + else if (!s.isEmpty()) { + System.out.print(s.pop() + " "); + } + } + + System.out.println("\n(" + s.size() + " left in the stack)"); + + } + +} diff --git a/src/Stats.java b/src/Stats.java new file mode 100644 index 0000000..46dc429 --- /dev/null +++ b/src/Stats.java @@ -0,0 +1,38 @@ +import java.util.Scanner; + +/** + * Previews LinkedBag + * + * @author R.J. Trenchard + * 2/15/2024 + */ + +public class Stats { + public static void main(String[] args) { + Scanner in = new Scanner("100 99 101 120 98 107 109 81 101 90"); + + Bag numbers = new LinkedBag<>(); + + while (in.hasNextDouble()) { + numbers.add(in.nextDouble()); + } + + int n = numbers.size(); + + double sum = 0f; + + for (double num : numbers) { + sum += num; + } + + double mean = sum / n; + + sum = 0.0; + for (double num : numbers) { + sum += (num - mean) * (num - mean); + } + double stddev = Math.sqrt(sum/(n-1)); + + System.out.printf("Mean: %.2f\nStddev: %.2f", mean, stddev); + } +} diff --git a/test/ArrayListTest.java b/test/ArrayListTest.java new file mode 100644 index 0000000..1250017 --- /dev/null +++ b/test/ArrayListTest.java @@ -0,0 +1,248 @@ +import org.junit.jupiter.api.Test; + +import java.util.Iterator; + +import static org.junit.jupiter.api.Assertions.*; + +class ArrayListTest { + + @Test + void autoResize() { + ArrayList t = new ArrayList<>(); + + for (int i = 0; i < 100; i++) { + t.addBack(String.format("test%d", i)); + } + + // should be 110ish? + assertTrue(t.getArraySize() > 100); + + for (var i: t) + t.removeFront(); + + var arraySize = t.getArraySize(); + var actual = t.size(); + + // the array should have shrunk + assertTrue(t.getArraySize() < 100); + } + + @Test + void add() { + ArrayList t = new ArrayList<>(); + + assertTrue(t.isEmpty()); + + // test add back functionality + t.add(0 , "test"); + assertEquals(t.size(),1); + assertEquals(t.get(0), "test"); + + // test add front functionality + t.add(0, "test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + // test add center functionality + t.add(1, "test3"); + assertEquals(t.size(), 3); + assertEquals(t.get(1), "test3"); + } + + @Test + void addFront() { + ArrayList t = new ArrayList<>(); + + t.addFront("test"); + assertEquals(t.size(), 1); + + t.addFront("test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + } + + @Test + void addBack() { + ArrayList t = new ArrayList<>(); + t.addBack("test"); + t.addBack("test2"); + t.addBack("test3"); + + assertEquals(t.get(0), "test"); + assertEquals(t.get(2), "test3"); + + } + + @Test + void get() { + ArrayList t = new ArrayList<>(); + + t.addBack("1"); + t.addBack("2"); + t.addBack("3"); + t.addBack("4"); + + // inside array + assertEquals("3", t.get(2)); + + // case: beginning of array + assertEquals("1", t.get(0)); + + // case: end of array + assertEquals("4", t.get(3)); + + } + + @Test + void set() { + ArrayList t = new ArrayList<>(); + + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + + // case: inner array + t.set(1, "set"); + assertEquals("set", t.get(1)); + + // case: beginning of array + t.set(0, "set2"); + assertEquals("set2", t.get(0)); + + // case: end of array + t.set(3, "set3"); + assertEquals("set3", t.get(3)); + } + + @Test + void removeFront() { + ArrayList t = new ArrayList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + + var retval = t.removeFront(); + assertEquals(retval, "test1"); + + retval = t.removeFront(); + assertEquals(retval, "test2"); + } + + @Test + void removeBack() { + ArrayList t = new ArrayList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + var retval = t.removeBack(); + assertEquals(retval, "test4"); + + retval = t.removeBack(); + assertEquals(retval, "test3"); + } + + @Test + void removeByIndex() { + ArrayList t = new ArrayList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test remove inner index + var retval = t.remove(1); + assertEquals(retval, "test2"); + + // test remove final index + retval = t.remove(t.size()-1); + assertEquals(retval, "test4"); + + // test remove beginning index + retval = t.remove(0); + assertEquals(retval, "test1"); + } + + @Test + void removeByElement() { + ArrayList t = new ArrayList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test removing element that does not exist + t.remove("test5"); + assertEquals(t.size(), 4); + + // test removing element that exists + t.remove("test2"); + assertEquals(t.size(), 3); + + } + + @Test + void contains() { + ArrayList t = new ArrayList<>(); + + t.addBack(""); + t.addBack("test"); + t.addBack("toast"); + + assertTrue(t.contains("test")); + + assertFalse(t.contains("test2")); + + } + + @Test + void isEmpty() { + ArrayList t = new ArrayList<>(); + + assertTrue(t.isEmpty()); + + t.addBack(""); + assertFalse(t.isEmpty()); + + t.removeBack(); + assertTrue(t.isEmpty()); + + } + + @Test + void size() { + ArrayList t = new ArrayList<>(); + + assertTrue(t.isEmpty()); + + t.addBack("test"); + assertTrue(t.size() == 1); + + t.removeBack(); + assertTrue(t.isEmpty()); + + } + + @Test + void iterator() { + ArrayList t = new ArrayList<>(); + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + for (var i : t) { + assertTrue(t.contains(i)); + } + } + +} \ No newline at end of file diff --git a/test/DequeImplTest.java b/test/DequeImplTest.java new file mode 100644 index 0000000..4097474 --- /dev/null +++ b/test/DequeImplTest.java @@ -0,0 +1,156 @@ +import org.junit.jupiter.api.Test; + +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class DequeImplTest { + + @Test + void isEmpty() { + DequeImpl deque = new DequeImpl<>(); + + assertTrue(deque.isEmpty()); + + deque.pushLeft(""); + assertFalse(deque.isEmpty()); + + deque.popLeft(); + assertTrue(deque.isEmpty()); + + } + + @Test + void size() { + DequeImpl deque = new DequeImpl<>(); + + assertEquals(deque.size(), 0); + + deque.pushLeft(""); + assertEquals(deque.size(), 1); + + deque.popLeft(); + assertEquals(deque.size(), 0); + + } + + @Test + void pushLeft() { + DequeImpl deque = new DequeImpl<>(); + + // from a 0 sized deque + deque.pushLeft("1"); + assertEquals(deque.size(), 1); + + // from a 1 sized deque + deque.pushLeft("2"); + assertEquals(deque.size(), 2); + + // from a n>1 sized deque + deque.pushLeft("3"); + assertEquals(deque.size(), 3); + + } + + @Test + void pushRight() { + DequeImpl deque = new DequeImpl<>(); + + // from a 0 sized deque + deque.pushRight("1"); + assertEquals(deque.size(), 1); + + // from a 1 sized deque + deque.pushRight("2"); + assertEquals(deque.size(), 2); + + // from a n>1 sized deque + deque.pushRight("3"); + assertEquals(deque.size(), 3); + } + + @Test + void popLeft() { + DequeImpl deque = new DequeImpl<>(); + + deque.pushLeft("1"); + // 1 + + deque.pushLeft("2"); + // 2 1 + + deque.pushLeft("3"); + // 3 2 1 + + deque.pushRight("2"); + // 3 2 1 2 + + deque.pushRight("1"); + // 3 2 1 2 1 + + + // n>1 sized deque + var n = deque.popLeft(); + assertEquals("3", n); + n = deque.popLeft(); + assertEquals("2", n); + n = deque.popLeft(); + assertEquals("1", n); + + // 2 elements left, resulting in a 1 sized data structure + n = deque.popLeft(); + assertEquals("2", n); + assertEquals(1, deque.size()); + + // 1 element left + n = deque.popLeft(); + assertEquals("1", n); + + assertTrue(deque.isEmpty()); + + } + + @Test + void popRight() { + DequeImpl deque = new DequeImpl<>(); + + deque.pushRight("1"); + // 1 + deque.pushRight("2"); + // 1 2 + deque.pushRight("3"); + // 1 2 3 + deque.pushLeft("2"); + // 2 1 2 3 + deque.pushLeft("1"); + // 1 2 1 2 3 + + // n>1 sized deque + var n = deque.popRight(); + assertEquals("3", n); + n = deque.popRight(); + assertEquals("2", n); + n = deque.popRight(); + assertEquals("1", n); + + // 2 elements left, resulting in a 1 sized data structure + n = deque.popRight(); + assertEquals("2", n); + assertEquals(1, deque.size()); + + // 1 element left + n = deque.popRight(); + assertEquals("1", n); + + assertTrue(deque.isEmpty()); + } + + @Test + void iterator() { + assertThrows( NoSuchElementException.class, () -> { + DequeImpl deque = new DequeImpl<>(); + var it = deque.iterator(); + it.next(); + }); + } +} \ No newline at end of file diff --git a/test/LinkedBagTest.java b/test/LinkedBagTest.java new file mode 100644 index 0000000..ee868d8 --- /dev/null +++ b/test/LinkedBagTest.java @@ -0,0 +1,70 @@ +import org.junit.jupiter.api.Test; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedBagTest { + + @Test + void add() { + Bag bag = new LinkedBag<>(); + + assertTrue(bag.isEmpty()); + + bag.add("item"); + assertEquals(1,bag.size()); + + bag.add("item"); + assertEquals(2,bag.size()); + + } + + @Test + void isEmpty() { + Bag bag = new LinkedBag<>(); + + assertTrue(bag.isEmpty()); + + bag.add("item"); + assertFalse(bag.isEmpty()); + } + + @Test + void size() { + Bag bag = new LinkedBag<>(); + + assertEquals(0,bag.size()); + + bag.add("item"); + assertEquals(1,bag.size()); + + bag.add("item2"); + assertEquals(2,bag.size()); + } + + @Test + void iterator() { + Bag bag = new LinkedBag<>(); + + bag.add("1"); + bag.add("2"); + bag.add("3"); + + Iterator it = bag.iterator(); + + var n = it.next(); + assertEquals("1", n); + + n = it.next(); + assertEquals("2", n); + + n = it.next(); + assertEquals("3", n); + + assertThrows(NoSuchElementException.class, it::next); + + + } +} \ No newline at end of file diff --git a/test/LinkedListTest.java b/test/LinkedListTest.java new file mode 100644 index 0000000..c23cdd2 --- /dev/null +++ b/test/LinkedListTest.java @@ -0,0 +1,224 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedListTest { + @Test + void add() { + LinkedList t = new LinkedList<>(); + + assertTrue(t.isEmpty()); + + // test add back functionality + t.add(0 , "test"); + assertEquals(t.size(),1); + assertEquals(t.get(0), "test"); + + // test add front functionality + t.add(0, "test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + // test add center functionality + t.add(1, "test3"); + assertEquals(t.size(), 3); + assertEquals(t.get(1), "test3"); + } + + @Test + void addFront() { + LinkedList t = new LinkedList<>(); + + t.addFront("test"); + assertEquals(t.size(), 1); + + t.addFront("test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + } + + @Test + void addBack() { + LinkedList t = new LinkedList<>(); + t.addBack("test"); + t.addBack("test2"); + t.addBack("test3"); + + assertEquals(t.get(0), "test"); + assertEquals(t.get(2), "test3"); + + } + + @Test + void get() { + LinkedList t = new LinkedList<>(); + + t.addBack("1"); + t.addBack("2"); + t.addBack("3"); + t.addBack("4"); + + // inside array + assertEquals("3", t.get(2)); + + // case: beginning of array + assertEquals("1", t.get(0)); + + // case: end of array + assertEquals("4", t.get(3)); + + } + + @Test + void set() { + LinkedList t = new LinkedList<>(); + + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + + // case: inner array + t.set(1, "set"); + assertEquals("set", t.get(1)); + + // case: beginning of array + t.set(0, "set2"); + assertEquals("set2", t.get(0)); + + // case: end of array + t.set(3, "set3"); + assertEquals("set3", t.get(3)); + } + + @Test + void removeFront() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + + var retval = t.removeFront(); + assertEquals(retval, "test1"); + + retval = t.removeFront(); + assertEquals(retval, "test2"); + } + + @Test + void removeBack() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + var retval = t.removeBack(); + assertEquals(retval, "test4"); + + retval = t.removeBack(); + assertEquals(retval, "test3"); + } + + @Test + void removeByIndex() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test remove inner index + var retval = t.remove(1); + assertEquals(retval, "test2"); + + // test remove final index + retval = t.remove(t.size()-1); + assertEquals(retval, "test4"); + + // test remove beginning index + retval = t.remove(0); + assertEquals(retval, "test1"); + } + + @Test + void removeByElement() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test removing element that does not exist + t.remove("test5"); + assertEquals(t.size(), 4); + + // test removing element that exists + t.remove("test2"); + assertEquals(t.size(), 3); + + } + + @Test + void contains() { + LinkedList t = new LinkedList<>(); + + t.addBack(""); + t.addBack("test"); + t.addBack("toast"); + + assertTrue(t.contains("test")); + + assertFalse(t.contains("test2")); + + } + + @Test + void isEmpty() { + LinkedList t = new LinkedList<>(); + + assertTrue(t.isEmpty()); + + t.addBack(""); + assertFalse(t.isEmpty()); + + t.removeBack(); + assertTrue(t.isEmpty()); + + } + + @Test + void size() { + LinkedList t = new LinkedList<>(); + + assertTrue(t.isEmpty()); + + t.addBack("test"); + assertTrue(t.size() == 1); + + t.removeBack(); + assertTrue(t.isEmpty()); + + } + + @Test + void iterator() { + LinkedList t = new LinkedList<>(); + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + for (var i : t) { + assertTrue(t.contains(i)); + } + } + +} \ No newline at end of file diff --git a/test/LinkedQueueTest.java b/test/LinkedQueueTest.java new file mode 100644 index 0000000..5d08c77 --- /dev/null +++ b/test/LinkedQueueTest.java @@ -0,0 +1,87 @@ +import org.junit.jupiter.api.Test; + +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedQueueTest { + + @Test + void enqueue() { + LinkedQueue queue = new LinkedQueue<>(); + + assertEquals(0, queue.size()); + + queue.enqueue(""); + assertEquals(1, queue.size()); + + queue.enqueue(""); + assertEquals(2, queue.size()); + + queue.enqueue(""); + assertEquals(3, queue.size()); + } + + @Test + void dequeue() { + LinkedQueue queue = new LinkedQueue<>(); + + queue.enqueue("1"); + queue.enqueue("2"); + queue.enqueue("3"); + queue.enqueue("4"); + + var n = queue.dequeue(); + assertEquals("1", n); + assertEquals(3, queue.size()); + + n = queue.dequeue(); + assertEquals("2", n); + assertEquals(2, queue.size()); + + n = queue.dequeue(); + assertEquals("3", n); + assertEquals(1, queue.size()); + + n = queue.dequeue(); + assertEquals("4", n); + assertEquals(0, queue.size()); + + } + + @Test + void isEmpty() { + LinkedQueue queue = new LinkedQueue<>(); + + assertTrue(queue.isEmpty()); + + queue.enqueue(""); + assertFalse(queue.isEmpty()); + + queue.dequeue(); + assertTrue(queue.isEmpty()); + } + + @Test + void size() { + LinkedQueue queue = new LinkedQueue<>(); + + assertEquals(0, queue.size()); + + queue.enqueue(""); + assertEquals(1, queue.size()); + + queue.dequeue(); + assertEquals(0, queue.size()); + + } + + @Test + void iterator() { + assertThrows( NoSuchElementException.class, () -> { + LinkedQueue queue = new LinkedQueue<>(); + var it = queue.iterator(); + it.next(); + }); + } +} \ No newline at end of file diff --git a/test/LinkedStackTest.java b/test/LinkedStackTest.java new file mode 100644 index 0000000..91733f5 --- /dev/null +++ b/test/LinkedStackTest.java @@ -0,0 +1,103 @@ +import org.junit.jupiter.api.Test; + +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedStackTest { + + @Test + void push() { + LinkedStack stack = new LinkedStack<>(); + + assertEquals(stack.size(), 0); + + stack.push("1"); + assertEquals(stack.size(), 1); + + stack.push("1"); + assertEquals(stack.size(), 2); + } + + @Test + void pop() { + LinkedStack stack = new LinkedStack<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + var n = stack.pop(); + assertEquals("2", n); + assertEquals(1, stack.size()); + + n = stack.pop(); + assertEquals("1", n); + assertEquals(0, stack.size()); + + } + + @Test + void peek() { + LinkedStack stack = new LinkedStack<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + // test peek top element + var n = stack.peek(); + assertEquals("2", n); + assertEquals(2, stack.size()); + + // test popping stack and then peeking the next value + stack.pop(); + n = stack.peek(); + assertEquals("1", n); + assertEquals(1, stack.size()); + + } + + @Test + void isEmpty() { + LinkedStack stack = new LinkedStack<>(); + + assertTrue(stack.isEmpty()); + + stack.push("1"); + assertFalse(stack.isEmpty()); + + stack.pop(); + assertTrue(stack.isEmpty()); + } + + @Test + void size() { + LinkedStack stack = new LinkedStack<>(); + + assertEquals(0, stack.size()); + + stack.push(""); + assertEquals(1, stack.size()); + + stack.push(""); + assertEquals(2, stack.size()); + + stack.pop(); + assertEquals(1, stack.size()); + + stack.pop(); + assertEquals(0, stack.size()); + } + + @Test + void iterator() { + assertThrows( NoSuchElementException.class, () -> { + LinkedStack stack = new LinkedStack<>(); + var it = stack.iterator(); + it.next(); + }); + } +} \ No newline at end of file diff --git a/test/MathSetImplTest.java b/test/MathSetImplTest.java new file mode 100644 index 0000000..597b161 --- /dev/null +++ b/test/MathSetImplTest.java @@ -0,0 +1,58 @@ +import org.junit.jupiter.api.Test; + +//import static org.junit.jupiter.api.Assertions.*; + +class MathSetImplTest { + + @Test + void add() { + } + + @Test + void remove() { + } + + @Test + void contains() { + } + + @Test + void testEquals() { + } + + @Test + void isSubsetOf() { + } + + @Test + void isProperSubsetOf() { + } + + @Test + void union() { + } + + @Test + void intersection() { + } + + @Test + void difference() { + } + + @Test + void symmetricDifference() { + } + + @Test + void isEmpty() { + } + + @Test + void size() { + } + + @Test + void iterator() { + } +} \ No newline at end of file diff --git a/test/ResizingArrayStackTest.java b/test/ResizingArrayStackTest.java new file mode 100644 index 0000000..1b29bd9 --- /dev/null +++ b/test/ResizingArrayStackTest.java @@ -0,0 +1,138 @@ +import org.junit.jupiter.api.Test; + +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class ResizingArrayStackTest { + + @Test + void arrayWillResizeOnMaxCapacity() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertDoesNotThrow( () -> { + for (int i = 0; i < 100; i++) { + stack.push("" + i); + } + }); + + assertTrue(stack.getArraySize() > 100); + } + + @Test + void arrayWillResizeOnMinCapacity() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertDoesNotThrow( () -> { + for (int i = 0; i < 100; i++) { + stack.push("" + i); + } + }); + + for ( var v : stack ) { + stack.pop(); + } + + assertTrue( stack.getArraySize() < 100); + } + + + + @Test + void push() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertEquals(stack.size(), 0); + + stack.push("1"); + assertEquals(stack.size(), 1); + + stack.push("1"); + assertEquals(stack.size(), 2); + + } + + @Test + void pop() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + var n = stack.pop(); + assertEquals("2", n); + assertEquals(1, stack.size()); + + n = stack.pop(); + assertEquals("1", n); + assertEquals(0, stack.size()); + + } + + @Test + void peek() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + // test peek top element + var n = stack.peek(); + assertEquals("2", n); + assertEquals(2, stack.size()); + + // test popping stack and then peeking the next value + stack.pop(); + n = stack.peek(); + assertEquals("1", n); + assertEquals(1, stack.size()); + + } + + @Test + void isEmpty() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertTrue(stack.isEmpty()); + + stack.push("1"); + assertFalse(stack.isEmpty()); + + stack.pop(); + assertTrue(stack.isEmpty()); + } + + @Test + void size() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertEquals(0, stack.size()); + + stack.push(""); + assertEquals(1, stack.size()); + + stack.push(""); + assertEquals(2, stack.size()); + + stack.pop(); + assertEquals(1, stack.size()); + + stack.pop(); + assertEquals(0, stack.size()); + } + + + + @Test + void iterator() { + assertThrows( NoSuchElementException.class, () -> { + ResizingArrayStack stack = new ResizingArrayStack<>(); + var it = stack.iterator(); + it.next(); + }); + } +} \ No newline at end of file