Upload files to "java/expression"
This commit is contained in:
114
java/expression/AbstractBinaryOperation.java
Normal file
114
java/expression/AbstractBinaryOperation.java
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package expression;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Doschennikov Nikita (me@fymio.us)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractBinaryOperation extends AbstractExpression {
|
||||||
|
|
||||||
|
protected final AbstractExpression left;
|
||||||
|
protected final AbstractExpression right;
|
||||||
|
|
||||||
|
protected AbstractBinaryOperation(
|
||||||
|
AbstractExpression left,
|
||||||
|
AbstractExpression right
|
||||||
|
) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String getOperator();
|
||||||
|
|
||||||
|
protected abstract int getPriority();
|
||||||
|
|
||||||
|
protected abstract boolean isRightAssoc();
|
||||||
|
|
||||||
|
protected abstract int applyInt(int a, int b);
|
||||||
|
|
||||||
|
protected abstract BigInteger applyBi(BigInteger a, BigInteger b);
|
||||||
|
|
||||||
|
protected abstract BigDecimal applyBd(BigDecimal a, BigDecimal b);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int evaluate(int x) {
|
||||||
|
return applyInt(left.evaluate(x), right.evaluate(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int evaluate(int x, int y, int z) {
|
||||||
|
return applyInt(left.evaluate(x, y, z), right.evaluate(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int evaluate(List<Integer> vars) {
|
||||||
|
return applyInt(left.evaluate(vars), right.evaluate(vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger evaluateBi(List<BigInteger> vars) {
|
||||||
|
return applyBi(left.evaluateBi(vars), right.evaluateBi(vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal evaluateBd(List<BigDecimal> vars) {
|
||||||
|
return applyBd(left.evaluateBd(vars), right.evaluateBd(vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + left + " " + getOperator() + " " + right + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toMiniString() {
|
||||||
|
return miniLeft() + " " + getOperator() + " " + miniRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String miniLeft() {
|
||||||
|
if (
|
||||||
|
left instanceof AbstractBinaryOperation op &&
|
||||||
|
op.getPriority() < getPriority()
|
||||||
|
) {
|
||||||
|
return "(" + op.toMiniString() + ")";
|
||||||
|
}
|
||||||
|
return left.toMiniString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String miniRight() {
|
||||||
|
if (right instanceof AbstractBinaryOperation op) {
|
||||||
|
boolean samePriority = op.getPriority() == getPriority();
|
||||||
|
boolean lowerPriority = op.getPriority() < getPriority();
|
||||||
|
boolean needParens =
|
||||||
|
lowerPriority ||
|
||||||
|
(samePriority && isRightAssoc()) ||
|
||||||
|
(samePriority && op.isRightAssoc() && getPriority() > 1) ||
|
||||||
|
(samePriority &&
|
||||||
|
!getOperator().equals(op.getOperator()) &&
|
||||||
|
!op.isRightAssoc() &&
|
||||||
|
!isRightAssoc());
|
||||||
|
if (needParens) {
|
||||||
|
return "(" + op.toMiniString() + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return right.toMiniString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
AbstractBinaryOperation other = (AbstractBinaryOperation) obj;
|
||||||
|
return left.equals(other.left) && right.equals(other.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (
|
||||||
|
31 * (31 * left.hashCode() + right.hashCode()) +
|
||||||
|
getClass().hashCode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
42
java/expression/AbstractExpression.java
Normal file
42
java/expression/AbstractExpression.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package expression;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Doschennikov Nikita (me@fymio.us)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractExpression
|
||||||
|
implements
|
||||||
|
Expression,
|
||||||
|
TripleExpression,
|
||||||
|
ListExpression,
|
||||||
|
BigIntegerListExpression,
|
||||||
|
BigDecimalListExpression
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract int evaluate(int x);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract int evaluate(int x, int y, int z);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract int evaluate(List<Integer> vars);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract BigInteger evaluateBi(List<BigInteger> vars);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract BigDecimal evaluateBd(List<BigDecimal> vars);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract String toString();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract boolean equals(Object obj);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract int hashCode();
|
||||||
|
}
|
||||||
44
java/expression/Add.java
Normal file
44
java/expression/Add.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package expression;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Doschennikov Nikita (me@fymio.us)
|
||||||
|
*/
|
||||||
|
public class Add extends AbstractBinaryOperation {
|
||||||
|
|
||||||
|
public Add(AbstractExpression l, AbstractExpression r) {
|
||||||
|
super(l, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getOperator() {
|
||||||
|
return "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getPriority() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isRightAssoc() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int applyInt(int a, int b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BigInteger applyBi(BigInteger a, BigInteger b) {
|
||||||
|
return a.add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BigDecimal applyBd(BigDecimal a, BigDecimal b) {
|
||||||
|
return a.add(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
363
java/expression/BigDecimalListExpression.java
Normal file
363
java/expression/BigDecimalListExpression.java
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
package expression;
|
||||||
|
|
||||||
|
import base.Asserts;
|
||||||
|
import base.Pair;
|
||||||
|
import base.TestCounter;
|
||||||
|
import expression.common.ExpressionKind;
|
||||||
|
import expression.common.Type;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One-argument arithmetic expression over {@link BigDecimal}s.
|
||||||
|
*
|
||||||
|
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
@SuppressWarnings("ClassReferencesSubclass")
|
||||||
|
public interface BigDecimalListExpression extends ToMiniString {
|
||||||
|
BigDecimal evaluateBd(List<BigDecimal> variables);
|
||||||
|
|
||||||
|
// Tests follow. You may temporarily remove everything til the end.
|
||||||
|
|
||||||
|
Add EXAMPLE = new Add(
|
||||||
|
new Subtract(new Variable(0), new Const(BigDecimal.ONE)),
|
||||||
|
new Multiply(new Variable(1), new Const(BigDecimal.TEN))
|
||||||
|
);
|
||||||
|
|
||||||
|
Type<BigDecimal> TYPE = new Type<>(
|
||||||
|
v -> new BigDecimal(v + ".000"),
|
||||||
|
random -> BigDecimal.valueOf(random.getRandom().nextGaussian()),
|
||||||
|
BigDecimal.class
|
||||||
|
);
|
||||||
|
ExpressionKind<BigDecimalListExpression, BigDecimal> KIND =
|
||||||
|
new ExpressionKind<>(
|
||||||
|
TYPE,
|
||||||
|
BigDecimalListExpression.class,
|
||||||
|
(r, c) ->
|
||||||
|
IntStream.range(0, c)
|
||||||
|
.mapToObj(name ->
|
||||||
|
Pair.<String, BigDecimalListExpression>of(
|
||||||
|
"$" + name,
|
||||||
|
new Variable(name)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
(expr, variables, values) -> expr.evaluateBd(values)
|
||||||
|
);
|
||||||
|
|
||||||
|
@SuppressWarnings("BigDecimalMethodWithoutRoundingCalled")
|
||||||
|
static ExpressionTester<?, ?> tester(final TestCounter counter) {
|
||||||
|
Asserts.assertEquals(
|
||||||
|
"Example toString()",
|
||||||
|
"(($0 - 1) + ($1 * 10))",
|
||||||
|
EXAMPLE.toString()
|
||||||
|
);
|
||||||
|
Asserts.assertEquals(
|
||||||
|
EXAMPLE + " at (2, 3)",
|
||||||
|
BigDecimal.valueOf(31),
|
||||||
|
EXAMPLE.evaluateBd(
|
||||||
|
List.of(BigDecimal.valueOf(2), BigDecimal.valueOf(3))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
final Variable vx = new Variable(0);
|
||||||
|
final Variable vy = new Variable(1);
|
||||||
|
|
||||||
|
return new ExpressionTester<>(
|
||||||
|
counter,
|
||||||
|
KIND,
|
||||||
|
c -> v -> c,
|
||||||
|
(op, a, b) -> v -> op.apply(a.evaluateBd(v), b.evaluateBd(v)),
|
||||||
|
BigDecimal::add,
|
||||||
|
BigDecimal::subtract,
|
||||||
|
BigDecimal::multiply,
|
||||||
|
BigDecimal::divide
|
||||||
|
)
|
||||||
|
.basic("10", "10", v -> v(10), c(10))
|
||||||
|
.basic("$x", "$x", BigDecimalListExpression::x, vx)
|
||||||
|
.basic("$y", "$y", BigDecimalListExpression::y, vy)
|
||||||
|
.basic("($x + $y)", "$x + $y", v -> x(v).add(y(v)), new Add(vx, vy))
|
||||||
|
.basic("($x + 2)", "$x + 2", v -> x(v).add(v(2)), new Add(vx, c(2)))
|
||||||
|
.basic(
|
||||||
|
"(2 - $x)",
|
||||||
|
"2 - $x",
|
||||||
|
v -> v(2).subtract(x(v)),
|
||||||
|
new Subtract(c(2), vx)
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(3 * $x)",
|
||||||
|
"3 * $x",
|
||||||
|
v -> v(3).multiply(x(v)),
|
||||||
|
new Multiply(c(3), vx)
|
||||||
|
)
|
||||||
|
.basic("($x + $x)", "$x + $x", v -> x(v).add(x(v)), new Add(vx, vx))
|
||||||
|
.basic(
|
||||||
|
"($x / -2)",
|
||||||
|
"$x / -2",
|
||||||
|
v -> x(v).divide(v(-2)),
|
||||||
|
new Divide(vx, c(-2))
|
||||||
|
)
|
||||||
|
.basic("(2 + $x)", "2 + $x", v -> v(2).add(x(v)), new Add(c(2), vx))
|
||||||
|
.basic(
|
||||||
|
"((1 + 2) + 3)",
|
||||||
|
"1 + 2 + 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Add(new Add(c(1), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 + (2 * 3))",
|
||||||
|
"1 + 2 * 3",
|
||||||
|
v -> v(7),
|
||||||
|
new Add(c(1), new Multiply(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 - (2 * 3))",
|
||||||
|
"1 - 2 * 3",
|
||||||
|
v -> v(-5),
|
||||||
|
new Subtract(c(1), new Multiply(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 + (2 + 3))",
|
||||||
|
"1 + 2 + 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Add(c(1), new Add(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"((1 - 2) - 3)",
|
||||||
|
"1 - 2 - 3",
|
||||||
|
v -> v(-4),
|
||||||
|
new Subtract(new Subtract(c(1), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 - (2 - 3))",
|
||||||
|
"1 - (2 - 3)",
|
||||||
|
v -> v(2),
|
||||||
|
new Subtract(c(1), new Subtract(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"((1 * 2) * 3)",
|
||||||
|
"1 * 2 * 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Multiply(new Multiply(c(1), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 * (2 * 3))",
|
||||||
|
"1 * 2 * 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Multiply(c(1), new Multiply(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"((10 / 2) / 3)",
|
||||||
|
"10 / 2 / 3",
|
||||||
|
v -> v(10).divide(v(2)).divide(v(3)),
|
||||||
|
new Divide(new Divide(c(10), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(10 / (3 / 2))",
|
||||||
|
"10 / (3 / 2)",
|
||||||
|
v -> v(10).divide(v(3).divide(v(2))),
|
||||||
|
new Divide(c(10), new Divide(c(3), c(2)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(($x * $x) + (($x - 1) / 10))",
|
||||||
|
"$x * $x + ($x - 1) / 10",
|
||||||
|
v -> x(v).multiply(x(v)).add(x(v).subtract(v(1)).divide(v(10))),
|
||||||
|
new Add(
|
||||||
|
new Multiply(vx, vx),
|
||||||
|
new Divide(new Subtract(vx, c(1)), c(10))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"($x * -1000000000)",
|
||||||
|
"$x * -1000000000",
|
||||||
|
v -> x(v).multiply(v(-1_000_000_000)),
|
||||||
|
new Multiply(vx, c(-1_000_000_000))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"($x * -1000000000000000)",
|
||||||
|
"$x * -1000000000000000",
|
||||||
|
v -> x(v).multiply(v(-1_000_000_000_000_000L)),
|
||||||
|
new Multiply(vx, c(-1_000_000_000_000_000L))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(10 / $x)",
|
||||||
|
"10 / $x",
|
||||||
|
v -> v(10).divide(x(v)),
|
||||||
|
new Divide(c(10), vx)
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"($x / $x)",
|
||||||
|
"$x / $x",
|
||||||
|
v -> x(v).divide(x(v)),
|
||||||
|
new Divide(vx, vx)
|
||||||
|
)
|
||||||
|
.advanced("(2 + 1)", "2 + 1", v -> v(2 + 1), new Add(c(2), c(1)))
|
||||||
|
.advanced(
|
||||||
|
"($x - 1)",
|
||||||
|
"$x - 1",
|
||||||
|
v -> x(v).subtract(v(1)),
|
||||||
|
new Subtract(vx, c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(1 * 2)",
|
||||||
|
"1 * 2",
|
||||||
|
v -> v(1 * 2),
|
||||||
|
new Multiply(c(1), c(2))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x / 1)",
|
||||||
|
"$x / 1",
|
||||||
|
v -> x(v).divide(v(1)),
|
||||||
|
new Divide(vx, c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(1 + (2 + 1))",
|
||||||
|
"1 + 2 + 1",
|
||||||
|
v -> v(1 + 2 + 1),
|
||||||
|
new Add(c(1), new Add(c(2), c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x - ($x - 1))",
|
||||||
|
"$x - ($x - 1)",
|
||||||
|
v -> x(v).subtract(x(v).subtract(v(1))),
|
||||||
|
new Subtract(vx, new Subtract(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(2 * ($x / 1))",
|
||||||
|
"2 * ($x / 1)",
|
||||||
|
v -> v(2).multiply(x(v).divide(v(1))),
|
||||||
|
new Multiply(c(2), new Divide(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(2 / ($x - 1))",
|
||||||
|
"2 / ($x - 1)",
|
||||||
|
v -> v(2).divide(x(v).subtract(v(1))),
|
||||||
|
new Divide(c(2), new Subtract(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((1 * 2) + $x)",
|
||||||
|
"1 * 2 + $x",
|
||||||
|
v -> v(1 * 2).add(x(v)),
|
||||||
|
new Add(new Multiply(c(1), c(2)), vx)
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x - 1) - 2)",
|
||||||
|
"$x - 1 - 2",
|
||||||
|
v -> x(v).subtract(v(3)),
|
||||||
|
new Subtract(new Subtract(vx, c(1)), c(2))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x / 1) * 2)",
|
||||||
|
"$x / 1 * 2",
|
||||||
|
v -> x(v).multiply(v(2)),
|
||||||
|
new Multiply(new Divide(vx, c(1)), c(2))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((2 + 1) / 1)",
|
||||||
|
"(2 + 1) / 1",
|
||||||
|
v -> v(3),
|
||||||
|
new Divide(new Add(c(2), c(1)), c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(1 + (1 + (2 + 1)))",
|
||||||
|
"1 + 1 + 2 + 1",
|
||||||
|
v -> v(1 + 1 + 2 + 1),
|
||||||
|
new Add(c(1), new Add(c(1), new Add(c(2), c(1))))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x - ((1 * 2) + $x))",
|
||||||
|
"$x - (1 * 2 + $x)",
|
||||||
|
v -> x(v).subtract(v(1 * 2).add(x(v))),
|
||||||
|
new Subtract(vx, new Add(new Multiply(c(1), c(2)), vx))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x * (2 / ($x - 1)))",
|
||||||
|
"$x * (2 / ($x - 1))",
|
||||||
|
v -> x(v).multiply(v(2).divide(x(v).subtract(v(1)))),
|
||||||
|
new Multiply(vx, new Divide(c(2), new Subtract(vx, c(1))))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x / (1 + (2 + 1)))",
|
||||||
|
"$x / (1 + 2 + 1)",
|
||||||
|
v -> x(v).divide(v(1 + 2 + 1)),
|
||||||
|
new Divide(vx, new Add(c(1), new Add(c(2), c(1))))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((1 * 2) + (2 + 1))",
|
||||||
|
"1 * 2 + 2 + 1",
|
||||||
|
v -> v(1 * 2 + 2 + 1),
|
||||||
|
new Add(new Multiply(c(1), c(2)), new Add(c(2), c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((2 + 1) - (2 + 1))",
|
||||||
|
"2 + 1 - (2 + 1)",
|
||||||
|
v -> v(2 + 1 - (2 + 1)),
|
||||||
|
new Subtract(new Add(c(2), c(1)), new Add(c(2), c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x - 1) * ($x / 1))",
|
||||||
|
"($x - 1) * ($x / 1)",
|
||||||
|
v -> x(v).subtract(v(1)).multiply(x(v).divide(v(1))),
|
||||||
|
new Multiply(new Subtract(vx, c(1)), new Divide(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x - 1) / (1 * 2))",
|
||||||
|
"($x - 1) / (1 * 2)",
|
||||||
|
v -> x(v).subtract(v(1)).divide(v(2)),
|
||||||
|
new Divide(new Subtract(vx, c(1)), new Multiply(c(1), c(2)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((($x - 1) - 2) + $x)",
|
||||||
|
"$x - 1 - 2 + $x",
|
||||||
|
v -> x(v).subtract(v(3)).add(x(v)),
|
||||||
|
new Add(new Subtract(new Subtract(vx, c(1)), c(2)), vx)
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(((1 * 2) + $x) - 1)",
|
||||||
|
"1 * 2 + $x - 1",
|
||||||
|
v -> v(1).add(x(v)),
|
||||||
|
new Subtract(new Add(new Multiply(c(1), c(2)), vx), c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(((2 + 1) / 1) * $x)",
|
||||||
|
"(2 + 1) / 1 * $x",
|
||||||
|
v -> v(3).multiply(x(v)),
|
||||||
|
new Multiply(new Divide(new Add(c(2), c(1)), c(1)), vx)
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((2 / ($x - 1)) / 2)",
|
||||||
|
"2 / ($x - 1) / 2",
|
||||||
|
v -> v(2).divide(x(v).subtract(v(1))).divide(v(2)),
|
||||||
|
new Divide(new Divide(c(2), new Subtract(vx, c(1))), c(2))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigDecimal x(final List<BigDecimal> vars) {
|
||||||
|
return vars.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigDecimal y(final List<BigDecimal> vars) {
|
||||||
|
return vars.get(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Const c(final BigDecimal v) {
|
||||||
|
return TYPE.constant(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Const c(final long v) {
|
||||||
|
return TYPE.constant(v(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigDecimal v(final long v) {
|
||||||
|
return BigDecimal.valueOf(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void main(final String... args) {
|
||||||
|
TripleExpression.SELECTOR.variant(
|
||||||
|
"BigDecimalList",
|
||||||
|
ExpressionTest.v(BigDecimalListExpression::tester)
|
||||||
|
).main(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
357
java/expression/BigIntegerListExpression.java
Normal file
357
java/expression/BigIntegerListExpression.java
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
package expression;
|
||||||
|
|
||||||
|
import base.Asserts;
|
||||||
|
import base.Pair;
|
||||||
|
import base.TestCounter;
|
||||||
|
import expression.common.ExpressionKind;
|
||||||
|
import expression.common.Type;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
@SuppressWarnings("ClassReferencesSubclass")
|
||||||
|
public interface BigIntegerListExpression extends ToMiniString {
|
||||||
|
BigInteger evaluateBi(List<BigInteger> variables);
|
||||||
|
|
||||||
|
// Tests follow. You may temporarily remove everything til the end.
|
||||||
|
|
||||||
|
Add EXAMPLE = new Add(
|
||||||
|
new Subtract(new Variable(0), new Const(BigInteger.ONE)),
|
||||||
|
new Multiply(new Variable(1), new Const(BigInteger.TEN))
|
||||||
|
);
|
||||||
|
|
||||||
|
Type<BigInteger> TYPE = new Type<>(
|
||||||
|
BigInteger::valueOf,
|
||||||
|
random -> v(random.getRandom().nextLong()),
|
||||||
|
BigInteger.class
|
||||||
|
);
|
||||||
|
ExpressionKind<BigIntegerListExpression, BigInteger> KIND =
|
||||||
|
new ExpressionKind<>(
|
||||||
|
TYPE,
|
||||||
|
BigIntegerListExpression.class,
|
||||||
|
(r, c) ->
|
||||||
|
IntStream.range(0, c)
|
||||||
|
.mapToObj(name ->
|
||||||
|
Pair.<String, BigIntegerListExpression>of(
|
||||||
|
"$" + name,
|
||||||
|
new Variable(name)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
(expr, variables, values) -> expr.evaluateBi(values)
|
||||||
|
);
|
||||||
|
|
||||||
|
@SuppressWarnings("PointlessArithmeticExpression")
|
||||||
|
static ExpressionTester<?, ?> tester(final TestCounter counter) {
|
||||||
|
Asserts.assertEquals(
|
||||||
|
"Example toString()",
|
||||||
|
"(($0 - 1) + ($1 * 10))",
|
||||||
|
EXAMPLE.toString()
|
||||||
|
);
|
||||||
|
Asserts.assertEquals(
|
||||||
|
EXAMPLE + " at (2, 3)",
|
||||||
|
BigInteger.valueOf(31),
|
||||||
|
EXAMPLE.evaluateBi(
|
||||||
|
List.of(BigInteger.valueOf(2), BigInteger.valueOf(3))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
final Variable vx = new Variable(0);
|
||||||
|
final Variable vy = new Variable(1);
|
||||||
|
|
||||||
|
return new ExpressionTester<>(
|
||||||
|
counter,
|
||||||
|
KIND,
|
||||||
|
c -> v -> c,
|
||||||
|
(op, a, b) -> v -> op.apply(a.evaluateBi(v), b.evaluateBi(v)),
|
||||||
|
BigInteger::add,
|
||||||
|
BigInteger::subtract,
|
||||||
|
BigInteger::multiply,
|
||||||
|
BigInteger::divide
|
||||||
|
)
|
||||||
|
.basic("10", "10", v -> v(10), c(10))
|
||||||
|
.basic("$x", "$x", BigIntegerListExpression::x, vx)
|
||||||
|
.basic("$y", "$y", BigIntegerListExpression::y, vy)
|
||||||
|
.basic("($x + $y)", "$x + $y", v -> x(v).add(y(v)), new Add(vx, vy))
|
||||||
|
.basic("($x + 2)", "$x + 2", v -> x(v).add(v(2)), new Add(vx, c(2)))
|
||||||
|
.basic(
|
||||||
|
"(2 - $x)",
|
||||||
|
"2 - $x",
|
||||||
|
v -> v(2).subtract(x(v)),
|
||||||
|
new Subtract(c(2), vx)
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(3 * $x)",
|
||||||
|
"3 * $x",
|
||||||
|
v -> v(3).multiply(x(v)),
|
||||||
|
new Multiply(c(3), vx)
|
||||||
|
)
|
||||||
|
.basic("($x + $x)", "$x + $x", v -> x(v).add(x(v)), new Add(vx, vx))
|
||||||
|
.basic(
|
||||||
|
"($x / -2)",
|
||||||
|
"$x / -2",
|
||||||
|
v -> x(v).divide(v(-2)),
|
||||||
|
new Divide(vx, c(-2))
|
||||||
|
)
|
||||||
|
.basic("(2 + $x)", "2 + $x", v -> v(2).add(x(v)), new Add(c(2), vx))
|
||||||
|
.basic(
|
||||||
|
"((1 + 2) + 3)",
|
||||||
|
"1 + 2 + 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Add(new Add(c(1), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 + (2 * 3))",
|
||||||
|
"1 + 2 * 3",
|
||||||
|
v -> v(7),
|
||||||
|
new Add(c(1), new Multiply(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 - (2 * 3))",
|
||||||
|
"1 - 2 * 3",
|
||||||
|
v -> v(-5),
|
||||||
|
new Subtract(c(1), new Multiply(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 + (2 + 3))",
|
||||||
|
"1 + 2 + 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Add(c(1), new Add(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"((1 - 2) - 3)",
|
||||||
|
"1 - 2 - 3",
|
||||||
|
v -> v(-4),
|
||||||
|
new Subtract(new Subtract(c(1), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 - (2 - 3))",
|
||||||
|
"1 - (2 - 3)",
|
||||||
|
v -> v(2),
|
||||||
|
new Subtract(c(1), new Subtract(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"((1 * 2) * 3)",
|
||||||
|
"1 * 2 * 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Multiply(new Multiply(c(1), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(1 * (2 * 3))",
|
||||||
|
"1 * 2 * 3",
|
||||||
|
v -> v(6),
|
||||||
|
new Multiply(c(1), new Multiply(c(2), c(3)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"((10 / 2) / 3)",
|
||||||
|
"10 / 2 / 3",
|
||||||
|
v -> v(10 / 2 / 3),
|
||||||
|
new Divide(new Divide(c(10), c(2)), c(3))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(10 / (3 / 2))",
|
||||||
|
"10 / (3 / 2)",
|
||||||
|
v -> v(10 / (3 / 2)),
|
||||||
|
new Divide(c(10), new Divide(c(3), c(2)))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(($x * $x) + (($x - 1) / 10))",
|
||||||
|
"$x * $x + ($x - 1) / 10",
|
||||||
|
v -> x(v).multiply(x(v)).add(x(v).subtract(v(1)).divide(v(10))),
|
||||||
|
new Add(
|
||||||
|
new Multiply(vx, vx),
|
||||||
|
new Divide(new Subtract(vx, c(1)), c(10))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"($x * -1000000000)",
|
||||||
|
"$x * -1000000000",
|
||||||
|
v -> x(v).multiply(v(-1_000_000_000)),
|
||||||
|
new Multiply(vx, c(-1_000_000_000))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"($x * -1000000000000000)",
|
||||||
|
"$x * -1000000000000000",
|
||||||
|
v -> x(v).multiply(v(-1_000_000_000_000_000L)),
|
||||||
|
new Multiply(vx, c(-1_000_000_000_000_000L))
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"(10 / $x)",
|
||||||
|
"10 / $x",
|
||||||
|
v -> v(10).divide(x(v)),
|
||||||
|
new Divide(c(10), vx)
|
||||||
|
)
|
||||||
|
.basic(
|
||||||
|
"($x / $x)",
|
||||||
|
"$x / $x",
|
||||||
|
v -> x(v).divide(x(v)),
|
||||||
|
new Divide(vx, vx)
|
||||||
|
)
|
||||||
|
.advanced("(2 + 1)", "2 + 1", v -> v(2 + 1), new Add(c(2), c(1)))
|
||||||
|
.advanced(
|
||||||
|
"($x - 1)",
|
||||||
|
"$x - 1",
|
||||||
|
v -> x(v).subtract(v(1)),
|
||||||
|
new Subtract(vx, c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(1 * 2)",
|
||||||
|
"1 * 2",
|
||||||
|
v -> v(1 * 2),
|
||||||
|
new Multiply(c(1), c(2))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x / 1)",
|
||||||
|
"$x / 1",
|
||||||
|
v -> x(v).divide(v(1)),
|
||||||
|
new Divide(vx, c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(1 + (2 + 1))",
|
||||||
|
"1 + 2 + 1",
|
||||||
|
v -> v(1 + 2 + 1),
|
||||||
|
new Add(c(1), new Add(c(2), c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x - ($x - 1))",
|
||||||
|
"$x - ($x - 1)",
|
||||||
|
v -> x(v).subtract(x(v).subtract(v(1))),
|
||||||
|
new Subtract(vx, new Subtract(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(2 * ($x / 1))",
|
||||||
|
"2 * ($x / 1)",
|
||||||
|
v -> v(2).multiply(x(v).divide(v(1))),
|
||||||
|
new Multiply(c(2), new Divide(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(2 / ($x - 1))",
|
||||||
|
"2 / ($x - 1)",
|
||||||
|
v -> v(2).divide(x(v).subtract(v(1))),
|
||||||
|
new Divide(c(2), new Subtract(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((1 * 2) + $x)",
|
||||||
|
"1 * 2 + $x",
|
||||||
|
v -> v(1 * 2).add(x(v)),
|
||||||
|
new Add(new Multiply(c(1), c(2)), vx)
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x - 1) - 2)",
|
||||||
|
"$x - 1 - 2",
|
||||||
|
v -> x(v).subtract(v(3)),
|
||||||
|
new Subtract(new Subtract(vx, c(1)), c(2))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x / 1) * 2)",
|
||||||
|
"$x / 1 * 2",
|
||||||
|
v -> x(v).multiply(v(2)),
|
||||||
|
new Multiply(new Divide(vx, c(1)), c(2))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((2 + 1) / 1)",
|
||||||
|
"(2 + 1) / 1",
|
||||||
|
v -> v(3),
|
||||||
|
new Divide(new Add(c(2), c(1)), c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(1 + (1 + (2 + 1)))",
|
||||||
|
"1 + 1 + 2 + 1",
|
||||||
|
v -> v(1 + 1 + 2 + 1),
|
||||||
|
new Add(c(1), new Add(c(1), new Add(c(2), c(1))))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x - ((1 * 2) + $x))",
|
||||||
|
"$x - (1 * 2 + $x)",
|
||||||
|
v -> x(v).subtract(v(1 * 2).add(x(v))),
|
||||||
|
new Subtract(vx, new Add(new Multiply(c(1), c(2)), vx))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x * (2 / ($x - 1)))",
|
||||||
|
"$x * (2 / ($x - 1))",
|
||||||
|
v -> x(v).multiply(v(2).divide(x(v).subtract(v(1)))),
|
||||||
|
new Multiply(vx, new Divide(c(2), new Subtract(vx, c(1))))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"($x / (1 + (2 + 1)))",
|
||||||
|
"$x / (1 + 2 + 1)",
|
||||||
|
v -> x(v).divide(v(1 + 2 + 1)),
|
||||||
|
new Divide(vx, new Add(c(1), new Add(c(2), c(1))))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((1 * 2) + (2 + 1))",
|
||||||
|
"1 * 2 + 2 + 1",
|
||||||
|
v -> v(1 * 2 + 2 + 1),
|
||||||
|
new Add(new Multiply(c(1), c(2)), new Add(c(2), c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((2 + 1) - (2 + 1))",
|
||||||
|
"2 + 1 - (2 + 1)",
|
||||||
|
v -> v(2 + 1 - (2 + 1)),
|
||||||
|
new Subtract(new Add(c(2), c(1)), new Add(c(2), c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x - 1) * ($x / 1))",
|
||||||
|
"($x - 1) * ($x / 1)",
|
||||||
|
v -> x(v).subtract(v(1)).multiply(x(v).divide(v(1))),
|
||||||
|
new Multiply(new Subtract(vx, c(1)), new Divide(vx, c(1)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(($x - 1) / (1 * 2))",
|
||||||
|
"($x - 1) / (1 * 2)",
|
||||||
|
v -> x(v).subtract(v(1)).divide(v(2)),
|
||||||
|
new Divide(new Subtract(vx, c(1)), new Multiply(c(1), c(2)))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((($x - 1) - 2) + $x)",
|
||||||
|
"$x - 1 - 2 + $x",
|
||||||
|
v -> x(v).subtract(v(3)).add(x(v)),
|
||||||
|
new Add(new Subtract(new Subtract(vx, c(1)), c(2)), vx)
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(((1 * 2) + $x) - 1)",
|
||||||
|
"1 * 2 + $x - 1",
|
||||||
|
v -> v(1).add(x(v)),
|
||||||
|
new Subtract(new Add(new Multiply(c(1), c(2)), vx), c(1))
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"(((2 + 1) / 1) * $x)",
|
||||||
|
"(2 + 1) / 1 * $x",
|
||||||
|
v -> v(3).multiply(x(v)),
|
||||||
|
new Multiply(new Divide(new Add(c(2), c(1)), c(1)), vx)
|
||||||
|
)
|
||||||
|
.advanced(
|
||||||
|
"((2 / ($x - 1)) / 2)",
|
||||||
|
"2 / ($x - 1) / 2",
|
||||||
|
v -> v(2).divide(x(v).subtract(v(1))).divide(v(2)),
|
||||||
|
new Divide(new Divide(c(2), new Subtract(vx, c(1))), c(2))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigInteger x(final List<BigInteger> vars) {
|
||||||
|
return vars.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigInteger y(final List<BigInteger> vars) {
|
||||||
|
return vars.get(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Const c(final long v) {
|
||||||
|
return TYPE.constant(v(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigInteger v(final long v) {
|
||||||
|
return BigInteger.valueOf(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void main(final String... args) {
|
||||||
|
TripleExpression.SELECTOR.variant(
|
||||||
|
"BigIntegerList",
|
||||||
|
ExpressionTest.v(BigIntegerListExpression::tester)
|
||||||
|
).main(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user