This commit is contained in:
Nathan Howard 2025-12-18 15:11:23 -08:00
parent 5c3e3909d1
commit f024d567cf
9 changed files with 530 additions and 0 deletions

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lab10_HashStackIterator</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -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

View File

@ -0,0 +1,170 @@
interface IPred<T> {
boolean apply(T t);
}
class MatchToData<T> implements IPred<T> {
T match;
MatchToData(T match) {
this.match = match;
}
public boolean apply(T t) {
return t.equals(match);
}
}
abstract class ANode<T> {
ANode<T> next;
ANode<T> prev;
ANode(ANode<T> next, ANode<T> prev) {
this.next = next;
this.prev = prev;
}
// inserts this node between before and after nodes
void insertBetween(ANode<T> next, ANode<T> 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<T> prev) {
this.insertBetween(prev.next, prev);
}
// inserts this node before provided node
void insertBefore(ANode<T> 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<T> find(IPred<T> p);
abstract T getData();
}
class Sentinel<T> extends ANode<T> {
Sentinel(ANode<T> next, ANode<T> prev) {
super(next, prev);
}
Sentinel() {
this(null, null);
this.insertBetween(this, this);
}
int sizeHelper(int cnt) {
return cnt;
}
ANode<T> removeNext() {
if (this.next == this) {
throw new RuntimeException("Cannot remove item from empty list");
}
ANode<T> r = this.next;
this.next.remove();
return r;
}
ANode<T> removePrev() {
if (this.next == this) {
throw new RuntimeException("Cannot remove item from empty list");
}
ANode<T> r = this.prev;
this.prev.remove();
return r;
}
void remove() {
throw new RuntimeException("Cannot remove sentinel node");
}
ANode<T> find(IPred<T> p) {
return this;
}
T getData() {
throw new RuntimeException("Sentinels have no data");
}
}
class Node<T> extends ANode<T> {
T data;
Node(T data, ANode<T> next, ANode<T> 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<T> find(IPred<T> pred) {
if (pred.apply(this.data)) {
return this;
} else {
return this.next.find(pred);
}
}
T getData() {
return this.data;
}
}
class Deque<T> {
Sentinel<T> header;
Deque(Sentinel<T> header) {
this.header = header;
}
Deque() {
this(new Sentinel<T>());
}
// 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<T> n) {
n.insertAfter(this.header);
}
// inserts node n at the end of the list.
void addAtTail(Node<T> 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<T> 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<T> removeFromTail() {
return this.header.removePrev();
}
// returns the first node in this Deque where the predicate returns true
// if nothing is found return header
ANode<T> find(IPred<T> 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<T> n) {
ANode<T> found = this.find(new MatchToData<T>(n.data));
// we dont want to remove the sentinel node
if (found instanceof Sentinel) {
return;
}
found.remove();
}
}

View File

@ -0,0 +1,102 @@
import tester.Tester;
import java.util.ArrayList;
import java.util.Iterator;
public class ListOfLists<T> implements Iterable<T> {
ArrayList<ArrayList<T>> contents;
ListOfLists(ArrayList<ArrayList<T>> contents) {
this.contents = contents;
}
ListOfLists() {
this(new ArrayList<ArrayList<T>>());
}
// adds a new empty ArrayList<T> to the end of the list-of-lists.
void addNewList() {
this.contents.add(new ArrayList<T>());
}
// adds the provided object to the end of the ArrayList<T> 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<T> 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<T> iterator() {
return new ListIterator<T>(this);
}
}
class ListIterator<T> implements Iterator<T> {
ListOfLists<T> listofList;
Iterator<T> currentSubListIter;
int nextIndex;
ListIterator(ListOfLists<T> 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<Integer> lol = new ListOfLists<Integer>();
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;
}
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,112 @@
import tester.Tester;
import java.util.ArrayList;
import java.util.Arrays;
class Stack<T> {
Deque<T> contents;
Stack(Deque<T> contents) {
this.contents = contents;
}
Stack() {
this.contents = new Deque<T>();
}
//adds an item to the stack
void push(T item) {
this.contents.addAtHead(new Node<T>(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:
<T> ArrayList<T> reverse(ArrayList<T> source) {
ArrayList<T> response = new ArrayList<T>();
Stack<T> intermediate = new Stack<T>();
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<Runner> s0;
Stack<Runner> s1;
Deque<Runner> 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<Runner>();
s1 = new Stack<Runner>();
dqAns = new Deque<Runner>();
}
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<Runner>(dave, dqAns.header, dqAns.header));
s1.push(cale);
t.checkExpect(s1.contents.header.next,
new Node<Runner>(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<Runner> fwd = new ArrayList<Runner>(Arrays.asList(amy, bob, cale, dave));
ArrayList<Runner> rev = new ArrayList<Runner>(Arrays.asList(dave, cale, bob, amy));
t.checkExpect(new Utils().reverse(fwd), rev);
}
}

View File

@ -0,0 +1,54 @@
import tester.Tester;
class StringCreator {
String contents;
Stack<String> actions;
StringCreator() {
contents = "";
actions = new Stack<String>();
}
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
}
}