/* * ############################################################### * Installation instructions: * 1. Create a fork of the MiniCP git repository: * https://inginious.org/course/minicp-s/repo-create * * 2. Make a local clone of the forked repository. * * 3. Set up your IDE (IntelliJ is recommended) for your cloned * repository: https://github.com/minicp/minicp#using-the-intellij-idea-editor * * 4. Using the IDE you set up, create the file * "LambdaExpressionTest.java" at "test/java/minicp/util/" * in your cloned repository. * * 5. Paste the contents of this file into the created java file. * * ############################################################### */ /* * mini-cp is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License v3 * as published by the Free Software Foundation. * * mini-cp is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with mini-cp. If not, see http://www.gnu.org/licenses/lgpl-3.0.en.html * * Copyright (c) 2018. by Laurent Michel, Pierre Schaus, Pascal Van Hentenryck * * These are some lambda warmup exercises for Combinatorial Optimisation and Constraint Programming (course 1DL441). * * Made by Frej Knutar Lewander 2021 * */ package minicp.util; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.*; import static org.junit.jupiter.api.Assertions.*; public class LambdaExpressionTest { private List<Integer> integers; private List<String> strings; @BeforeEach public void setUp() { integers = Arrays.asList(9, -6, 4, -6, -5, 0, 9, 4, -3, 4); strings = Arrays.asList( "jYt4Tq5b", "13Jl4w", "CUdwAnxgVz", "", "v", "GGqHztUmw", "RNt59s9Z", "Reg", "QQyq", "dGrm7U1XHZ"); } /** * Returns a list consisting of the elements of collection for which predicate holds. * @param collection The collection containing the elements that predicate is applied to. * @param predicate The predicate that is applied to each element in collection. * @return The filtered list. */ private static <T> List<T> filter(Collection<T> collection, Predicate<T> predicate) { List<T> result = new ArrayList<>(collection.size()); for (T element : collection) { if (predicate.test(element)) { result.add(element); } } return result; } /** * Returns the list consisting of the results of applying the given function to the elements of collection. * @param collection The collection containing the elements the function is applied to. * @param fun The function that is applied to each element in collection. * @return The new list. */ private static <T, R> List<R> map(Collection<T> collection, Function<T, R> fun) { List<R> result = new ArrayList<>(collection.size()); for (T element : collection) { result.add(fun.apply(element)); } return result; } /** * Performs a reduction on the elements of collection, using the provided initial value and an associative * accumulation function, and returns the reduced value. * @param collection The collection containing the elements to be reduced. * @param initial The initial accumulated value * @param fun The accumulation function * @return The result of the reduction. */ private static <T, R> R reduce(Collection<T> collection, R initial, BiFunction<R, T, R> fun) { R accumulator = initial; for (T element : collection) { accumulator = fun.apply(accumulator, element); } return accumulator; } @Test public void filterLambdas() { // Create a lambda that returns true if the input number is 0 or greater, and false otherwise. Predicate<Integer> isNonNegative = null; List<Integer> filteredIntegers = filter(integers, isNonNegative); assertArrayEquals(new Integer[] { 9, 4, 0, 9, 4, 4 }, filteredIntegers.toArray(new Integer[0])); // Create a lambda that returns true if the input string contains the upper-case letter G, and false // otherwise. Predicate<String> containsG = null; List<String> filteredStrings = filter(strings, containsG); assertArrayEquals(new String[] { "GGqHztUmw", "dGrm7U1XHZ" }, filteredStrings.toArray(new String[0])); } @Test public void mapLambdas() { // Create a lambda that returns the square of the input integer. Function<Integer, Integer> square = i -> null; List<Integer> squaredIntegers = map(integers, square); assertArrayEquals(new Integer[] { 81, 36, 16, 36, 25, 0, 81, 16, 9, 16 }, squaredIntegers.toArray(new Integer[0])); // Create a lambda that given a string s truncates all characters after the third character of s. // For example; the input "ab" returns "ab", while the input "cdef" returns "cde". Function<String, String> stringTruncator = s -> null; List<String> truncatedStrings = map(strings, stringTruncator); assertArrayEquals(new String[] { "jYt", "13J", "CUd", "", "v", "GGq", "RNt", "Reg", "QQy", "dGr" }, truncatedStrings.toArray(new String[0])); } @Test public void reduceLambdas() { // Create a lambda that sums over the inputs. BiFunction<Integer, Integer, Integer> sum = (accumulator, cur) -> null; assertEquals(10, (int) reduce(integers, 0, sum)); // Create a lambda that returns the greatest value. BiFunction<Integer, Integer, Integer> max = (accumulator, cur) -> null; assertEquals(9, (int) reduce(integers, Integer.MIN_VALUE, max)); // Create a lambda that given the inputs accumulator and cur returns cur if accumulator is null, otherwise // concatenates accumulator and cur with a comma and a space (i.e., accumulator + ", " + cur). BiFunction<String, String, String> commaConcat = (accumulator, cur) -> null; assertEquals("jYt4Tq5b, 13Jl4w, CUdwAnxgVz, , v, GGqHztUmw, RNt59s9Z, Reg, QQyq, dGrm7U1XHZ", reduce(strings, null, commaConcat)); } @Test public void combineLambdas() { // Combine filter, map, and reduce calls with lambdas you created earlier to // 1. Remove all negative integers, // 2. square the remaining integers, and finally // 3. converting and comma concatenating the squared integers. // Create any needed lambdas String result = ""; // Use filter, map, and reduce calls assertEquals("81, 16, 0, 81, 16, 16", result); } @Test public void difficultLambdas() { // Create a lambda that given an integer input n returns a truncation lambda function that given a string s // truncates all characters after the first n characters. Function<Integer, Function<String, String>> stringTruncatorFactory = i -> null; assertArrayEquals(new String[] { "jYt", "13J", "CUd", "", "v", "GGq", "RNt", "Reg", "QQy", "dGr" }, map(strings, stringTruncatorFactory.apply(3)).toArray(new String[0])); assertArrayEquals(new String[] { "", "", "", "", "", "", "", "", "", "" }, map(strings, stringTruncatorFactory.apply(0)).toArray(new String[0])); assertArrayEquals(new String[] { "jYt4Tq5b", "13Jl4w", "CUdwAnxgVz", "", "v", "GGqHztUmw", "RNt59s9Z", "Reg", "QQyq", "dGrm7U1XHZ" }, map(strings, stringTruncatorFactory.apply(10)).toArray(new String[0])); // Create a supplier that returns the next element in the integers List field. // Hint: use nextIndex to keep track of the index of the next element of integers that is to be returned. AtomicInteger nextIndex = new AtomicInteger(0); Supplier<Integer> nextInteger = () -> null; for (int val : integers) { assertEquals(val, (int) nextInteger.get()); } } }