diff --git a/.gitignore b/.gitignore index 208a567..58c67b4 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,7 @@ .idea/ target/** + +build +.gradle +classes diff --git a/pom.xml b/pom.xml index 4bc64f2..825310e 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ com.google.guava guava - 19.0 + 21.0 diff --git a/src/main/java/ru/spbau/mit/FirstPartTasks.java b/src/main/java/ru/spbau/mit/FirstPartTasks.java index 0e71f48..d3ec196 100644 --- a/src/main/java/ru/spbau/mit/FirstPartTasks.java +++ b/src/main/java/ru/spbau/mit/FirstPartTasks.java @@ -1,73 +1,119 @@ package ru.spbau.mit; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; +import java.util.function.Function; +import java.util.function.IntBinaryOperator; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; public final class FirstPartTasks { +// private static Function> albumTracksStreamGetter = ; private FirstPartTasks() {} // Список названий альбомов public static List allNames(Stream albums) { - throw new UnsupportedOperationException(); + return albums.map(Album::getName).collect(Collectors.toList()); } // Список названий альбомов, отсортированный лексикографически по названию public static List allNamesSorted(Stream albums) { - throw new UnsupportedOperationException(); + return albums.map(Album::getName).sorted().collect(Collectors.toList()); } // Список треков, отсортированный лексикографически по названию, включающий все треки альбомов из 'albums' public static List allTracksSorted(Stream albums) { - throw new UnsupportedOperationException(); + return albums + .map(Album::getTracks) + .flatMap(Collection::stream) + .map(Track::getName) + .sorted() + .collect(Collectors.toList()); } // Список альбомов, в которых есть хотя бы один трек с рейтингом более 95, отсортированный по названию public static List sortedFavorites(Stream s) { - throw new UnsupportedOperationException(); + final int threshold = 95; + return s.filter(a -> a.getTracks().stream() + .anyMatch(track -> track.getRating() > threshold)) + .sorted(Comparator.comparing(Album::getName)) + .collect(Collectors.toList()); } // Сгруппировать альбомы по артистам public static Map> groupByArtist(Stream albums) { - throw new UnsupportedOperationException(); + return albums.collect(Collectors.groupingBy(Album::getArtist)); } // Сгруппировать альбомы по артистам (в качестве значения вместо объекта 'Album' использовать его имя) public static Map> groupByArtistMapName(Stream albums) { - throw new UnsupportedOperationException(); + return albums.collect( + Collectors.groupingBy( + Album::getArtist, + Collectors.mapping( + Album::getName, + Collectors.toList() + ) + ) + ); } // Число повторяющихся альбомов в потоке public static long countAlbumDuplicates(Stream albums) { - throw new UnsupportedOperationException(); + Map albumsCount = albums.collect( + Collectors.groupingBy( + Function.identity(), + Collectors.counting() + )); + return albumsCount.entrySet() + .stream() + .map(e -> e.getValue() - 1) + .mapToLong(Long::longValue) + .sum(); } // Альбом в котором максимум рейтинга минимален // (если в альбоме нет ни одного трека, считать, что максимум рейтинга в нем --- 0) public static Optional minMaxRating(Stream albums) { - throw new UnsupportedOperationException(); + ToIntFunction ratingGetter = a -> a.getTracks() + .stream() + .mapToInt(Track::getRating) + .max() + .orElse(0); + Comparator albumComparator = Comparator.comparingInt(ratingGetter); + return albums.min(albumComparator); } // Список альбомов, отсортированный по убыванию среднего рейтинга его треков (0, если треков нет) public static List sortByAverageRating(Stream albums) { - throw new UnsupportedOperationException(); + ToDoubleFunction averageRatingGetter = value -> value.getTracks() + .stream() + .mapToDouble(Track::getRating) + .average() + .orElse(0.0); + return albums.sorted(Comparator + .comparingDouble(averageRatingGetter) + .reversed()) + .collect(Collectors.toList()); } // Произведение всех чисел потока по модулю 'modulo' // (все числа от 0 до 10000) public static int moduloProduction(IntStream stream, int modulo) { - throw new UnsupportedOperationException(); + IntBinaryOperator sumModule = (left, right) -> (left * right) % modulo; + return stream.reduce(1, sumModule); } // Вернуть строку, состояющую из конкатенаций переданного массива, и окруженную строками "<", ">" // см. тесты public static String joinTo(String... strings) { - throw new UnsupportedOperationException(); + Stream ss = Stream.of(strings); + return ss.collect(Collectors.joining(", ", "<", ">")); } // Вернуть поток из объектов класса 'clazz' public static Stream filterIsInstance(Stream s, Class clazz) { - throw new UnsupportedOperationException(); + return s.filter(clazz::isInstance).map(clazz::cast); } } diff --git a/src/main/java/ru/spbau/mit/SecondPartTasks.java b/src/main/java/ru/spbau/mit/SecondPartTasks.java index 7b0d5a2..7b1e980 100644 --- a/src/main/java/ru/spbau/mit/SecondPartTasks.java +++ b/src/main/java/ru/spbau/mit/SecondPartTasks.java @@ -1,15 +1,34 @@ package ru.spbau.mit; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Random; +import java.util.function.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; public final class SecondPartTasks { - private SecondPartTasks() {} // Найти строки из переданных файлов, в которых встречается указанная подстрока. public static List findQuotes(List paths, CharSequence sequence) { - throw new UnsupportedOperationException(); + Function> linesGetter = s -> { + Path p = Paths.get(s); + try { + return Files.lines(p); + } catch (IOException e) { + return Stream.empty(); + } + }; + return paths.stream() + .flatMap(linesGetter) + .filter(s -> s.contains(sequence)) + .collect(Collectors.toList()); } // В квадрат с длиной стороны 1 вписана мишень. @@ -17,18 +36,70 @@ public static List findQuotes(List paths, CharSequence sequence) // Надо промоделировать этот процесс с помощью класса java.util.Random и посчитать, // какова вероятность попасть в мишень. public static double piDividedBy4() { - throw new UnsupportedOperationException(); + final int pointsLimit = 10000000; + final Predicate isHit = p -> p.sqr() <= 1.0; + Point seed = new Point(); + + UnaryOperator pointGenerator = point -> new Point(); + + final double hitNumber = (double) Stream.iterate(seed, pointGenerator) + .limit(pointsLimit) + .filter(isHit) + .count(); + return hitNumber / pointsLimit; } // Дано отображение из имени автора в список с содержанием его произведений. // Надо вычислить, чья общая длина произведений наибольшая. public static String findPrinter(Map> compositions) { - throw new UnsupportedOperationException(); + Function>, Pair> mapper = stringListEntry -> { + String name = stringListEntry.getKey(); + Integer length = stringListEntry.getValue().stream() + .mapToInt(String::length) + .sum(); + return new Pair<>(name, length); + }; + + Comparator> bestAuthorComparator = Comparator.comparing(o -> o.second); + + return compositions.entrySet() + .stream() + .map(mapper) + .max(bestAuthorComparator) + .orElseThrow(UnsupportedOperationException::new).first; } // Вы крупный поставщик продуктов. Каждая торговая сеть делает вам заказ в виде Map<Товар, Количество>. // Необходимо вычислить, какой товар и в каком количестве надо поставить. public static Map calculateGlobalOrder(List> orders) { - throw new UnsupportedOperationException(); + Function, String> classifier = e -> e.getKey(); + return orders.stream() + .flatMap(m -> m.entrySet().stream()) + .collect(Collectors.groupingBy(classifier, Collectors.summingInt(Map.Entry::getValue))); + } + + private static class Point { + private static Random pointsRandomizer = new Random(); + private final double x; + private final double y; + + Point() { + x = pointsRandomizer.nextDouble(); + y = pointsRandomizer.nextDouble(); + } + + public double sqr() { + return x * x + y * y; + } + } + + private static class Pair { + private F first; + private S second; + + Pair(F first, S second) { + this.first = first; + this.second = second; + } } } diff --git a/src/test/java/ru/spbau/mit/FirstPartTasksTest.java b/src/test/java/ru/spbau/mit/FirstPartTasksTest.java index c4d9d8c..94e6fd3 100644 --- a/src/test/java/ru/spbau/mit/FirstPartTasksTest.java +++ b/src/test/java/ru/spbau/mit/FirstPartTasksTest.java @@ -11,7 +11,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; -import static junitx.framework.Assert.assertEquals; +import static org.junit.Assert.assertEquals; import static ru.spbau.mit.FirstPartTasks.*; public class FirstPartTasksTest { diff --git a/src/test/java/ru/spbau/mit/SecondPartTasksTest.java b/src/test/java/ru/spbau/mit/SecondPartTasksTest.java index 8fa2df0..c302991 100644 --- a/src/test/java/ru/spbau/mit/SecondPartTasksTest.java +++ b/src/test/java/ru/spbau/mit/SecondPartTasksTest.java @@ -1,28 +1,116 @@ package ru.spbau.mit; +import com.google.common.collect.ImmutableMap; import org.junit.Test; -import static org.junit.Assert.fail; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.*; +import static ru.spbau.mit.SecondPartTasks.*; public class SecondPartTasksTest { @Test public void testFindQuotes() { - fail(); + List files = Arrays.asList( + "src/main/java/fru/spbau/mit/Artist.java" + , "src/main/java/ru/spbau/mit/Album.java" + , "src/main/java/ru/spbau/mit/.gitkeep" + , "src/main/java/ru/spbau/mit/Track.java" + , "src/main/java/ru/spbau/mit/FirstPartTasks.java" + , "src/main/java/ru/spbau/mit/SecondPartTasks.java" + ); + assertEquals(Collections.emptyList(), findQuotes(files, "qaef2wefadsf")); + + assertEquals(Stream.of( + " private String name;" + , " public Album(Artist artist, String name, Track... tracks) {" + , " private final String name;" + , " Track(String name, int rating) {" + , " String name = stringListEntry.getKey();").sorted().collect(Collectors.toList()), + findQuotes(files, "String name").stream().sorted().collect(Collectors.toList())); } @Test public void testPiDividedBy4() { - fail(); + final double piDividedBy4 = 0.78539816339; + final double delta = 1e-1; + assertEquals(piDividedBy4, SecondPartTasks.piDividedBy4(), delta); } @Test public void testFindPrinter() { - fail(); + assertEquals(ARTIST_7, findPrinter( + ImmutableMap.of(ARTIST_0, ALBUM_2 + , ARTIST_3, ALBUM_9 + , ARTIST_7, ALBUM_5 + , ARTIST_1, Collections.emptyList() + ) + ) + ); + + assertEquals(ARTIST_5, findPrinter( + ImmutableMap.of(ARTIST_2, ALBUM_0 + , ARTIST_4, ALBUM_1 + , ARTIST_5, ALBUM_3 + , ARTIST_6, ALBUM_4 + , ALBUM_6.get(0), ALBUM_7 + ) + ) + ); } @Test public void testCalculateGlobalOrder() { - fail(); + assertEquals(ImmutableMap.of(), calculateGlobalOrder(Arrays.asList( + ImmutableMap.of(), + ImmutableMap.of(), + ImmutableMap.of(), + ImmutableMap.of() + ) + )); + + assertEquals(ImmutableMap.of( + "pepper", 4, + "bread", 47, + "salt", 72, + "meat", -1, + "birds", 100004000 + ), calculateGlobalOrder(Arrays.asList( + ImmutableMap.of( + "bread", 12, + "meat", -1, + "birds", 100000000, + "salt", 72 + ), + ImmutableMap.of( + "birds", 4000, + "bread", 35 + ), + ImmutableMap.of( + "pepper", 4 + ) + ) + )); } + + private static final String ARTIST_0 = "Morcheeba"; + private static final String ARTIST_1 = "Temples"; + private static final String ARTIST_2 = "God Help the Girl"; + private static final String ARTIST_3 = "All India Radio"; + private static final String ARTIST_4 = "UNKLE"; + private static final String ARTIST_5 = "Bonobo"; + private static final String ARTIST_6 = "Grimes"; + private static final String ARTIST_7 = "Massive Attack"; + private static final List ALBUM_0 = Arrays.asList("Sun Structures", "Shelter Song", "Sun Structures", "The Golden Throne", "Keep in the Dark", "Mesmerise", "Move With The Season", "Colours to Life", "A Question Isn't Answered", "The Guesser", "Test of Time", "Sand Dance", "Fragment's Light"); + private static final List ALBUM_1 = Arrays.asList("Keep In The Dark", "Keep in the Dark", "Jewel of Mine Eye"); + private static final List ALBUM_2 = Arrays.asList("Big Calm", "The Sea", "Shoulder Holster", "Part of the Process", "Blindfold", "Let Me See", "Bullet Proof", "Over and Over", "Friction", "diggin' in a watery grave", "Fear and Love", "Big Calm"); + private static final List ALBUM_3 = Arrays.asList("Charango", "Slow Down", "Otherwise", "Aqualung", "Sao Paulo", "Charango (Feat: Pace Won)", "What New York Couples Fight About (Feat: Kurt Wagner)", "Undress Me Now", "Way Beyond", "Women Lose Weight (Feat: Slick Rick)", "Get Along (Feat: Pace Won)", "Public Displays of Affection", "The Great London Traffic Warden Massacre", "Slow Down (Instrumental)", "Otherwise (Instrumental)", "Aqualung (Instrumental)", "Sao Paulo (Instrumental)", "Charango (Feat: Pace Won) (Instrumental)", "What New York Couples Fight About (Instrumental)", "Undress Me Now (Instrumental)", "Way Beyond (Instrumental)", "Women Lose Weight (Feat: Slick Rick) (Instrumental)", "Get Along (Feat: Pace Won) (Instrumental)", "Public Displays Of Affection (Instrumental)", "The Great London Traffic Warden Massacre (Instrumental)"); + private static final List ALBUM_4 = Arrays.asList("Shelter Song", "Shelter Song", "Prisms"); + private static final List ALBUM_5 = Arrays.asList("God Help The Girl", "I Suppose That Was A Prayer", "Act of the Apostle", "I Dumped You First", "Pretty When The Wind Blows", "I Know I Have To Eat", "God Help the Girl", "The Psychiatrist Is In", "The God Of Music", "If You Could Speak", "The Catwalk Of The Dukes", "Perfection as a Hipster", "Fuck This Shit", "Pretty Eve in the Tub", "A loving Kind Of Boy", "What Do You Want This Band To Sound Like", "Come Monday Night", "Collective Idiocy", "I'm Not Rich", "I'll Have to Dance With Cassie", "Stalinist Russia", "Baby’s Just Waiting", "Partick Whistle", "Musician, Please Take Heed", "I Just Want Your Jeans", "Invisible", "The World's Last Cassette", "A Down and Dusky Blonde", "Dress Up In You"); + private static final List ALBUM_6 = Arrays.asList("God Help The Girl sd (Original Motion Picture Soundtrack)"); + private static final List ALBUM_7 = Arrays.asList("Stills EP"); + private static final List ALBUM_9 = Arrays.asList("Permanent Evolutions", "Open Sky Experiment (St-2Remix)", "Permanent Revolutions (Don Meers remix)", "Little Mexico", "How Many, For How Long (Morphodic Bliss Mix)", "Dark Ambient (am mix)", "Life and How to Do It", "For Angel (All India Radio vs. Don Meers Mix)", "Lo Fi Groovy", "Walking On A.I.R.", "Delhi Dub", "Pray To The TV Funk (Left Brain Mix)", "A Moment (TV Version)", "Old India", "The Long Goodbye"); }