From f024d567cf07780b1a8a402c55ed0265a6852e23 Mon Sep 17 00:00:00 2001 From: Nathan Howard Date: Thu, 18 Dec 2025 15:11:23 -0800 Subject: [PATCH] Lab10 --- .../Lab10_HashStackIterator/.classpath | 11 ++ .../Lab10_HashStackIterator/.project | 17 ++ .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 11 ++ .../Lab10_HashStackIterator/src/Deque.java | 170 ++++++++++++++++++ .../src/ListOfLists.java | 102 +++++++++++ .../Lab10_HashStackIterator/src/Runner.java | 51 ++++++ .../Lab10_HashStackIterator/src/Stack.java | 112 ++++++++++++ .../src/StringCreator.java | 54 ++++++ 9 files changed, 530 insertions(+) create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.classpath create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.project create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.core.resources.prefs create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.jdt.core.prefs create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Deque.java create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/ListOfLists.java create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Runner.java create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Stack.java create mode 100644 completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/StringCreator.java diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.classpath b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.classpath new file mode 100644 index 0000000..8e3d409 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.project b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.project new file mode 100644 index 0000000..b75612c --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.project @@ -0,0 +1,17 @@ + + + Lab10_HashStackIterator + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.core.resources.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.jdt.core.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..e71285a --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Deque.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Deque.java new file mode 100644 index 0000000..17a4fe9 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Deque.java @@ -0,0 +1,170 @@ +interface IPred { + boolean apply(T t); +} + +class MatchToData implements IPred { + T match; + MatchToData(T match) { + this.match = match; + } + public boolean apply(T t) { + return t.equals(match); + } +} + +abstract class ANode { + ANode next; + ANode prev; + ANode(ANode next, ANode prev) { + this.next = next; + this.prev = prev; + } + // inserts this node between before and after nodes + void insertBetween(ANode next, ANode prev) { + if (prev == null || next == null) { + throw new IllegalArgumentException("Cannot assign next or prev to null"); + } + prev.next = this; + this.prev = prev; + this.next = next; + next.prev = this; + } + // inserts this node after provided node + void insertAfter(ANode prev) { + this.insertBetween(prev.next, prev); + } + // inserts this node before provided node + void insertBefore(ANode next) { + this.insertBetween(next, next.prev); + } + int size() { + if (this.next == null) { + return 0; + } else { + return this.next.sizeHelper(0); + } + } + abstract void remove(); + abstract int sizeHelper(int cnt); + abstract ANode find(IPred p); + abstract T getData(); +} + +class Sentinel extends ANode { + Sentinel(ANode next, ANode prev) { + super(next, prev); + } + Sentinel() { + this(null, null); + this.insertBetween(this, this); + } + int sizeHelper(int cnt) { + return cnt; + } + ANode removeNext() { + if (this.next == this) { + throw new RuntimeException("Cannot remove item from empty list"); + } + ANode r = this.next; + this.next.remove(); + return r; + } + ANode removePrev() { + if (this.next == this) { + throw new RuntimeException("Cannot remove item from empty list"); + } + ANode r = this.prev; + this.prev.remove(); + return r; + } + void remove() { + throw new RuntimeException("Cannot remove sentinel node"); + } + ANode find(IPred p) { + return this; + } + T getData() { + throw new RuntimeException("Sentinels have no data"); + } +} + +class Node extends ANode { + T data; + Node(T data, ANode next, ANode prev) { + super(next, prev); + this.data = data; + this.insertBetween(prev, next); + } + Node(T data) { + super(null, null); + this.data = data; + } + int sizeHelper(int cnt) { + return this.next.sizeHelper(cnt + 1); + } + void remove() { + this.prev.next = this.next; + this.next.prev = this.prev; + } + ANode find(IPred pred) { + if (pred.apply(this.data)) { + return this; + } else { + return this.next.find(pred); + } + } + T getData() { + return this.data; + } +} + +class Deque { + Sentinel header; + Deque(Sentinel header) { + this.header = header; + } + Deque() { + this(new Sentinel()); + } + // returns the number of nodes in a list Deque, not including the header node + int size() { + return this.header.size(); // + } + // inserts node n at the front of the list. + void addAtHead(Node n) { + n.insertAfter(this.header); + } + // inserts node n at the end of the list. + void addAtTail(Node n) { + n.insertBefore(this.header); + } + // returns and removes the first node from this Deque. + // Throw a RuntimeException if an attempt is made to remove + // from an empty list. + ANode removeFromHead() { + return this.header.removeNext(); + } + // returns and removes the last node from this Deque. + // Throw a RuntimeException if an attempt is made to remove + // from an empty list. + ANode removeFromTail() { + return this.header.removePrev(); + } + // returns the first node in this Deque where the predicate returns true + // if nothing is found return header + ANode find(IPred p) { + // start at first node so when we hit sentinel we return sentinel + return this.header.next.find(p); + } + // removes the given node from this Deque + // If the given node is the Sentinel header, the method does nothing + void removeNode(Node n) { + ANode found = this.find(new MatchToData(n.data)); + // we dont want to remove the sentinel node + if (found instanceof Sentinel) { + return; + } + found.remove(); + } + +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/ListOfLists.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/ListOfLists.java new file mode 100644 index 0000000..676490f --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/ListOfLists.java @@ -0,0 +1,102 @@ +import tester.Tester; +import java.util.ArrayList; +import java.util.Iterator; + +public class ListOfLists implements Iterable { + ArrayList> contents; + ListOfLists(ArrayList> contents) { + this.contents = contents; + } + ListOfLists() { + this(new ArrayList>()); + } + // adds a new empty ArrayList to the end of the list-of-lists. + void addNewList() { + this.contents.add(new ArrayList()); + } + // adds the provided object to the end of the ArrayList at the + // provided index in teh list-of-lists. If the index is invalid, + // this method should throw an IndexOutOfBoundsException with a + // suitable message. + void add(int index, T object) { + this.contents.get(index).add(object); + } + ArrayList get(int index) { + if (index < 0 && index > this.contents.size()) { + throw new IndexOutOfBoundsException("Bad Index Value"); + } + return this.contents.get(index); + } + public int size() { + return this.contents.size(); + } + @Override + public Iterator iterator() { + return new ListIterator(this); + } +} + +class ListIterator implements Iterator { + ListOfLists listofList; + Iterator currentSubListIter; + int nextIndex; + ListIterator(ListOfLists listofList) { + this.listofList = listofList; + this.nextIndex = 0; + this.currentSubListIter = listofList.get(nextIndex).iterator(); + this.nextIndex++; + } + public boolean hasNext() { + return nextIndex < listofList.size() && currentSubListIter.hasNext(); + } + public T next() { + if (!currentSubListIter.hasNext()) { + this.currentSubListIter = listofList.get(nextIndex).iterator(); + this.nextIndex++; + } + return currentSubListIter.next(); + } + public void remove() { + throw new UnsupportedOperationException("Remove Action Unsupported."); + } +} + +class LofLExamples { + void testListOfLists(Tester t) { + ListOfLists lol = new ListOfLists(); + t.checkExpect(lol.contents.size(), 0); + //add 3 lists + lol.addNewList(); + lol.addNewList(); + lol.addNewList(); + t.checkExpect(lol.contents.size(), 3); + + //add elements 1,2,3 in first list + t.checkExpect(lol.contents.get(0).size(), 0); + lol.add(0, 1); + lol.add(0, 2); + lol.add(0, 3); + t.checkExpect(lol.contents.get(0).size(), 3); + + //add elements 4,5,6 in second list + t.checkExpect(lol.contents.get(1).size(), 0); + lol.add(1, 4); + lol.add(1, 5); + lol.add(1, 6); + t.checkExpect(lol.contents.get(1).size(), 3); + + //add elements 7,8,9 in third list + t.checkExpect(lol.contents.get(2).size(), 0); + lol.add(2, 7); + lol.add(2, 8); + lol.add(2, 9); + t.checkExpect(lol.contents.get(0).size(), 3); + + //iterator should return elements in order 1,2,3,4,5,6,7,8,9 + int number = 1; + for (Integer num : lol) { + t.checkExpect(num, number); + number = number + 1; + } + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Runner.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Runner.java new file mode 100644 index 0000000..a5b740b --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Runner.java @@ -0,0 +1,51 @@ +import java.util.Objects; +import tester.Tester; + +class Runner { + int age; + String name; + + Runner(int age, String name) { + this.age = age; + this.name = name; + } + + public boolean equals(Object obj) { + if (!(obj instanceof Runner)) { + return false; + } + Runner rObj = (Runner) obj; + return this.name.equals(rObj.name) && this.age == rObj.age; + } + + public int hashCode() { + return Objects.hash(this.name, this.age); + } +} + +class RunnerExamples { + Runner amy; + Runner bob; + Runner cale; + Runner dave; + Runner stillBob; + Runner notBob; + void init() { + amy = new Runner(50, "amy"); + bob = new Runner(40, "bob"); + cale = new Runner(30, "cale"); + dave = new Runner(20, "dave"); + + stillBob = new Runner(40, "bob"); + notBob = new Runner(20, "bob"); + } + void testHashEquality(Tester t) { + init(); + t.checkExpect(this.bob.equals(this.bob), true); + t.checkExpect(this.bob.equals(this.stillBob), true); + t.checkExpect(this.bob.equals(this.notBob), false); + t.checkExpect(this.bob.hashCode(), this.stillBob.hashCode()); + t.checkExpect(this.amy.hashCode(), new Runner(50, "amy").hashCode()); + t.checkExpect(this.bob.hashCode() == this.notBob.hashCode(), false); + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Stack.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Stack.java new file mode 100644 index 0000000..c1898e8 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/Stack.java @@ -0,0 +1,112 @@ +import tester.Tester; +import java.util.ArrayList; +import java.util.Arrays; + +class Stack { + Deque contents; + + Stack(Deque contents) { + this.contents = contents; + } + Stack() { + this.contents = new Deque(); + } + + //adds an item to the stack + void push(T item) { + this.contents.addAtHead(new Node(item)); + } + // returns true if contents are empty + boolean isEmpty() { + if (contents.size() == 0) { + return true; + } else { + return false; + } + } + //removes and returns the top of the stack + T pop() { + return this.contents.removeFromHead().getData(); + } +} + +class Utils { + // Using loops and one or more stacks, define the method that reverses an ArrayList: + ArrayList reverse(ArrayList source) { + ArrayList response = new ArrayList(); + Stack intermediate = new Stack(); + int size = 0; + for (T item : source) { + intermediate.push(item); + size++; + } + for (int i = 0; i < size; i++) { + response.add(i, intermediate.pop()); + } + return response; + } +} + +class StackExamples { + Stack s0; + Stack s1; + Deque dqAns; + + Runner amy; + Runner bob; + Runner cale; + Runner dave; + Runner stillBob; + Runner notBob; + void init() { + amy = new Runner(50, "amy"); + bob = new Runner(40, "bob"); + cale = new Runner(30, "cale"); + dave = new Runner(20, "dave"); + stillBob = new Runner(40, "bob"); + notBob = new Runner(20, "bob"); + + s0 = new Stack(); + s1 = new Stack(); + dqAns = new Deque(); + } + void testPush(Tester t) { + init(); + t.checkExpect(s1.contents.header.next, s1.contents.header); + s1.push(dave); + t.checkExpect(s1.contents.header.next, + new Node(dave, dqAns.header, dqAns.header)); + s1.push(cale); + t.checkExpect(s1.contents.header.next, + new Node(cale, dqAns.header, dqAns.header.prev)); + } + void testIsEmpty(Tester t) { + init(); + t.checkExpect(s0.isEmpty(), true); + t.checkExpect(s1.isEmpty(), true); + s1.push(dave); + t.checkExpect(s1.isEmpty(), false); + } + void testPop(Tester t) { + init(); + t.checkException( + new RuntimeException("Cannot remove item from empty list"), + s1, + "pop"); + s1.push(dave); + t.checkExpect(s1.pop(), dave); + s1.push(dave); + s1.push(cale); + s1.push(bob); + s1.push(amy); + t.checkExpect(s1.pop(), amy); + t.checkExpect(s1.pop(), bob); + t.checkExpect(s1.pop(), cale); + t.checkExpect(s1.pop(), dave); + } + void testReverseArrayList(Tester t) { + ArrayList fwd = new ArrayList(Arrays.asList(amy, bob, cale, dave)); + ArrayList rev = new ArrayList(Arrays.asList(dave, cale, bob, amy)); + t.checkExpect(new Utils().reverse(fwd), rev); + } +} diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/StringCreator.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/StringCreator.java new file mode 100644 index 0000000..65bf5e8 --- /dev/null +++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab10_HashStackIterator/src/StringCreator.java @@ -0,0 +1,54 @@ +import tester.Tester; + +class StringCreator { + String contents; + Stack actions; + StringCreator() { + contents = ""; + actions = new Stack(); + } + + String getString() { + return contents; + } + void add(char item) { + this.actions.push(this.contents); + this.contents = this.contents + item; + } + void remove() { + this.actions.push(this.contents); + this.contents = this.contents.substring(0, this.contents.length() - 1); + } + void undo() { + if (!this.actions.isEmpty()) { + this.contents = this.actions.pop(); + } + } +} + +class StringExamples { + void testRun(Tester t) { + StringCreator creator = new StringCreator(); + t.checkExpect(creator.getString(), ""); + creator.add('c'); + creator.add('d'); + t.checkExpect(creator.getString(), "cd"); + creator.add('e'); + t.checkExpect(creator.getString(), "cde"); + creator.remove(); + creator.remove(); + t.checkExpect(creator.getString(), "c"); + creator.undo(); //undoes the removal of 'd' + t.checkExpect(creator.getString(), "cd"); + creator.undo(); //undoes the removal of 'e' + creator.undo(); //undoes the addition of 'e' + t.checkExpect(creator.getString(), "cd"); + creator.add('a'); + t.checkExpect(creator.getString(), "cda"); + creator.undo(); //undoes the addition of 'a' + creator.undo(); //undoes the addition of 'd' + creator.undo(); //undoes the addition of 'c' + t.checkExpect(creator.getString(), ""); + creator.undo(); //no effect, there is nothing to undo + } +}