mirror of
https://github.com/ossu/computer-science.git
synced 2026-04-11 14:21:57 +08:00
loops and iter lectures
This commit is contained in:
parent
f9e9b11866
commit
44babaab79
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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")));
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user