Upload files to "java/sum"
This commit is contained in:
45
java/sum/SumDoubleHex.java
Normal file
45
java/sum/SumDoubleHex.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package sum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikita Doschennikov (me@fymio.us)
|
||||||
|
*/
|
||||||
|
public class SumDoubleHex {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
double res = 0;
|
||||||
|
for (String arg : args) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
boolean containsDot = false;
|
||||||
|
for (char c : arg.toCharArray()) {
|
||||||
|
if (!Character.isWhitespace(c)) {
|
||||||
|
builder.append(c);
|
||||||
|
if (c == '.') {
|
||||||
|
containsDot = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res += compute(builder.toString(), containsDot);
|
||||||
|
containsDot = false;
|
||||||
|
builder = new StringBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res += compute(builder.toString(), containsDot);
|
||||||
|
}
|
||||||
|
System.out.println(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double compute(String num, boolean containsDot) {
|
||||||
|
double res = 0;
|
||||||
|
if (num.isEmpty()) {
|
||||||
|
res += 0;
|
||||||
|
} else if (
|
||||||
|
num.charAt(0) == '0' &&
|
||||||
|
(num.charAt(1) == 'x' || num.charAt(1) == 'X')
|
||||||
|
) {
|
||||||
|
res += (containsDot) ? Double.parseDouble(num) : Long.decode(num);
|
||||||
|
} else {
|
||||||
|
res += Double.parseDouble(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
java/sum/SumHex.java
Normal file
42
java/sum/SumHex.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package sum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikita Doschennikov (me@fymio.us)
|
||||||
|
*/
|
||||||
|
public class SumHex {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int res = 0;
|
||||||
|
for (String arg : args) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (char c : arg.toCharArray()) {
|
||||||
|
if (!Character.isWhitespace(c)) {
|
||||||
|
builder.append(c);
|
||||||
|
} else {
|
||||||
|
res += compute(builder.toString());
|
||||||
|
|
||||||
|
builder = new StringBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res += compute(builder.toString());
|
||||||
|
}
|
||||||
|
System.out.println(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compute(String num) {
|
||||||
|
int res = 0;
|
||||||
|
if (num.isEmpty()) {
|
||||||
|
res += 0;
|
||||||
|
} else if (
|
||||||
|
num.length() >= 2 &&
|
||||||
|
num.charAt(0) == '0' &&
|
||||||
|
(num.charAt(1) == 'x' || num.charAt(1) == 'X')
|
||||||
|
) {
|
||||||
|
res += Long.decode(num);
|
||||||
|
} else {
|
||||||
|
res += Integer.parseInt(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
45
java/sum/SumLongOctal.java
Normal file
45
java/sum/SumLongOctal.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package sum;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikita Doschennikov (me@fymio.us)
|
||||||
|
*/
|
||||||
|
public class SumLongOctal {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
long res = 0;
|
||||||
|
for (String arg : args) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (char c : arg.toCharArray()) {
|
||||||
|
if (!Character.isWhitespace(c)) {
|
||||||
|
builder.append(c);
|
||||||
|
} else {
|
||||||
|
res += compute(builder.toString());
|
||||||
|
builder = new StringBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res += compute(builder.toString());
|
||||||
|
}
|
||||||
|
System.out.println(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long compute(String num) {
|
||||||
|
if (num.isEmpty()) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numLength = num.length();
|
||||||
|
|
||||||
|
if (
|
||||||
|
num.charAt(numLength - 1) == 'o' || num.charAt(numLength - 1) == 'O'
|
||||||
|
) {
|
||||||
|
return new BigInteger(
|
||||||
|
num.substring(0, num.length() - 1),
|
||||||
|
8
|
||||||
|
).longValue();
|
||||||
|
} else {
|
||||||
|
return Long.parseLong(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
311
java/sum/SumTest.java
Normal file
311
java/sum/SumTest.java
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
package sum;
|
||||||
|
|
||||||
|
import base.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.function.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
|
||||||
|
*/
|
||||||
|
public final class SumTest {
|
||||||
|
|
||||||
|
// === Base
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
/* package-private */ interface Op<
|
||||||
|
T extends Number
|
||||||
|
> extends UnaryOperator<SumTester<T>> {}
|
||||||
|
|
||||||
|
private static final BiConsumer<Number, String> TO_STRING = (
|
||||||
|
expected,
|
||||||
|
out
|
||||||
|
) -> Asserts.assertEquals("Sum", expected.toString(), out);
|
||||||
|
|
||||||
|
private static final Named<Supplier<SumTester<Integer>>> BASE = Named.of(
|
||||||
|
"",
|
||||||
|
() ->
|
||||||
|
new SumTester<>(
|
||||||
|
Integer::sum,
|
||||||
|
n -> (int) n,
|
||||||
|
(r, max) -> r.nextInt() % max,
|
||||||
|
TO_STRING,
|
||||||
|
10,
|
||||||
|
100,
|
||||||
|
Integer.MAX_VALUE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* package-private */ static <T extends Number> Named<Op<T>> plain() {
|
||||||
|
return Named.of("", test -> test);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === DoubleHex
|
||||||
|
|
||||||
|
private static BiConsumer<Number, String> approximate(
|
||||||
|
final Function<String, Number> parser,
|
||||||
|
final double precision
|
||||||
|
) {
|
||||||
|
return (expected, out) ->
|
||||||
|
Asserts.assertEquals(
|
||||||
|
"Sum",
|
||||||
|
expected.doubleValue(),
|
||||||
|
parser.apply(out).doubleValue(),
|
||||||
|
precision
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Named<Supplier<SumTester<Double>>> DOUBLE = Named.of(
|
||||||
|
"Double",
|
||||||
|
() ->
|
||||||
|
new SumTester<>(
|
||||||
|
Double::sum,
|
||||||
|
n -> (double) n,
|
||||||
|
(r, max) -> (r.getRandom().nextDouble() - 0.5) * 2 * max,
|
||||||
|
approximate(Double::parseDouble, 1e-10),
|
||||||
|
10.0,
|
||||||
|
0.01,
|
||||||
|
1e20,
|
||||||
|
1e100,
|
||||||
|
Double.MAX_VALUE / 10000
|
||||||
|
)
|
||||||
|
.test(5, "2.5 2.5")
|
||||||
|
.test(0, "1e100 -1e100")
|
||||||
|
.testT(2e100, "1.5e100 0.5e100")
|
||||||
|
);
|
||||||
|
|
||||||
|
private static <T extends Number> Named<Op<T>> hexFull(
|
||||||
|
final Function<T, String> toHex
|
||||||
|
) {
|
||||||
|
final Function<T, String> toHexSpoiled = toHex.andThen(s ->
|
||||||
|
s
|
||||||
|
.chars()
|
||||||
|
.map(ch ->
|
||||||
|
((ch ^ s.hashCode()) & 1) == 0
|
||||||
|
? Character.toLowerCase(ch)
|
||||||
|
: Character.toUpperCase(ch)
|
||||||
|
)
|
||||||
|
.mapToObj(Character::toString)
|
||||||
|
.collect(Collectors.joining())
|
||||||
|
);
|
||||||
|
return Named.of("Hex", test ->
|
||||||
|
test
|
||||||
|
.test(toHex, 1)
|
||||||
|
.test(toHex, 0x1a)
|
||||||
|
.test(toHexSpoiled, 0xA2)
|
||||||
|
.test(toHexSpoiled, 0X0, 0X1, 0XF, 0XF, 0x0, 0x1, 0xF, 0xf)
|
||||||
|
.test(toHexSpoiled, 0x12345678)
|
||||||
|
.test(toHexSpoiled, 0x09abcdef)
|
||||||
|
.test(toHexSpoiled, 0x3CafeBab)
|
||||||
|
.test(toHexSpoiled, 0x3DeadBee)
|
||||||
|
.test(toHex, Integer.MAX_VALUE)
|
||||||
|
.test(toHex, Integer.MIN_VALUE)
|
||||||
|
.setToString(number -> {
|
||||||
|
final int hashCode = number.hashCode();
|
||||||
|
if ((hashCode & 1) == 0) {
|
||||||
|
return number.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return toHexSpoiled.apply(number);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Octal
|
||||||
|
private static <T extends Number> Named<Op<T>> octal(
|
||||||
|
final Function<T, String> toOctal
|
||||||
|
) {
|
||||||
|
//noinspection OctalInteger,StringConcatenationMissingWhitespace
|
||||||
|
return Named.of("Octal", test ->
|
||||||
|
test
|
||||||
|
.test(1, "1o")
|
||||||
|
.test(017, "17o")
|
||||||
|
.testSpaces(6, " 1o 2o 3O ")
|
||||||
|
.test(01234567, "1234567O")
|
||||||
|
.test(
|
||||||
|
Integer.MIN_VALUE,
|
||||||
|
"-0" + String.valueOf(Integer.MIN_VALUE).substring(1)
|
||||||
|
)
|
||||||
|
.test(Integer.MAX_VALUE, "0" + Integer.MAX_VALUE)
|
||||||
|
.test(
|
||||||
|
Integer.MAX_VALUE,
|
||||||
|
Integer.toOctalString(Integer.MAX_VALUE) + "o"
|
||||||
|
)
|
||||||
|
.test(
|
||||||
|
Integer.MAX_VALUE,
|
||||||
|
"0" + Integer.toOctalString(Integer.MAX_VALUE) + "O"
|
||||||
|
)
|
||||||
|
.setToString(number -> {
|
||||||
|
final int hashCode = number.hashCode();
|
||||||
|
if ((hashCode & 1) == 0) {
|
||||||
|
return number.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
final String lower =
|
||||||
|
toOctal.apply(number).toLowerCase(Locale.ROOT) + "o";
|
||||||
|
return (hashCode & 2) == 0
|
||||||
|
? lower
|
||||||
|
: lower.toUpperCase(Locale.ROOT);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Long
|
||||||
|
|
||||||
|
private static final Named<Supplier<SumTester<Long>>> LONG = Named.of(
|
||||||
|
"Long",
|
||||||
|
() ->
|
||||||
|
new SumTester<>(
|
||||||
|
Long::sum,
|
||||||
|
n -> n,
|
||||||
|
(r, max) -> r.getRandom().nextLong() % max,
|
||||||
|
TO_STRING,
|
||||||
|
10L,
|
||||||
|
100L,
|
||||||
|
(long) Integer.MAX_VALUE,
|
||||||
|
Long.MAX_VALUE
|
||||||
|
)
|
||||||
|
.test(12345678901234567L, " +12345678901234567 ")
|
||||||
|
.test(0L, " +12345678901234567 -12345678901234567")
|
||||||
|
.test(0L, " +12345678901234567 -12345678901234567")
|
||||||
|
);
|
||||||
|
|
||||||
|
// === BigInteger
|
||||||
|
|
||||||
|
private static final Named<Supplier<SumTester<BigInteger>>> BIG_INTEGER =
|
||||||
|
Named.of("BigInteger", () ->
|
||||||
|
new SumTester<>(
|
||||||
|
BigInteger::add,
|
||||||
|
BigInteger::valueOf,
|
||||||
|
(r, max) -> new BigInteger(max.bitLength(), r.getRandom()),
|
||||||
|
TO_STRING,
|
||||||
|
BigInteger.TEN,
|
||||||
|
BigInteger.TEN.pow(10),
|
||||||
|
BigInteger.TEN.pow(100),
|
||||||
|
BigInteger.TWO.pow(1000)
|
||||||
|
).test(
|
||||||
|
0,
|
||||||
|
"10000000000000000000000000000000000000000 -10000000000000000000000000000000000000000"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// === BigDecimalHex
|
||||||
|
|
||||||
|
@SuppressWarnings("BigDecimalMethodWithoutRoundingCalled")
|
||||||
|
private static final Named<Supplier<SumTester<BigDecimal>>> BIG_DECIMAL =
|
||||||
|
Named.of("BigDecimal", () ->
|
||||||
|
new SumTester<>(
|
||||||
|
BigDecimal::add,
|
||||||
|
BigDecimal::valueOf,
|
||||||
|
(r, max) -> {
|
||||||
|
final BigInteger unscaled = new BigInteger(
|
||||||
|
(max.precision() - max.scale() + 2) * 3,
|
||||||
|
r.getRandom()
|
||||||
|
);
|
||||||
|
return new BigDecimal(unscaled, 3);
|
||||||
|
},
|
||||||
|
TO_STRING,
|
||||||
|
BigDecimal.TEN,
|
||||||
|
BigDecimal.TEN.pow(10),
|
||||||
|
BigDecimal.TEN.pow(100),
|
||||||
|
BigDecimal.ONE.add(BigDecimal.ONE).pow(1000)
|
||||||
|
)
|
||||||
|
.testT(
|
||||||
|
BigDecimal.ZERO.setScale(3),
|
||||||
|
"10000000000000000000000000000000000000000.123 -10000000000000000000000000000000000000000.123"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
private static String bigDecimalToString(final BigDecimal number) {
|
||||||
|
final int scale = number.scale();
|
||||||
|
return (
|
||||||
|
"0x" +
|
||||||
|
number.unscaledValue().toString(16) +
|
||||||
|
(scale == 0 ? "" : "s" + Integer.toString(scale, 16))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Hex
|
||||||
|
|
||||||
|
private static <T extends Number> Named<Op<T>> hex(
|
||||||
|
final Function<T, String> toHex
|
||||||
|
) {
|
||||||
|
return hexFull(v -> "0x" + toHex.apply(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Common
|
||||||
|
|
||||||
|
/* package-private */ static <T extends Number> Consumer<
|
||||||
|
TestCounter
|
||||||
|
> variant(
|
||||||
|
final Named<Function<String, Runner>> runner,
|
||||||
|
final Named<Supplier<SumTester<T>>> test,
|
||||||
|
final Named<
|
||||||
|
? extends Function<? super SumTester<T>, ? extends SumTester<?>>
|
||||||
|
> modifier
|
||||||
|
) {
|
||||||
|
return counter ->
|
||||||
|
modifier
|
||||||
|
.value()
|
||||||
|
.apply(test.value().get())
|
||||||
|
.test(
|
||||||
|
"Sum" + test.name() + modifier.name() + runner.name(),
|
||||||
|
counter,
|
||||||
|
runner.value()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package-private */ static final Named<Function<String, Runner>> RUNNER =
|
||||||
|
Named.of("", Runner.packages("", "sum")::args);
|
||||||
|
|
||||||
|
public static final Selector SELECTOR = selector(SumTest.class, RUNNER);
|
||||||
|
|
||||||
|
private SumTest() {
|
||||||
|
// Utility class
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Selector selector(
|
||||||
|
final Class<?> owner,
|
||||||
|
final Named<Function<String, Runner>> runner
|
||||||
|
) {
|
||||||
|
return new Selector(owner)
|
||||||
|
.variant("Base", variant(runner, BASE, plain()))
|
||||||
|
.variant(
|
||||||
|
"3637",
|
||||||
|
variant(
|
||||||
|
runner,
|
||||||
|
DOUBLE,
|
||||||
|
hexFull(value ->
|
||||||
|
value == value.intValue() && value > 0
|
||||||
|
? "0x" + Integer.toHexString(value.intValue())
|
||||||
|
: Double.toHexString(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.variant(
|
||||||
|
"3839",
|
||||||
|
variant(
|
||||||
|
runner,
|
||||||
|
BIG_DECIMAL,
|
||||||
|
hexFull(SumTest::bigDecimalToString)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.variant("3435", variant(runner, BASE, hex(Integer::toHexString)))
|
||||||
|
.variant("3233", variant(runner, DOUBLE, plain()))
|
||||||
|
.variant("4749", variant(runner, LONG, octal(Long::toOctalString)))
|
||||||
|
.variant(
|
||||||
|
"4142",
|
||||||
|
variant(
|
||||||
|
runner,
|
||||||
|
BIG_INTEGER,
|
||||||
|
octal(number -> number.toString(8))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(final String... args) {
|
||||||
|
SELECTOR.main(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
232
java/sum/SumTester.java
Normal file
232
java/sum/SumTester.java
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
package sum;
|
||||||
|
|
||||||
|
import base.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.LongStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
|
||||||
|
*/
|
||||||
|
public class SumTester<T extends Number> {
|
||||||
|
|
||||||
|
private static final List<String> SPACES = List.of(
|
||||||
|
" \t\n\u000B\u2029\f",
|
||||||
|
IntStream.rangeClosed(0, Character.MAX_VALUE)
|
||||||
|
.filter(Character::isWhitespace)
|
||||||
|
.mapToObj(Character::toString)
|
||||||
|
.collect(Collectors.joining())
|
||||||
|
);
|
||||||
|
|
||||||
|
private final BinaryOperator<T> add;
|
||||||
|
private final LongFunction<T> fromLong;
|
||||||
|
private BiFunction<ExtendedRandom, T, String> toString;
|
||||||
|
private final BiFunction<ExtendedRandom, T, T> randomValue;
|
||||||
|
private final BiConsumer<Number, String> verifier;
|
||||||
|
private List<String> spaces;
|
||||||
|
private final List<T> limits;
|
||||||
|
|
||||||
|
private final List<Consumer<Checker>> tests = new ArrayList<>();
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public SumTester(
|
||||||
|
final BinaryOperator<T> add,
|
||||||
|
final LongFunction<T> fromLong,
|
||||||
|
final BiFunction<ExtendedRandom, T, T> randomValue,
|
||||||
|
final BiConsumer<Number, String> verifier,
|
||||||
|
final T... limits
|
||||||
|
) {
|
||||||
|
this.add = add;
|
||||||
|
this.fromLong = fromLong;
|
||||||
|
this.randomValue = randomValue;
|
||||||
|
this.verifier = verifier;
|
||||||
|
this.limits = List.of(limits);
|
||||||
|
|
||||||
|
setSpaces(SPACES);
|
||||||
|
setToString(String::valueOf);
|
||||||
|
|
||||||
|
test(1, "1");
|
||||||
|
test(6, "1", "2", "3");
|
||||||
|
test(1, " 1");
|
||||||
|
test(1, "1 ");
|
||||||
|
test(1, " 1 ");
|
||||||
|
test(12345, " 12345 ");
|
||||||
|
test(60, "010", "020", "030");
|
||||||
|
testSpaces(1368, " 123 456 789 ");
|
||||||
|
test(-1, "-1");
|
||||||
|
test(-6, "-1", "-2", "-3");
|
||||||
|
test(-12345, " -12345 ");
|
||||||
|
testSpaces(-1368, " -123 -456 -789 ");
|
||||||
|
test(1, "+1");
|
||||||
|
test(6, "+1", "+2", "+3");
|
||||||
|
test(12345, " +12345 ");
|
||||||
|
testSpaces(1368, " +123 +456 +789 ");
|
||||||
|
test(0);
|
||||||
|
testSpaces(0, " ", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SumTester<T> setSpaces(final List<String> spaces) {
|
||||||
|
this.spaces = spaces;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SumTester<T> addSpaces(final String... spaces) {
|
||||||
|
this.spaces = Stream.concat(
|
||||||
|
this.spaces.stream(),
|
||||||
|
Arrays.stream(spaces)
|
||||||
|
).toList();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SumTester<T> setToString(final Function<T, String> toString) {
|
||||||
|
return setToString((r, n) -> toString.apply(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SumTester<T> setToString(
|
||||||
|
final BiFunction<ExtendedRandom, T, String> toString
|
||||||
|
) {
|
||||||
|
this.toString = toString;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SumTester<T> test(
|
||||||
|
final Function<T, String> toString,
|
||||||
|
final long... input
|
||||||
|
) {
|
||||||
|
return testT(
|
||||||
|
fromLong.apply(LongStream.of(input).sum()),
|
||||||
|
LongStream.of(input)
|
||||||
|
.mapToObj(fromLong)
|
||||||
|
.map(toString)
|
||||||
|
.collect(Collectors.joining(" "))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SumTester<T> test(final long result, final String... input) {
|
||||||
|
return testT(fromLong.apply(result), input);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SumTester<T> testT(final T result, final String... input) {
|
||||||
|
return testT(result, Arrays.asList(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SumTester<T> testT(final T result, final List<String> input) {
|
||||||
|
tests.add(checker -> checker.test(result, input));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SumTester<T> testSpaces(final long result, final String... input) {
|
||||||
|
final T res = fromLong.apply(result);
|
||||||
|
tests.add(checker ->
|
||||||
|
spaces
|
||||||
|
.stream()
|
||||||
|
.flatMapToInt(String::chars)
|
||||||
|
.forEach(space ->
|
||||||
|
checker.test(
|
||||||
|
res,
|
||||||
|
Functional.map(Arrays.asList(input), s ->
|
||||||
|
s.replace(' ', (char) space)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test(
|
||||||
|
final String name,
|
||||||
|
final TestCounter counter,
|
||||||
|
final Function<String, Runner> runner
|
||||||
|
) {
|
||||||
|
new Checker(counter, runner.apply(name)).test();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Checker extends BaseChecker {
|
||||||
|
|
||||||
|
private final Runner runner;
|
||||||
|
|
||||||
|
public Checker(final TestCounter counter, final Runner runner) {
|
||||||
|
super(counter);
|
||||||
|
this.runner = runner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test() {
|
||||||
|
tests.forEach(test -> test.accept(this));
|
||||||
|
|
||||||
|
for (final T limit : limits) {
|
||||||
|
for (
|
||||||
|
int n = 10;
|
||||||
|
n <= 10_000 / TestCounter.DENOMINATOR;
|
||||||
|
n *= 10
|
||||||
|
) {
|
||||||
|
randomTest(n, limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void test(final T result, final List<String> input) {
|
||||||
|
counter.test(() -> {
|
||||||
|
final List<String> out = runner.run(counter, input);
|
||||||
|
Asserts.assertEquals("Single line expected", 1, out.size());
|
||||||
|
verifier.accept(result, out.get(0));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void randomTest(final int numbers, final T max) {
|
||||||
|
for (final String spaces : spaces) {
|
||||||
|
randomTest(numbers, max, spaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void randomTest(
|
||||||
|
final int numbers,
|
||||||
|
final T max,
|
||||||
|
final String spaces
|
||||||
|
) {
|
||||||
|
final List<T> values = new ArrayList<>();
|
||||||
|
for (int i = 0; i < numbers; i++) {
|
||||||
|
values.add(randomValue.apply(random(), max));
|
||||||
|
}
|
||||||
|
testRandom(
|
||||||
|
values.stream().reduce(fromLong.apply(0), add),
|
||||||
|
values,
|
||||||
|
spaces
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testRandom(
|
||||||
|
final T result,
|
||||||
|
final List<T> args,
|
||||||
|
final String spaces
|
||||||
|
) {
|
||||||
|
final List<String> spaced = args
|
||||||
|
.stream()
|
||||||
|
.map(n -> toString.apply(random(), n))
|
||||||
|
.map(value -> randomSpace(spaces) + value + randomSpace(spaces))
|
||||||
|
.toList();
|
||||||
|
final List<String> argsList = new ArrayList<>();
|
||||||
|
for (
|
||||||
|
final Iterator<String> i = spaced.listIterator();
|
||||||
|
i.hasNext();
|
||||||
|
|
||||||
|
) {
|
||||||
|
final StringBuilder next = new StringBuilder(i.next());
|
||||||
|
while (i.hasNext() && random().nextBoolean()) {
|
||||||
|
next.append(randomSpace(spaces)).append(i.next());
|
||||||
|
}
|
||||||
|
argsList.add(next.toString());
|
||||||
|
}
|
||||||
|
test(result, argsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String randomSpace(final String spaces) {
|
||||||
|
return random().randomString(spaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user