Introduce SequenceProcessor as a way to work with anything sequence related

This commit is contained in:
2021-08-29 19:02:44 +02:00
parent b11c1683c1
commit 0f12449954
7 changed files with 594 additions and 0 deletions

View File

@ -0,0 +1,6 @@
package aud.exam.prep;
public class Pair<T, S> {
public T fst;
public S snd;
}

View File

@ -0,0 +1,68 @@
package aud.exam.prep;
import java.util.Comparator;
public interface SequenceProcessor<T, S> {
boolean find(S s, T t);
boolean findBinary(S s, T t, Comparator<T> cmp);
boolean override(S s, T from, T to);
boolean overrideAll(S s, T from, T to);
boolean overrideAt(S s, T to, int index);
void insertInOrder(S s, T t, Comparator<T> cmp);
boolean remove(S s, T t);
boolean removeAll(S s, T t);
boolean isAscending(S s, Comparator<T> cmp);
T max(S s, Comparator<T> cmp);
T secondMax(S s, Comparator<T> cmp);
boolean check(S s);
boolean isItemWiseLessOrEqual(S a, S b, Comparator<T> cmp);
boolean isItemWiseLess(S a, S b, Comparator<T> cmp);
boolean isLexSmaller(S a, S b, Comparator<T> cmp);
void exchangePairs(S s);
void rotateTriples(S s);
void removeEverySecond(S s);
void doubleAllKeys(S s);
S rotateRight(S s);
S rotateLeft(S s);
void removeDuplicates(S s);
S invert(S s);
S clone(S s);
S alternate(S a, S b);
S merge(S a, S b, Comparator<T> cmp);
Pair<S, S> divideAlternating(S s);
Pair<S, S> divideAlternatingByRuns(S s, Comparator<T> cmp);
Pair<S, S> divideByPivot(S s, T pivot, Comparator<T> cmp);
S create(Iterable<T> iterable);
Iterable<T> iterate(S s);
}

View File

@ -0,0 +1,28 @@
package aud.exam.prep;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DoubleLatinProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
return Stream
.generate(() ->
Arguments.of(randomLatin(), randomLatin()))
.limit(Tests.STEAM_SIZE);
}
private String randomLatin() {
var size = Tests.RANDOM.nextInt(100);
return Tests.RANDOM
.ints(size, 'A', 'Z'+1)
.mapToObj(n ->
String.valueOf((char) n))
.collect(Collectors.joining());
}
}

View File

@ -0,0 +1,35 @@
package aud.exam.prep;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DuplicateListProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
return Stream
.generate(this::randomListWithDuplicates)
.map(Arguments::of)
.limit(Tests.STEAM_SIZE);
}
private List<Integer> randomListWithDuplicates() {
var size = Tests.RANDOM.nextInt(50);
return Tests.RANDOM
.ints(size, 0, 100)
.boxed()
.flatMap(n -> {
var count = Tests.RANDOM.nextInt(10);
return Collections
.nCopies(count, n)
.stream();
})
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,28 @@
package aud.exam.prep;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ListProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
return Stream
.generate(this::randomList)
.map(Arguments::of)
.limit(Tests.STEAM_SIZE);
}
private List<Integer> randomList() {
var size = Tests.RANDOM.nextInt(50);
return Tests.RANDOM
.ints(size, 0, 100)
.boxed()
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,419 @@
package aud.exam.prep;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public abstract class SequenceProcessorTest<S> {
protected final Comparator<Integer> cmp = Integer::compareTo;
protected final SequenceProcessor<Integer, S> processor;
protected SequenceProcessorTest(SequenceProcessor<Integer, S> processor) {
this.processor = processor;
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_createAndIterateWork(List<Integer> list) {
S s = processor.create(list);
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_findOfNonExistsIsFalse(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.find(s, -1));
assertFalse(processor.find(s, 999));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_findOfExistsIsTrue(List<Integer> list) {
S s = processor.create(list);
for (var n : list) {
assertTrue(processor.find(s, n));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_findBinaryOfNonExistsIsFalse(List<Integer> list) {
list.sort(cmp);
S s = processor.create(list);
assertFalse(processor.findBinary(s, -1, cmp));
assertFalse(processor.findBinary(s, 999, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_findBinaryOfExistsIsTrue(List<Integer> list) {
list.sort(Comparable::compareTo);
S s = processor.create(list);
for (var n : list) {
assertTrue(processor.findBinary(s, n, cmp));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_overrideOfNotExistsIsFalseAndDoesNotModify(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.override(s, -1, -5));
assertFalse(processor.override(s, 999, -5));
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_overrideOfExistsIsTrueAndDoesModify(List<Integer> list) {
S s = processor.create(list);
for (int i = 0; i < list.size(); i++) {
var to = -(i*i) - 5;
assertTrue(processor.override(s, list.get(i), to));
list.set(i, to);
assertIterableEquals(list, processor.iterate(s));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_overrideAllOfNotExistsIsFalseAndDoesNotModify(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.overrideAll(s, -1, -5));
assertFalse(processor.overrideAll(s, 999, -5));
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_overrideAllOfExistsIsTrueAndDoesModify(List<Integer> list) {
S s = processor.create(list);
for (int i = 0; i < list.size(); i++) {
var from = list.get(i);
var to = -(i*i) - 5;
assertTrue(processor.overrideAll(s, from, to));
list.replaceAll(k ->
Objects.equals(k, from) ? to : k);
assertIterableEquals(list, processor.iterate(s));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_overrideAtOfBadIndexIsFalseAndDoesNotModify(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.overrideAt(s, -5, -1));
assertFalse(processor.overrideAt(s, -5, 999));
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_overrideAtOfExistsIsTrueAndDoesModify(List<Integer> list) {
S s = processor.create(list);
for (int i = 0; i < list.size(); i++) {
var to = -(i*i) - 5;
assertTrue(processor.overrideAt(s, to, i));
list.set(i, to);
assertIterableEquals(list, processor.iterate(s));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_insertInOrderWorks(List<Integer> list) {
list.sort(cmp);
S s = processor.create(list);
for (int i = -1; i < 110; i++) {
processor.insertInOrder(s, i, cmp);
list.add(i);
list.sort(cmp);
assertIterableEquals(list, processor.iterate(s));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_removeOfNonExistsIsFalseAndDoesNotModify(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.remove(s, -1));
assertFalse(processor.remove(s, 999));
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_removeOfExistsIsTrueAndDoesModify(List<Integer> list) {
S s = processor.create(list);
while (!list.isEmpty()) {
var toRemove = list.get(list.size()/2);
list.remove(toRemove);
assertTrue(processor.remove(s, toRemove));
assertIterableEquals(list, processor.iterate(s));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_removeAllOfNonExistsIsFalseAndDoesNotModify(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.removeAll(s, -1));
assertFalse(processor.removeAll(s, 999));
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_removeAllOfExistsIsTrueAndDoesModify(List<Integer> list) {
S s = processor.create(list);
while (!list.isEmpty()) {
var toRemove = list.get(list.size()/2);
list.removeAll(Collections.singleton(toRemove));
assertTrue(processor.removeAll(s, toRemove));
assertIterableEquals(list, processor.iterate(s));
}
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_ifAscendingOfUnsortedIsFalse(List<Integer> list) {
assumeTrue(list.size() > 2, "The list is to small");
list.add(list.size()/2, -1);
S s = processor.create(list);
assertFalse(processor.isAscending(s, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_ifAscendingOfSortedIsTrue(List<Integer> list) {
list.sort(cmp);
S s = processor.create(list);
assertTrue(processor.isAscending(s, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_maxWorks(List<Integer> list) {
list.add(-1);
S s = processor.create(list);
var max = list
.stream()
.max(cmp)
.orElseThrow();
assertEquals(max, processor.max(s, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_secondMaxWorks(List<Integer> list) {
list.add(-1);
list.add(-2);
S s = processor.create(list);
var max = list
.stream()
.sorted(cmp.reversed())
.skip(1)
.findFirst()
.orElseThrow();
assertEquals(max, processor.secondMax(s, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_isItemWiseLessOrEqualOfSameIsTrue(List<Integer> list) {
S s = processor.create(list);
assertTrue(processor.isItemWiseLessOrEqual(s, s, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_isItemWiseLessOrEqualWithPlus5Works(List<Integer> list) {
S a = processor.create(list);
for (int i = 0; i < list.size(); i++) {
if (i % 2 == 0) {
list.set(i, list.get(i)+5);
}
}
S b = processor.create(list);
assertTrue(processor.isItemWiseLessOrEqual(a, b, cmp));
assumeTrue(!list.isEmpty(), "List must not be empty to be less then");
assertFalse(processor.isItemWiseLessOrEqual(b, a, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_isItemWiseLessOrEqualWithMoreElementsWorks(List<Integer> list) {
S a = processor.create(list);
for (int i = 1; i < 4; i++) {
list.add(-i);
}
S b = processor.create(list);
assertTrue(processor.isItemWiseLessOrEqual(a, b, cmp));
assertFalse(processor.isItemWiseLessOrEqual(b, a, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_isItemWiseLessOfSameIsFalse(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.isItemWiseLess(s, s, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_isItemWiseLessWithAlmostSameIsTrue(List<Integer> list) {
S a = processor.create(list);
var index = list.size()/2;
if (list.isEmpty()) {
list.add(1);
} else {
list.set(index, list.get(index)+1);
}
S b = processor.create(list);
assertTrue(processor.isItemWiseLess(a, b, cmp));
assertFalse(processor.isItemWiseLess(b, a, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_isItemWiseLessWithPlus5Works(List<Integer> list) {
S a = processor.create(list);
for (int i = 0; i < list.size(); i++) {
if (i % 2 == 0) {
list.set(i, list.get(i)+5);
}
}
if (list.isEmpty()) {
list.add(1);
}
S b = processor.create(list);
assertTrue(processor.isItemWiseLess(a, b, cmp));
assertFalse(processor.isItemWiseLess(b, a, cmp));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_isLexSmallerOfSameIfFalse(List<Integer> list) {
S s = processor.create(list);
assertFalse(processor.isLexSmaller(s, s, cmp));
}
@ParameterizedTest
@ArgumentsSource(DoubleLatinProvider.class)
void testThat_isLexSmallerWithWorksLikeStrings(String stringA, String stringB) {
S a = toSequenceByAscii(stringA);
S b = toSequenceByAscii(stringB);
assertEquals(
stringA.compareTo(stringB) < 0,
processor.isLexSmaller(a, b, cmp));
assertEquals(
stringB.compareTo(stringA) < 0,
processor.isLexSmaller(b, a, cmp));
}
protected S toSequenceByAscii(String string) {
var list = string
.chars()
.boxed()
.collect(Collectors.toList());
return processor.create(list);
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_doubleAllKeysWorks(List<Integer> list) {
S s = processor.create(list);
list = list
.stream()
.flatMap(n ->
Stream.of(n, n))
.collect(Collectors.toList());
processor.doubleAllKeys(s);
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_rotateRightWorks(List<Integer> list) {
S s = processor.create(list);
if (list.size() > 1) {
var right = list.remove(list.size()-1);
list.add(0, right);
}
s = processor.rotateRight(s);
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(ListProvider.class)
void testThat_rotateLeftWorks(List<Integer> list) {
S s = processor.create(list);
if (list.size() > 1) {
var left = list.remove(0);
list.add(left);
}
s = processor.rotateLeft(s);
assertIterableEquals(list, processor.iterate(s));
}
@ParameterizedTest
@ArgumentsSource(DuplicateListProvider.class)
void testThat_removeDuplicatesWorks(List<Integer> list) {
S s = processor.create(list);
var noDuplicatesList = new ArrayList<Integer>();
for (var n : list) {
if (noDuplicatesList.isEmpty() || !Objects.equals(n, noDuplicatesList.get(noDuplicatesList.size()-1))) {
noDuplicatesList.add(n);
}
}
processor.removeDuplicates(s);
assertIterableEquals(noDuplicatesList, processor.iterate(s));
}
}

View File

@ -0,0 +1,10 @@
package aud.exam.prep;
import java.util.Random;
public class Tests {
public static final int STEAM_SIZE = 50;
public static final Random RANDOM = new Random();
}