diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..b58b603
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..c0071b2
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..9dc782b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/fundamentals/ResizingArrayQueue.java b/src/main/java/fundamentals/ResizingArrayQueue.java
new file mode 100644
index 0000000..5120099
--- /dev/null
+++ b/src/main/java/fundamentals/ResizingArrayQueue.java
@@ -0,0 +1,153 @@
+package fundamentals;
+
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * We are interested in the implementation of a Queue using an array.
+ * The array size needs to be updated when it is full or close to empty
+ * i.e. when the array is full, the size of the array should double
+ * and when the array is less than 1/4 full, the size of the array should halve.
+ *
+ * You are asked to implement this Queue by completing the class see (TODO's)
+ * Most important methods are:
+ * - the enqueue method to add an element
+ * - the remove method [The NoSuchElementException is thrown when the queue is empty]
+ * - the iterator used to browse the queue in FIFO
+ *
+ * Hint : when the head of the stack reaches the end of the array, go back at its beginning.
+ *
+ * @param -
+ */
+public class ResizingArrayQueue
- implements Iterable
- {
+
+ public Item[] q;
+ private long nOp = 0;
+ // BEGIN STRIP
+ private int head;
+ private int tail;
+ private int size;
+ // END STRIP
+
+ @SuppressWarnings("unchecked")
+ public ResizingArrayQueue() {
+ q = (Item[]) new Object[2];
+ nOp = 0;
+ // BEGIN STRIP
+ head = 0;
+ tail = 0;
+ size = 0;
+ // END STRIP
+ }
+
+ public boolean isEmpty() {
+ // TODO
+ // Student return false;
+ // BEGIN STRIP
+ return size == 0;
+ // END STRIP
+ }
+
+ public int size() {
+ // TODO
+ // Student return 0;
+ // BEGIN STRIP
+ return size;
+ // END STRIP
+ }
+
+ private long getnOp() {
+ return nOp;
+ }
+ // BEGIN STRIP
+ @SuppressWarnings("unchecked")
+ private void resize(int capacity) {
+ nOp++;
+ Item[] temp = (Item[]) new Object[capacity];
+ for (int i = 0; i < size; i++) {
+ temp[i] = q[(head + i) % q.length];
+ }
+ q = temp;
+ head = 0;
+ tail = size;
+ }
+ // END STRIP
+
+ /**
+ * Add an item at the tail of the queue.
+ * Resize the array if needed.
+ * @param item the item to add.
+ */
+ public void enqueue(Item item) {
+ // TODO
+ // BEGIN STRIP
+ nOp++;
+ if (size == q.length) {
+ resize(2 * q.length);
+ }
+ q[tail] = item;
+ tail = (tail + 1) % q.length;
+ size++;
+ // END STRIP
+ }
+
+ /**
+ * Removes and return the element at the head of the queue.
+ * Resize the array if needed.
+ * @return The item freshly removed.
+ * @throws NoSuchElementException when the queue is empty.
+ */
+ public Item dequeue() throws NoSuchElementException{
+ // TODO
+ // STUDENT return null;
+ // BEGIN STRIP
+ nOp++;
+ if (isEmpty()) throw new NoSuchElementException();
+
+ Item val = q[head];
+ q[head] = null;
+ head = (head + 1) % q.length;
+ size--;
+
+ if (size > 0 && size == q.length / 4) {
+ resize(q.length / 2);
+ }
+
+ return val;
+ // END STRIP
+ }
+
+ /**
+ * Returns an iterator that iterates through the items in FIFO order.
+ * @return an iterator that iterates through the items in FIFO order.
+ */
+ @Override
+ public Iterator
- iterator() {
+ // TODO
+ // STUDENT return null;
+ // BEGIN STRIP
+ return new QueueIterator();
+ // END STRIP
+ }
+
+ // BEGIN STRIP
+ private class QueueIterator implements Iterator
- {
+ private final long nOp = getnOp();
+ private int currentHead = head;
+
+ @Override
+ public boolean hasNext() {
+ return currentHead != tail;
+ }
+
+ @Override
+ public Item next() {
+ if (nOp != getnOp()) throw new ConcurrentModificationException();
+ Item current = q[currentHead];
+ currentHead = (currentHead + 1) % q.length;
+ return current;
+ }
+ }
+ // END STRIP
+}
diff --git a/src/test/java/fundamentals/ResizingArrayQueueTest.java b/src/test/java/fundamentals/ResizingArrayQueueTest.java
new file mode 100644
index 0000000..d7c3469
--- /dev/null
+++ b/src/test/java/fundamentals/ResizingArrayQueueTest.java
@@ -0,0 +1,122 @@
+package fundamentals;
+
+import org.javagrader.Grade;
+import org.junit.jupiter.api.Test;
+
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@Grade
+public class ResizingArrayQueueTest {
+
+ @Test
+ @Grade(value = 1, cpuTimeout = 1)
+ public void testBasicEnqueueDequeue() {
+ ResizingArrayQueue q = new ResizingArrayQueue<>();
+
+ assertTrue(q.isEmpty());
+ q.enqueue(1);
+ q.enqueue(2);
+ q.enqueue(3);
+
+ assertEquals(3, q.size());
+ assertEquals(Integer.valueOf(1), q.dequeue());
+ assertEquals(Integer.valueOf(2), q.dequeue());
+ assertEquals(Integer.valueOf(3), q.dequeue());
+ assertTrue(q.isEmpty());
+ }
+
+ @Test
+ @Grade(value = 1, cpuTimeout = 1)
+ public void testWrapAround() {
+ ResizingArrayQueue q = new ResizingArrayQueue<>();
+
+ for (int i = 0; i < 10; i++) q.enqueue(i);
+ for (int i = 0; i < 5; i++) assertEquals(Integer.valueOf(i), q.dequeue());
+ for (int i = 10; i < 15; i++) q.enqueue(i);
+
+ for (int i = 5; i < 15; i++) assertEquals(Integer.valueOf(i), q.dequeue());
+ assertTrue(q.isEmpty());
+ }
+
+ @Test
+ @Grade(value = 1, cpuTimeout = 1)
+ public void testResizeDown() {
+ ResizingArrayQueue q = new ResizingArrayQueue<>();
+
+ for (int i = 0; i < 32; i++) q.enqueue(i);
+ Object[] arr = q.q;
+ int oldCap = arr.length;
+ assertTrue(oldCap >= 32);
+
+ while (q.size() > oldCap / 4 + 1) q.dequeue();
+ q.dequeue(); // should shrink here
+
+ arr = q.q;
+ int len = arr.length;
+ assertEquals(oldCap / 2, len);
+ }
+
+ @Test
+ @Grade(value = 1, cpuTimeout = 1)
+ public void testResizeUp() {
+ ResizingArrayQueue q = new ResizingArrayQueue<>();
+
+ q.enqueue(1);
+ q.enqueue(2);
+ Object[] arr = q.q;
+ int len = arr.length;
+ assertEquals(2, len);
+
+ q.enqueue(3); // should trigger resize
+ arr = q.q;
+ len = arr.length;
+ assertEquals(4, len);
+
+ q.enqueue(4);
+ q.enqueue(5); // trigger resize again
+ arr = q.q;
+ len = arr.length;
+ assertEquals(8, len);
+ }
+
+ @Test
+ @Grade(value = 1, cpuTimeout = 1)
+ public void testIteratorOrderAndWrap() {
+ ResizingArrayQueue q = new ResizingArrayQueue<>();
+
+ q.enqueue(1);
+ q.enqueue(2);
+ q.enqueue(3);
+ q.enqueue(4);
+ q.dequeue(); // head moves
+ q.dequeue(); // head moves
+ q.enqueue(5);
+ q.enqueue(6);
+
+ int[] expected = {3, 4, 5, 6};
+ int idx = 0;
+
+ for (int x : q) {
+ assertEquals(expected[idx++], x);
+ }
+ }
+
+ @Test
+ @Grade(value = 1, cpuTimeout = 1)
+ public void testIteratorFailFast() {
+ ResizingArrayQueue q = new ResizingArrayQueue<>();
+ q.enqueue(1);
+ q.enqueue(2);
+ q.enqueue(3);
+
+ Iterator it = q.iterator();
+ assertTrue(it.hasNext());
+ assertEquals(1, it.next());
+
+ q.enqueue(4); // structural modification => should break iterator
+ assertThrows(ConcurrentModificationException.class, it::next);
+ }
+}