feat: update structure
This commit is contained in:
53
cs2030s/labs/Lab1/Array.java
Executable file
53
cs2030s/labs/Lab1/Array.java
Executable file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* The Array for CS2030S
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY21/22 Semester 2
|
||||
*/
|
||||
|
||||
class Array<T extends Comparable<T>> {
|
||||
private T[] array;
|
||||
|
||||
public Array(int size) {
|
||||
// The only way to add values to `array` is via set(), and we can only put
|
||||
// objects of type T via that method. Thus, it is safe to cast Comparable[]
|
||||
// to T[].
|
||||
@SuppressWarnings("unchecked")
|
||||
T[] temp = (T[]) new Comparable[size];
|
||||
this.array = temp;
|
||||
}
|
||||
|
||||
public void set(int index, T item) {
|
||||
this.array[index] = item;
|
||||
}
|
||||
|
||||
public T get(int index) {
|
||||
return this.array[index];
|
||||
}
|
||||
|
||||
public T min() {
|
||||
T result = this.array[0];
|
||||
for (T i : this.array) {
|
||||
if (i.compareTo(result) < 0) {
|
||||
result = i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return this.array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder s = new StringBuilder("[ ");
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
s.append(i + ":" + array[i]);
|
||||
if (i != array.length - 1) {
|
||||
s.append(", ");
|
||||
}
|
||||
}
|
||||
return s.append(" ]").toString();
|
||||
}
|
||||
}
|
||||
64
cs2030s/labs/Lab1/ArrayTest.java
Executable file
64
cs2030s/labs/Lab1/ArrayTest.java
Executable file
@@ -0,0 +1,64 @@
|
||||
class ArrayTest {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest i = new CS2030STest();
|
||||
|
||||
Array<Integer> a = new Array<Integer>(4);
|
||||
i.expect("initializing an empty array",
|
||||
a.toString(), "[ 0:null, 1:null, 2:null, 3:null ]");
|
||||
a.set(0, 3);
|
||||
i.expect("set element 0 to 3",
|
||||
a.toString(), "[ 0:3, 1:null, 2:null, 3:null ]");
|
||||
a.set(1, 4);
|
||||
i.expect("set element 1 to 4",
|
||||
a.toString(), "[ 0:3, 1:4, 2:null, 3:null ]");
|
||||
a.set(2, 1);
|
||||
i.expect("set element 2 to 1",
|
||||
a.toString(), "[ 0:3, 1:4, 2:1, 3:null ]");
|
||||
a.set(3, 6);
|
||||
i.expect("set element 3 to 6",
|
||||
a.toString(), "[ 0:3, 1:4, 2:1, 3:6 ]");
|
||||
i.expect("get element 0",
|
||||
a.get(0), 3);
|
||||
i.expect("get element 1",
|
||||
a.get(1), 4);
|
||||
i.expect("get element 2",
|
||||
a.get(2), 1);
|
||||
i.expect("get element 3",
|
||||
a.get(3), 6);
|
||||
|
||||
i.expect("smallest element is 1",
|
||||
a.min(), 1);
|
||||
i.expect("a.min() does not change the array",
|
||||
a.toString(), "[ 0:3, 1:4, 2:1, 3:6 ]");
|
||||
a.set(2, 9);
|
||||
i.expect("update element 2 to 9",
|
||||
a.toString(), "[ 0:3, 1:4, 2:9, 3:6 ]");
|
||||
i.expect("smallest element is now 3",
|
||||
a.min(), 3);
|
||||
|
||||
i.expectCompile("cannot put a non-integer into an array of integer",
|
||||
"new Array<Integer>(4).set(0, false)", false);
|
||||
|
||||
i.expectCompile("cannot get a non-integer from an array of integer",
|
||||
"String s = new Array<Integer>(4).get(0)", false);
|
||||
|
||||
i.expectCompile("cannot create an array of non-comparable element",
|
||||
"class A {} Array<A> a;", false);
|
||||
|
||||
i.expectCompile("cannot create an array of comparable element (but not to itself)",
|
||||
"class A implements Comparable<Long> {" +
|
||||
" public int compareTo(Long i) {" +
|
||||
" return 0; " +
|
||||
" }" +
|
||||
"}" +
|
||||
"Array<A> a;", false);
|
||||
|
||||
i.expectCompile("can create an array of comparable element (to itself)",
|
||||
"class A implements Comparable<A> {" +
|
||||
" public int compareTo(A i) {" +
|
||||
" return 0; " +
|
||||
" }" +
|
||||
"}" +
|
||||
"Array<A> a;", true);
|
||||
}
|
||||
}
|
||||
50
cs2030s/labs/Lab1/ArrivalEvent.java
Normal file
50
cs2030s/labs/Lab1/ArrivalEvent.java
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
/**
|
||||
* The ArrivalEvent is an Event which handles the arrival of a customer
|
||||
* It decides whether a customer should go into queue or go to a counter
|
||||
* It also allocates a counter to the customer. This event thus returns either a
|
||||
* DepartureEvent or a ServiceBeginEvent
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
class ArrivalEvent extends Event {
|
||||
|
||||
private Customer customer;
|
||||
private Shop shop;
|
||||
|
||||
public ArrivalEvent(Customer customer, Shop shop) {
|
||||
super(customer.getArrivalTIme());
|
||||
this.customer = customer;
|
||||
this.shop = shop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event[] simulate() {
|
||||
ServiceCounter availableCounter = this.shop.getAvailableCounter();
|
||||
// check if counters are available. If available, start service for that
|
||||
// customer
|
||||
if (availableCounter != null) {
|
||||
return new Event[] {
|
||||
new ServiceBeginEvent(this.getTime(), customer, shop, availableCounter) };
|
||||
}
|
||||
// if no counters available, check if queue slots avialable in counters
|
||||
availableCounter = this.shop.findCounterWithQueue();
|
||||
if (availableCounter != null) {
|
||||
return new Event[] {
|
||||
new JoinCounterQueueEvent(this.getTime(), this.customer, availableCounter)
|
||||
};
|
||||
}
|
||||
// if shop queue isn't empty, join shop queue
|
||||
if (!this.shop.isQueueFull()) {
|
||||
return new Event[] { new JoinShopQueueEvent(customer, shop) };
|
||||
}
|
||||
return new Event[] { new DepartureEvent(this.getTime(), customer) };
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: %s arrived %s", super.toString(), this.customer, this.shop);
|
||||
}
|
||||
}
|
||||
77
cs2030s/labs/Lab1/CS2030STest.java
Executable file
77
cs2030s/labs/Lab1/CS2030STest.java
Executable file
@@ -0,0 +1,77 @@
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import javax.tools.DiagnosticCollector;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
class CS2030STest {
|
||||
|
||||
public static final String ANSI_RESET = "\u001B[0m";
|
||||
public static final String ANSI_RED = "\u001B[31m";
|
||||
public static final String ANSI_GREEN = "\u001B[32m";
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
} else {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
System.out.println(" expected: " + expect);
|
||||
System.out.println(" got this: " + output);
|
||||
}
|
||||
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 JavaSourceFromString extends SimpleJavaFileObject {
|
||||
final String code;
|
||||
|
||||
JavaSourceFromString(String code) {
|
||||
super(URI.create("string:///TempClass.java"), Kind.SOURCE);
|
||||
this.code = "class TempClass {void foo(){" + code + ";}}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
boolean noError = ToolProvider
|
||||
.getSystemJavaCompiler()
|
||||
.getTask(null, null, new DiagnosticCollector<>(), null, null,
|
||||
List.of(new JavaSourceFromString(statement)))
|
||||
.call();
|
||||
|
||||
if (noError != success) {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
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 {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
34
cs2030s/labs/Lab1/Customer.java
Normal file
34
cs2030s/labs/Lab1/Customer.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* This is a data class which holds information about the Customer.
|
||||
* It has a incrementing counter for the customer id;
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
public class Customer {
|
||||
private static int lastId = 0;
|
||||
|
||||
private final int id;
|
||||
private final double serviceTime;
|
||||
private final double arrivalTIme;
|
||||
|
||||
public Customer(double serviceTime, double arrivalTime) {
|
||||
this.id = lastId++;
|
||||
this.serviceTime = serviceTime;
|
||||
this.arrivalTIme = arrivalTime;
|
||||
}
|
||||
|
||||
public double getServiceTime() {
|
||||
return this.serviceTime;
|
||||
}
|
||||
|
||||
public double getArrivalTIme() {
|
||||
return arrivalTIme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "C" + id;
|
||||
}
|
||||
|
||||
}
|
||||
28
cs2030s/labs/Lab1/DepartureEvent.java
Normal file
28
cs2030s/labs/Lab1/DepartureEvent.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* The DepartureEvent is an Event which handles the end of a service.
|
||||
* It handles allocating customers in queue to a counter.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
class DepartureEvent extends Event {
|
||||
|
||||
private Customer customer;
|
||||
|
||||
public DepartureEvent(double time, Customer customer) {
|
||||
super(time);
|
||||
this.customer = customer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: %s departed", super.toString(), this.customer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event[] simulate() {
|
||||
// when customer departs, check if there are customers in queue
|
||||
return new Event[] {};
|
||||
}
|
||||
|
||||
}
|
||||
72
cs2030s/labs/Lab1/Event.java
Normal file
72
cs2030s/labs/Lab1/Event.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* The Event class is an abstract class that encapsulates a
|
||||
* discrete event to be simulated. An event encapsulates the
|
||||
* time the event occurs. A subclass of event _must_ override
|
||||
* the simulate() method to implement the logic of the
|
||||
* simulation when this event is simulated. The simulate method
|
||||
* returns an array of events, which the simulator will then
|
||||
* add to the event queue. Note that an event also implements
|
||||
* the Comparable interface so that a PriorityQueue can
|
||||
* arrange the events in the order of event time.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
abstract class Event implements Comparable<Event> {
|
||||
/** The time this event occurs in the simulation. */
|
||||
private final double time;
|
||||
|
||||
/**
|
||||
* Creates an event that occurs at the given time.
|
||||
*
|
||||
* @param time The time the event occurs.
|
||||
*/
|
||||
public Event(double time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter to return the time of this event.
|
||||
*
|
||||
* @return The time this event occurs.
|
||||
*/
|
||||
public double getTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare this event with a given event e.
|
||||
*
|
||||
* @param e The other event to compare to.
|
||||
* @return 1 if this event occurs later than e;
|
||||
* 0 if they occur the same time;
|
||||
* -1 if this event occurs earlier.
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Event e) {
|
||||
if (this.time > e.time) {
|
||||
return 1;
|
||||
} else if (this.time == e.time) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the string representation this event.
|
||||
*
|
||||
* @return A string consists of the time this event occurs.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%.3f", this.time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate this event.
|
||||
*
|
||||
* @return An array of new events to be scheduled by the simulator.
|
||||
*/
|
||||
public abstract Event[] simulate();
|
||||
}
|
||||
23
cs2030s/labs/Lab1/JoinCounterQueueEvent.java
Normal file
23
cs2030s/labs/Lab1/JoinCounterQueueEvent.java
Normal file
@@ -0,0 +1,23 @@
|
||||
public class JoinCounterQueueEvent extends Event {
|
||||
private Customer customer;
|
||||
private ServiceCounter counter;
|
||||
|
||||
public JoinCounterQueueEvent(double time, Customer customer, ServiceCounter counter) {
|
||||
super(time);
|
||||
this.customer = customer;
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event[] simulate() {
|
||||
this.counter.joinQueue(customer);
|
||||
return new Event[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: %s joined counter queue (at %s)",
|
||||
super.toString(),
|
||||
this.customer, this.counter);
|
||||
}
|
||||
}
|
||||
24
cs2030s/labs/Lab1/JoinShopQueueEvent.java
Normal file
24
cs2030s/labs/Lab1/JoinShopQueueEvent.java
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
class JoinShopQueueEvent extends Event {
|
||||
private Customer customer;
|
||||
private Shop shop;
|
||||
|
||||
public JoinShopQueueEvent(Customer customer, Shop shop) {
|
||||
super(customer.getArrivalTIme());
|
||||
this.customer = customer;
|
||||
this.shop = shop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event[] simulate() {
|
||||
this.shop.joinQueue(customer);
|
||||
return new Event[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: %s joined shop queue %s",
|
||||
super.toString(),
|
||||
this.customer, this.shop);
|
||||
}
|
||||
}
|
||||
26
cs2030s/labs/Lab1/Lab1.java
Normal file
26
cs2030s/labs/Lab1/Lab1.java
Normal file
@@ -0,0 +1,26 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* The main class for CS2030S Lab 1.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
class Lab1 {
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Create a scanner to read from standard input.
|
||||
Scanner sc = new Scanner(System.in);
|
||||
|
||||
// Create a simulation. The ShopSimulation
|
||||
// constructor will read the simulation parameters
|
||||
// and initial events using the scanner.
|
||||
Simulation simulation = new ShopSimulation(sc);
|
||||
|
||||
// Create a new simulator and run the simulation
|
||||
new Simulator(simulation).run();
|
||||
|
||||
// Clean up the scanner.
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
26
cs2030s/labs/Lab1/Lab2.java
Normal file
26
cs2030s/labs/Lab1/Lab2.java
Normal file
@@ -0,0 +1,26 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* The main class for CS2030S Lab 1.
|
||||
*
|
||||
* @author Wei Tsang
|
||||
* @version CS2030S AY20/21 Semester 2
|
||||
*/
|
||||
class Lab2 {
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Create a scanner to read from standard input.
|
||||
Scanner sc = new Scanner(System.in);
|
||||
|
||||
// Create a simulation. The ShopSimulation
|
||||
// constructor will read the simulation parameters
|
||||
// and initial events using the scanner.
|
||||
Simulation simulation = new ShopSimulation(sc);
|
||||
|
||||
// Create a new simulator and run the simulation
|
||||
new Simulator(simulation).run();
|
||||
|
||||
// Clean up the scanner.
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
26
cs2030s/labs/Lab1/Lab3.java
Executable file
26
cs2030s/labs/Lab1/Lab3.java
Executable file
@@ -0,0 +1,26 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* The main class for CS2030S Lab 3.
|
||||
*
|
||||
* @author Wei Tsang
|
||||
* @version CS2030S AY21/22 Semester 2
|
||||
*/
|
||||
class Lab3 {
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Create a scanner to read from standard input.
|
||||
Scanner sc = new Scanner(System.in);
|
||||
|
||||
// Create a simulation. The ShopSimulation
|
||||
// constructor will read the simulation parameters
|
||||
// and initial events using the scanner.
|
||||
Simulation simulation = new ShopSimulation(sc);
|
||||
|
||||
// Create a new simulator and run the simulation
|
||||
new Simulator(simulation).run();
|
||||
|
||||
// Clean up the scanner.
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
17
cs2030s/labs/Lab1/Makefile
Normal file
17
cs2030s/labs/Lab1/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
CLASSES := $(wildcard *.java)
|
||||
|
||||
default: classes
|
||||
|
||||
lab1:
|
||||
java Lab1
|
||||
|
||||
lab2:
|
||||
java Lab2
|
||||
|
||||
classes: $(CLASSES:.java=.class)
|
||||
|
||||
%.class : %.java
|
||||
javac "$<"
|
||||
|
||||
clean:
|
||||
$(RM) *.class
|
||||
125
cs2030s/labs/Lab1/Queue.java
Normal file
125
cs2030s/labs/Lab1/Queue.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* The Queue class implements a simple FIFO data structure
|
||||
* with limited capacity that can store any Object instances.
|
||||
* Not to be confused with java.util.Queue.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY21/22 Semester 2
|
||||
*/
|
||||
class Queue<T> {
|
||||
/** An array to store the items in the queue. */
|
||||
private T[] items;
|
||||
|
||||
/** Index of the first element in the queue. */
|
||||
private int first;
|
||||
|
||||
/** Index of the last element in the queue. */
|
||||
private int last;
|
||||
|
||||
/** Maximum size of the queue. */
|
||||
private int maxSize;
|
||||
|
||||
/** Number of elements in the queue. */
|
||||
private int len;
|
||||
|
||||
/**
|
||||
* Constructor for a queue.
|
||||
*
|
||||
* @param size The maximum num of elements we can put in the queue.
|
||||
*/
|
||||
public Queue(int size) {
|
||||
this.maxSize = size;
|
||||
// The only way to add values to `items` is via enq(), and we can only put
|
||||
// objects of type T via that method. Thus, it is safe to cast Comparable[]
|
||||
// to T[].
|
||||
@SuppressWarnings("unchecked")
|
||||
T[] temp = (T[]) new Object[size];
|
||||
this.items = temp;
|
||||
this.first = -1;
|
||||
this.last = -1;
|
||||
this.len = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the object e into the queue.
|
||||
*
|
||||
* @param e The item to put in the queue.
|
||||
* @return false if the queue is full; true if e is added successfully.
|
||||
*/
|
||||
public boolean enq(T e) {
|
||||
if (this.isFull()) {
|
||||
return false;
|
||||
}
|
||||
if (this.isEmpty()) {
|
||||
this.first = 0;
|
||||
this.last = 0;
|
||||
} else {
|
||||
this.last = (this.last + 1) % this.maxSize;
|
||||
}
|
||||
this.items[last] = e;
|
||||
this.len += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the object from the queue.
|
||||
*
|
||||
* @return null if the queue is empty; the object removed from the queue
|
||||
* otherwise.
|
||||
*/
|
||||
public T deq() {
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
T item = this.items[this.first];
|
||||
this.first = (this.first + 1) % this.maxSize;
|
||||
this.len -= 1;
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the queue is full.
|
||||
*
|
||||
* @return true if the queue is full; false otherwise.
|
||||
*/
|
||||
boolean isFull() {
|
||||
return (this.len == this.maxSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the queue is empty.
|
||||
*
|
||||
* @return true if the queue is empty; false otherwise.
|
||||
*/
|
||||
boolean isEmpty() {
|
||||
return (this.len == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of elements in the queue.
|
||||
*
|
||||
* @return The number of elements in the queue.
|
||||
*/
|
||||
public int length() {
|
||||
return this.len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of the queue.
|
||||
*
|
||||
* @return A string consisting of the string representation of
|
||||
* every object in the queue.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = "[ ";
|
||||
int i = this.first;
|
||||
int count = 0;
|
||||
while (count < this.len) {
|
||||
str += this.items[i] + " ";
|
||||
i = (i + 1) % this.maxSize;
|
||||
count++;
|
||||
}
|
||||
return str + "]";
|
||||
}
|
||||
}
|
||||
23
cs2030s/labs/Lab1/QueueTest.java
Executable file
23
cs2030s/labs/Lab1/QueueTest.java
Executable file
@@ -0,0 +1,23 @@
|
||||
class QueueTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
CS2030STest i = new CS2030STest();
|
||||
Queue<Integer> q = new Queue<Integer>(2);
|
||||
i.expect("insert 4 into a queue of integer",
|
||||
q.enq(4), true);
|
||||
i.expect("insert 8 into a queue of integer",
|
||||
q.enq(8), true);
|
||||
i.expect("insert 0 into a full queue",
|
||||
q.enq(0), false);
|
||||
i.expect("remove 4 from queue",
|
||||
q.deq(), 4);
|
||||
i.expect("remove 8 from queue",
|
||||
q.deq(), 8);
|
||||
i.expect("cannot deque anymore",
|
||||
q.deq(), null);
|
||||
i.expectCompile("cannot deque a non-integer from a queue of integer",
|
||||
"String s = new Queue<Integer>(3).deq();", false);
|
||||
i.expectCompile("cannot insert a non-integer into a queue of integer",
|
||||
"new Queue<Integer>(3).enqueue(false);", false);
|
||||
}
|
||||
}
|
||||
34
cs2030s/labs/Lab1/ServiceBeginEvent.java
Normal file
34
cs2030s/labs/Lab1/ServiceBeginEvent.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* The ServiceBeginEvent is an Event which handles the starting of a service.
|
||||
* It handles occupying a counter and also generating a serviceEndEvent
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
class ServiceBeginEvent extends Event {
|
||||
|
||||
private ServiceCounter counter;
|
||||
private Customer customer;
|
||||
private Shop shop;
|
||||
|
||||
public ServiceBeginEvent(double time, Customer customer, Shop shop, ServiceCounter counter) {
|
||||
super(time);
|
||||
this.customer = customer;
|
||||
this.shop = shop;
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString()
|
||||
+ String.format(": %s service begin (by %s)", this.customer, this.counter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event[] simulate() {
|
||||
this.counter.occupy();
|
||||
double endTime = this.getTime() + this.customer.getServiceTime();
|
||||
return new Event[] {
|
||||
new ServiceEndEvent(endTime, this.customer, this.shop, this.counter) };
|
||||
}
|
||||
}
|
||||
64
cs2030s/labs/Lab1/ServiceCounter.java
Normal file
64
cs2030s/labs/Lab1/ServiceCounter.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* This is a data class which holds information about a counter. It has a
|
||||
* incrementing counter for the conuter Id.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
public class ServiceCounter implements Comparable<ServiceCounter> {
|
||||
private static int lastId;
|
||||
|
||||
private final int id;
|
||||
private boolean available;
|
||||
private Queue<Customer> queue;
|
||||
|
||||
public boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
public void occupy() {
|
||||
this.available = false;
|
||||
}
|
||||
|
||||
public void free() {
|
||||
this.available = true;
|
||||
}
|
||||
|
||||
public boolean isQueueFull() {
|
||||
return this.queue.isFull();
|
||||
}
|
||||
|
||||
public boolean isQueueEmpty() {
|
||||
return this.queue.isEmpty();
|
||||
}
|
||||
|
||||
public void joinQueue(Customer customer) {
|
||||
this.queue.enq(customer);
|
||||
}
|
||||
|
||||
public Customer leaveQueue() {
|
||||
return this.queue.deq();
|
||||
}
|
||||
|
||||
public ServiceCounter(int queueSize) {
|
||||
this.id = lastId++;
|
||||
this.available = true;
|
||||
this.queue = new Queue<Customer>(queueSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("S%s %s", id, this.queue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ServiceCounter o) {
|
||||
if (this.queue.length() < o.queue.length()) {
|
||||
return -1;
|
||||
}
|
||||
if (this.id < o.id) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
58
cs2030s/labs/Lab1/ServiceEndEvent.java
Normal file
58
cs2030s/labs/Lab1/ServiceEndEvent.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* The ServiceEndEvent is an Event which handles the end of a service.
|
||||
* It handles freeing the counter and also generating a departure event
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
class ServiceEndEvent extends Event {
|
||||
|
||||
private ServiceCounter counter;
|
||||
private Customer customer;
|
||||
private Shop shop;
|
||||
|
||||
public ServiceEndEvent(double time, Customer customer, Shop shop, ServiceCounter counter) {
|
||||
super(time);
|
||||
this.customer = customer;
|
||||
this.shop = shop;
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString()
|
||||
+ String.format(": %s service done (by %s)", this.customer, this.counter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event[] simulate() {
|
||||
// if there are customers in the counter queue, they will be serviced next.
|
||||
// Customers in the shop queue will then be added to the counter queue
|
||||
if (!this.counter.isQueueEmpty()) {
|
||||
Customer serviceCustomer = this.counter.leaveQueue();
|
||||
|
||||
if (!this.shop.isQueueEmpty()) {
|
||||
return new Event[] {
|
||||
new DepartureEvent(this.getTime(), this.customer),
|
||||
new ServiceBeginEvent(this.getTime(), serviceCustomer, this.shop, this.counter),
|
||||
new JoinCounterQueueEvent(this.getTime(), this.shop.leaveQueue(), counter)
|
||||
};
|
||||
}
|
||||
return new Event[] {
|
||||
new DepartureEvent(this.getTime(), this.customer),
|
||||
new ServiceBeginEvent(this.getTime(), serviceCustomer, this.shop, this.counter),
|
||||
};
|
||||
}
|
||||
// There can also be the case where the counter queue may be empty but there are
|
||||
// customers in the shop queue.
|
||||
if (!this.shop.isQueueEmpty()) {
|
||||
return new Event[] {
|
||||
new DepartureEvent(this.getTime(), this.customer),
|
||||
new ServiceBeginEvent(this.getTime(), this.shop.leaveQueue(), this.shop, this.counter),
|
||||
};
|
||||
}
|
||||
// else there are no more customers in the queue, and the counter can be freed
|
||||
this.counter.free();
|
||||
return new Event[] { new DepartureEvent(this.getTime(), this.customer) };
|
||||
}
|
||||
}
|
||||
67
cs2030s/labs/Lab1/Shop.java
Normal file
67
cs2030s/labs/Lab1/Shop.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Shop is a data class which holds information about a shop.
|
||||
* It stores the list of counters and the queue in which new customers can join.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
public class Shop {
|
||||
private Array<ServiceCounter> counters;
|
||||
private Queue<Customer> queue;
|
||||
|
||||
public Shop(int numOfCounters, int shopQueueSize, int counterQueueSize) {
|
||||
this.counters = new Array<ServiceCounter>(numOfCounters);
|
||||
for (int i = 0; i < numOfCounters; i++) {
|
||||
this.counters.set(i, new ServiceCounter(counterQueueSize));
|
||||
}
|
||||
|
||||
this.queue = new Queue<Customer>(shopQueueSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* getAvailableCounter returns the first available counter it finds.
|
||||
* If there are none, returns null
|
||||
*
|
||||
* @return the available counter or null if none found
|
||||
*/
|
||||
|
||||
public ServiceCounter getAvailableCounter() {
|
||||
for (int i = 0; i < this.counters.length(); i++) {
|
||||
ServiceCounter counter = this.counters.get(i);
|
||||
if (counter.isAvailable()) {
|
||||
return counter;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isQueueFull() {
|
||||
return this.queue.isFull();
|
||||
}
|
||||
|
||||
public boolean isQueueEmpty() {
|
||||
return this.queue.isEmpty();
|
||||
}
|
||||
|
||||
public void joinQueue(Customer customer) {
|
||||
this.queue.enq(customer);
|
||||
}
|
||||
|
||||
public Customer leaveQueue() {
|
||||
return this.queue.deq();
|
||||
}
|
||||
|
||||
public ServiceCounter findCounterWithQueue() {
|
||||
ServiceCounter minCounter = this.counters.min();
|
||||
if (!minCounter.isQueueFull()) {
|
||||
return minCounter;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.queue.toString();
|
||||
}
|
||||
|
||||
}
|
||||
53
cs2030s/labs/Lab1/ShopSimulation.java
Normal file
53
cs2030s/labs/Lab1/ShopSimulation.java
Normal file
@@ -0,0 +1,53 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* This class implements a shop simulation.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
class ShopSimulation extends Simulation {
|
||||
|
||||
/**
|
||||
* The list of customer arrival events to populate
|
||||
* the simulation with.
|
||||
*/
|
||||
private Event[] initEvents;
|
||||
|
||||
/**
|
||||
* Constructor for a shop simulation.
|
||||
*
|
||||
* @param sc A scanner to read the parameters from. The first
|
||||
* integer scanned is the number of customers; followed
|
||||
* by the number of service counters. Next is a
|
||||
* sequence of (arrival time, service time) pair, each
|
||||
* pair represents a customer.
|
||||
*/
|
||||
public ShopSimulation(Scanner sc) {
|
||||
initEvents = new Event[sc.nextInt()];
|
||||
int numOfCounters = sc.nextInt();
|
||||
int maxCounterQueueSize = sc.nextInt();
|
||||
int maxShopQueueSize = sc.nextInt();
|
||||
|
||||
Shop shop = new Shop(numOfCounters, maxShopQueueSize, maxCounterQueueSize);
|
||||
|
||||
int id = 0;
|
||||
while (sc.hasNextDouble()) {
|
||||
double arrivalTime = sc.nextDouble();
|
||||
double serviceTime = sc.nextDouble();
|
||||
initEvents[id] = new ArrivalEvent(new Customer(serviceTime, arrivalTime), shop);
|
||||
id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an array of events to populate the
|
||||
* simulator with.
|
||||
*
|
||||
* @return An array of events for the simulator.
|
||||
*/
|
||||
@Override
|
||||
public Event[] getInitialEvents() {
|
||||
return initEvents;
|
||||
}
|
||||
}
|
||||
20
cs2030s/labs/Lab1/Simulation.java
Normal file
20
cs2030s/labs/Lab1/Simulation.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* This class is a general abstract class that
|
||||
* encapsulates a simulation. To implement a
|
||||
* simulation, inherit from this class and implement
|
||||
* the `getInitialEvents` method.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
abstract class Simulation {
|
||||
/**
|
||||
* An abstract method to return an array of events
|
||||
* used to initialize the simulation.
|
||||
*
|
||||
* @return An array of initial events that the
|
||||
* simulator can use to kick-start the
|
||||
* simulation.
|
||||
*/
|
||||
public abstract Event[] getInitialEvents();
|
||||
}
|
||||
51
cs2030s/labs/Lab1/Simulator.java
Normal file
51
cs2030s/labs/Lab1/Simulator.java
Normal file
@@ -0,0 +1,51 @@
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
/**
|
||||
* This class implements a discrete event simulator.
|
||||
* The simulator maintains a priority queue of events.
|
||||
* It runs through the events and simulates each one until
|
||||
* the queue is empty.
|
||||
*
|
||||
* @author Yadunand Prem
|
||||
* @version CS2030S AY22/23 Semester 2
|
||||
*/
|
||||
public class Simulator {
|
||||
/** The event queue. */
|
||||
private final PriorityQueue<Event> events;
|
||||
|
||||
/**
|
||||
* The constructor for a simulator. It takes in
|
||||
* a simulation as an argument, and calls the
|
||||
* getInitialEvents method of that simulation to
|
||||
* initialize the event queue.
|
||||
*
|
||||
* @param simulation The simulation to simulate.
|
||||
*/
|
||||
public Simulator(Simulation simulation) {
|
||||
this.events = new PriorityQueue<Event>();
|
||||
for (Event e : simulation.getInitialEvents()) {
|
||||
this.events.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the simulation until no more events is in
|
||||
* the queue. For each event in the queue (in
|
||||
* increasing order of time), print out its string
|
||||
* representation, then simulate it. If the
|
||||
* simulation returns one or more events, add them
|
||||
* to the queue, and repeat.
|
||||
*/
|
||||
public void run() {
|
||||
Event event = this.events.poll();
|
||||
while (event != null) {
|
||||
System.out.println(event);
|
||||
Event[] newEvents = event.simulate();
|
||||
for (Event e : newEvents) {
|
||||
this.events.add(e);
|
||||
}
|
||||
event = this.events.poll();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
4
cs2030s/labs/Lab1/inputs/Lab1.1.in
Normal file
4
cs2030s/labs/Lab1/inputs/Lab1.1.in
Normal file
@@ -0,0 +1,4 @@
|
||||
3 1
|
||||
1.0 1.0
|
||||
3.0 1.0
|
||||
5.0 1.0
|
||||
4
cs2030s/labs/Lab1/inputs/Lab1.2.in
Normal file
4
cs2030s/labs/Lab1/inputs/Lab1.2.in
Normal file
@@ -0,0 +1,4 @@
|
||||
3 1
|
||||
1.1 2.0
|
||||
2.2 2.0
|
||||
3.3 2.0
|
||||
6
cs2030s/labs/Lab1/inputs/Lab1.3.in
Normal file
6
cs2030s/labs/Lab1/inputs/Lab1.3.in
Normal file
@@ -0,0 +1,6 @@
|
||||
5 2
|
||||
1.0 1.0
|
||||
1.2 1.0
|
||||
1.4 1.0
|
||||
1.6 1.0
|
||||
2.1 1.0
|
||||
5
cs2030s/labs/Lab1/inputs/Lab1.4.in
Normal file
5
cs2030s/labs/Lab1/inputs/Lab1.4.in
Normal file
@@ -0,0 +1,5 @@
|
||||
4 2
|
||||
1.0 1.0
|
||||
1.1 1.0
|
||||
2.2 1.0
|
||||
2.3 1.0
|
||||
4
cs2030s/labs/Lab1/inputs/Lab1.5.in
Normal file
4
cs2030s/labs/Lab1/inputs/Lab1.5.in
Normal file
@@ -0,0 +1,4 @@
|
||||
3 2
|
||||
1.0 4
|
||||
2.1 1
|
||||
4.2 1
|
||||
4
cs2030s/labs/Lab1/inputs/Lab2.1.in
Normal file
4
cs2030s/labs/Lab1/inputs/Lab2.1.in
Normal file
@@ -0,0 +1,4 @@
|
||||
3 1 2
|
||||
1.0 1.0
|
||||
3.0 1.0
|
||||
5.0 1.0
|
||||
6
cs2030s/labs/Lab1/inputs/Lab2.10.in
Normal file
6
cs2030s/labs/Lab1/inputs/Lab2.10.in
Normal file
@@ -0,0 +1,6 @@
|
||||
5 2 2
|
||||
1.0 1.5
|
||||
1.2 1.0
|
||||
1.4 1.0
|
||||
1.6 1.0
|
||||
2.1 1.0
|
||||
4
cs2030s/labs/Lab1/inputs/Lab2.2.in
Normal file
4
cs2030s/labs/Lab1/inputs/Lab2.2.in
Normal file
@@ -0,0 +1,4 @@
|
||||
3 1 2
|
||||
1.1 2.0
|
||||
2.2 2.0
|
||||
3.3 2.0
|
||||
7
cs2030s/labs/Lab1/inputs/Lab2.3.in
Normal file
7
cs2030s/labs/Lab1/inputs/Lab2.3.in
Normal file
@@ -0,0 +1,7 @@
|
||||
6 1 2
|
||||
1.1 2
|
||||
1.2 2
|
||||
1.3 2
|
||||
1.4 2
|
||||
4.0 2
|
||||
5.0 2
|
||||
7
cs2030s/labs/Lab1/inputs/Lab2.4.in
Normal file
7
cs2030s/labs/Lab1/inputs/Lab2.4.in
Normal file
@@ -0,0 +1,7 @@
|
||||
6 1 3
|
||||
1.1 2
|
||||
1.2 2
|
||||
1.3 2
|
||||
1.4 2
|
||||
4.0 2
|
||||
5.0 2
|
||||
5
cs2030s/labs/Lab1/inputs/Lab2.5.in
Normal file
5
cs2030s/labs/Lab1/inputs/Lab2.5.in
Normal file
@@ -0,0 +1,5 @@
|
||||
4 2 1
|
||||
1.0 1.0
|
||||
1.1 1.0
|
||||
2.2 1.0
|
||||
2.3 1.0
|
||||
5
cs2030s/labs/Lab1/inputs/Lab2.6.in
Normal file
5
cs2030s/labs/Lab1/inputs/Lab2.6.in
Normal file
@@ -0,0 +1,5 @@
|
||||
4 2 2
|
||||
1.0 1.0
|
||||
1.1 1.0
|
||||
2.2 1.0
|
||||
2.3 1.0
|
||||
4
cs2030s/labs/Lab1/inputs/Lab2.7.in
Normal file
4
cs2030s/labs/Lab1/inputs/Lab2.7.in
Normal file
@@ -0,0 +1,4 @@
|
||||
3 2 1
|
||||
1.0 4
|
||||
2.1 1
|
||||
4.2 1
|
||||
6
cs2030s/labs/Lab1/inputs/Lab2.8.in
Normal file
6
cs2030s/labs/Lab1/inputs/Lab2.8.in
Normal file
@@ -0,0 +1,6 @@
|
||||
5 2 1
|
||||
1.0 1.0
|
||||
1.2 1.0
|
||||
1.4 1.0
|
||||
1.6 1.0
|
||||
2.1 1.0
|
||||
6
cs2030s/labs/Lab1/inputs/Lab2.9.in
Normal file
6
cs2030s/labs/Lab1/inputs/Lab2.9.in
Normal file
@@ -0,0 +1,6 @@
|
||||
5 2 2
|
||||
1.0 1.0
|
||||
1.2 1.0
|
||||
1.4 1.0
|
||||
1.6 1.0
|
||||
2.1 1.0
|
||||
4
cs2030s/labs/Lab1/inputs/Lab3.1.in
Executable file
4
cs2030s/labs/Lab1/inputs/Lab3.1.in
Executable file
@@ -0,0 +1,4 @@
|
||||
3 1 0 2
|
||||
1.0 1.0
|
||||
3.0 1.0
|
||||
5.0 1.0
|
||||
6
cs2030s/labs/Lab1/inputs/Lab3.10.in
Executable file
6
cs2030s/labs/Lab1/inputs/Lab3.10.in
Executable file
@@ -0,0 +1,6 @@
|
||||
5 2 0 2
|
||||
1.0 1.5
|
||||
1.2 1.0
|
||||
1.4 1.0
|
||||
1.6 1.0
|
||||
2.1 1.0
|
||||
6
cs2030s/labs/Lab1/inputs/Lab3.11.in
Executable file
6
cs2030s/labs/Lab1/inputs/Lab3.11.in
Executable file
@@ -0,0 +1,6 @@
|
||||
5 1 2 0
|
||||
1.0 1.0
|
||||
1.1 1.0
|
||||
1.2 1.0
|
||||
1.3 1.0
|
||||
1.4 1.0
|
||||
12
cs2030s/labs/Lab1/inputs/Lab3.12.in
Executable file
12
cs2030s/labs/Lab1/inputs/Lab3.12.in
Executable file
@@ -0,0 +1,12 @@
|
||||
11 3 3 0
|
||||
1.0 2
|
||||
1.1 1
|
||||
1.2 1
|
||||
1.3 1
|
||||
1.4 1
|
||||
1.5 2
|
||||
1.6 2
|
||||
1.7 2
|
||||
1.8 2
|
||||
1.9 2
|
||||
2.15 1
|
||||
12
cs2030s/labs/Lab1/inputs/Lab3.13.in
Executable file
12
cs2030s/labs/Lab1/inputs/Lab3.13.in
Executable file
@@ -0,0 +1,12 @@
|
||||
11 3 3 0
|
||||
1.0 2
|
||||
1.1 1
|
||||
1.2 1
|
||||
1.3 1
|
||||
1.4 1
|
||||
1.5 2
|
||||
1.6 2
|
||||
1.7 2
|
||||
1.8 2
|
||||
1.9 2
|
||||
2.25 1
|
||||
13
cs2030s/labs/Lab1/inputs/Lab3.14.in
Executable file
13
cs2030s/labs/Lab1/inputs/Lab3.14.in
Executable file
@@ -0,0 +1,13 @@
|
||||
12 3 2 2
|
||||
1.0 2
|
||||
1.1 2
|
||||
1.2 2
|
||||
1.3 2
|
||||
1.4 2
|
||||
1.5 2
|
||||
1.6 2
|
||||
1.7 2
|
||||
1.8 2
|
||||
1.9 2
|
||||
2.0 2
|
||||
2.1 2
|
||||
13
cs2030s/labs/Lab1/inputs/Lab3.15.in
Executable file
13
cs2030s/labs/Lab1/inputs/Lab3.15.in
Executable file
@@ -0,0 +1,13 @@
|
||||
12 3 2 3
|
||||
1.0 2
|
||||
1.1 3
|
||||
1.2 2
|
||||
1.3 3
|
||||
1.4 2
|
||||
1.5 3
|
||||
1.6 2
|
||||
1.7 3
|
||||
1.8 2
|
||||
1.9 3
|
||||
2.0 2
|
||||
2.1 3
|
||||
4
cs2030s/labs/Lab1/inputs/Lab3.2.in
Executable file
4
cs2030s/labs/Lab1/inputs/Lab3.2.in
Executable file
@@ -0,0 +1,4 @@
|
||||
3 1 0 2
|
||||
1.1 2.0
|
||||
2.2 2.0
|
||||
3.3 2.0
|
||||
7
cs2030s/labs/Lab1/inputs/Lab3.3.in
Executable file
7
cs2030s/labs/Lab1/inputs/Lab3.3.in
Executable file
@@ -0,0 +1,7 @@
|
||||
6 1 0 2
|
||||
1.1 2
|
||||
1.2 2
|
||||
1.3 2
|
||||
1.4 2
|
||||
4.0 2
|
||||
5.0 2
|
||||
7
cs2030s/labs/Lab1/inputs/Lab3.4.in
Executable file
7
cs2030s/labs/Lab1/inputs/Lab3.4.in
Executable file
@@ -0,0 +1,7 @@
|
||||
6 1 0 3
|
||||
1.1 2
|
||||
1.2 2
|
||||
1.3 2
|
||||
1.4 2
|
||||
4.0 2
|
||||
5.0 2
|
||||
5
cs2030s/labs/Lab1/inputs/Lab3.5.in
Executable file
5
cs2030s/labs/Lab1/inputs/Lab3.5.in
Executable file
@@ -0,0 +1,5 @@
|
||||
4 2 0 1
|
||||
1.0 1.0
|
||||
1.1 1.0
|
||||
2.2 1.0
|
||||
2.3 1.0
|
||||
5
cs2030s/labs/Lab1/inputs/Lab3.6.in
Executable file
5
cs2030s/labs/Lab1/inputs/Lab3.6.in
Executable file
@@ -0,0 +1,5 @@
|
||||
4 2 0 2
|
||||
1.0 1.0
|
||||
1.1 1.0
|
||||
2.2 1.0
|
||||
2.3 1.0
|
||||
4
cs2030s/labs/Lab1/inputs/Lab3.7.in
Executable file
4
cs2030s/labs/Lab1/inputs/Lab3.7.in
Executable file
@@ -0,0 +1,4 @@
|
||||
3 2 0 1
|
||||
1.0 4
|
||||
2.1 1
|
||||
4.2 1
|
||||
6
cs2030s/labs/Lab1/inputs/Lab3.8.in
Executable file
6
cs2030s/labs/Lab1/inputs/Lab3.8.in
Executable file
@@ -0,0 +1,6 @@
|
||||
5 2 0 1
|
||||
1.0 1.0
|
||||
1.2 1.0
|
||||
1.4 1.0
|
||||
1.6 1.0
|
||||
2.1 1.0
|
||||
6
cs2030s/labs/Lab1/inputs/Lab3.9.in
Executable file
6
cs2030s/labs/Lab1/inputs/Lab3.9.in
Executable file
@@ -0,0 +1,6 @@
|
||||
5 2 0 2
|
||||
1.0 1.0
|
||||
1.2 1.0
|
||||
1.4 1.0
|
||||
1.6 1.0
|
||||
2.1 1.0
|
||||
77
cs2030s/labs/Lab1/test.sh
Executable file
77
cs2030s/labs/Lab1/test.sh
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
set -o nounset
|
||||
function control_c() {
|
||||
if [ -e $out ]
|
||||
then
|
||||
rm -f $out
|
||||
fi
|
||||
}
|
||||
|
||||
trap control_c INT
|
||||
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
echo "usage: $0 <main class>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PROG=$1
|
||||
if [ ! -e $PROG.class ]
|
||||
then
|
||||
echo "$PROG.class does not exist. Have you compiled it with make or javac?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
num_failed=0
|
||||
i=1
|
||||
while true
|
||||
do
|
||||
if [ -e inputs/$PROG.$i.in ]
|
||||
then
|
||||
if [ $(uname) == "Darwin" ]
|
||||
then
|
||||
out=$(mktemp -t $PROG)
|
||||
else
|
||||
out=$(mktemp --suffix=$PROG)
|
||||
fi
|
||||
java $PROG < inputs/$PROG.$i.in > $out
|
||||
status="$?"
|
||||
if [ "$status" -ne "0" ]
|
||||
then
|
||||
echo "$PROG: return non-zero status $status for test case $i"
|
||||
# cat inputs/$PROG.$i.in
|
||||
num_failed=$((num_failed + 1))
|
||||
else
|
||||
if [ -e $out ]
|
||||
then
|
||||
if [ `diff -bB $out outputs/$PROG.$i.out | wc -l` -ne 0 ]
|
||||
then
|
||||
echo "$PROG test $i: failed"
|
||||
#cat inputs/$PROG.$i.in
|
||||
num_failed=$((num_failed + 1))
|
||||
else
|
||||
echo "$PROG test $i: passed"
|
||||
fi
|
||||
rm -f $out
|
||||
else
|
||||
echo "$PROG: cannot find output file. Execution interrupted?"
|
||||
num_failed=$((num_failed + 1))
|
||||
fi
|
||||
fi
|
||||
i=$((i + 1))
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $i -eq 1 ]
|
||||
then
|
||||
echo "$PROG: no test cases found 🤷"
|
||||
elif [ $num_failed -eq 0 ]
|
||||
then
|
||||
echo "$PROG: passed everything 🎉"
|
||||
fi
|
||||
# Run style checker
|
||||
#java -jar ~cs2030s/bin/checkstyle.jar -c ~cs2030s/bin/cs2030_checks.xml *.java
|
||||
java -jar ./checkstyle.jar -c ./cs2030_checks.xml *.java
|
||||
# vim:noexpandtab:sw=4:ts=4
|
||||
12
cs2030s/labs/Lab4/Action.java
Normal file
12
cs2030s/labs/Lab4/Action.java
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* The Action interface that can be called
|
||||
* on an object of type T to act.
|
||||
* Contains a single abstract method call.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
interface Action<T> {
|
||||
void call(T item);
|
||||
}
|
||||
13
cs2030s/labs/Lab4/Actionable.java
Normal file
13
cs2030s/labs/Lab4/Actionable.java
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* The Actionable interface that can
|
||||
* act when given an action.
|
||||
* Contains a single abstract method act.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
// act consumes the T and passes it to action, thus super
|
||||
interface Actionable<T> {
|
||||
public void act(Action<? super T> action);
|
||||
}
|
||||
14
cs2030s/labs/Lab4/Applicable.java
Normal file
14
cs2030s/labs/Lab4/Applicable.java
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* The Applicable interface that can probably
|
||||
* transform if given something that is
|
||||
* probably an Immutator.
|
||||
* Contains a single abstract method apply.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
*
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
interface Applicable<T> {
|
||||
<R> Applicable<R> apply(Probably<? extends Immutator<? extends R, ? super T>> probablyImmutator);
|
||||
}
|
||||
75
cs2030s/labs/Lab4/CS2030STest.java
Normal file
75
cs2030s/labs/Lab4/CS2030STest.java
Normal file
@@ -0,0 +1,75 @@
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import javax.tools.DiagnosticCollector;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
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";
|
||||
|
||||
public void expect(String test, Object output, Object expect) {
|
||||
System.out.print(test);
|
||||
if ((expect == null && output == null) || output.equals(expect)) {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
} else {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
System.out.println(" expected: " + expect);
|
||||
System.out.println(" got this: " + output);
|
||||
}
|
||||
}
|
||||
|
||||
public static String clean(String txt) {
|
||||
String res = "";
|
||||
for (int i=0; i<txt.length(); i++) {
|
||||
if (txt.charAt(i) != '\r' && txt.charAt(i) != '\n') {
|
||||
res += txt.charAt(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public void expectPrint(String test, Object expect, ByteArrayOutputStream baos, PrintStream old) {
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
expect(test, CS2030STest.clean(baos.toString()), expect);
|
||||
}
|
||||
|
||||
public void expectCompile(String test, String statement, boolean success) {
|
||||
System.out.print(test);
|
||||
|
||||
class JavaSourceFromString extends SimpleJavaFileObject {
|
||||
final String code;
|
||||
|
||||
JavaSourceFromString(String code) {
|
||||
super(URI.create("string:///TempClass.java"), Kind.SOURCE);
|
||||
this.code = "class TempClass {void foo(){" + code + ";}}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
boolean noError = ToolProvider
|
||||
.getSystemJavaCompiler()
|
||||
.getTask(null, null, new DiagnosticCollector<>(), null, null,
|
||||
List.of(new JavaSourceFromString(statement)))
|
||||
.call();
|
||||
|
||||
if (noError != success) {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
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 {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
cs2030s/labs/Lab4/Immutator.java
Normal file
12
cs2030s/labs/Lab4/Immutator.java
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* The Immutator interface that can transform
|
||||
* to type T2, an object of type T1.
|
||||
* Contains a single abstract method invoke.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
interface Immutator<R, P> {
|
||||
public R invoke(P param);
|
||||
}
|
||||
13
cs2030s/labs/Lab4/Immutatorable.java
Normal file
13
cs2030s/labs/Lab4/Immutatorable.java
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* The Immutatorable interface that can
|
||||
* transform when given something that is
|
||||
* Immutator.
|
||||
* Contains a single abstract method transform.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
interface Immutatorable<T> {
|
||||
public <R> Immutatorable<R> transform(Immutator<? extends R, ? super T> immutator);
|
||||
}
|
||||
15
cs2030s/labs/Lab4/Improbable.java
Normal file
15
cs2030s/labs/Lab4/Improbable.java
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* A generic Immutator that takes in an object
|
||||
* that is T and returns an object that is probably T.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
*
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
class Improbable<T> implements Immutator<Probably<T>, T> {
|
||||
@Override
|
||||
public Probably<T> invoke(T param) {
|
||||
return Probably.just(param);
|
||||
}
|
||||
}
|
||||
27
cs2030s/labs/Lab4/IsModEq.java
Normal file
27
cs2030s/labs/Lab4/IsModEq.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* A non-generic Immutator with parameter
|
||||
* div and mod that takes in an integer val
|
||||
* and return the boolean value by checking
|
||||
* if the given value is equal to mod when
|
||||
* divided by div.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
*
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
class IsModEq implements Immutator<Boolean, Integer> {
|
||||
|
||||
private int div;
|
||||
private int check;
|
||||
|
||||
public IsModEq(int div, int check) {
|
||||
this.div = div;
|
||||
this.check = check;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(Integer val) {
|
||||
return val % div == check;
|
||||
}
|
||||
}
|
||||
247
cs2030s/labs/Lab4/Lab4.java
Normal file
247
cs2030s/labs/Lab4/Lab4.java
Normal file
@@ -0,0 +1,247 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* The main class for CS2030S Lab 4.
|
||||
*
|
||||
* @author Wei Tsang
|
||||
* @version CS2030S AY21/22 Semester 2
|
||||
*/
|
||||
class Lab4 {
|
||||
|
||||
/**
|
||||
* Inner class for testing.
|
||||
*/
|
||||
static class Incr implements Immutator<Integer,Integer> {
|
||||
public Integer invoke(Integer t1) {
|
||||
return t1 + 1;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Inner class for testing.
|
||||
*/
|
||||
static class Length implements Immutator<Integer,String> {
|
||||
public Integer invoke(String t1) {
|
||||
return t1.length();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to clean a string from
|
||||
* any newline.
|
||||
*
|
||||
* @param txt Input string.
|
||||
* @return The cleaned string.
|
||||
*/
|
||||
public static String clean(String txt) {
|
||||
String res = "";
|
||||
for (int i=0; i<txt.length(); i++) {
|
||||
if (txt.charAt(i) != '\r' && txt.charAt(i) != '\n') {
|
||||
res += txt.charAt(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Create a scanner to read from standard input.
|
||||
Scanner sc = new Scanner(System.in);
|
||||
|
||||
// Read a single integer from the test file
|
||||
// and then run the appropriate test case
|
||||
switch (sc.nextInt()) {
|
||||
case 1:
|
||||
test1();
|
||||
break;
|
||||
case 2:
|
||||
test2();
|
||||
break;
|
||||
case 3:
|
||||
test3();
|
||||
break;
|
||||
case 4:
|
||||
test4();
|
||||
break;
|
||||
case 5:
|
||||
test5();
|
||||
break;
|
||||
case 6:
|
||||
test6();
|
||||
break;
|
||||
}
|
||||
|
||||
// Clean up the scanner.
|
||||
sc.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test #1.
|
||||
*/
|
||||
public static void test1() {
|
||||
PrintStream old = System.out;
|
||||
ByteArrayOutputStream baos;
|
||||
PrintStream ps;
|
||||
|
||||
try {
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
new Print().call(17);
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
|
||||
System.out.println(Lab4.clean(baos.toString()));
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
|
||||
try {
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
new Print().call("string");
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
|
||||
System.out.println(Lab4.clean(baos.toString()));
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test #2.
|
||||
*/
|
||||
public static void test2() {
|
||||
PrintStream old = System.out;
|
||||
ByteArrayOutputStream baos;
|
||||
PrintStream ps;
|
||||
|
||||
try {
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
Probably.just(4).act(new Print());
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
|
||||
System.out.println(Lab4.clean(baos.toString()));
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
|
||||
try {
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
Probably.just("string").act(new Print());
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
|
||||
System.out.println(Lab4.clean(baos.toString()));
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
|
||||
try {
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
Probably.none().act(new Print());
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
|
||||
System.out.println(Lab4.clean(baos.toString()));
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test #3.
|
||||
*/
|
||||
public static void test3() {
|
||||
try {
|
||||
System.out.println(new Incr().invoke(4).toString());
|
||||
System.out.println(new Incr().invoke(new Incr().invoke(4)).toString());
|
||||
System.out.println(new Length().invoke("string").toString());
|
||||
System.out.println(new Incr().invoke(new Length().invoke("string")).toString());
|
||||
|
||||
System.out.println(new Improbable<Integer>().invoke(1).toString());
|
||||
System.out.println(new Improbable<String>().invoke(null).toString());
|
||||
System.out.println(new Improbable<Integer>().invoke(1).transform(new Incr()).toString());
|
||||
System.out.println(new Improbable<>().invoke(new Improbable<Integer>().invoke(1)).toString());
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test #4.
|
||||
*/
|
||||
public static void test4() {
|
||||
try {
|
||||
System.out.println(Probably.just(4).transform(new Incr()).toString());
|
||||
System.out.println(Probably.just(4).transform(new Incr()).transform(new Incr()).toString());
|
||||
System.out.println(Probably.just("string").transform(new Length()).toString());
|
||||
System.out.println(Probably.just("string").transform(new Length()).transform(new Incr()).toString());
|
||||
|
||||
System.out.println(Probably.<Integer>none().transform(new Incr()).toString());
|
||||
System.out.println(Probably.<String>none().transform(new Length()).toString());
|
||||
System.out.println(Probably.<String>just(null).transform(new Length()).transform(new Incr()).toString());
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test #5.
|
||||
*/
|
||||
public static void test5() {
|
||||
Probably<Immutator<Integer,Integer>> justIncr = Probably.just(new Incr());
|
||||
Probably<Immutator<Integer,String>> justLength = Probably.just(new Length());
|
||||
Probably<Immutator<Integer,Integer>> noIncr = Probably.none();
|
||||
Probably<Immutator<Integer,String>> noLength = Probably.none();
|
||||
|
||||
try {
|
||||
System.out.println(Probably.just(17).check(new IsModEq(3,2)).toString());
|
||||
System.out.println(Probably.just(18).check(new IsModEq(3,2)).toString());
|
||||
|
||||
System.out.println(Probably.just(16).transform(new Incr()).check(new IsModEq(3,2)).toString());
|
||||
System.out.println(Probably.just("string").transform(new Length()).transform(new Incr()).transform(new Incr()).check(new IsModEq(3,2)).toString());
|
||||
System.out.println(Probably.<Integer>just(null).check(new IsModEq(0,2)).toString());
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test #6.
|
||||
*/
|
||||
public static void test6() {
|
||||
Probably<Immutator<Integer,Integer>> justIncr = Probably.just(new Incr());
|
||||
Probably<Immutator<Integer,String>> justLength = Probably.just(new Length());
|
||||
Probably<Immutator<Integer,Integer>> noIncr = Probably.none();
|
||||
Probably<Immutator<Integer,String>> noLength = Probably.none();
|
||||
|
||||
try {
|
||||
System.out.println(Probably.just(17).apply(justIncr).toString());
|
||||
System.out.println(Probably.<Integer>none().apply(justIncr).toString());
|
||||
System.out.println(Probably.just(17).apply(noIncr).toString());
|
||||
System.out.println(Probably.<Integer>none().apply(noIncr).toString());
|
||||
|
||||
System.out.println(Probably.just("string").apply(justLength).toString());
|
||||
System.out.println(Probably.<String>none().apply(justLength).toString());
|
||||
System.out.println(Probably.just("string").apply(noLength).toString());
|
||||
System.out.println(Probably.<String>none().apply(noLength).toString());
|
||||
} catch(Exception e) {
|
||||
System.out.println("Error occurred");
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
cs2030s/labs/Lab4/Lab4.pdf
Normal file
BIN
cs2030s/labs/Lab4/Lab4.pdf
Normal file
Binary file not shown.
60
cs2030s/labs/Lab4/MyTest.java
Normal file
60
cs2030s/labs/Lab4/MyTest.java
Normal file
@@ -0,0 +1,60 @@
|
||||
interface Function<T, R> {
|
||||
R apply(T t);
|
||||
}
|
||||
|
||||
interface Functor<T, F extends Functor<?, ?>> {
|
||||
<R> F map(Function<T, R> f);
|
||||
}
|
||||
|
||||
class Identity<T> implements Functor<T, Identity<?>> {
|
||||
private final T value;
|
||||
|
||||
public Identity(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Identity<R> map(Function<T, R> f) {
|
||||
final R result = f.apply(this.value);
|
||||
return new Identity<>(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Incr implements Immutator<Integer, Integer> {
|
||||
|
||||
@Override
|
||||
public Integer invoke(Integer param) {
|
||||
return param + 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Length implements Immutator<Integer, String> {
|
||||
|
||||
@Override
|
||||
public Integer invoke(String param) {
|
||||
return param.length();
|
||||
}
|
||||
}
|
||||
|
||||
class Print implements Action<Object> {
|
||||
|
||||
@Override
|
||||
public void call(Object item) {
|
||||
System.out.println(item);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Probably<Integer> maybeInt = Probably.just(10);
|
||||
maybeInt.act(new Print());
|
||||
System.out.println(Probably.just(2030).check(new IsModEq(0, 2)));
|
||||
|
||||
Identity<String> idString = new Identity<>("abc");
|
||||
Identity<Integer> idInt = idString.map(String::length);
|
||||
}
|
||||
}
|
||||
17
cs2030s/labs/Lab4/Print.java
Normal file
17
cs2030s/labs/Lab4/Print.java
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* A non-generic Action to print the String
|
||||
* representation of the object.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
*
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
class Print implements Action<Object> {
|
||||
|
||||
@Override
|
||||
public void call(Object item) {
|
||||
System.out.println(item);
|
||||
}
|
||||
|
||||
}
|
||||
134
cs2030s/labs/Lab4/Probably.java
Normal file
134
cs2030s/labs/Lab4/Probably.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* This class implements something that
|
||||
* probably is just a value but may be nothing.
|
||||
* We will never return null in this class, but
|
||||
* we may return something that contains nothing
|
||||
* where the nothing is a null.
|
||||
*
|
||||
* @author Yadunand Prem (10B)
|
||||
* @version CS2030S AY22/23 Semester 1
|
||||
*/
|
||||
class Probably<T> implements Actionable<T>, Immutatorable<T>, Applicable<T> {
|
||||
private final T value;
|
||||
|
||||
private static final Probably<?> NONE = new Probably<>(null);
|
||||
|
||||
/**
|
||||
* Private constructor, can only be invoked inside.
|
||||
* This is called a factory method. We can only
|
||||
* create this using the two public static method.
|
||||
*
|
||||
* @param value T
|
||||
*/
|
||||
private Probably(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* It is probably nothing, no value inside.
|
||||
*
|
||||
* @param <T> type T
|
||||
* @return The shared NOTHING.
|
||||
*/
|
||||
public static <T> Probably<T> none() {
|
||||
@SuppressWarnings("unchecked")
|
||||
Probably<T> res = (Probably<T>) NONE;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* It is probably just the given value.
|
||||
* Unless the value is null, then nothing is
|
||||
* given again.
|
||||
*
|
||||
* @param <T> type T
|
||||
*
|
||||
* @param value Probably this is the value
|
||||
* unless it is null then we say
|
||||
* that there is no
|
||||
* @return The given value or nothing but
|
||||
* never null.
|
||||
*/
|
||||
public static <T> Probably<T> just(T value) {
|
||||
if (value == null) {
|
||||
return none();
|
||||
}
|
||||
return new Probably<>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for equality between something that
|
||||
* is probably a value but maybe nothing.
|
||||
*
|
||||
* @param obj The other value to be compared.
|
||||
* @return True if the two values are equal,
|
||||
* false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Probably<?>) {
|
||||
Probably<?> some = (Probably<?>) obj;
|
||||
if (this.value == some.value) {
|
||||
return true;
|
||||
}
|
||||
if (this.value == null || some.value == null) {
|
||||
return false;
|
||||
}
|
||||
return this.value.equals(some.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of something that
|
||||
* is probably a value but maybe nothing.
|
||||
*
|
||||
* @return The string representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this.value == null) {
|
||||
return "<>";
|
||||
} else {
|
||||
return "<" + this.value.toString() + ">";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(Action<? super T> action) {
|
||||
if (this.value == null) {
|
||||
return;
|
||||
}
|
||||
action.call(this.value);
|
||||
}
|
||||
|
||||
public Probably<T> check(Immutator<Boolean, ? super T> eq) {
|
||||
if (this.value == null) {
|
||||
return none();
|
||||
}
|
||||
if (eq.invoke(this.value)) {
|
||||
return this;
|
||||
}
|
||||
return none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Probably<R> transform(Immutator<? extends R, ? super T> immutator) {
|
||||
if (this.value == null) {
|
||||
return none();
|
||||
}
|
||||
return just(immutator.invoke(this.value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Probably<R> apply(Probably<? extends Immutator<? extends R, ? super T>> probablyImmutator) {
|
||||
if (probablyImmutator.value != null) {
|
||||
return this.transform(probablyImmutator.value);
|
||||
}
|
||||
return none();
|
||||
}
|
||||
|
||||
}
|
||||
32
cs2030s/labs/Lab4/Test1.java
Normal file
32
cs2030s/labs/Lab4/Test1.java
Normal file
@@ -0,0 +1,32 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
class Test1 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
PrintStream old = System.out;
|
||||
ByteArrayOutputStream baos;
|
||||
PrintStream ps;
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
new Print().call(17);
|
||||
we.expectPrint("new Print().call(17)",
|
||||
"17",
|
||||
baos,
|
||||
old);
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
new Print().call("string");
|
||||
we.expectPrint("new Print().call(\"string\")",
|
||||
"string",
|
||||
baos,
|
||||
old);
|
||||
}
|
||||
}
|
||||
42
cs2030s/labs/Lab4/Test2.java
Normal file
42
cs2030s/labs/Lab4/Test2.java
Normal file
@@ -0,0 +1,42 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
class Test2 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
PrintStream old = System.out;
|
||||
ByteArrayOutputStream baos;
|
||||
PrintStream ps;
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
Probably.just(4).act(new Print());
|
||||
we.expectPrint("Probably.just(4).act(new Print())",
|
||||
"4",
|
||||
baos,
|
||||
old);
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
Probably.just("string").act(new Print());
|
||||
we.expectPrint("Probably.just(\"string\").act(new Print())",
|
||||
"string",
|
||||
baos,
|
||||
old);
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
|
||||
Probably.none().act(new Print());
|
||||
we.expectPrint("Probably.none().act(new Print())",
|
||||
"",
|
||||
baos,
|
||||
old);
|
||||
}
|
||||
}
|
||||
43
cs2030s/labs/Lab4/Test3.java
Normal file
43
cs2030s/labs/Lab4/Test3.java
Normal file
@@ -0,0 +1,43 @@
|
||||
class Test3 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
class Incr implements Immutator<Integer, Integer> {
|
||||
public Integer invoke(Integer t1) {
|
||||
return t1 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Length implements Immutator<Integer, String> {
|
||||
public Integer invoke(String t1) {
|
||||
return t1.length();
|
||||
}
|
||||
}
|
||||
|
||||
we.expect("new Incr().invoke(4)",
|
||||
new Incr().invoke(4).toString(),
|
||||
"5");
|
||||
we.expect("new Incr().invoke(new Incr().invoke(4))",
|
||||
new Incr().invoke(new Incr().invoke(4)).toString(),
|
||||
"6");
|
||||
we.expect("new Length().invoke(\"string\")",
|
||||
new Length().invoke("string").toString(),
|
||||
"6");
|
||||
we.expect("new Incr().invoke(new Length().invoke(\"string\"))",
|
||||
new Incr().invoke(new Length().invoke("string")).toString(),
|
||||
"7");
|
||||
|
||||
we.expect("new Improbable<>().invoke(1)",
|
||||
new Improbable<Integer>().invoke(1).toString(),
|
||||
"<1>");
|
||||
we.expect("new Improbable<String>().invoke(null)",
|
||||
new Improbable<String>().invoke(null).toString(),
|
||||
"<>");
|
||||
we.expect("new Improbable<Integer>().invoke(1).transform(new Incr())",
|
||||
new Improbable<Integer>().invoke(1).transform(new Incr()).toString(),
|
||||
"<2>");
|
||||
we.expect("new Improbable<>().invoke(new Improbable<>().invoke(1))",
|
||||
new Improbable<>().invoke(new Improbable<Integer>().invoke(1)).toString(),
|
||||
"<<1>>");
|
||||
}
|
||||
}
|
||||
40
cs2030s/labs/Lab4/Test4.java
Normal file
40
cs2030s/labs/Lab4/Test4.java
Normal file
@@ -0,0 +1,40 @@
|
||||
class Test4 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
class Incr implements Immutator<Integer, Integer> {
|
||||
public Integer invoke(Integer t1) {
|
||||
return t1 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Length implements Immutator<Integer, String> {
|
||||
public Integer invoke(String t1) {
|
||||
return t1.length();
|
||||
}
|
||||
}
|
||||
|
||||
we.expect("Probably.just(4).transform(new Incr())",
|
||||
Probably.just(4).transform(new Incr()).toString(),
|
||||
"<5>");
|
||||
we.expect("Probably.just(4).transform(new Incr()).transform(new Incr())",
|
||||
Probably.just(4).transform(new Incr()).transform(new Incr()).toString(),
|
||||
"<6>");
|
||||
we.expect("Probably.just(\"string\").transform(new Length())",
|
||||
Probably.just("string").transform(new Length()).toString(),
|
||||
"<6>");
|
||||
we.expect("Probably.just(\"string\").transform(new Length()).transform(new Incr())",
|
||||
Probably.just("string").transform(new Length()).transform(new Incr()).toString(),
|
||||
"<7>");
|
||||
|
||||
we.expect("Probably.<Integer>none().transform(new Incr())",
|
||||
Probably.<Integer>none().transform(new Incr()).toString(),
|
||||
"<>");
|
||||
we.expect("Probably.<String>none().transform(new Length())",
|
||||
Probably.<String>none().transform(new Length()).toString(),
|
||||
"<>");
|
||||
we.expect("Probably.<String>just(null).transform(new Length()).transform(new Incr())",
|
||||
Probably.<String>just(null).transform(new Length()).transform(new Incr()).toString(),
|
||||
"<>");
|
||||
}
|
||||
}
|
||||
34
cs2030s/labs/Lab4/Test5.java
Normal file
34
cs2030s/labs/Lab4/Test5.java
Normal file
@@ -0,0 +1,34 @@
|
||||
class Test5 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
class Incr implements Immutator<Integer, Integer> {
|
||||
public Integer invoke(Integer t1) {
|
||||
return t1 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Length implements Immutator<Integer, String> {
|
||||
public Integer invoke(String t1) {
|
||||
return t1.length();
|
||||
}
|
||||
}
|
||||
|
||||
we.expect("Probably.just(17).check(new IsModEq(3,2)) // 17 % 3 is equal to 2",
|
||||
Probably.just(17).check(new IsModEq(3, 2)).toString(),
|
||||
"<17>");
|
||||
we.expect("Probably.just(18).check(new IsModEq(3,2)) // 18 % 3 is not equal to 2",
|
||||
Probably.just(18).check(new IsModEq(3,2)).toString(),
|
||||
"<>");
|
||||
|
||||
we.expect("Probably.just(16).transform(new Incr()).check(new IsModEq(3,2)) // 17 % 3 is not equal to 2",
|
||||
Probably.just(16).transform(new Incr()).check(new IsModEq(3,2)).toString(),
|
||||
"<17>");
|
||||
we.expect("Probably.just(\"string\").transform(new Length()).check(new IsModEq(3,2))",
|
||||
Probably.just("string").transform(new Length()).transform(new Incr()).transform(new Incr()).check(new IsModEq(3,2)).toString(),
|
||||
"<8>");
|
||||
we.expect("Probably.<Integer>just(null).check(new IsModEq(0,2))",
|
||||
Probably.<Integer>just(null).check(new IsModEq(0,2)).toString(),
|
||||
"<>");
|
||||
}
|
||||
}
|
||||
48
cs2030s/labs/Lab4/Test6.java
Normal file
48
cs2030s/labs/Lab4/Test6.java
Normal file
@@ -0,0 +1,48 @@
|
||||
class Test6 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
class Incr implements Immutator<Integer, Integer> {
|
||||
public Integer invoke(Integer t1) {
|
||||
return t1 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Length implements Immutator<Integer, String> {
|
||||
public Integer invoke(String t1) {
|
||||
return t1.length();
|
||||
}
|
||||
}
|
||||
|
||||
Probably<Immutator<Integer, Integer>> justIncr = Probably.just(new Incr());
|
||||
Probably<Immutator<Integer, String>> justLength = Probably.just(new Length());
|
||||
Probably<Immutator<Integer, Integer>> noIncr = Probably.none();
|
||||
Probably<Immutator<Integer, String>> noLength = Probably.none();
|
||||
|
||||
we.expect("Probably.just(17).<Integer>apply(justIncr)",
|
||||
Probably.just(17).apply(justIncr).toString(),
|
||||
"<18>");
|
||||
we.expect("Probably.<Integer>none().<Integer>apply(justIncr)",
|
||||
Probably.<Integer>none().apply(justIncr).toString(),
|
||||
"<>");
|
||||
we.expect("Probably.just(17).<Integer>apply(noIncr)",
|
||||
Probably.just(17).apply(noIncr).toString(),
|
||||
"<>");
|
||||
we.expect("Probably.<Integer>none().<Integer>apply(noIncr)",
|
||||
Probably.<Integer>none().apply(noIncr).toString(),
|
||||
"<>");
|
||||
|
||||
we.expect("Probably.just(\"string\").<Integer>apply(justLength)",
|
||||
Probably.just("string").apply(justLength).toString(),
|
||||
"<6>");
|
||||
we.expect("Probably.<String>none().<Integer>apply(justLength)",
|
||||
Probably.<String>none().apply(justLength).toString(),
|
||||
"<>");
|
||||
we.expect("Probably.just(\"string\").<Integer>apply(noLength)",
|
||||
Probably.just("string").apply(noLength).toString(),
|
||||
"<>");
|
||||
we.expect("Probably.<String>none().<Integer>apply(noLength)",
|
||||
Probably.<String>none().apply(noLength).toString(),
|
||||
"<>");
|
||||
}
|
||||
}
|
||||
58
cs2030s/labs/Lab4/TestProbably.java
Normal file
58
cs2030s/labs/Lab4/TestProbably.java
Normal file
@@ -0,0 +1,58 @@
|
||||
class TestProbably {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
we.expect("Probably.just(4)",
|
||||
Probably.just(4).toString(),
|
||||
"<4>");
|
||||
we.expect("Probably.just(Probably.just(0))",
|
||||
Probably.just(Probably.just(0)).toString(),
|
||||
"<<0>>");
|
||||
we.expect("Probably.just(Probably.just(Probably.just(\"null\")))",
|
||||
Probably.just(Probably.just(Probably.just("null"))).toString(),
|
||||
"<<<null>>>");
|
||||
we.expect("Probably.just(Probably.just(Probably.none()))",
|
||||
Probably.just(Probably.just(Probably.none())).toString(),
|
||||
"<<<>>>");
|
||||
we.expect("Probably.just(Probably.just(null))",
|
||||
Probably.just(Probably.just(null)).toString(),
|
||||
"<<>>");
|
||||
|
||||
we.expect("Probably.just(4).equals(Probably.just(4))",
|
||||
Probably.just(4).equals(Probably.just(4)),
|
||||
true);
|
||||
we.expect("Probably.just(4).equals(4)",
|
||||
Probably.just(4).equals(4),
|
||||
false);
|
||||
we.expect("Probably.just(Probably.just(0)).equals(Probably.just(0))",
|
||||
Probably.just(Probably.just(0)).equals(Probably.just(0)),
|
||||
false);
|
||||
we.expect("Probably.just(Probably.just(0)).equals(Probably.just(Probably.just(0)))",
|
||||
Probably.just(Probably.just(0)).equals(Probably.just(Probably.just(0))),
|
||||
true);
|
||||
|
||||
we.expect("Probably.just(\"string\")",
|
||||
Probably.just("string").toString(),
|
||||
"<string>");
|
||||
|
||||
we.expect("Probably.just(\"string\").equals(Probably.just(4))",
|
||||
Probably.just("string").equals(Probably.just(4)),
|
||||
false);
|
||||
we.expect("Probably.just(\"string\").equals(Probably.just(\"null\"))",
|
||||
Probably.just("string").equals(Probably.just("null")),
|
||||
false);
|
||||
|
||||
we.expect("Probably.just(null)",
|
||||
Probably.just(null).toString(),
|
||||
"<>");
|
||||
we.expect("Probably.none()",
|
||||
Probably.none().toString(),
|
||||
"<>");
|
||||
we.expect("Probably.none().equals(Probably.just(null))",
|
||||
Probably.none().equals(Probably.just(null)),
|
||||
true);
|
||||
we.expect("Probably.none() == Probably.just(null)",
|
||||
Probably.none() == Probably.just(null),
|
||||
true);
|
||||
}
|
||||
}
|
||||
1
cs2030s/labs/Lab4/inputs/Lab4.1.in
Normal file
1
cs2030s/labs/Lab4/inputs/Lab4.1.in
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
1
cs2030s/labs/Lab4/inputs/Lab4.2.in
Normal file
1
cs2030s/labs/Lab4/inputs/Lab4.2.in
Normal file
@@ -0,0 +1 @@
|
||||
2
|
||||
1
cs2030s/labs/Lab4/inputs/Lab4.3.in
Normal file
1
cs2030s/labs/Lab4/inputs/Lab4.3.in
Normal file
@@ -0,0 +1 @@
|
||||
3
|
||||
1
cs2030s/labs/Lab4/inputs/Lab4.4.in
Normal file
1
cs2030s/labs/Lab4/inputs/Lab4.4.in
Normal file
@@ -0,0 +1 @@
|
||||
4
|
||||
1
cs2030s/labs/Lab4/inputs/Lab4.5.in
Normal file
1
cs2030s/labs/Lab4/inputs/Lab4.5.in
Normal file
@@ -0,0 +1 @@
|
||||
5
|
||||
1
cs2030s/labs/Lab4/inputs/Lab4.6.in
Normal file
1
cs2030s/labs/Lab4/inputs/Lab4.6.in
Normal file
@@ -0,0 +1 @@
|
||||
6
|
||||
76
cs2030s/labs/Lab5/CS2030STest.java
Normal file
76
cs2030s/labs/Lab5/CS2030STest.java
Normal file
@@ -0,0 +1,76 @@
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import javax.tools.DiagnosticCollector;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public 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";
|
||||
|
||||
public void expect(String test, Object output, Object expect) {
|
||||
System.out.print(test);
|
||||
if ((expect == null && output == null) || output.equals(expect)) {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
} else {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
System.out.println(" expected: " + expect);
|
||||
System.out.println(" got this: " + output);
|
||||
}
|
||||
}
|
||||
|
||||
public static String clean(String txt) {
|
||||
String res = "";
|
||||
for (int i=0; i<txt.length(); i++) {
|
||||
if (txt.charAt(i) != '\r' && txt.charAt(i) != '\n') {
|
||||
res += txt.charAt(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public void expectPrint(String test, Object expect, ByteArrayOutputStream baos, PrintStream old) {
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
expect(test, CS2030STest.clean(baos.toString()), expect);
|
||||
}
|
||||
|
||||
public void expectCompile(String test, String statement, boolean success) {
|
||||
System.out.print(test);
|
||||
|
||||
class JavaSourceFromString extends SimpleJavaFileObject {
|
||||
final String code;
|
||||
|
||||
JavaSourceFromString(String code) {
|
||||
super(URI.create("string:///TempClass.java"), Kind.SOURCE);
|
||||
this.code = "class TempClass {void foo(){" + code + ";}}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
boolean noError = ToolProvider
|
||||
.getSystemJavaCompiler()
|
||||
.getTask(null, null, new DiagnosticCollector<>(), null, null,
|
||||
List.of(new JavaSourceFromString(statement)))
|
||||
.call();
|
||||
|
||||
if (noError != success) {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
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 {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
cs2030s/labs/Lab5/Lab5.h
Normal file
17
cs2030s/labs/Lab5/Lab5.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir cs2030s
|
||||
cd cs2030s
|
||||
mkdir fp
|
||||
cd ..
|
||||
|
||||
mv Action.java cs2030s/fp/Action.java
|
||||
mv Actionable.java cs2030s/fp/Actionable.java
|
||||
mv Actually.java cs2030s/fp/Actually.java
|
||||
mv Constant.java cs2030s/fp/Constant.java
|
||||
mv Immutator.java cs2030s/fp/Immutator.java
|
||||
mv Immutatorable.java cs2030s/fp/Immutatorable.java
|
||||
mv Transformer.java cs2030s/fp/Transformer.java
|
||||
|
||||
javac cs2030s/fp/*.java
|
||||
javac *.java
|
||||
222
cs2030s/labs/Lab5/Lab5.java
Normal file
222
cs2030s/labs/Lab5/Lab5.java
Normal file
@@ -0,0 +1,222 @@
|
||||
import cs2030s.fp.Action;
|
||||
import cs2030s.fp.Actually;
|
||||
import cs2030s.fp.Constant;
|
||||
import cs2030s.fp.Immutator;
|
||||
import cs2030s.fp.Transformer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
class Lab5 {
|
||||
|
||||
public static String getGrade(String module, String student, String assessment,
|
||||
Map<String, Map<String, Map<String, String>>> db) {
|
||||
Constant<Actually<Map<String, Map<String, Map<String, String>>>>> constantDb = () -> Actually.ok(db);
|
||||
|
||||
Constant<String> constantNoEntry = () -> "No such entry";
|
||||
|
||||
Immutator<Actually<Map<String, Map<String, String>>>, Map<String, Map<String, Map<String, String>>>> getModule = param -> Actually
|
||||
.ok(param.get(module));
|
||||
|
||||
Immutator<Actually<Map<String, String>>, Map<String, Map<String, String>>> getStudent = param -> Actually
|
||||
.ok(param.get(student));
|
||||
|
||||
Immutator<Actually<String>, Map<String, String>> getAssessment = param -> Actually
|
||||
.ok(param.get(assessment).toString());
|
||||
|
||||
return constantDb.init().next(getModule).next(getStudent).next(getAssessment).except(constantNoEntry);
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Create a scanner to read from standard input.
|
||||
Scanner sc = new Scanner(System.in);
|
||||
|
||||
// Read a single integer from the test file
|
||||
// and then run the appropriate test case
|
||||
switch (sc.nextInt()) {
|
||||
case 1:
|
||||
test1();
|
||||
break;
|
||||
case 2:
|
||||
test2();
|
||||
break;
|
||||
case 3:
|
||||
test3();
|
||||
break;
|
||||
case 4:
|
||||
test4();
|
||||
break;
|
||||
case 5:
|
||||
test5();
|
||||
break;
|
||||
case 6:
|
||||
test6();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void test1() {
|
||||
String none = null;
|
||||
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.err(new Exception("Err"))));
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.err(new Exception("Error"))));
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.err(new Exception(none))));
|
||||
System.out.println(Actually.err(new ArithmeticException(none)).equals(Actually.err(new Exception(none))));
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.ok("Err")));
|
||||
System.out.println(Actually.ok("Err").equals(Actually.ok("Err")));
|
||||
System.out.println(Actually.ok("Err").equals(Actually.err(new Exception("Error"))));
|
||||
System.out.println(Actually.ok("Err").equals("Err"));
|
||||
System.out.println(Actually.ok(null).equals(Actually.ok("Err")));
|
||||
System.out.println(Actually.ok(null).equals(Actually.ok(null)));
|
||||
System.out.println(Actually.ok(null).equals("Err"));
|
||||
System.out.println(Actually.ok(null).equals(null));
|
||||
}
|
||||
|
||||
public static void test2() {
|
||||
Constant<Integer> zero = new Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
Action<Integer> print = new Action<>() {
|
||||
public void call(Integer i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
Actually.<Number>ok(0).unwrap().toString();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
Actually.<Integer>ok(9).finish(print);
|
||||
Actually.<Integer>err(new Exception("Err")).finish(print);
|
||||
System.out.println(Actually.<Number>ok(9).except(zero).toString());
|
||||
System.out.println(Actually.<Number>err(new ArithmeticException("div by 0")).except(zero).toString());
|
||||
System.out.println(Actually.<Number>err(new ArithmeticException("div by 0")).unless(4).toString());
|
||||
System.out.println(Actually.<Number>ok(0).unless(4).toString());
|
||||
}
|
||||
|
||||
public static void test3() {
|
||||
Immutator<Integer, Integer> inc = new Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p + 1;
|
||||
}
|
||||
};
|
||||
Immutator<Integer, Integer> inv = new Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return 1 / p;
|
||||
}
|
||||
};
|
||||
Immutator<Number, Integer> incNum = new Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return p + 1;
|
||||
}
|
||||
};
|
||||
Immutator<Number, Integer> invNum = new Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return 1 / p;
|
||||
}
|
||||
};
|
||||
|
||||
System.out.println(Actually.<Integer>ok(0).transform(inc).toString());
|
||||
System.out.println(Actually.<Integer>ok(0).transform(inv).toString());
|
||||
System.out.println(Actually.ok(0).transform(inc).toString());
|
||||
System.out.println(Actually.ok(0).transform(inv).toString());
|
||||
System.out.println(Actually.<Integer>ok(0).transform(incNum).toString());
|
||||
System.out.println(Actually.<Integer>ok(0).transform(invNum).toString());
|
||||
System.out.println(Actually.ok(0).transform(incNum).toString());
|
||||
System.out.println(Actually.ok(0).transform(invNum).toString());
|
||||
}
|
||||
|
||||
public static void test4() {
|
||||
Transformer<Integer, Integer> inc = new Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p + 1;
|
||||
}
|
||||
};
|
||||
Transformer<Integer, Integer> sqr = new Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p * p;
|
||||
}
|
||||
};
|
||||
|
||||
Transformer<Integer, Integer> sqrPlusOneA = sqr.before(inc);
|
||||
Transformer<Integer, Integer> sqrPlusOneB = inc.after(sqr);
|
||||
Transformer<Integer, Integer> plusOneSqrA = sqr.after(inc);
|
||||
Transformer<Integer, Integer> plusOneSqrB = inc.before(sqr);
|
||||
|
||||
System.out.println(sqrPlusOneA.invoke(2).toString());
|
||||
System.out.println(sqrPlusOneA.invoke(2).toString());
|
||||
System.out.println(plusOneSqrA.invoke(2).toString());
|
||||
System.out.println(plusOneSqrB.invoke(2).toString());
|
||||
}
|
||||
|
||||
public static void test5() {
|
||||
Immutator<Actually<Integer>, Integer> half = new Immutator<>() {
|
||||
public Actually<Integer> invoke(Integer p) {
|
||||
if (p % 2 == 0) {
|
||||
return Actually.<Integer>ok(p / 2);
|
||||
} else {
|
||||
return Actually.<Integer>err(new Exception("odd number"));
|
||||
}
|
||||
}
|
||||
};
|
||||
Immutator<Actually<Integer>, Integer> inc = new Immutator<>() {
|
||||
public Actually<Integer> invoke(Integer p) {
|
||||
return Actually.<Integer>ok(p + 1);
|
||||
}
|
||||
};
|
||||
Immutator<Actually<Integer>, Integer> make = new Immutator<>() {
|
||||
public Actually<Integer> invoke(Integer p) {
|
||||
return Actually.<Integer>ok(p);
|
||||
}
|
||||
};
|
||||
Constant<Integer> zero = new Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
System.out.println(make.invoke(0).next(inc).next(inc).next(half).toString());
|
||||
System.out.println(make.invoke(0).next(inc).next(half).next(inc).toString());
|
||||
System.out.println(make.invoke(0).next(inc).next(inc).next(half).except(zero).toString());
|
||||
System.out.println(make.invoke(0).next(inc).next(half).next(inc).except(zero).toString());
|
||||
}
|
||||
|
||||
public static void test6() {
|
||||
Map<String, Map<String, Map<String, String>>> nus = Map.of(
|
||||
"CS2030S", Map.of(
|
||||
"Steve", Map.of(
|
||||
"lab1", "A",
|
||||
"lab2", "A-",
|
||||
"lab3", "A+",
|
||||
"lab4", "B",
|
||||
"pe1", "C"),
|
||||
"Tony", Map.of(
|
||||
"lab1", "C",
|
||||
"lab2", "C",
|
||||
"lab3", "B-",
|
||||
"lab4", "B+",
|
||||
"pe1", "A")),
|
||||
"CS2040S", Map.of(
|
||||
"Steve", Map.of(
|
||||
"lab1", "A",
|
||||
"lab2", "A+",
|
||||
"lab3", "A+",
|
||||
"lab4", "A",
|
||||
"midterm", "A+")));
|
||||
|
||||
System.out.println(getGrade("CS2030S", "Steve", "lab1", nus));
|
||||
System.out.println(getGrade("CS2030S", "Steve", "lab2", nus));
|
||||
System.out.println(getGrade("CS2040S", "Steve", "lab3", nus));
|
||||
System.out.println(getGrade("CS2040S", "Steve", "lab4", nus));
|
||||
System.out.println(getGrade("CS2030S", "Tony", "lab1", nus));
|
||||
System.out.println(getGrade("CS2030S", "Tony", "midterm", nus));
|
||||
System.out.println(getGrade("CS2040S", "Tony", "lab4", nus));
|
||||
System.out.println(getGrade("CS2040S", "Bruce", "lab4", nus));
|
||||
}
|
||||
}
|
||||
BIN
cs2030s/labs/Lab5/Lab5.pdf
Normal file
BIN
cs2030s/labs/Lab5/Lab5.pdf
Normal file
Binary file not shown.
24
cs2030s/labs/Lab5/Test0.java
Normal file
24
cs2030s/labs/Lab5/Test0.java
Normal file
@@ -0,0 +1,24 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test0 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
we.expectCompile("Actually<Object> a = new Actually<>() should not compile",
|
||||
"cs2030s.fp.Actually<Object> a = new cs2030s.fp.Actually<>();", false);
|
||||
we.expectCompile("Actually.Success<Object> s should not compile",
|
||||
"cs2030s.fp.Actually.Success<Object> s;", false);
|
||||
we.expectCompile("Actually.Failure f should not compile",
|
||||
"cs2030s.fp.Actually.Failure f;", false);
|
||||
|
||||
we.expectCompile("Actually<String> success = Actually.ok(\"success\") should compile",
|
||||
"cs2030s.fp.Actually<String> success = cs2030s.fp.Actually.ok(\"success\");", true);
|
||||
we.expectCompile("Actually<Integer> none = Actually.ok(null) should compile",
|
||||
"cs2030s.fp.Actually<Integer> none = cs2030s.fp.Actually.ok(null);", true);
|
||||
we.expectCompile("Actually<Integer> four = Actually.ok(4) should compile",
|
||||
"cs2030s.fp.Actually<Integer> four = cs2030s.fp.Actually.ok(4);", true);
|
||||
we.expectCompile("Actually<Object> div0 = Actually.err(new ArithmeticException(\"Divide by 0\")) should compile",
|
||||
"cs2030s.fp.Actually<Object> div0 = cs2030s.fp.Actually.err(new ArithmeticException(\"Divide by 0\"));", true);
|
||||
}
|
||||
}
|
||||
73
cs2030s/labs/Lab5/Test1.java
Normal file
73
cs2030s/labs/Lab5/Test1.java
Normal file
@@ -0,0 +1,73 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test1 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
String none = null;
|
||||
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.err(new Exception(\"Err\")))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.err(new Exception("Err"))),
|
||||
true
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.err(new Exception(\"Error\")))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.err(new Exception("Error"))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.err(new Exception(null)))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.err(new Exception(none))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(null)).equals(Actually.err(new Exception(null)))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException(none)).equals(cs2030s.fp.Actually.err(new Exception(none))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.ok(\"Err\"))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.ok("Err")),
|
||||
false
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.ok(\"Err\").equals(Actually.ok(\"Err\"))",
|
||||
cs2030s.fp.Actually.ok("Err").equals(cs2030s.fp.Actually.ok("Err")),
|
||||
true
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(\"Err\").equals(Actually.err(new Exception(\"Error\")))",
|
||||
cs2030s.fp.Actually.ok("Err").equals(cs2030s.fp.Actually.err(new Exception("Error"))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(\"Err\").equals(\"Err\")",
|
||||
cs2030s.fp.Actually.ok("Err").equals("Err"),
|
||||
false
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(Actually.ok(\"Err\"))",
|
||||
cs2030s.fp.Actually.ok(null).equals(cs2030s.fp.Actually.ok("Err")),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(Actually.ok(null))",
|
||||
cs2030s.fp.Actually.ok(null).equals(cs2030s.fp.Actually.ok(null)),
|
||||
true
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(\"Err\")",
|
||||
cs2030s.fp.Actually.ok(null).equals("Err"),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(null)",
|
||||
cs2030s.fp.Actually.ok(null).equals(null),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
72
cs2030s/labs/Lab5/Test2.java
Normal file
72
cs2030s/labs/Lab5/Test2.java
Normal file
@@ -0,0 +1,72 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test2 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
PrintStream old = System.out;
|
||||
ByteArrayOutputStream baos;
|
||||
PrintStream ps;
|
||||
|
||||
cs2030s.fp.Constant<Integer> zero = new cs2030s.fp.Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Action<Integer> print = new cs2030s.fp.Action<>() {
|
||||
public void call(Integer i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
we.expect(
|
||||
"Actually.<Number>ok(0).unwrap()",
|
||||
cs2030s.fp.Actually.<Number>ok(0).unwrap().toString(),
|
||||
"0"
|
||||
);
|
||||
} catch(Exception e) {
|
||||
System.out.println("Unexpected error occurs");
|
||||
}
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
cs2030s.fp.Actually.<Integer>ok(9).finish(print);
|
||||
we.expectPrint("Actually.<Integer>ok(9).finish(print)",
|
||||
"9",
|
||||
baos,
|
||||
old);
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
cs2030s.fp.Actually.<Integer>err(new Exception("Err")).finish(print);
|
||||
we.expectPrint("Actually.<Integer>err(new Exception(\"Err\")).finish(print)",
|
||||
"",
|
||||
baos,
|
||||
old);
|
||||
|
||||
we.expect(
|
||||
"Actually.<Number>ok(9).except(zero)",
|
||||
cs2030s.fp.Actually.<Number>ok(9).except(zero).toString(),
|
||||
"9"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Number>err(new ArithmeticException(\"div by 0\")).except(zero)",
|
||||
cs2030s.fp.Actually.<Number>err(new ArithmeticException("div by 0")).except(zero).toString(),
|
||||
"0"
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.<Number>err(new ArithmeticException(\"div by 0\")).unless(4)",
|
||||
cs2030s.fp.Actually.<Number>err(new ArithmeticException("div by 0")).unless(4).toString(),
|
||||
"4"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Number>ok(0).unless(4)",
|
||||
cs2030s.fp.Actually.<Number>ok(0).unless(4).toString(),
|
||||
"0"
|
||||
);
|
||||
}
|
||||
}
|
||||
71
cs2030s/labs/Lab5/Test3.java
Normal file
71
cs2030s/labs/Lab5/Test3.java
Normal file
@@ -0,0 +1,71 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test3 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
cs2030s.fp.Immutator<Integer,Integer> inc = new cs2030s.fp.Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p+1;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<Integer,Integer> inv = new cs2030s.fp.Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return 1/p;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<Number,Integer> incNum = new cs2030s.fp.Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return p+1;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<Number,Integer> invNum = new cs2030s.fp.Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return 1/p;
|
||||
}
|
||||
};
|
||||
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(inc)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(inc).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(inv)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(inv).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(inc)",
|
||||
cs2030s.fp.Actually.ok(0).transform(inc).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(inv)",
|
||||
cs2030s.fp.Actually.ok(0).transform(inv).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(incNum)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(incNum).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(invNum)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(invNum).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(incNum)",
|
||||
cs2030s.fp.Actually.ok(0).transform(incNum).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(invNum)",
|
||||
cs2030s.fp.Actually.ok(0).transform(invNum).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
}
|
||||
}
|
||||
45
cs2030s/labs/Lab5/Test4.java
Normal file
45
cs2030s/labs/Lab5/Test4.java
Normal file
@@ -0,0 +1,45 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test4 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
cs2030s.fp.Transformer<Integer,Integer> inc = new cs2030s.fp.Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p+1;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Transformer<Integer,Integer> sqr = new cs2030s.fp.Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p*p;
|
||||
}
|
||||
};
|
||||
|
||||
cs2030s.fp.Transformer<Integer,Integer> sqrPlusOneA = sqr.before(inc);
|
||||
cs2030s.fp.Transformer<Integer,Integer> sqrPlusOneB = inc.after(sqr);
|
||||
cs2030s.fp.Transformer<Integer,Integer> plusOneSqrA = sqr.after(inc);
|
||||
cs2030s.fp.Transformer<Integer,Integer> plusOneSqrB = inc.before(sqr);
|
||||
|
||||
we.expect(
|
||||
"sqrPlusOneA.invoke(2)",
|
||||
sqrPlusOneA.invoke(2).toString(),
|
||||
"5"
|
||||
);
|
||||
we.expect(
|
||||
"sqrPlusOneB.invoke(2)",
|
||||
sqrPlusOneA.invoke(2).toString(),
|
||||
"5"
|
||||
);
|
||||
we.expect(
|
||||
"plusOneSqrA.invoke(2)",
|
||||
plusOneSqrA.invoke(2).toString(),
|
||||
"9"
|
||||
);
|
||||
we.expect(
|
||||
"plusOneSqrB.invoke(2)",
|
||||
plusOneSqrB.invoke(2).toString(),
|
||||
"9"
|
||||
);
|
||||
}
|
||||
}
|
||||
55
cs2030s/labs/Lab5/Test5.java
Normal file
55
cs2030s/labs/Lab5/Test5.java
Normal file
@@ -0,0 +1,55 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test5 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
cs2030s.fp.Immutator<cs2030s.fp.Actually<Integer>,Integer> half = new cs2030s.fp.Immutator<>() {
|
||||
public cs2030s.fp.Actually<Integer> invoke(Integer p) {
|
||||
if (p%2 == 0) {
|
||||
return cs2030s.fp.Actually.<Integer>ok(p/2);
|
||||
} else {
|
||||
return cs2030s.fp.Actually.<Integer>err(new Exception("odd number"));
|
||||
}
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<cs2030s.fp.Actually<Integer>,Integer> inc = new cs2030s.fp.Immutator<>() {
|
||||
public cs2030s.fp.Actually<Integer> invoke(Integer p) {
|
||||
return cs2030s.fp.Actually.<Integer>ok(p+1);
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<cs2030s.fp.Actually<Integer>,Integer> make = new cs2030s.fp.Immutator<>() {
|
||||
public cs2030s.fp.Actually<Integer> invoke(Integer p) {
|
||||
return cs2030s.fp.Actually.<Integer>ok(p);
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Constant<Integer> zero = new cs2030s.fp.Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(inc).next(half)",
|
||||
make.invoke(0).next(inc).next(inc).next(half).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(half).next(inc)",
|
||||
make.invoke(0).next(inc).next(half).next(inc).toString(),
|
||||
"[java.lang.Exception] odd number"
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(inc).next(half).except(zero)",
|
||||
make.invoke(0).next(inc).next(inc).next(half).except(zero).toString(),
|
||||
"1"
|
||||
);
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(half).next(inc).except(zero)",
|
||||
make.invoke(0).next(inc).next(half).next(inc).except(zero).toString(),
|
||||
"0"
|
||||
);
|
||||
}
|
||||
}
|
||||
14
cs2030s/labs/Lab5/cs2030s/fp/Action.java
Normal file
14
cs2030s/labs/Lab5/cs2030s/fp/Action.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Action interface that can be called
|
||||
* on an object of type T to act.
|
||||
* Contains a single abstract method call.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
public interface Action<T> {
|
||||
void call(T item);
|
||||
}
|
||||
15
cs2030s/labs/Lab5/cs2030s/fp/Actionable.java
Normal file
15
cs2030s/labs/Lab5/cs2030s/fp/Actionable.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Actionable interface that can
|
||||
* act when given an action.
|
||||
* Contains a single abstract method act.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
// act consumes the T and passes it to action, thus super
|
||||
public interface Actionable<T> {
|
||||
public void act(Action<? super T> action);
|
||||
}
|
||||
179
cs2030s/labs/Lab5/cs2030s/fp/Actually.java
Normal file
179
cs2030s/labs/Lab5/cs2030s/fp/Actually.java
Normal file
@@ -0,0 +1,179 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
public abstract class Actually<T> implements Immutatorable<T>, Actionable<T> {
|
||||
|
||||
public static <T> Actually<T> ok(T value) {
|
||||
return new Success<T>(value);
|
||||
}
|
||||
|
||||
public static <T> Actually<T> err(Exception e) {
|
||||
// It is okay to do an unchecked cast here as failure types don't use
|
||||
// the value T.
|
||||
@SuppressWarnings("unchecked")
|
||||
Actually<T> failure = (Actually<T>) new Failure(e);
|
||||
return failure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract <R> Actually<R> transform(Immutator<? extends R, ? super T> immutator);
|
||||
|
||||
public abstract T unwrap() throws Exception;
|
||||
|
||||
public abstract <U extends T> T except(Constant<? extends U> c);
|
||||
|
||||
public abstract void finish(Action<? super T> action);
|
||||
|
||||
public abstract <U extends T> T unless(U other);
|
||||
|
||||
public abstract <R> Actually<R> next(Immutator<? extends Actually<? extends R>, ? super T> immutator);
|
||||
|
||||
private static class Success<T> extends Actually<T> {
|
||||
private final T value;
|
||||
|
||||
private Success(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T unwrap() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends T> T except(Constant<? extends U> c) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(Action<? super T> action) {
|
||||
action.call(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends T> T unless(U other) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> next(Immutator<? extends Actually<? extends R>, ? super T> immutator) {
|
||||
try {
|
||||
// it is okay to cast from <? extends R> to <R>
|
||||
@SuppressWarnings("unchecked")
|
||||
Actually<R> result = (Actually<R>) immutator.invoke(this.value);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
return Actually.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> transform(Immutator<? extends R, ? super T> immutator) {
|
||||
try {
|
||||
return Actually.ok(immutator.invoke(this.value));
|
||||
} catch (Exception e) {
|
||||
return Actually.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(Action<? super T> action) {
|
||||
action.call(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<" + value + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Success<?>) {
|
||||
Success<?> other = (Success<?>) obj;
|
||||
if (this.value == other.value) {
|
||||
return true;
|
||||
}
|
||||
if (this.value != null && this.value.equals(other.value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Failure extends Actually<Object> {
|
||||
private final Exception e;
|
||||
|
||||
Failure(Exception e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unwrap() throws Exception {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> U except(Constant<? extends U> c) {
|
||||
return c.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unless(Object other) {
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(Action<? super Object> action) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> transform(Immutator<? extends R, ? super Object> immutator) {
|
||||
return Actually.err(this.e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> next(Immutator<? extends Actually<? extends R>, ? super Object> immutator) {
|
||||
return Actually.err(this.e);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(Action<? super Object> action) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + e.getClass().getName() + "] " + e.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Failure) {
|
||||
Failure other = (Failure) obj;
|
||||
if (this.e == other.e) {
|
||||
return true;
|
||||
}
|
||||
if (this.e == null || other.e == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.e.getMessage() == null || other.e.getMessage() == null) {
|
||||
return false;
|
||||
}
|
||||
return this.e.getMessage() == other.e.getMessage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
5
cs2030s/labs/Lab5/cs2030s/fp/Constant.java
Normal file
5
cs2030s/labs/Lab5/cs2030s/fp/Constant.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
public interface Constant<T> {
|
||||
T init();
|
||||
}
|
||||
14
cs2030s/labs/Lab5/cs2030s/fp/Immutator.java
Normal file
14
cs2030s/labs/Lab5/cs2030s/fp/Immutator.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Immutator interface that can transform
|
||||
* to type T2, an object of type T1.
|
||||
* Contains a single abstract method invoke.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
public interface Immutator<R, P> {
|
||||
public R invoke(P param);
|
||||
}
|
||||
15
cs2030s/labs/Lab5/cs2030s/fp/Immutatorable.java
Normal file
15
cs2030s/labs/Lab5/cs2030s/fp/Immutatorable.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Immutatorable interface that can
|
||||
* transform when given something that is
|
||||
* Immutator.
|
||||
* Contains a single abstract method transform.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
public interface Immutatorable<T> {
|
||||
public <R> Immutatorable<R> transform(Immutator<? extends R, ? super T> immutator);
|
||||
}
|
||||
23
cs2030s/labs/Lab5/cs2030s/fp/Transformer.java
Normal file
23
cs2030s/labs/Lab5/cs2030s/fp/Transformer.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
public abstract class Transformer<R, P> implements Immutator<R, P> {
|
||||
public <N> Transformer<R, N> after(Transformer<P, N> g) {
|
||||
Transformer<R, P> f = this;
|
||||
return new Transformer<R, N>() {
|
||||
@Override
|
||||
public R invoke(N param) {
|
||||
return f.invoke(g.invoke(param));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public <T> Transformer<T, P> before(Transformer<T, R> g) {
|
||||
Transformer<R, P> f = this;
|
||||
return new Transformer<T, P>() {
|
||||
@Override
|
||||
public T invoke(P param) {
|
||||
return g.invoke(f.invoke(param));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
38
cs2030s/labs/Lab6/And.java
Normal file
38
cs2030s/labs/Lab6/And.java
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Represents the And type, a conditional which returns true if both left and
|
||||
* right values are true. This operator short circuits, which means if the first
|
||||
* value is false, the right value is not evaluated
|
||||
*/
|
||||
class And implements Cond {
|
||||
private Cond lVal;
|
||||
private Cond rVal;
|
||||
|
||||
/**
|
||||
* Constructor for the And conditional.
|
||||
*
|
||||
* @param lVal the left value in the And Operation.
|
||||
* @param rVal This is only evaluated if lVal is true
|
||||
*/
|
||||
public And(Cond lVal, Cond rVal) {
|
||||
this.lVal = lVal;
|
||||
this.rVal = rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval() {
|
||||
if (!this.lVal.eval()) {
|
||||
return false;
|
||||
}
|
||||
return this.rVal.eval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + this.lVal + " & " + this.rVal + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cond neg() {
|
||||
return new Or(lVal.neg(), rVal.neg());
|
||||
}
|
||||
}
|
||||
25
cs2030s/labs/Lab6/Bool.java
Normal file
25
cs2030s/labs/Lab6/Bool.java
Normal file
@@ -0,0 +1,25 @@
|
||||
import cs2030s.fp.Constant;
|
||||
import cs2030s.fp.Memo;
|
||||
|
||||
class Bool implements Cond {
|
||||
private Memo<Boolean> val;
|
||||
|
||||
public Bool(Constant<Boolean> val) {
|
||||
this.val = Memo.from(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval() {
|
||||
return this.val.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.val.toString().substring(0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cond neg() {
|
||||
return new Not(this);
|
||||
}
|
||||
}
|
||||
76
cs2030s/labs/Lab6/CS2030STest.java
Normal file
76
cs2030s/labs/Lab6/CS2030STest.java
Normal file
@@ -0,0 +1,76 @@
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import javax.tools.DiagnosticCollector;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public 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";
|
||||
|
||||
public void expect(String test, Object output, Object expect) {
|
||||
System.out.print(test);
|
||||
if ((expect == null && output == null) || output.equals(expect)) {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
} else {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
System.out.println(" expected: " + expect);
|
||||
System.out.println(" got this: " + output);
|
||||
}
|
||||
}
|
||||
|
||||
public static String clean(String txt) {
|
||||
String res = "";
|
||||
for (int i=0; i<txt.length(); i++) {
|
||||
if (txt.charAt(i) != '\r' && txt.charAt(i) != '\n') {
|
||||
res += txt.charAt(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public void expectPrint(String test, Object expect, ByteArrayOutputStream baos, PrintStream old) {
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
expect(test, CS2030STest.clean(baos.toString()), expect);
|
||||
}
|
||||
|
||||
public void expectCompile(String test, String statement, boolean success) {
|
||||
System.out.print(test);
|
||||
|
||||
class JavaSourceFromString extends SimpleJavaFileObject {
|
||||
final String code;
|
||||
|
||||
JavaSourceFromString(String code) {
|
||||
super(URI.create("string:///TempClass.java"), Kind.SOURCE);
|
||||
this.code = "class TempClass {void foo(){" + code + ";}}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
boolean noError = ToolProvider
|
||||
.getSystemJavaCompiler()
|
||||
.getTask(null, null, new DiagnosticCollector<>(), null, null,
|
||||
List.of(new JavaSourceFromString(statement)))
|
||||
.call();
|
||||
|
||||
if (noError != success) {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
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 {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
cs2030s/labs/Lab6/Cond.java
Normal file
21
cs2030s/labs/Lab6/Cond.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Represents a conditional type.
|
||||
* CS2030S Lab 5
|
||||
* AY20/21 Semester 2
|
||||
*
|
||||
*/
|
||||
interface Cond {
|
||||
/**
|
||||
* Evaluates the given conditional.
|
||||
*
|
||||
* @return the boolean result of the evaluation
|
||||
*/
|
||||
boolean eval();
|
||||
|
||||
/**
|
||||
* negates the value of the conditional, without evaluating it.
|
||||
*
|
||||
* @return a new conditional, with the negated value
|
||||
*/
|
||||
Cond neg();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user