loops and iter lectures

This commit is contained in:
Nathan Howard 2025-12-04 10:57:23 -08:00
parent f9e9b11866
commit 44babaab79
17 changed files with 1781 additions and 0 deletions

View File

@ -0,0 +1,380 @@
import tester.Tester;
import java.util.ArrayList;
import java.util.Arrays;
//Represents functions of signature A -> R, for some argument type A and
//result type R
interface IFunc<A, R> {
R apply(A input);
}
interface IFunc2<A1, A2, R> {
R apply(A1 arg1, A2 arg2);
}
interface IPred<T> {
boolean apply(T t);
}
interface IComparator<T> {
int compare(T t1, T t2);
}
class DoubleInteger implements IFunc<Integer, Integer> {
public Integer apply(Integer input) {
return input * 2;
}
}
class IntToString implements IFunc<Integer, String> {
public String apply(Integer input) {
return input.toString();
}
}
class SumIntegers implements IFunc2<Integer, Integer, Integer> {
public Integer apply(Integer arg1, Integer arg2) {
return arg1 + arg2;
}
}
class AppendIntToString implements IFunc2<Integer, String, String> {
public String apply(Integer arg1, String arg2) {
return arg2 + arg1.toString();
}
}
class MatchString implements IPred<String> {
String find;
MatchString(String find) {
this.find = find;
}
public boolean apply(String s) {
return this.find.compareTo(s) == 0;
}
}
class CompareStrings implements IComparator<String> {
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
}
class CompareInts implements IComparator<Integer> {
public int compare(Integer i1, Integer i2) {
return i1 - i2;
}
}
class ArrayUtils {
// EFFECT: Exchanges the values at the given two indices in the given array
<T> void swap(ArrayList<T> arr, int index1, int index2) {
T oldValueAtIndex1 = arr.get(index1);
T oldValueAtIndex2 = arr.get(index2);
arr.set(index2, oldValueAtIndex1);
arr.set(index1, oldValueAtIndex2);
}
<T, U> ArrayList<U> map(ArrayList<T> arr, IFunc<T, U> func) {
ArrayList<U> result = new ArrayList<U>();
for (T t : arr) {
result.add(func.apply(t));
}
return result;
}
<T, U> U foldr(ArrayList<T> arr, IFunc2<T, U, U> func, U base) {
U result = base;
for (T t : arr) {
result = func.apply(t, result);
}
return result;
}
<T, U> U foldl(ArrayList<T> arr, IFunc2<T, U, U> func, U base) {
return this.foldlHelp(arr, func, base, arr.size() - 1);
}
<T, U> U foldlHelp(ArrayList<T> source, IFunc2<T, U, U> func, U base, int curIdx) {
U result = base;
if (curIdx < 0) {
return result;
} else {
result = func.apply(source.get(curIdx), result);
return this.foldlHelp(source, func, result, curIdx - 1);
}
}
<T, U> U foldl_Loop(ArrayList<T> arr, IFunc2<T, U, U> func, U base) {
ArrayList<T> reversedList = this.reverseList(arr);
return this.foldr(reversedList, func, base);
}
<T> ArrayList<T> reverseList(ArrayList<T> arr) {
ArrayList<T> result = new ArrayList<T>();
for (T t : arr) {
result.add(0, t);
}
return result;
}
//Returns the index of the first item passing the predicate,
//or -1 if no such item was found
<T> int find(ArrayList<T> arr, IPred<T> whichOne) {
return this.findHelp(arr, whichOne, 0);
}
// Returns the index of the first item passing the predicate at or after the
//given index, or -1 if no such such item was found
<T> int findHelp(ArrayList<T> arr, IPred<T> whichOne, int index) {
if (index >= arr.size()) {
return -1;
} else if (whichOne.apply(arr.get(index))) {
return index;
} else {
return findHelp(arr, whichOne, index + 1);
}
}
// Returns the index of the target string in the given ArrayList, or -1 if the string is not found
//Assumes that the given ArrayList is sorted aphabetically
int binarySearch_v1(ArrayList<String> strings, String target) {
return binarySearchHelp_v1(strings, target, 0, strings.size() - 1);
}
int binarySearchHelp_v1(ArrayList<String> strings, String target, int lowIdx, int highIdx) {
int midIdx = (lowIdx + highIdx) / 2;
if (lowIdx > highIdx) {
return -1; // not found
} else if (target.compareTo(strings.get(midIdx)) == 0) {
return midIdx; // found it!
} else if (target.compareTo(strings.get(midIdx)) > 0) {
return this.binarySearchHelp_v1(strings, target, midIdx + 1, highIdx); // too low
} else {
return this.binarySearchHelp_v1(strings, target, lowIdx, midIdx - 1); // too high
}
}
//Returns the index of the target string in the given ArrayList, or -1 if the string is not found
//Assumes that the given ArrayList is sorted aphabetically
int binarySearch_v2(ArrayList<String> strings, String target) {
return this.binarySearchHelp_v2(strings, target, 0, strings.size());
}
//Returns the index of the target string in the given ArrayList, or -1 if the string is not found
//Assumes that the given ArrayList is sorted aphabetically
//Assumes that [lowIdx, highIdx) is a semi-open interval of indices
int binarySearchHelp_v2(ArrayList<String> strings, String target, int lowIdx, int highIdx) {
int midIdx = (lowIdx + highIdx) / 2;
if (lowIdx >= highIdx) {
return -1; // not found
} else if (target.compareTo(strings.get(midIdx)) == 0) {
return midIdx; // found it!
} else if (target.compareTo(strings.get(midIdx)) > 0) {
return this.binarySearchHelp_v2(strings, target, midIdx + 1, highIdx); // too low
} else {
return this.binarySearchHelp_v2(strings, target, lowIdx, midIdx); // too high
}
}
<T> int gen_binarySearch_v2(ArrayList<T> arr, T target, IComparator<T> comp) {
return this.gen_binarySearchHelp_v2(arr, target, comp, 0, arr.size());
}
<T> int gen_binarySearchHelp_v2(ArrayList<T> arr, T target, IComparator<T> comp,
int lowIdx, int highIdx) {
int midIdx = (lowIdx + highIdx) / 2;
if (lowIdx >= highIdx) {
return -1;
} else if (comp.compare(target, arr.get(midIdx)) == 0) {
return midIdx;
} else if (comp.compare(target, arr.get(midIdx)) > 0) {
return this.gen_binarySearchHelp_v2(arr, target, comp, midIdx + 1, highIdx);
} else {
return this.gen_binarySearchHelp_v2(arr, target, comp, lowIdx, midIdx);
}
}
// EFFECT: Sorts the given list of strings alphabetically
void sort(ArrayList<String> arr) {
for (int idx = 0; idx < arr.size(); idx = idx + 1) {
int idxOfMinValue = this.findMinValue(arr, idx, idx + 1);
this.swap(arr, idx, idxOfMinValue);
}
}
int findMinValue(ArrayList<String> arr, int minValIdx, int currIdx) {
if (currIdx >= arr.size()) {
return minValIdx;
} else if (arr.get(minValIdx).compareTo(arr.get(currIdx)) < 0) {
return this.findMinValue(arr, minValIdx, currIdx + 1);
} else {
return this.findMinValue(arr, currIdx, currIdx + 1);
}
}
// returns an ArrayList consisting of one item from arr1, then one from arr2, alternating until one list is expended
// attaches rest of other list to the end;
<T> ArrayList<T> interleave(ArrayList<T> arr1, ArrayList<T> arr2) {
ArrayList<T> r = new ArrayList<T>();
for (int idx = 0; idx < arr1.size() || idx < arr2.size(); idx++) {
if (idx >= arr1.size()) {
r.add(arr2.get(idx));
} else if (idx >= arr2.size()) {
r.add(arr1.get(idx));
} else {
r.add(arr1.get(idx));
r.add(arr2.get(idx));
}
}
return r;
}
// returns a new list containing the first, third, fifth ... items of the list, followed by the second, fourth, sixth ... items.
<T> ArrayList<T> unshuffle(ArrayList<T> arr) {
ArrayList<T> list1 = new ArrayList<T>();
ArrayList<T> list2 = new ArrayList<T>();
for (int idx = 0; idx < arr.size(); idx++) {
if (idx % 2 == 0) {
list1.add(arr.get(idx));
} else {
list2.add(arr.get(idx));
}
}
list1.addAll(list2);
return list1;
}
<U> ArrayList<U> buildList(int n, IFunc<Integer, U> func) {
ArrayList<U> resultArray = new ArrayList<U>();
for (int i = 0; i < n; i++) {
resultArray.add(func.apply(i));
}
return resultArray;
}
//Capitalizes the titles of all books in the given ArrayList
void capitalizeTitles(ArrayList<Book> books) {
for (Book b : books) {
b.capitalizeTitle();
}
}
}
class ExampleArrayLists {
ArrayUtils u;
ArrayList<Integer> nums;
ArrayList<String> strings;
ArrayList<Integer> nums_unsorted;
ArrayList<String> strings_unsorted;
ArrayList<Integer> numsInterleave;
ArrayList<String> stringsInterleave;
void init() {
u = new ArrayUtils();
nums = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
nums_unsorted = new ArrayList<Integer>(Arrays.asList(2, 3, 1));
strings = new ArrayList<String>(
Arrays.asList("apple", "banana", "cherry", "date",
"fig", "grape", "honeydew", "kiwi", "watermelon"));
strings_unsorted = new ArrayList<String>(
Arrays.asList("cherry", "apple", "watermelon", "banana",
"fig", "date", "honeydew", "kiwi", "grape"));
numsInterleave = new ArrayList<Integer>(Arrays.asList(1, 4, 2, 5, 3, 6));
stringsInterleave = new ArrayList<String>(
Arrays.asList("apple", "artichoke", "banana", "broccoli", "cherry", "carrot", "date",
"fig", "grape", "honeydew", "kiwi", "watermelon"));
}
void testAdd(Tester t) {
ArrayList<String> someStrings = new ArrayList<String>();
someStrings.add("First string");
someStrings.add("Second string");
t.checkExpect(someStrings.get(0), "First string");
t.checkExpect(someStrings.get(1), "Second string");
// Insert this item at index 1, and move everything else back
someStrings.add(1, "Squeezed in");
t.checkExpect(someStrings.get(0), "First string");
t.checkExpect(someStrings.get(1), "Squeezed in");
t.checkExpect(someStrings.get(2), "Second string");
}
void testSwap(Tester t) {
ArrayList<String> someStrings = new ArrayList<String>();
someStrings.add("Second string");
someStrings.add("First string");
ArrayUtils u = new ArrayUtils();
u.swap(someStrings, 0, 1);
t.checkExpect(someStrings.get(0), "First string");
t.checkExpect(someStrings.get(1), "Second string");
}
void testMap(Tester t) {
init();
t.checkExpect(this.u.map(this.nums, new DoubleInteger()),
new ArrayList<Integer>(Arrays.asList(2, 4, 6)));
}
void testFold(Tester t) {
init();
t.checkExpect(u.foldr(nums, new SumIntegers(), 0), 6);
t.checkExpect(u.foldr(nums, new AppendIntToString(), ""), "123");
t.checkExpect(u.foldl(nums, new AppendIntToString(), ""), "321");
t.checkExpect(u.foldl_Loop(nums, new AppendIntToString(), ""), "321");
}
void testFind(Tester t) {
init();
t.checkExpect(u.find(this.strings, new MatchString("apple")), 0);
t.checkExpect(u.find(this.strings, new MatchString("cherry")), 2);
t.checkExpect(u.find(this.strings, new MatchString("watermelon")), 8);
t.checkExpect(u.find(this.strings, new MatchString("notFound")), -1);
t.checkExpect(u.binarySearch_v1(strings, "apple"), 0);
t.checkExpect(u.binarySearch_v1(this.strings, "cherry"), 2);
t.checkExpect(u.binarySearch_v1(this.strings, "watermelon"), 8);
t.checkExpect(u.binarySearch_v1(this.strings, "notFound"), -1);
t.checkExpect(u.binarySearch_v2(strings, "apple"), 0);
t.checkExpect(u.binarySearch_v2(this.strings, "cherry"), 2);
t.checkExpect(u.binarySearch_v2(this.strings, "watermelon"), 8);
t.checkExpect(u.binarySearch_v2(this.strings, "notFound"), -1);
CompareStrings compStr = new CompareStrings();
t.checkExpect(u.gen_binarySearch_v2(strings, "apple", compStr), 0);
t.checkExpect(u.gen_binarySearch_v2(this.strings, "cherry", compStr), 2);
t.checkExpect(u.gen_binarySearch_v2(this.strings, "watermelon", compStr), 8);
t.checkExpect(u.gen_binarySearch_v2(this.strings, "notFound", compStr), -1);
CompareInts compInt = new CompareInts();
t.checkExpect(u.gen_binarySearch_v2(this.nums, 1, compInt), 0);
t.checkExpect(u.gen_binarySearch_v2(this.nums, 2, compInt), 1);
t.checkExpect(u.gen_binarySearch_v2(this.nums, 3, compInt), 2);
t.checkExpect(u.gen_binarySearch_v2(this.nums, 0, compInt), -1);
}
void testSort(Tester t) {
init();
t.checkExpect(strings_unsorted.equals(strings), false);
u.sort(strings_unsorted);
t.checkExpect(strings_unsorted.equals(strings), true);
}
void testInterleave(Tester t) {
ArrayList<Integer> moreNums = new ArrayList<Integer>(Arrays.asList(4, 5, 6));
ArrayList<String> moreStrings = new ArrayList<String>(
Arrays.asList("artichoke", "broccoli", "carrot"));
init();
t.checkExpect(u.interleave(nums, moreNums), numsInterleave);
t.checkExpect(u.interleave(strings, moreStrings), stringsInterleave);
}
void testUnshuffle(Tester t) {
init();
ArrayList<Integer> numsUnshuffled = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6));
ArrayList<String> stringsUnshuffled = new ArrayList<String>(
Arrays.asList("apple", "banana", "cherry", "date",
"grape", "kiwi", "artichoke", "broccoli",
"carrot", "fig", "honeydew", "watermelon"));
t.checkExpect(u.unshuffle(numsInterleave), numsUnshuffled);
t.checkExpect(u.unshuffle(stringsInterleave), stringsUnshuffled);
}
void testBuildList(Tester t) {
init();
t.checkExpect(u.buildList(5, new IntToString()),
new ArrayList<String>(Arrays.asList("0", "1", "2", "3", "4")));
}
void testCapTitles(Tester t) {
Book htdpLow = new Book("htDP", "MF", 0.0, 2014);
Book hpLow = new Book("hp", "JKR", 9000.00, 2015);
Book gatsbyLow = new Book("the great gatsby", "FSF", 15.99, 1930);
Book htdpUp = new Book("HTDP", "MF", 0.0, 2014);
Book hpUp = new Book("HP", "JKR", 9000.00, 2015);
Book gatsbyUp = new Book("THE GREAT GATSBY", "FSF", 15.99, 1930);
ArrayList<Book> bookList = new ArrayList<Book>(Arrays.asList(
htdpLow, hpLow, gatsbyLow));
ArrayList<Book> bookListUp = new ArrayList<Book>(Arrays.asList(
htdpUp, hpUp, gatsbyUp));
u.capitalizeTitles(bookList);
t.checkExpect(bookList, bookListUp);
}
}

View File

@ -0,0 +1,27 @@
class Book {
String name;
String author;
double price;
int year;
Book(String name, String author, double price, int year) {
this.name = name;
this.author = author;
this.price = price;
this.year = year;
}
double getPrice() {
return this.price;
}
// to return the discounted price of this book given the discount rate
double discount(double rate) {
return this.price - (rate * this.price);
}
// to return a new book with the same author and name as this book,
// but with price discounted at the given rate
Book discountedBook(double rate) {
return new Book(this.name, this.author, this.discount(rate), this.year);
}
void capitalizeTitle() {
this.name = this.name.toUpperCase();
}
}

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>Lect24_WhileLoops</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,372 @@
import tester.Tester;
import java.util.ArrayList;
import java.util.Arrays;
//Represents functions of signature A -> R, for some argument type A and
//result type R
interface IFunc<A, R> {
R apply(A input);
}
interface IFunc2<A1, A2, R> {
R apply(A1 arg1, A2 arg2);
}
interface IPred<T> {
boolean apply(T t);
}
interface IComparator<T> {
int compare(T t1, T t2);
}
class DoubleInteger implements IFunc<Integer, Integer> {
public Integer apply(Integer input) {
return input * 2;
}
}
class IntToString implements IFunc<Integer, String> {
public String apply(Integer input) {
return input.toString();
}
}
class SumIntegers implements IFunc2<Integer, Integer, Integer> {
public Integer apply(Integer arg1, Integer arg2) {
return arg1 + arg2;
}
}
class AppendIntToString implements IFunc2<Integer, String, String> {
public String apply(Integer arg1, String arg2) {
return arg2 + arg1.toString();
}
}
class MatchString implements IPred<String> {
String find;
MatchString(String find) {
this.find = find;
}
public boolean apply(String s) {
return this.find.compareTo(s) == 0;
}
}
class CompareStrings implements IComparator<String> {
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
}
class CompareInts implements IComparator<Integer> {
public int compare(Integer i1, Integer i2) {
return i1 - i2;
}
}
class ArrayUtils {
// EFFECT: Exchanges the values at the given two indices in the given array
<T> void swap(ArrayList<T> arr, int index1, int index2) {
T oldValueAtIndex1 = arr.get(index1);
T oldValueAtIndex2 = arr.get(index2);
arr.set(index2, oldValueAtIndex1);
arr.set(index1, oldValueAtIndex2);
}
<T, U> ArrayList<U> map(ArrayList<T> arr, IFunc<T, U> func) {
ArrayList<U> result = new ArrayList<U>();
for (T t : arr) {
result.add(func.apply(t));
}
return result;
}
<T, U> U foldr(ArrayList<T> arr, IFunc2<T, U, U> func, U base) {
U result = base;
for (T t : arr) {
result = func.apply(t, result);
}
return result;
}
<T, U> U foldl(ArrayList<T> arr, IFunc2<T, U, U> func, U base) {
return this.foldlHelp(arr, func, base, arr.size() - 1);
}
<T, U> U foldlHelp(ArrayList<T> source, IFunc2<T, U, U> func, U base, int curIdx) {
U result = base;
if (curIdx < 0) {
return result;
} else {
result = func.apply(source.get(curIdx), result);
return this.foldlHelp(source, func, result, curIdx - 1);
}
}
<T, U> U foldl_Loop(ArrayList<T> arr, IFunc2<T, U, U> func, U base) {
ArrayList<T> reversedList = this.reverseList(arr);
return this.foldr(reversedList, func, base);
}
<T> ArrayList<T> reverseList(ArrayList<T> arr) {
ArrayList<T> result = new ArrayList<T>();
for (T t : arr) {
result.add(0, t);
}
return result;
}
//Returns the index of the first item passing the predicate,
//or -1 if no such item was found
<T> int find(ArrayList<T> arr, IPred<T> whichOne) {
return this.findHelp(arr, whichOne, 0);
}
// Returns the index of the first item passing the predicate at or after the
//given index, or -1 if no such such item was found
<T> int findHelp(ArrayList<T> arr, IPred<T> whichOne, int index) {
if (index >= arr.size()) {
return -1;
} else if (whichOne.apply(arr.get(index))) {
return index;
} else {
return findHelp(arr, whichOne, index + 1);
}
}
// Returns the index of the target string in the given ArrayList, or -1 if the string is not found
//Assumes that the given ArrayList is sorted aphabetically
int binarySearch_v1(ArrayList<String> strings, String target) {
return binarySearchHelp_v1(strings, target, 0, strings.size() - 1);
}
int binarySearchHelp_v1(ArrayList<String> strings, String target, int lowIdx, int highIdx) {
int midIdx = (lowIdx + highIdx) / 2;
if (lowIdx > highIdx) {
return -1; // not found
} else if (target.compareTo(strings.get(midIdx)) == 0) {
return midIdx; // found it!
} else if (target.compareTo(strings.get(midIdx)) > 0) {
return this.binarySearchHelp_v1(strings, target, midIdx + 1, highIdx); // too low
} else {
return this.binarySearchHelp_v1(strings, target, lowIdx, midIdx - 1); // too high
}
}
//Returns the index of the target string in the given ArrayList, or -1 if the string is not found
//Assumes that the given ArrayList is sorted aphabetically
int binarySearch_v2(ArrayList<String> strings, String target) {
return this.binarySearchHelp_v2(strings, target, 0, strings.size());
}
//Returns the index of the target string in the given ArrayList, or -1 if the string is not found
//Assumes that the given ArrayList is sorted aphabetically
//Assumes that [lowIdx, highIdx) is a semi-open interval of indices
int binarySearchHelp_v2(ArrayList<String> strings, String target, int lowIdx, int highIdx) {
int midIdx = (lowIdx + highIdx) / 2;
if (lowIdx >= highIdx) {
return -1; // not found
} else if (target.compareTo(strings.get(midIdx)) == 0) {
return midIdx; // found it!
} else if (target.compareTo(strings.get(midIdx)) > 0) {
return this.binarySearchHelp_v2(strings, target, midIdx + 1, highIdx); // too low
} else {
return this.binarySearchHelp_v2(strings, target, lowIdx, midIdx); // too high
}
}
<T> int gen_binarySearch_v2(ArrayList<T> arr, T target, IComparator<T> comp) {
return this.gen_binarySearchHelp_v2(arr, target, comp, 0, arr.size());
}
<T> int gen_binarySearchHelp_v2(ArrayList<T> arr, T target, IComparator<T> comp,
int lowIdx, int highIdx) {
int midIdx = (lowIdx + highIdx) / 2;
if (lowIdx >= highIdx) {
return -1;
} else if (comp.compare(target, arr.get(midIdx)) == 0) {
return midIdx;
} else if (comp.compare(target, arr.get(midIdx)) > 0) {
return this.gen_binarySearchHelp_v2(arr, target, comp, midIdx + 1, highIdx);
} else {
return this.gen_binarySearchHelp_v2(arr, target, comp, lowIdx, midIdx);
}
}
// EFFECT: Sorts the given list of strings alphabetically
void sort(ArrayList<String> arr) {
for (int idx = 0; idx < arr.size(); idx = idx + 1) {
int idxOfMinValue = this.findMinValue(arr, idx, idx + 1);
this.swap(arr, idx, idxOfMinValue);
}
}
// new while loop version
int findMinValue(ArrayList<String> arr, int minValIdx, int currIdx) {
while (currIdx < arr.size()) {
if (arr.get(minValIdx).compareTo(arr.get(currIdx)) < 0) {
return this.findMinValue(arr, minValIdx, currIdx + 1);
} else {
return this.findMinValue(arr, currIdx, currIdx + 1);
}
}
return minValIdx;
}
// old for loop version
int findMinValue_old(ArrayList<String> arr, int minValIdx, int currIdx) {
if (currIdx >= arr.size()) {
return minValIdx;
} else if (arr.get(minValIdx).compareTo(arr.get(currIdx)) < 0) {
return this.findMinValue(arr, minValIdx, currIdx + 1);
} else {
return this.findMinValue(arr, currIdx, currIdx + 1);
}
}
// returns an ArrayList consisting of one item from arr1, then one from arr2, alternating until one list is expended
// attaches rest of other list to the end;
<T> ArrayList<T> interleave(ArrayList<T> arr1, ArrayList<T> arr2) {
ArrayList<T> r = new ArrayList<T>();
for (int idx = 0; idx < arr1.size() || idx < arr2.size(); idx++) {
if (idx >= arr1.size()) {
r.add(arr2.get(idx));
} else if (idx >= arr2.size()) {
r.add(arr1.get(idx));
} else {
r.add(arr1.get(idx));
r.add(arr2.get(idx));
}
}
return r;
}
// returns a new list containing the first, third, fifth ... items of the list, followed by the second, fourth, sixth ... items.
<T> ArrayList<T> unshuffle(ArrayList<T> arr) {
ArrayList<T> list1 = new ArrayList<T>();
ArrayList<T> list2 = new ArrayList<T>();
for (int idx = 0; idx < arr.size(); idx++) {
if (idx % 2 == 0) {
list1.add(arr.get(idx));
} else {
list2.add(arr.get(idx));
}
}
list1.addAll(list2);
return list1;
}
<U> ArrayList<U> buildList(int n, IFunc<Integer, U> func) {
ArrayList<U> resultArray = new ArrayList<U>();
for (int i = 0; i < n; i++) {
resultArray.add(func.apply(i));
}
return resultArray;
}
}
class ExampleArrayLists {
ArrayUtils u;
ArrayList<Integer> nums;
ArrayList<String> strings;
ArrayList<Integer> nums_unsorted;
ArrayList<String> strings_unsorted;
ArrayList<Integer> numsInterleave;
ArrayList<String> stringsInterleave;
void init() {
u = new ArrayUtils();
nums = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
nums_unsorted = new ArrayList<Integer>(Arrays.asList(2, 3, 1));
strings = new ArrayList<String>(
Arrays.asList("apple", "banana", "cherry", "date",
"fig", "grape", "honeydew", "kiwi", "watermelon"));
strings_unsorted = new ArrayList<String>(
Arrays.asList("cherry", "apple", "watermelon", "banana",
"fig", "date", "honeydew", "kiwi", "grape"));
numsInterleave = new ArrayList<Integer>(Arrays.asList(1, 4, 2, 5, 3, 6));
stringsInterleave = new ArrayList<String>(
Arrays.asList("apple", "artichoke", "banana", "broccoli", "cherry", "carrot", "date",
"fig", "grape", "honeydew", "kiwi", "watermelon"));
}
void testAdd(Tester t) {
ArrayList<String> someStrings = new ArrayList<String>();
someStrings.add("First string");
someStrings.add("Second string");
t.checkExpect(someStrings.get(0), "First string");
t.checkExpect(someStrings.get(1), "Second string");
// Insert this item at index 1, and move everything else back
someStrings.add(1, "Squeezed in");
t.checkExpect(someStrings.get(0), "First string");
t.checkExpect(someStrings.get(1), "Squeezed in");
t.checkExpect(someStrings.get(2), "Second string");
}
void testSwap(Tester t) {
ArrayList<String> someStrings = new ArrayList<String>();
someStrings.add("Second string");
someStrings.add("First string");
ArrayUtils u = new ArrayUtils();
u.swap(someStrings, 0, 1);
t.checkExpect(someStrings.get(0), "First string");
t.checkExpect(someStrings.get(1), "Second string");
}
void testMap(Tester t) {
init();
t.checkExpect(this.u.map(this.nums, new DoubleInteger()),
new ArrayList<Integer>(Arrays.asList(2, 4, 6)));
}
void testFold(Tester t) {
init();
t.checkExpect(u.foldr(nums, new SumIntegers(), 0), 6);
t.checkExpect(u.foldr(nums, new AppendIntToString(), ""), "123");
t.checkExpect(u.foldl(nums, new AppendIntToString(), ""), "321");
t.checkExpect(u.foldl_Loop(nums, new AppendIntToString(), ""), "321");
}
void testFind(Tester t) {
init();
t.checkExpect(u.find(this.strings, new MatchString("apple")), 0);
t.checkExpect(u.find(this.strings, new MatchString("cherry")), 2);
t.checkExpect(u.find(this.strings, new MatchString("watermelon")), 8);
t.checkExpect(u.find(this.strings, new MatchString("notFound")), -1);
t.checkExpect(u.binarySearch_v1(strings, "apple"), 0);
t.checkExpect(u.binarySearch_v1(this.strings, "cherry"), 2);
t.checkExpect(u.binarySearch_v1(this.strings, "watermelon"), 8);
t.checkExpect(u.binarySearch_v1(this.strings, "notFound"), -1);
t.checkExpect(u.binarySearch_v2(strings, "apple"), 0);
t.checkExpect(u.binarySearch_v2(this.strings, "cherry"), 2);
t.checkExpect(u.binarySearch_v2(this.strings, "watermelon"), 8);
t.checkExpect(u.binarySearch_v2(this.strings, "notFound"), -1);
CompareStrings compStr = new CompareStrings();
t.checkExpect(u.gen_binarySearch_v2(strings, "apple", compStr), 0);
t.checkExpect(u.gen_binarySearch_v2(this.strings, "cherry", compStr), 2);
t.checkExpect(u.gen_binarySearch_v2(this.strings, "watermelon", compStr), 8);
t.checkExpect(u.gen_binarySearch_v2(this.strings, "notFound", compStr), -1);
CompareInts compInt = new CompareInts();
t.checkExpect(u.gen_binarySearch_v2(this.nums, 1, compInt), 0);
t.checkExpect(u.gen_binarySearch_v2(this.nums, 2, compInt), 1);
t.checkExpect(u.gen_binarySearch_v2(this.nums, 3, compInt), 2);
t.checkExpect(u.gen_binarySearch_v2(this.nums, 0, compInt), -1);
}
void testSort(Tester t) {
init();
t.checkExpect(strings_unsorted.equals(strings), false);
u.sort(strings_unsorted);
t.checkExpect(strings_unsorted.equals(strings), true);
}
void testInterleave(Tester t) {
ArrayList<Integer> moreNums = new ArrayList<Integer>(Arrays.asList(4, 5, 6));
ArrayList<String> moreStrings = new ArrayList<String>(
Arrays.asList("artichoke", "broccoli", "carrot"));
init();
t.checkExpect(u.interleave(nums, moreNums), numsInterleave);
t.checkExpect(u.interleave(strings, moreStrings), stringsInterleave);
}
void testUnshuffle(Tester t) {
init();
ArrayList<Integer> numsUnshuffled = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6));
ArrayList<String> stringsUnshuffled = new ArrayList<String>(
Arrays.asList("apple", "banana", "cherry", "date",
"grape", "kiwi", "artichoke", "broccoli",
"carrot", "fig", "honeydew", "watermelon"));
t.checkExpect(u.unshuffle(numsInterleave), numsUnshuffled);
t.checkExpect(u.unshuffle(stringsInterleave), stringsUnshuffled);
}
void testBuildList(Tester t) {
init();
t.checkExpect(u.buildList(5, new IntToString()),
new ArrayList<String>(Arrays.asList("0", "1", "2", "3", "4")));
}
}

View File

@ -0,0 +1,47 @@
import tester.Tester;
import java.util.ArrayList;
import java.util.Arrays;
class Utils2 {
boolean getsToOne(int n) {
ArrayList<Integer> listN = new ArrayList<Integer>();
listN.add(n);
while (n > 1) {
if (n % 2 == 0) {
n = n / 2;
} else {
n = 3 * n + 1;
}
if (listN.contains(n)) {
return false;
}
listN.add(n);
}
return true;
}
ArrayList<Integer> getsToOne_detail(int n) {
ArrayList<Integer> listN = new ArrayList<Integer>();
listN.add(n);
while (n > 1) {
if (n % 2 == 0) {
n = n / 2;
} else {
n = 3 * n + 1;
}
listN.add(n);
}
return listN;
}
}
class ExampleNProblem {
Utils2 u = new Utils2();
void testNProblem(Tester t) {
ArrayList<Integer> n10List = new ArrayList<Integer>(Arrays.asList(
10, 5, 16, 8, 4, 2, 1));
t.checkExpect(u.getsToOne(10), true);
t.checkExpect(u.getsToOne_detail(10), n10List);
}
}

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>Lect25_Iterators</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,182 @@
import java.util.Iterator;
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 boolean isNode();
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;
}
boolean isNode() {
return false;
}
T getData() {
throw new RuntimeException("Sentinels do not contain 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);
}
}
boolean isNode() {
return true;
}
T getData() {
return this.data;
}
}
class Deque<T> implements Iterable<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();
}
public Iterator<T> iterator() {
// Choose a forward iteration by default
return new DequeForwardIterator<T>(this);
}
// But...also provide a reverse iterator if needed
Iterator<T> reverseIterator() {
return new DequeReverseIterator<T>(this);
}
}

View File

@ -0,0 +1,220 @@
interface IComparator<T> {
public int compare(T t1, T t2);
}
class StringByAlpha implements IComparator<String> {
public int compare(String str1, String str2) {
return str1.compareTo(str2);
}
}
abstract class IBinaryTree<T> {
public T getData() {
throw new RuntimeException("No data item in an empty tree");
}
public IBinaryTree<T> getLeft() {
return this;
}
public IBinaryTree<T> getRight() {
return this;
}
public IBinaryTree<T> order(IComparator<T> comp) {
return this;
}
public IBinaryTree<T> insert(T t, IComparator<T> comp) {
return new BSTNode<T>(t, new Leaf<T>(), new Leaf<T>());
}
public boolean present(T t, IComparator<T> comp) {
return false;
}
public T getLeftMost(IComparator<T> comp) {
throw new RuntimeException("No leftmost item of an empty tree");
}
public T getRightMost(IComparator<T> comp) {
throw new RuntimeException("No rightmost item of an empty tree");
}
public T getLeftMostHelper(T rsf, IComparator<T> comp) {
return rsf;
}
public T getRighttMostHelper(T rsf, IComparator<T> comp) {
return rsf;
}
public IBinaryTree<T> removeLeftMost(IComparator<T> comp) {
throw new RuntimeException("No left item of an empty tree");
}
public IBinaryTree<T> removeRightMost(IComparator<T> comp) {
throw new RuntimeException("No right item of an empty tree");
}
public IBinaryTree<T> removeLeftMostHelper(T t, IComparator<T> comp) {
return this;
}
public IBinaryTree<T> removeRightMostHelper(T t, IComparator<T> comp) {
return this;
}
public boolean sameTree(IBinaryTree<T> that, IComparator<T> comp) {
return that.sameLeaf();
}
public boolean sameNode(T t, IBinaryTree<T> that, IComparator<T> comp) {
return false;
}
public boolean sameLeaf() {
return false;
}
public boolean sameData(IBinaryTree<T> that, IComparator<T> thisComp, IComparator<T> thatComp) {
return that.sameLeaf();
}
public boolean sameDataHelper(IBinaryTree<T> that, IComparator<T> comp) {
return true;
}
public IList<T> buildList(IComparator<T> comp) {
return new MtList<T>();
}
abstract boolean isNode();
abstract BSTNode<T> getNode();
}
class Leaf<T> extends IBinaryTree<T> {
Leaf() {}
@Override
public boolean sameLeaf() {
return true;
}
public boolean isNode() {
return false;
}
public BSTNode<T> getNode() {
throw new RuntimeException("Cannot return node of leaf");
}
}
class BSTNode<T> extends IBinaryTree<T> {
T data;
IBinaryTree<T> left;
IBinaryTree<T> right;
BSTNode(T data, IBinaryTree<T> left, IBinaryTree<T> right) {
this.data = data;
this.left = left;
this.right = right;
}
@Override
public IBinaryTree<T> getLeft() {
return this.left;
}
@Override
public IBinaryTree<T> getRight() {
return this.right;
}
@Override
public T getData() {
return this.data;
}
@Override
public IBinaryTree<T> insert(T t, IComparator<T> comp) {
if (comp.compare(this.data, t) > 0) {
return new BSTNode<T>(this.data, this.left.insert(t, comp), this.right);
} else {
return new BSTNode<T>(this.data, this.left, this.right.insert(t, comp));
}
}
@Override
public boolean present(T t, IComparator<T> comp) {
int r = comp.compare(this.data, t);
if (r == 0) {
return true;
} else if (r > 0) {
return this.left.present(t, comp);
} else {
return this.right.present(t, comp);
}
}
@Override
public T getLeftMost(IComparator<T> comp) {
return this.left.getLeftMostHelper(this.data, comp);
}
@Override
public T getRightMost(IComparator<T> comp) {
return this.right.getRighttMostHelper(this.data, comp);
}
@Override
public T getLeftMostHelper(T rsf, IComparator<T> comp) {
return this.left.getLeftMostHelper(this.data, comp);
}
@Override
public T getRighttMostHelper(T rsf, IComparator<T> comp) {
return this.right.getRighttMostHelper(this.data, comp);
}
@Override
public IBinaryTree<T> removeRightMost(IComparator<T> comp) {
T rightMost = this.getRightMost(comp);
if (comp.compare(this.data, rightMost) == 0) {
return this.left;
} else {
return new BSTNode<T>(this.data,
this.left,
this.right.removeRightMostHelper(rightMost, comp));
}
}
@Override
public IBinaryTree<T> removeLeftMost(IComparator<T> comp) {
T leftMost = this.getLeftMost(comp);
if (comp.compare(this.data, leftMost) == 0) {
return this.right;
} else {
return new BSTNode<T>(this.data,
this.left.removeLeftMostHelper(leftMost, comp),
this.right);
}
}
@Override
public IBinaryTree<T> removeRightMostHelper(T t, IComparator<T> comp) {
if (comp.compare(this.data, t) == 0) {
return this.left;
} else {
return new BSTNode<T>(this.data,
this.left,
this.right.removeRightMostHelper(t, comp));
}
}
@Override
public IBinaryTree<T> removeLeftMostHelper(T t, IComparator<T> comp) {
if (comp.compare(this.data, t) == 0) {
return this.right;
} else {
return new BSTNode<T>(this.data,
this.left.removeLeftMostHelper(t, comp),
this.right);
}
}
@Override
public boolean sameTree(IBinaryTree<T> that, IComparator<T> comp) {
return that.sameNode(this.data, this, comp);
}
@Override
public boolean sameNode(T t, IBinaryTree<T> that, IComparator<T> comp) {
return comp.compare(this.data, t) == 0 &&
this.left.sameTree(that.getLeft(), comp) &&
this.right.sameTree(that.getRight(), comp);
}
@Override
public boolean sameData(IBinaryTree<T> that, IComparator<T> thisComp, IComparator<T> thatComp) {
return this.sameDataHelper(that, thatComp) &&
that.sameDataHelper(this, thisComp);
}
@Override
public boolean sameDataHelper(IBinaryTree<T> that, IComparator<T> comp) {
return that.present(this.getData(), comp) &&
this.left.sameDataHelper(that, comp) &&
this.right.sameDataHelper(that, comp);
}
public IList<T> buildList(IComparator<T> comp) {
return new ConsList<T>(this.getLeftMost(comp),
this.removeLeftMost(comp).buildList(comp));
}
public boolean isNode() {
return true;
}
public BSTNode<T> getNode() {
return this;
}
}

View File

@ -0,0 +1,51 @@
import java.util.Iterator;
interface IList<T> extends Iterable<T> {
<U> IList<U> map(IFunc<T, U> func);
<U> U foldr(IFunc2<T, U, U> func, U base);
boolean isCons();
ConsList<T> asCons();
}
class MtList<T> implements IList<T> {
public <U> IList<U> map(IFunc<T, U> f) {
return new MtList<U>();
}
public <U> U foldr(IFunc2<T, U, U> func, U base) {
return base;
}
public boolean isCons() {
return false;
}
public ConsList<T> asCons() {
throw new RuntimeException("Cannot return Cons of Empty List");
}
public Iterator<T> iterator() {
return new IListIterator<T>(this);
}
}
class ConsList<T> implements IList<T> {
T first;
IList<T> rest;
ConsList(T first, IList<T> rest) {
this.first = first;
this.rest = rest;
}
public <U> IList<U> map(IFunc<T, U> func) {
return new ConsList<U>(func.apply(this.first), this.rest.map(func));
}
public <U> U foldr(IFunc2<T, U, U> func, U base) {
return func.apply(this.first,
this.rest.foldr(func, base));
}
public boolean isCons() {
return true;
}
public ConsList<T> asCons() {
return this;
}
public Iterator<T> iterator() {
return new IListIterator<T>(this);
}
}

View File

@ -0,0 +1,409 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import tester.Tester;
//// Represents the ability to produce a sequence of values
//// of type T, one at a time
//interface Iterator<T> {
// // Does this sequence have at least one more value?
// boolean hasNext();
// // Get the next value in this sequence
// // EFFECT: Advance the iterator to the subsequent value
// T next();
// // EFFECT: Remove the item just returned by next()
// // NOTE: This method may not be supported by every iterator; ignore it for now
// void remove();
//}
//Represents anything that can be iterated over
interface Iterable<T> {
// Returns an iterator over this collection
Iterator<T> iterator();
}
class ArrayListIterator<T> implements Iterator<T> {
// the list of items that this iterator iterates over
ArrayList<T> items;
// the index of the next item to be returned
int nextIdx;
// Construct an iterator for a given ArrayList
ArrayListIterator(ArrayList<T> items) {
this.items = items;
this.nextIdx = 0;
}
//Does this sequence (of items in the array list) have at least one more value?
public boolean hasNext() {
return this.nextIdx < this.items.size();
}
//Get the next value in this sequence
//EFFECT: Advance the iterator to the subsequent value
public T next() {
T answer = this.items.get(this.nextIdx);
this.nextIdx++;
return answer;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class IListIterator<T> implements Iterator<T> {
IList<T> items;
IListIterator(IList<T> items) {
this.items = items;
}
public boolean hasNext() {
return this.items.isCons();
}
public T next() {
ConsList<T> itemsAsCons = this.items.asCons();
T answer = itemsAsCons.first;
this.items = itemsAsCons.rest;
return answer;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class DequeForwardIterator<T> implements Iterator<T> {
ANode<T> currentNode;
DequeForwardIterator(Deque<T> deque) {
this.currentNode = deque.header;
}
public boolean hasNext() {
return this.currentNode.next.isNode();
}
public T next() {
T result = this.currentNode.next.getData();
this.currentNode = this.currentNode.next;
return result;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class DequeReverseIterator<T> implements Iterator<T> {
ANode<T> currentNode;
DequeReverseIterator(Deque<T> deque) {
this.currentNode = deque.header;
}
public boolean hasNext() {
return this.currentNode.prev.isNode();
}
public T next() {
T result = this.currentNode.prev.getData();
this.currentNode = this.currentNode.prev;
return result;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class FibonacciIterator implements Iterator<Integer> {
int prevVal = 0;
int curVal = 1;
// There are always more Fibonacci numbers
public boolean hasNext() {
return true;
}
// Compute the next Fibonacci number
public Integer next() {
int answer = this.prevVal + this.curVal;
this.prevVal = this.curVal;
this.curVal = answer;
return answer;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class EveryOtherIter<T> implements Iterator<T> {
Iterator<T> source;
EveryOtherIter(Iterator<T> source) {
this.source = source;
}
public boolean hasNext() {
// this sequence has a next item if the source does
return this.source.hasNext();
}
public T next() {
T answer = this.source.next(); // gets the answer, and advances the source
// We need to have the source "skip" the next value
if (this.source.hasNext()) {
this.source.next(); // get the next value and ignore it
}
return answer;
}
public void remove() {
// We can remove an item if our source can remove the item
this.source.remove(); // so just delegate to the source
}
}
class TakeN<T> implements Iterator<T> {
Iterator<T> source;
int howMany;
int countSoFar;
TakeN(Iterator<T> source, int n) {
this.source = source;
this.howMany = n;
this.countSoFar = 0;
}
public boolean hasNext() {
return (countSoFar < howMany) && source.hasNext();
}
public T next() {
countSoFar = countSoFar + 1;
return source.next();
}
public void remove() {
// We can remove an item if our source can remove the item
this.source.remove(); // so just delegate to the source
}
}
class AlternateIter<T> implements Iterator<T> {
Iterator<T> iter1;
Iterator<T> iter2;
int currentIter;
AlternateIter(Iterator<T> iter1, Iterator<T> iter2) {
this.iter1 = iter1;
this.iter2 = iter2;
}
public boolean hasNext() {
// this sequence has a next item if the source does
if (currentIter % 2 == 0) {
return iter1.hasNext();
} else {
return iter2.hasNext();
}
}
public T next() {
// this sequence has a next item if the source does
if (currentIter % 2 == 0) {
currentIter++;
return iter1.next();
} else {
currentIter++;
return iter2.next();
}
}
public void remove() {
// We can remove an item if our source can remove the item
// this sequence has a next item if the source does
if (currentIter % 2 == 0) {
iter1.remove();
} else {
iter2.remove();
}
}
}
class BreadthFirstIterator<T> implements Iterator<T> {
Deque<IBinaryTree<T>> worklist;
BreadthFirstIterator(IBinaryTree<T> source) {
this.worklist = new Deque<IBinaryTree<T>>();
this.addIfNotLeaf(source);
}
// EFFECT: only adds the given binary-tree if it's not a leaf
void addIfNotLeaf(IBinaryTree<T> bt) {
if (bt.isNode()) {
this.worklist.addAtTail(new Node<IBinaryTree<T>>(bt));
}
}
public boolean hasNext() {
// we have a next item if the worklist isn't empty
return this.worklist.size() > 0;
}
public T next() {
// Get (and remove) the first item on the worklist --
// and we know it must be a BTNode
BSTNode<T> node = this.worklist.removeFromHead().getData().getNode();
// Add the children of the node to the tail of the list
this.addIfNotLeaf(node.left);
this.addIfNotLeaf(node.right);
// return the answer
return node.data;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class PreOrderIterator<T> implements Iterator<T> {
Deque<IBinaryTree<T>> worklist;
PreOrderIterator(IBinaryTree<T> source) {
this.worklist = new Deque<IBinaryTree<T>>();
this.addIfNotLeaf(source);
}
// EFFECT: only adds the given binary-tree if it's not a leaf
void addIfNotLeaf(IBinaryTree<T> bt) {
if (bt.isNode()) {
this.worklist.addAtHead(new Node<IBinaryTree<T>>(bt));
}
}
public boolean hasNext() {
// we have a next item if the worklist isn't empty
return this.worklist.size() > 0;
}
public T next() {
// Get (and remove) the first item on the worklist,
// but we must convert to correct data type --
// and we know it must be a BTNode
BSTNode<T> node = this.worklist.removeFromHead().getData().getNode();
// Add the children of the node to the head of the list
this.addIfNotLeaf(node.right);
this.addIfNotLeaf(node.left);
// return the answer
return node.data;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class PostOrderIterator<T> implements Iterator<T> {
Deque<IBinaryTree<T>> worklist;
PostOrderIterator(IBinaryTree<T> source) {
this.worklist = new Deque<IBinaryTree<T>>();
this.addAllNodes(source);
}
// EFFECT: recursively adds all nodes in tree
void addAllNodes(IBinaryTree<T> bt) {
if (bt.isNode()) {
this.worklist.addAtHead(new Node<IBinaryTree<T>>(bt));
this.addAllNodes(bt.getRight());
this.addAllNodes(bt.getLeft());
}
}
public boolean hasNext() {
// we have a next item if the worklist isn't empty
return this.worklist.size() > 0;
}
// d
// b f
// a c e g
// acbefgd
public T next() {
// Get (and remove) the first item on the worklist,
// but we must convert to correct data type --
// and we know it must be a BTNode
BSTNode<T> node = this.worklist.removeFromHead().getData().getNode();
// return the answer
return node.data;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class InOrderIterator<T> implements Iterator<T> {
Deque<IBinaryTree<T>> worklist;
InOrderIterator(IBinaryTree<T> source) {
this.worklist = new Deque<IBinaryTree<T>>();
this.addAllNodes(source);
}
// EFFECT: recursively adds all nodes in tree
void addAllNodes(IBinaryTree<T> bt) {
if (bt.isNode()) {
this.addAllNodes(bt.getRight());
this.worklist.addAtHead(new Node<IBinaryTree<T>>(bt));
this.addAllNodes(bt.getLeft());
}
}
public boolean hasNext() {
// we have a next item if the worklist isn't empty
return this.worklist.size() > 0;
}
// d
// b f
// a c e g
// abcdefg
public T next() {
// Get (and remove) the first item on the worklist,
// but we must convert to correct data type --
// and we know it must be a BTNode
BSTNode<T> node = this.worklist.removeFromHead().getData().getNode();
// return the answer
return node.data;
}
public void remove() {
throw new UnsupportedOperationException("Don't do this!");
}
}
class Examples {
ArrayList<String> strArray;
IList<String> strList;
Deque<String> deq;
IBinaryTree<String> bst;
IComparator<String> comp;
// simple testing functions
String concate(Iterator<String> iter) {
String result = "";
while (iter.hasNext()) {
result = result + iter.next();
}
return result;
}
String intConcate(Iterator<Integer> iter) {
String result = "";
while (iter.hasNext()) {
result = result + iter.next();
}
return result;
}
void init() {
strArray = new ArrayList<String>(Arrays.asList(
"a", "b", "c"));
strList = new ConsList<String>("a",
new ConsList<String>("b", new ConsList<String>("c",
new MtList<String>())));
deq = new Deque<String>();
deq.addAtTail(new Node<String>("a"));
deq.addAtTail(new Node<String>("b"));
deq.addAtTail(new Node<String>("c"));
deq.addAtTail(new Node<String>("d"));
deq.addAtTail(new Node<String>("e"));
// d
// b f
// a c e g
comp = new StringByAlpha();
bst = new BSTNode<String>("d", new Leaf<String>(), new Leaf<String>());
bst = bst.insert("b", comp);
bst = bst.insert("f", comp);
bst = bst.insert("a", comp);
bst = bst.insert("c", comp);
bst = bst.insert("e", comp);
bst = bst.insert("g", comp);
}
void testNext(Tester t) {
init();
t.checkExpect(this.concate(new ArrayListIterator<String>(strArray)), "abc");
t.checkExpect(this.concate(new IListIterator<String>(strList)), "abc");
t.checkExpect(this.concate(new DequeForwardIterator<String>(deq)), "abcde");
t.checkExpect(this.concate(new DequeReverseIterator<String>(deq)), "edcba");
t.checkExpect(this.concate(new EveryOtherIter<String>(
new DequeForwardIterator<String>(deq))), "ace");
t.checkExpect(this.intConcate(new TakeN<Integer>(new FibonacciIterator(), 5)), "12358");
t.checkExpect(this.concate(new AlternateIter<String>(
new ArrayListIterator<String>(strArray), new IListIterator<String>(strList))),
"aabbcc");
t.checkExpect(this.concate(new BreadthFirstIterator<String>(bst)), "dbfaceg");
t.checkExpect(this.concate(new PreOrderIterator<String>(bst)), "dbacfeg");
t.checkExpect(this.concate(new PostOrderIterator<String>(bst)), "acbegfd");
t.checkExpect(this.concate(new InOrderIterator<String>(bst)), "abcdefg");
}
}

View File

@ -0,0 +1,11 @@
interface IPred<T> {
boolean apply(T t);
}
interface IFunc<A, R> {
R apply(A arg);
}
interface IFunc2<A1, A2, R> {
R apply(A1 arg1, A2 arg2);
}