diff --git a/.keep b/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/config.json b/config.json index 7f5ecb3d6..06aa1d91e 100644 --- a/config.json +++ b/config.json @@ -303,6 +303,11 @@ "slug": "change", "difficulty": 1, "topics": [] + }, + { + "slug": "list-ops", + "difficulty": 1, + "topics": [] } ], "deprecated": [ diff --git a/exercises/list-ops/build.gradle b/exercises/list-ops/build.gradle new file mode 100644 index 000000000..9e1448e14 --- /dev/null +++ b/exercises/list-ops/build.gradle @@ -0,0 +1,18 @@ +apply plugin: "java" +apply plugin: "eclipse" +apply plugin: "idea" + +repositories { + mavenCentral() +} + +dependencies { + testCompile "junit:junit:4.12" +} + +test { + testLogging { + exceptionFormat = 'full' + events = ["passed", "failed", "skipped"] + } +} diff --git a/exercises/list-ops/src/example/java/ListOps.java b/exercises/list-ops/src/example/java/ListOps.java new file mode 100644 index 000000000..7a0fe66dd --- /dev/null +++ b/exercises/list-ops/src/example/java/ListOps.java @@ -0,0 +1,51 @@ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ListOps { + + private ListOps() { + } + + public static int length(final List list) { + return list.size(); + } + + public static List reverse(final List list) { + List result = new ArrayList(list); + Collections.reverse(result); + return result; + } + + public static List map(final List list, + UnaryOperator mapper) { + return list.stream().map(mapper).collect(Collectors.toList()); + } + + public static List filter(final List list, + Predicate predicate) { + return list.stream().filter(predicate).collect(Collectors.toList()); + } + + public static U reduce(final List list, + U identity, + BiFunction accumulator, + BinaryOperator combiner) { + return list.stream().reduce(identity, accumulator, combiner); + } + + public static List concat(final List... lists) { + return Stream.of(lists) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + +} diff --git a/exercises/list-ops/src/main/java/.keep b/exercises/list-ops/src/main/java/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/exercises/list-ops/src/test/java/ListOpsTest.java b/exercises/list-ops/src/test/java/ListOpsTest.java new file mode 100644 index 000000000..6857556c2 --- /dev/null +++ b/exercises/list-ops/src/test/java/ListOpsTest.java @@ -0,0 +1,316 @@ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertTrue; +import org.junit.Ignore; +import org.junit.Test; + +public class ListOpsTest { + + private static final List EMPTY_LIST + = Collections.emptyList(); + + @Test + public void lengthOfAnEmptyListShouldBeZero() { + final int expected = 0; + final int actual = ListOps.length(EMPTY_LIST); + + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldReturnTheCorrectLengthOfAnNonEmptyList() { + final List list = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4) + ); + final int actual = ListOps.length(list); + final int expected = list.size(); + + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldReverseAnEmptyList() { + final List actual = ListOps.reverse(EMPTY_LIST); + + assertNotNull(actual); + assertTrue(actual.isEmpty()); + } + + @Test + @Ignore + public void shouldReverseANonEmptyList() { + final List list = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8) + ); + final List actual + = ListOps.reverse(list); + final List expected + = Arrays.asList(8, 7, 6, 5, 4, 3, 2, 1, 0); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldMapAnEmptyListAndReturnAnEmptyList() { + final List actual = ListOps.map(EMPTY_LIST, x -> x + 1); + + assertNotNull(actual); + assertTrue(actual.isEmpty()); + } + + @Test + @Ignore + public void shouldMapNonEmptyList() { + final List list + = Collections.unmodifiableList(Arrays.asList(1, 3, 5, 7)); + final List actual = ListOps.map(list, x -> x + 1); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(Arrays.asList(2, 4, 6, 8), actual); + } + + @Test + @Ignore + public void shouldFilterAnEmptyListanddReturnAnEmptyList() { + final List actual = ListOps.filter(EMPTY_LIST, x -> x > 0); + + assertNotNull(actual); + assertTrue(actual.isEmpty()); + } + + @Test + @Ignore + public void shouldFilterNonEmptyList() { + Predicate predicate = x -> x % 2 > 0; + final List list = Collections.unmodifiableList( + IntStream.range(0, 100).boxed().collect(Collectors.toList()) + ); + final List actual = ListOps.filter(list, predicate); + final List expected = list.stream() + .filter(predicate) + .collect(Collectors.toList()); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldConcatenateZeroLists() { + List actual = ListOps.concat(); + + assertNotNull(actual); + assertTrue(actual.isEmpty()); + } + + @Test + @Ignore + public void shouldConcatenateOneNonEmptyList() { + final List list + = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4) + ); + final List actual = ListOps.concat(list); + final List expected = Arrays.asList(0, 1, 2, 3, 4); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldConcatenateOneEmptyList() { + final List actual = ListOps.concat(EMPTY_LIST); + + assertNotNull(actual); + assertTrue(actual.isEmpty()); + } + + @Test + @Ignore + public void shouldConcatenateTwoEmptyLists() { + final List actual = ListOps.concat(EMPTY_LIST, EMPTY_LIST); + + assertNotNull(actual); + assertTrue(actual.isEmpty()); + } + + @Test + @Ignore + public void shouldConcatenateOneEmptyAndOneNonEmptyLists() { + final List list + = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4) + ); + final List actual = ListOps.concat(list, EMPTY_LIST); + final List expected + = Arrays.asList(0, 1, 2, 3, 4); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldConcatenateOneNonEmptyAndOneEmptyLists() { + final List list + = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4) + ); + final List actual = ListOps.concat(EMPTY_LIST, list); + final List expected + = Arrays.asList(0, 1, 2, 3, 4); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldConcatenateTwoListsWithSameElements() { + final List list1 = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4) + ); + final List list2 = Collections.unmodifiableList( + Arrays.asList(1, 2, 3, 4, 5, 6) + ); + final List expected + = Arrays.asList(0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6); + final List actual = ListOps.concat(list1, list2); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldConcatenateSeveralLists() { + final List list1 = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3) + ); + final List list2 = Collections.unmodifiableList( + Arrays.asList(4, 5, 6, 7) + ); + final List list3 = Collections.unmodifiableList( + Arrays.asList(8, 9, 10, 11) + ); + final List list4 = Collections.unmodifiableList( + Arrays.asList(12, 13, 14, 15) + ); + final List expected + = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15); + + final List actual + = ListOps.concat(list1, list2, EMPTY_LIST, list3, list4); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldReturnIdentityWhenAnEmptyListIsReduced() { + final int expected = 0; + final int actual + = ListOps.reduce(EMPTY_LIST, 0, (x, y) -> x + y, Integer::sum); + + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldCalculateTheSumOfANonEmptyIntegerList() { + final List list = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4) + ); + final int actual = ListOps.reduce(list, 0, + (x, y) -> x + y, + Integer::sum); + + assertEquals(10, actual); + } + + /* + https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html + https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-U-java.util.function.BiFunction-java.util.function.BinaryOperator- + */ + private BiFunction, Integer, List> accumulator + = (List partial, Integer elem) -> { + List result = new ArrayList<>(partial); + result.add(elem); + return result; + }; + + private BinaryOperator> combiner + = (list1, list2) -> { + List result = new ArrayList<>(list1); + result.addAll(list2); + return result; + }; + + @Test + @Ignore + public void shouldReduceAnEmptyListAndANonEmptyListAndReturnConcatenation() { + final List list = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4, 5) + ); + final List actual + = ListOps.reduce(list, + new ArrayList(), + accumulator, + combiner); + final List expected + = Arrays.asList(0, 1, 2, 3, 4, 5); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + + @Test + @Ignore + public void shouldReduceTwoNonEmptyListsAndReturnConcatenation() { + final List listOne = Collections.unmodifiableList( + Arrays.asList(0, 1, 2, 3, 4) + ); + final List listTwo = Collections.unmodifiableList( + Arrays.asList(5, 6, 7, 8, 9) + ); + final List actual + = ListOps.reduce(listTwo, + listOne, + accumulator, + combiner); + final List expected + = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + + assertNotNull(actual); + assertFalse(actual.isEmpty()); + assertEquals(expected, actual); + } + +} diff --git a/exercises/settings.gradle b/exercises/settings.gradle index 112e2f662..8a9070756 100644 --- a/exercises/settings.gradle +++ b/exercises/settings.gradle @@ -25,6 +25,7 @@ include 'hexadecimal' include 'hello-world' include 'largest-series-product' include 'linked-list' +include 'list-ops' include 'luhn' include 'matrix' include 'meetup'