$30
Parametric and subtype polymorphism
] Figure 1: The expected vertex-ordering for Cuboid. Note that v0 through v3 form one face in counterlockwise order and v4 through v7 form the exact opposite face, where v4 is the corner directly connected to v3. In this first section, an incomplete codebase is given to you with many method bodies simply marked with a TODO tag. Your task is to follow the documentation provided in these methods and complete the codebase. A few things to keep in mind during this code completion: - You will probably have to read up on two interfaces used in sorting: Comparable and Comparator. The assignment itself will illustrate how they are used, and why both are needed. - Any fields you need/want to add to the classes must be private, with the corresponding getter() and setter() methods added by you. Note that setter methods only make sense for attributes that are modifiable. - You may, in general, add more methods to the classes if you feel the need. But do not modify/remove any methods or fields already implemented in the codebase. Also do not modify any interface. 1. Complete the parts marked by “TODO” in the codebase. (a) Circle#setPosition(List) (2) (b) Cuboid#volume() and Cuboid#center() (4) (c) Add the method missing from Cuboid, defined in an interface it implements. (4) (d) Quadrilateral#getSideLengths() (3) (e) Quadrilateral#setPosition(List) (3) (f) Rectangle#center(), Rectangle#isMember(List), and Rectangle#area() (6) (g) Resolve the issue with the constructor in Square. Note that you are not allowed to modify the (2) constructor itself. (h) Square#snap() (3) (i) Complete the ThreeDPoint class as marked by the two “TODO” comments. (3) (j) Complete the TwoDPoint class as marked by the two “TODO” comments. (3) (k) Carefully consider the codes of Cuboid and Circle, and create a class Sphere that implements the (5) ThreeDShape interface. (l) Complete the code in the class Ordering.java. The main(String[]) method in this class serves (6) as a test code of sorts. If, after following the instructions in the comments, your code does not compile or run properly, then it indicates a definite error in your implementation(s)1 . 2. Create two static methods as follows: (a) Cuboid#random(), which will generate a cuboid with random vertices. Please note that in spite of (3) that randomness, the object must actually be a geometric cuboid shape. (b) Sphere#random(), which will generate a sphere with a random center and radius. (2)
2 Functional Programming: Streams
return sequence.stream() .intermediate_operation_1(...) .intermediate_operation_2(...) .intermediate_operation_3(...).terminal_operation(); Example 1: A Java function implemented as a single method chain. Each function implementation must be done using a single method chain (as shown in example 1 above), and all the functions must be implemented in a file named StreamUtils.java. 1. Capitalized strings. (5) /** * @param strings: the input collection of Strings. * @return a collection of those Strings in the input collection that start with a capital letter. */ public static Collection capitalized(Collection strings); 2. The longest string. (5) /** * Find and return the longest String in a given collection of Strings. * * @param strings: the given collection of Strings. * @param from_start: a boolean flag that decides how ties are broken. If true, then the element encountered earlier in * the iteration is returned, otherwise the later element is returned. * @return the longest String in the given collection, * where ties are broken based on from_start. */ public static String longest(Collection strings, boolean from_start); 3. The least element. In this function, the single method chain can return a java.util.Optional. (5) So you must write additional code to convert it to an object of type T (handling any potential exceptions). 1Keep in mind, though, that a complete suite of tests is not provided here. You are, of course, free to add your own tests to check whether or not your completed code is running as expected. Find and return the least element from a collection of given elements that are comparable. * * @param items: the given collection of elements * @param from_start: a boolean flag that decides how ties are broken. * If true, the element encountered earlier in the * iteration is returned, otherwise the later element is returned. * @param : the type parameter of the collection (i.e., the items are all of type T). * @return the least element in items, where ties are * broken based on from_start. */ public static > T least(Collection items, boolean from_start); 4. Flatten a map. (5) /** * Flattens a map to a stream of Strings, where each element in the list * is formatted as "key -> value". * * @param aMap the specified input map. * @param the type parameter of keys in aMap. * @param the type parameter of values in aMap. * @return the flattened list representation of aMap. */ public static <K, V> List flatten(Map<K, V> aMap)
3 Functional Programming: Higher-order functions Code
for this section must be written in a file named HigherOrderUtils.java. You may also have to consult some of the official Java documentation and/or the reference text on Functional Programming in Java. 1. First, write a nested interface in HigherOrderUtils called NamedBiFunction that extends the interface (4) java.util.Function.BiFunction. The interface should just have one method declaration: String name();, i.e., a class implementing this interface must provide a “name” for every instance of that class. 2. Next, create public static NamedBiFunction instances as follows: (8) (a) add, with the name “add”, to perform addition of two Doubles. (b) subtract, with the name “diff”, to perform subtraction of one Double from another. (c) multiply, with the name “mult”, to perform multiplication of two Doubles. (d) divide, with the name “div”, to divide one Double by another. This operation should throw a java.lang.ArithmeticException if there is a division by zero being attempted. 3. Write a function called zip as follows: (9) /** * Applies a given list of bifunctions -- functions that take two arguments of a certain type and produce * a single instance of that type -- to a list of arguments of that type. The functions are applied * iteratively, and the result of each function is stored in the list iteratively as well, to be * used by the next bifunction in the next iteration. E.g., * List args = Arrays.asList(1d, 1d, 3d, 0d, 4d), and * List<NamedBiFunction<Double, Double, Double>> bfs = [add, multiply, add, divide], * zip(args, bfs) will proceed iteratively as follows: * - index 0: the result of add(1,1) is stored in args[1] to yield args = [1,2,3,0,4] * - index 1: the result of multiply(2,3) is stored in args[2] to yield args = [1,2,6,0,4] * - index 2: the result of add(6,0) is stored in args[3] to yield args = [1,2,6,6,4] * - index 3: the result of divide(6,4) is stored in args[4] to yield args = [1,2,6,6,1] * * @param args: the arguments over which bifunctions will be applied. * @param bifunctions: the list of bifunctions that will be applied on args. * @param : the type parameter of the arguments (e.g., Integer, Double) * @return the item in the last index of args, which has the final * result of all the bifunctions being applied in sequence. */ public static T zip(List args, List<NamedBiFunction<T, T, T>> bifunctions); 4. Based on the above zip function, think about what a function composition would look like. Write a (9) static inner class called FunctionComposition that is parameterized by three type parameters. This class should have no methods, and no constructor. It should only have a single BiFunction called composition, which takes in two functions and provides their composition as the output function. Function composition should be consistent with the types – if there is a function f: char -> String, and another function g: String -> int, the output of composition should be a function h: char -> int. For example, if f concatenates a char some number of times (say, ‘b’ yields “bb”, ‘c’ yields “ccc”, ‘d’ yields “dddd”, etc.), and g converts a string to its length, then composition(f, g) should output a function that maps ‘z’ to 26.