feat: add PE2

This commit is contained in:
Yadunand Prem 2022-11-08 18:00:55 +08:00
parent 44c87f3500
commit 1b99ba182d
20 changed files with 1027 additions and 1 deletions

4
.gitignore vendored
View File

@ -6,4 +6,6 @@ checkstyle.jar
cs2030_checks.xml
*.swp
Lab6/docs
Lab6/docs
.vscode/

View File

@ -0,0 +1,171 @@
import java.net.URI;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.tools.DiagnosticCollector;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
/**
* A helper class to test CS2030S labs.
*/
class CS2030STest {
private static final String ANSI_RESET = "\u001B[0m";
private static final String ANSI_RED = "\u001B[31m";
private static final String ANSI_GREEN = "\u001B[32m";
private void ok() {
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
}
private void fail() {
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
}
/**
* Test if two objects are equals.
*
* @param test A description of the test.
* @param output The output from an expression.
* @param expect The expected output from that expression.
* @return this object.
*/
public CS2030STest expect(String test, Object output, Object expect) {
System.out.print(test);
if ((expect == null && output == null) || output.equals(expect)) {
ok();
} else {
fail();
System.out.println(" expected: " + expect);
System.out.println(" got this: " + output);
}
return this;
}
/**
* Test if a given supplier produces a given object.
*
* @param <T> The type of object the given task will produce.
* @param test A description of the test.
* @param task The task to run.
* @param expect The expected output from that expression.
* @return this object.
*/
public <T> CS2030STest expect(String test, Supplier<T> task, Object expect) {
System.out.print(test);
try {
T output = CompletableFuture.supplyAsync(() -> {
try {
return task.get();
} catch (Throwable e) {
// shouldn't reach here
fail();
System.out.println(" with exception: " + e.getMessage());
e.printStackTrace();
return null;
}
}
).get(1, TimeUnit.SECONDS);
if ((expect == null && output == null) || output.equals(expect)) {
ok();
} else {
fail();
System.out.println(" expected: " + expect);
System.out.println(" got this: " + output);
}
} catch (Throwable e) {
fail();
System.out.println(" with exception: " + e.getMessage());
e.printStackTrace();
}
return this;
}
/**
* Test if a given producer returns a value. Wrapper around expect(..)
* to simplify caller.
*
* @param <T> The type of object the given task will produce.
* @param test A description of the test.
* @param task The task to run.
* @param expect The expected output from that expression.
* @return this object.
*/
public <T> CS2030STest expectReturn(String test, Supplier<T> task, Object expect) {
return this.expect(test + " returns " + expect, task, expect);
}
/**
* Test if an expression throws an exception.
*
* @param test A description of the test.
* @param task A lambda expression of the expression.
* @param expectedE A exception instance of the same type as the expected one.
* @return this object.
*/
public CS2030STest expectException(String test, Runnable task, Exception expectedE) {
System.out.print(test + " throws " + expectedE.getClass().getSimpleName());
boolean gotException = false;
try {
task.run();
} catch (Throwable e) {
if (e.getClass().equals(expectedE.getClass())) {
gotException = true;
}
}
if (gotException) {
ok();
} else {
fail();
System.out.println(" did not catch expected exception " + expectedE.getClass());
}
return this;
}
/**
* Test if an expression compiles with/without error.
*
* @param test A description of the test.
* @param statement The java statement to compile
* @param success Whether the statement is expected to compile or not
* (true if yes; false otherwise)
* @return this object.
*/
public CS2030STest expectCompile(String test, String statement, boolean success) {
System.out.print(test);
class Code extends SimpleJavaFileObject {
final String code;
Code(String code) {
super(URI.create("string:///TestCompile.java"), Kind.SOURCE);
this.code = "class TestCompile {void test(){\n " + code + ";\n}}";
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
boolean noError = ToolProvider
.getSystemJavaCompiler()
.getTask(null, null, new DiagnosticCollector<>(), null, null,
List.of(new Code(statement)))
.call();
if (noError != success) {
fail();
if (!success) {
System.out.println(" expected compilation error but it compiles fine.");
} else {
System.out.println(" expected the statement to compile without errors but it does not.");
}
} else {
ok();
}
return this;
}
}

View File

@ -0,0 +1,11 @@
import cs2030s.fp.Saveable;
import cs2030s.fp.Immutator;
import java.util.stream.Stream;
import java.util.List;
class MyTest {
public static void main(String[] args){
Immutator<Saveable<Integer>, Object> hash = o -> Saveable.<Integer>of(o.hashCode() + 10);
Saveable.<Number>of(4).flatMap2(hash);
}
}

View File

@ -0,0 +1,43 @@
/**
* CS2030S PE2
* AY2022/23 Semester 2.
*
* @author A0253252M
**/
class Pair<T,S> {
private T fst;
private S snd;
public Pair(T fst, S snd) {
this.fst = fst;
this.snd = snd;
}
public T getFst() {
return this.fst;
}
public S getSnd() {
return this.snd;
}
public void setFst(T fst) {
this.fst = fst;
}
public void setSnd(S snd) {
this.snd = snd;
}
@Override
public String toString() {
return "(" + this.fst + ", " + this.snd + ")";
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if(!(obj instanceof Pair<?,?>)) {
return false;
}
Pair<?,?> pr = (Pair<?,?>) obj;
return this.fst.equals(pr.fst) &&
this.snd.equals(pr.snd);
}
}

View File

@ -0,0 +1,43 @@
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* CS2030S PE2
* AY2022/23 Semester 1.
*
* @author A0253252M
**/
public class Streaming {
public static Stream<Integer> evenTriangular(int n) {
return Stream.iterate(1, i -> i + 1)
.map(i -> i * (i + 1) / 2)
.filter(i -> i % 2 == 0)
.limit(n);
}
// return a list of positive divisors for n
// go down from n,
public static boolean isPerfect(int n) {
return Stream.iterate(n - 1, i -> i - 1)
.takeWhile(i -> i > 0)
.filter(i -> n % i == 0)
.reduce(0, (x, y) -> x + y) == n;
}
public static List<Integer> allPerfect(int start, int end) {
return Stream.iterate(start, i -> i + 1)
.takeWhile(i -> i <= end)
.filter(i -> isPerfect(i))
.collect(Collectors.toList());
}
public static <T> List<T> decode(Stream<Pair<Integer, T>> stream) {
return stream.flatMap(p ->
Stream.generate(() -> p.getSnd()).limit(p.getFst())
)
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,100 @@
import cs2030s.fp.Saveable;
import java.util.NoSuchElementException;
class Test1 {
public static void main(String[] args) {
CS2030STest i = new CS2030STest();
i.expectCompile("Saveable<String> u = Saveable.of(\"PE2\") compiles",
"cs2030s.fp.Saveable<String> u = cs2030s.fp.Saveable.of(\"PE2\")",
true);
i.expectReturn("Saveable.of(\"PE2\").toString()",
() -> Saveable.of("PE2").toString(),
"Saveable[PE2]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\");",
() -> Saveable.of("PE2").map(x -> x + "!").toString(),
"Saveable[PE2!]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").map(x -> x + \"?\");",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").toString(),
"Saveable[PE2!?]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").undo()",
() -> Saveable.of("PE2").map(x -> x + "!").undo().toString(),
"Saveable[PE2]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").undo().map(x -> x + \"?\")",
() -> Saveable.of("PE2").map(x -> x + "!").undo().map(x -> x + "?").toString(),
"Saveable[PE2?]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").undo().map(x -> x + \"?\").undo()",
() -> Saveable.of("PE2").map(x -> x + "!").undo().map(x -> x + "?").undo().toString(),
"Saveable[PE2]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").map(x -> x + \"?\").undo()",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").undo().toString(),
"Saveable[PE2!]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").map(x -> x + \"?\").undo().undo()",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").undo().undo().toString(),
"Saveable[PE2]");
i.expectException("Saveable.of(\"PE2\").map(x -> x + \"!\").map(x -> x + \"?\")" +
".undo().undo().undo()",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").undo().undo().undo(),
new NoSuchElementException());
i.expectException("Saveable.of(\"PE2\").undo()",
() -> Saveable.of("PE2").undo(),
new NoSuchElementException());
// with redo
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").undo()",
() -> Saveable.of("PE2").map(x -> x + "!").undo().toString(),
"Saveable[PE2]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").undo().redo()",
() -> Saveable.of("PE2").map(x -> x + "!").undo().redo().toString(),
"Saveable[PE2!]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").undo().redo().map(x -> x + \"?\")",
() -> Saveable.of("PE2").map(x -> x + "!").undo().redo().map(x -> x + "?").toString(),
"Saveable[PE2!?]");
i.expectException("Saveable.of(\"PE2\").map(x -> x + \"!\").undo().map(x -> x + \"?\")" +
".redo()",
() -> Saveable.of("PE2").map(x -> x + "!").undo().map(x -> x + "?").redo(),
new NoSuchElementException());
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").map(x -> x + \"?\").undo().redo()",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").undo().redo().toString(),
"Saveable[PE2!?]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").undo().map(x -> x + \"?\").undo().redo()",
() -> Saveable.of("PE2").map(x -> x + "!").undo().map(x -> x + "?").undo().redo().toString(),
"Saveable[PE2?]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").map(x -> x + \"?\")" +
".undo().undo().redo()",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").undo().undo().redo()
.toString(),
"Saveable[PE2!]");
i.expectReturn("Saveable.of(\"PE2\").map(x -> x + \"!\").map(x -> x + \"?\")" +
".undo().undo().redo().redo()",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").undo().undo().redo().redo()
.toString(),
"Saveable[PE2!?]");
i.expectException("Saveable.of(\"PE2\").map(x -> x + \"!\").undo().redo().redo()",
() -> Saveable.of("PE2").map(x -> x + "!").map(x -> x + "?").undo().redo().redo(),
new NoSuchElementException());
i.expectCompile("Saveable<Number> x = Saveable.<Number>of(4).map(hash); compiles",
"cs2030s.fp.Immutator<Integer,Object> hash = o -> o.hashCode();\n" +
"cs2030s.fp.Saveable<Number> x = cs2030s.fp.Saveable.<Number>of(4).map(hash);",
true);
}
}

View File

@ -0,0 +1,27 @@
import cs2030s.fp.Immutator
import cs2030s.fp.Saveable
Saveable<String> u = Saveable.of("PE2")
u.map(x -> x + "!")
u.map(x -> x + "!").map(x -> x + "?")
u.map(x -> x + "!").undo()
u.map(x -> x + "!").undo().map(x -> x + "?")
u.map(x -> x + "!").map(x -> x + "?").undo()
u.map(x -> x + "!").undo().map(x -> x + "?").undo()
u.map(x -> x + "!").map(x -> x + "?").undo().undo()
u.map(x -> x + "!").map(x -> x + "?").undo().undo().undo()
u.undo()
u.map(x -> x + "!").undo()
u.map(x -> x + "!").undo().redo()
u.map(x -> x + "!").undo().redo().map(x -> x + "?")
u.map(x -> x + "!").undo().map(x -> x + "?").redo()
u.map(x -> x + "!").map(x -> x + "?").undo().redo()
u.map(x -> x + "!").undo().map(x -> x + "?").undo().redo()
u.map(x -> x + "!").map(x -> x + "?").undo().undo().redo()
u.map(x -> x + "!").map(x -> x + "?").undo().undo().redo().redo()
u.map(x -> x + "!").undo().redo().redo()
Immutator<Integer,Object> hash = o -> o.hashCode();
Saveable<Number> x = Saveable.<Number>of(4).map(hash); // should compile

View File

@ -0,0 +1,36 @@
import cs2030s.fp.Saveable;
class Test2 {
public static void main(String[] args) {
CS2030STest i = new CS2030STest();
i.expectReturn("Saveable.of(10).equals(Saveable.of(10))",
() -> Saveable.of(10).equals(Saveable.of(10)),
true);
i.expectReturn("Saveable.of(10).map(x -> x + 4).equals(Saveable.of(14))",
() -> Saveable.of(10).map(x -> x + 4).equals(Saveable.of(14)),
true);
i.expectReturn("Saveable.of(10).map(x -> x + 4).equals(Saveable.of(10).map(x -> x + 4))",
() -> Saveable.of(10).map(x -> x + 4).equals(Saveable.of(10).map(x -> x + 4)),
true);
i.expectReturn("Saveable.of(10).map(x -> x + 4).undo().equals(Saveable.of(14))",
() -> Saveable.of(10).map(x -> x + 4).undo().equals(Saveable.of(14)),
false);
i.expectReturn("Saveable.of(10).map(x -> x + 4).undo().equals(Saveable.of(10).map(x -> x + 4)" +
".undo())",
() -> Saveable.of(10).map(x -> x + 4).undo().equals(Saveable.of(10).map(x -> x + 4).undo()),
true);
i.expectReturn("Saveable.of(10).map(x -> x + 4).undo().redo().equals(Saveable.of(10)" +
".map(x -> x + 4))",
() -> Saveable.of(10).map(x -> x + 4).undo().redo().equals(Saveable.of(10).map(x -> x + 4)),
true);
i.expectReturn("Saveable.of(10).map(x -> x + 4).map(x -> x).equals(Saveable.of(4)" +
".map(x -> x + 10)",
() -> Saveable.of(10).map(x -> x + 4).equals(Saveable.of(4).map(x -> x + 10)),
true);
i.expectReturn("Saveable.of(\"hi\").equals(Saveable.of(new String(\"hi\")))",
() -> Saveable.of("hi").equals(Saveable.of(new String("hi"))),
true);
}
}

View File

@ -0,0 +1,11 @@
import cs2030s.fp.Saveable
Saveable<Integer> u = Saveable.of(10)
u.equals(u)
u.map(x -> x + 4).equals(u.map(x -> x + 4))
u.map(x -> x + 4).undo().equals(Saveable.of(14))
u.map(x -> x + 4).undo().equals(u.map(x -> x + 4).undo())
u.map(x -> x + 4).undo().redo().equals(u.map(x -> x + 4))
u.map(x -> x + 4).equals(Saveable.of(4).map(x -> x + 10))
Saveable.of("hi").equals(Saveable.of(new String("hi")));

View File

@ -0,0 +1,84 @@
import cs2030s.fp.Immutator;
import cs2030s.fp.Saveable;
import java.util.NoSuchElementException;
class Test3 {
public static void main(String[] args) {
CS2030STest i = new CS2030STest();
System.out.println("Immutator<Saveable<Integer>, Integer> f = " +
"x -> Saveable.of(x).map(y -> y + 1).map(y -> y + 10);");
Immutator<Saveable<Integer>, Integer> f =
x -> Saveable.of(x).map(y -> y + 1).map(y -> y + 10);
i.expectReturn("Saveable.of(0).flatMap1(f)",
() -> Saveable.of(0).flatMap1(f).toString(),
"Saveable[11]");
i.expectReturn("Saveable.of(0).flatMap1(f).flatMap1(f)",
() -> Saveable.of(0).flatMap1(f).flatMap1(f).toString(),
"Saveable[22]");
i.expectReturn("Saveable.of(0).flatMap1(f).undo()",
() -> Saveable.of(0).flatMap1(f).undo().toString(),
"Saveable[1]");
i.expectReturn("Saveable.of(0).flatMap1(f).undo().undo()",
() -> Saveable.of(0).flatMap1(f).undo().undo().toString(),
"Saveable[0]");
i.expectReturn("Saveable.of(0).flatMap1(f).flatMap1(f).undo()",
() -> Saveable.of(0).flatMap1(f).flatMap1(f).undo().toString(),
"Saveable[12]");
i.expectReturn("Saveable.of(0).flatMap1(f).flatMap1(f).undo().undo()",
() -> Saveable.of(0).flatMap1(f).flatMap1(f).undo().undo().toString(),
"Saveable[11]");
i.expectException("Saveable.of(0).flatMap1(f).flatMap1(f).undo().undo().undo()",
() -> Saveable.of(0).flatMap1(f).flatMap1(f).undo().undo().undo().toString(),
new NoSuchElementException());
i.expectReturn("Saveable.of(0).flatMap2(f)",
() -> Saveable.of(0).flatMap2(f).toString(),
"Saveable[11]");
i.expectReturn("Saveable.of(0).flatMap2(f).flatMap2(f)",
() -> Saveable.of(0).flatMap2(f).flatMap2(f).toString(),
"Saveable[22]");
i.expectReturn("Saveable.of(0).flatMap2(f).undo()",
() -> Saveable.of(0).flatMap2(f).undo().toString(),
"Saveable[0]");
i.expectException("Saveable.of(0).flatMap2(f).undo().undo()",
() -> Saveable.of(0).flatMap2(f).undo().undo(),
new NoSuchElementException());
i.expectReturn("Saveable.of(0).flatMap2(f).flatMap2(f).undo()",
() -> Saveable.of(0).flatMap2(f).flatMap2(f).undo().toString(),
"Saveable[11]");
i.expectReturn("Saveable.of(0).flatMap2(f).flatMap2(f).undo().undo()",
() -> Saveable.of(0).flatMap2(f).flatMap2(f).undo().undo().toString(),
"Saveable[0]");
i.expectException("Saveable.of(0).flatMap2(f).flatMap2(f).undo().undo().undo()",
() -> Saveable.of(0).flatMap2(f).flatMap2(f).undo().undo().undo().toString(),
new NoSuchElementException());
System.out.println("Immutator<Saveable<Integer>, Object> hash = " +
"o -> Saveable.<Integer>of(o.hashCode() + 10);");
Immutator<Saveable<Integer>, Object> hash = o -> Saveable.<Integer>of(o.hashCode() + 10);
i.expectCompile("Saveable.<Number>of(4).flatMap1(hash);",
"cs2030s.fp.Immutator<cs2030s.fp.Saveable<Integer>, Object> hash = " +
"o -> cs2030s.fp.Saveable.<Integer>of(o.hashCode() + 10);\n" +
"cs2030s.fp.Saveable.<Number>of(4).flatMap1(hash);",
true);
i.expectCompile("Saveable.<Number>of(4).flatMap2(hash);",
"cs2030s.fp.Immutator<cs2030s.fp.Saveable<Integer>, Object> hash = " +
"o -> cs2030s.fp.Saveable.<Integer>of(o.hashCode() + 10);\n" +
"cs2030s.fp.Saveable.<Number>of(4).flatMap2(hash);",
true);
}
}

View File

@ -0,0 +1,26 @@
import cs2030s.fp.Immutator;
import cs2030s.fp.Saveable;
Immutator<Saveable<Integer>, Integer> f = x -> Saveable.of(x).map(y -> y + 1).map(y -> y + 10);
Saveable<Integer> zero = Saveable.of(0)
zero.flatMap1(f)
zero.flatMap1(f).flatMap1(f)
zero.flatMap1(f).undo()
zero.flatMap1(f).undo().undo()
zero.flatMap1(f).flatMap1(f).undo()
zero.flatMap1(f).flatMap1(f).undo().undo()
zero.flatMap1(f).flatMap1(f).undo().undo().undo()
zero.flatMap2(f)
zero.flatMap2(f).flatMap2(f)
zero.flatMap2(f).undo()
zero.flatMap2(f).undo().undo()
zero.flatMap2(f).flatMap2(f).undo()
zero.flatMap2(f).flatMap2(f).undo().undo()
zero.flatMap2(f).flatMap2(f).undo().undo().undo()
Immutator<Saveable<Integer>, Object> hash = o -> Saveable.<Integer>of(o.hashCode() + 10);
Saveable.<Number>of(4).flatMap1(hash); // should compile
Saveable.<Number>of(4).flatMap2(hash); // should compile

View File

@ -0,0 +1,20 @@
import java.util.stream.Collectors;
import java.util.List;
class Test4 {
public static void main(String[] args) {
CS2030STest i = new CS2030STest();
i.expectReturn("Streaming.evenTriangular(5).count()",
() -> Streaming.evenTriangular(5).count(),
5L);
i.expectReturn("Streaming.evenTriangular(5).collect(Collectors.toList())",
() -> Streaming.evenTriangular(5).collect(Collectors.toList()),
List.of(6,10,28,36,66));
i.expectReturn("Streaming.evenTriangular(10).collect(Collectors.toList())",
() -> Streaming.evenTriangular(10).collect(Collectors.toList()),
List.of(6,10,28,36,66,78,120,136,190,210));
}
}

View File

@ -0,0 +1,8 @@
/open Pair.java
/open Streaming.java
Streaming.evenTriangular(5).count();
Streaming.evenTriangular(5).forEach(System.out::println);
Streaming.evenTriangular(5).toArray();
Streaming.evenTriangular(10).forEach(System.out::println);
Streaming.evenTriangular(5).collect(Collectors.toList());

View File

@ -0,0 +1,56 @@
import java.util.stream.Collectors;
import java.util.List;
class Test5 {
public static void main(String[] args) {
CS2030STest i = new CS2030STest();
i.expectReturn("Streaming.isPerfect(4)",
() -> Streaming.isPerfect(4),
false);
i.expectReturn("Streaming.isPerfect(5)",
() -> Streaming.isPerfect(5),
false);
i.expectReturn("Streaming.isPerfect(6)",
() -> Streaming.isPerfect(6),
true);
i.expectReturn("Streaming.isPerfect(7)",
() -> Streaming.isPerfect(7),
false);
i.expectReturn("Streaming.isPerfect(8)",
() -> Streaming.isPerfect(8),
false);
i.expectReturn("Streaming.isPerfect(26)",
() -> Streaming.isPerfect(26),
false);
i.expectReturn("Streaming.isPerfect(27)",
() -> Streaming.isPerfect(27),
false);
i.expectReturn("Streaming.isPerfect(28)",
() -> Streaming.isPerfect(28),
true);
i.expectReturn("Streaming.isPerfect(29)",
() -> Streaming.isPerfect(29),
false);
i.expectReturn("Streaming.isPerfect(30)",
() -> Streaming.isPerfect(30),
false);
i.expectReturn("Streaming.allPerfect(1, 10)",
() -> Streaming.allPerfect(1, 10),
List.of(6));
i.expectReturn("Streaming.allPerfect(1, 100)",
() -> Streaming.allPerfect(1, 100),
List.of(6, 28));
}
}

View File

@ -0,0 +1,17 @@
/open Pair.java
/open Streaming.java
Streaming.isPerfect(4);
Streaming.isPerfect(5);
Streaming.isPerfect(6);
Streaming.isPerfect(7);
Streaming.isPerfect(8);
Streaming.isPerfect(26);
Streaming.isPerfect(27);
Streaming.isPerfect(28);
Streaming.isPerfect(29);
Streaming.isPerfect(30);
Streaming.allPerfect(1, 10);
Streaming.allPerfect(1, 100);

View File

@ -0,0 +1,52 @@
/open Pair.java
/open Streaming.java
List<Integer> intList1 = List.of(
1, 1, 1, 2, 2, 1, 1, 1, 1, 4, 3, 3
)
List<Integer> intList2 = List.of(
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
)
List<String> strList1 = List.of(
"A", "A", "A", "B", "B", "A",
"A", "A", "A", "R", "Z", "Z"
)
List<String> strList2 = List.of(
"A", "A", "A", "A", "A", "A",
"A", "A", "A", "A", "A", "A"
)
List<Pair<Integer,Integer>> pairLst1 = List.of(
new Pair<Integer, Integer>(3, 1),
new Pair<Integer, Integer>(2, 2),
new Pair<Integer, Integer>(4, 1),
new Pair<Integer, Integer>(1, 4),
new Pair<Integer, Integer>(2, 3)
)
List<Pair<Integer,Integer>> pairLst2 = List.of(
new Pair<Integer, Integer>(12, 1)
)
List<Pair<Integer,String>> pairLst3 = List.of(
new Pair<Integer, String>(3, "A"),
new Pair<Integer, String>(2, "B"),
new Pair<Integer, String>(4, "A"),
new Pair<Integer, String>(1, "R"),
new Pair<Integer, String>(2, "Z")
)
List<Pair<Integer,String>> pairLst4 = List.of(
new Pair<Integer, String>(12, "A")
)
Streaming.decode(pairLst1.stream())
Streaming.decode(pairLst2.stream())
Streaming.decode(pairLst3.stream())
Streaming.decode(pairLst4.stream())
Streaming.decode(pairLst1.stream()).equals(intList1)
Streaming.decode(pairLst2.stream()).equals(intList2)
Streaming.decode(pairLst3.stream()).equals(strList1)
Streaming.decode(pairLst4.stream()).equals(strList2)
Streaming.decode(pairLst1.stream()).equals(intList2)
Streaming.decode(pairLst2.stream()).equals(intList1)
Streaming.decode(pairLst3.stream()).equals(strList2)
Streaming.decode(pairLst4.stream()).equals(strList1)

View File

@ -0,0 +1,91 @@
import java.util.stream.Collectors;
import java.util.List;
class Test7 {
public static void main(String[] args) {
CS2030STest i = new CS2030STest();
List<Integer> intList1 = List.of(
1, 1, 1, 2, 2, 1, 1, 1, 1, 4, 3, 3
);
List<Integer> intList2 = List.of(
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
);
List<String> strList1 = List.of(
"A", "A", "A", "B", "B", "A",
"A", "A", "A", "R", "Z", "Z"
);
List<String> strList2 = List.of(
"A", "A", "A", "A", "A", "A",
"A", "A", "A", "A", "A", "A"
);
List<Pair<Integer,Integer>> pairLst1 = List.of(
new Pair<Integer, Integer>(3, 1),
new Pair<Integer, Integer>(2, 2),
new Pair<Integer, Integer>(4, 1),
new Pair<Integer, Integer>(1, 4),
new Pair<Integer, Integer>(2, 3)
);
List<Pair<Integer,Integer>> pairLst2 = List.of(
new Pair<Integer, Integer>(12, 1)
);
List<Pair<Integer,String>> pairLst3 = List.of(
new Pair<Integer, String>(3, "A"),
new Pair<Integer, String>(2, "B"),
new Pair<Integer, String>(4, "A"),
new Pair<Integer, String>(1, "R"),
new Pair<Integer, String>(2, "Z")
);
List<Pair<Integer,String>> pairLst4 = List.of(
new Pair<Integer, String>(12, "A")
);
i.expectReturn("Streaming.decode(pairLst1.stream().parallel())",
() -> Streaming.decode(pairLst1.stream().parallel()),
intList1);
i.expectReturn("Streaming.decode(pairLst2.stream().parallel())",
() -> Streaming.decode(pairLst2.stream().parallel()),
intList2);
i.expectReturn("Streaming.decode(pairLst3.stream().parallel())",
() -> Streaming.decode(pairLst3.stream().parallel()),
strList1);
i.expectReturn("Streaming.decode(pairLst4.stream().parallel())",
() -> Streaming.decode(pairLst4.stream().parallel()),
strList2);
i.expectReturn("Streaming.decode(pairLst1.stream().parallel()).equals(intList1)",
() -> Streaming.decode(pairLst1.stream().parallel()).equals(intList1),
true);
i.expectReturn("Streaming.decode(pairLst2.stream().parallel()).equals(intList2)",
() -> Streaming.decode(pairLst2.stream().parallel()).equals(intList2),
true);
i.expectReturn("Streaming.decode(pairLst3.stream().parallel()).equals(strList1)",
() -> Streaming.decode(pairLst3.stream().parallel()).equals(strList1),
true);
i.expectReturn("Streaming.decode(pairLst4.stream().parallel()).equals(strList2)",
() -> Streaming.decode(pairLst4.stream().parallel()).equals(strList2),
true);
i.expectReturn("Streaming.decode(pairLst1.stream().parallel()).equals(intList2)",
() -> Streaming.decode(pairLst1.stream().parallel()).equals(intList2),
false);
i.expectReturn("Streaming.decode(pairLst2.stream().parallel()).equals(intList1)",
() -> Streaming.decode(pairLst2.stream().parallel()).equals(intList1),
false);
i.expectReturn("Streaming.decode(pairLst3.stream().parallel()).equals(strList2)",
() -> Streaming.decode(pairLst3.stream().parallel()).equals(strList2),
false);
i.expectReturn("Streaming.decode(pairLst4.stream().parallel()).equals(strList1)",
() -> Streaming.decode(pairLst4.stream().parallel()).equals(strList1),
false);
}
}

View File

@ -0,0 +1,52 @@
/open Pair.java
/open Streaming.java
List<Integer> intList1 = List.of(
1, 1, 1, 2, 2, 1, 1, 1, 1, 4, 3, 3
)
List<Integer> intList2 = List.of(
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
)
List<String> strList1 = List.of(
"A", "A", "A", "B", "B", "A",
"A", "A", "A", "R", "Z", "Z"
)
List<String> strList2 = List.of(
"A", "A", "A", "A", "A", "A",
"A", "A", "A", "A", "A", "A"
)
List<Pair<Integer,Integer>> pairLst1 = List.of(
new Pair<Integer, Integer>(3, 1),
new Pair<Integer, Integer>(2, 2),
new Pair<Integer, Integer>(4, 1),
new Pair<Integer, Integer>(1, 4),
new Pair<Integer, Integer>(2, 3)
)
List<Pair<Integer,Integer>> pairLst2 = List.of(
new Pair<Integer, Integer>(12, 1)
)
List<Pair<Integer,String>> pairLst3 = List.of(
new Pair<Integer, String>(3, "A"),
new Pair<Integer, String>(2, "B"),
new Pair<Integer, String>(4, "A"),
new Pair<Integer, String>(1, "R"),
new Pair<Integer, String>(2, "Z")
)
List<Pair<Integer,String>> pairLst4 = List.of(
new Pair<Integer, String>(12, "A")
)
Streaming.decode(pairLst1.stream().parallel())
Streaming.decode(pairLst2.stream().parallel())
Streaming.decode(pairLst3.stream().parallel())
Streaming.decode(pairLst4.stream().parallel())
Streaming.decode(pairLst1.stream().parallel()).equals(intList1)
Streaming.decode(pairLst2.stream().parallel()).equals(intList2)
Streaming.decode(pairLst3.stream().parallel()).equals(strList1)
Streaming.decode(pairLst4.stream().parallel()).equals(strList2)
Streaming.decode(pairLst1.stream().parallel()).equals(intList2)
Streaming.decode(pairLst2.stream().parallel()).equals(intList1)
Streaming.decode(pairLst3.stream().parallel()).equals(strList2)
Streaming.decode(pairLst4.stream().parallel()).equals(strList1)

View File

@ -0,0 +1,20 @@
package cs2030s.fp;
/**
* Represent a function that immutate one value into another, possible of different types.
* CS2030S
* AY22/23 Semester 1
*
* @param <R> The type of the result value.
* @param <P> The type of the input value.
*/
@FunctionalInterface
public interface Immutator<R, P> {
/**
* The functional method to immutate the value p.
*
* @param p The input value.
* @return The value after applying the given immutation on p.
*/
R invoke(P p);
}

View File

@ -0,0 +1,156 @@
/**
* CS2030S PE2
* AY2022/23 Semester 1.
*
* @author A0253252M
**/
package cs2030s.fp;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Saveable is a container which allows us to have an undo / redo history over the value in the box.
*
* @param <T> the type of the value in the box
**/
public class Saveable<T> {
/**
* The history of changes made to T.
**/
List<T> list;
/**
* The current position in history.
**/
int index = 0;
private Saveable(List<T> list, int index) {
this.list = list;
this.index = index;
}
/**
* Create a new Saveable of type T.
* @param <T> The type of the value in Saveable
* @param value The value to be stored in Saveable
* @return The new Saveable created
**/
public static <T> Saveable<T> of(T value) {
return new Saveable<T>(List.of(value), 0);
}
/**
* Maps the value in Saveable and creates a "checkpoint".
* This will allow for undo to be called on it.
* @param mapper The function to modify the value in the Saveable
* @return The new Saveable created with a undo history attached
**/
public Saveable<T> map(Immutator<? extends T, ? super T> mapper) {
T newVal = mapper.invoke(this.get());
List<T> newList = new ArrayList<>();
for (int i = 0; i <= this.index; i++) {
newList.add(this.list.get(i));
}
newList.add(newVal);
return new Saveable<>(newList, this.index + 1);
}
/**
* Undo's the last operation done on the saveable. If no previous history
* exists, it throws an NoSuchElementException.
*
* @return The Saveable with the last map rolled back
**/
public Saveable<T> undo() {
if (this.index <= 0) {
throw new NoSuchElementException();
}
return new Saveable<>(this.list, this.index - 1);
}
/**
* Goes back forward in time to undo the last undo. If no future history
* exists, it throws a NoSuchElementException.
*
* @return The Saveable with the last undo rolled back
**/
public Saveable<T> redo() {
if (this.index >= this.list.size() - 1) {
throw new NoSuchElementException();
}
return new Saveable<>(this.list, this.index + 1);
}
/**
* Flatmap1 maps the value from T to Saveable. It keeps the
* history of the Saveable returned by mapper
*
* @param mapper The function to map from type T to Saveable
* @return The Saveable with the last undo rolled back
**/
public Saveable<T> flatMap1(Immutator<
? extends Saveable<? extends T>,
? super T> mapper) {
// This cast is ok, as it is casting ? extends Saveable to Saveable, which
// is ok, and also ? extends T to T, which is also ok.
@SuppressWarnings("unchecked")
Saveable<T> result = (Saveable<T>) mapper.invoke(this.get());
return result;
}
/**
* Flatmap2 maps the value from T to Saveable. It keeps the
* history of original Saveable.
*
* @param mapper The function to map from type T to Saveable
* @return The Saveable with the last undo rolled back
**/
public Saveable<T> flatMap2(Immutator<
? extends Saveable<? extends T>,
? super T> mapper) {
// This cast is ok, as it is casting ? extends Saveable to Saveable, which
// is ok, and also ? extends T to T, which is also ok.
@SuppressWarnings("unchecked")
Saveable<T> result = (Saveable<T>) mapper.invoke(this.get());
Saveable<T> tmp = this.map(i -> result.get());
return tmp;
}
private T get() {
return this.list.get(this.index);
}
@Override
public String toString() {
return "Saveable[" + this.get() + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof Saveable<?>) {
Saveable<?> tmp = (Saveable<?>) o;
if (tmp.get() == this.get()) {
return true;
}
if (tmp.get().equals(this.get())) {
return true;
}
}
return false;
}
}