Upload files to "java/expression"

This commit is contained in:
2026-04-13 10:50:13 +03:00
parent 8b9612d1ec
commit d6e1e5893f
5 changed files with 527 additions and 0 deletions

51
java/expression/High.java Normal file
View File

@@ -0,0 +1,51 @@
package expression;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
/**
* @author Doschennikov Nikita (me@fymio.us)
*/
public class High extends AbstractExpression {
private final AbstractExpression operand;
public High(AbstractExpression operand) {
this.operand = operand;
}
private static int highestBit(int n) {
if (n == 0) return 0;
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
return n - (n >>> 1);
}
@Override public int evaluate(int x) { return highestBit(operand.evaluate(x)); }
@Override public int evaluate(int x, int y, int z) { return highestBit(operand.evaluate(x,y,z)); }
@Override public int evaluate(List<Integer> vars) { return highestBit(operand.evaluate(vars)); }
@Override public BigInteger evaluateBi(List<BigInteger> vars) { throw new UnsupportedOperationException(); }
@Override public BigDecimal evaluateBd(List<BigDecimal> vars) { throw new UnsupportedOperationException(); }
@Override public String toString() { return "high(" + operand + ")"; }
@Override
public String toMiniString() {
if (operand instanceof AbstractBinaryOperation) {
return "high(" + operand.toMiniString() + ")";
}
return "high " + operand.toMiniString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof High)) return false;
return operand.equals(((High) obj).operand);
}
@Override public int hashCode() { return operand.hashCode() ^ 0x48494748; }
}

View File

@@ -0,0 +1,337 @@
package expression;
import base.Asserts;
import base.ExtendedRandom;
import base.Pair;
import base.TestCounter;
import expression.common.ExpressionKind;
import expression.common.Type;
import java.util.List;
import java.util.stream.IntStream;
/**
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
*/
@SuppressWarnings("ClassReferencesSubclass")
@FunctionalInterface
public interface ListExpression extends ToMiniString {
int evaluate(List<Integer> variables);
// Tests follow. You may temporarily remove everything til the end.
Add EXAMPLE = new Add(
new Subtract(new Variable(0), new Const(1)),
new Multiply(new Variable(1), new Const(10))
);
Type<Integer> TYPE = new Type<>(a -> a, ExtendedRandom::nextInt, int.class);
ExpressionKind<ListExpression, Integer> KIND = new ExpressionKind<>(
TYPE,
ListExpression.class,
(r, c) ->
IntStream.range(0, c)
.mapToObj(name ->
Pair.<String, ListExpression>of(
"$" + name,
new Variable(name)
)
)
.toList(),
(expr, variables, values) -> expr.evaluate(values)
);
private static Const c(final Integer c) {
return TYPE.constant(c);
}
@SuppressWarnings({ "PointlessArithmeticExpression", "Convert2MethodRef" })
static ExpressionTester<?, ?> tester(final TestCounter counter) {
Asserts.assertEquals(
"Example toString()",
"(($0 - 1) + ($1 * 10))",
EXAMPLE.toString()
);
Asserts.assertEquals(
EXAMPLE + " at (2, 3)",
31,
EXAMPLE.evaluate(List.of(2, 3))
);
final Variable vx = new Variable(0);
return new ExpressionTester<>(
counter,
KIND,
c -> vars -> c,
(op, a, b) -> vars -> op.apply(a.evaluate(vars), b.evaluate(vars)),
(a, b) -> a + b,
(a, b) -> a - b,
(a, b) -> a * b,
(a, b) -> a / b
)
.basic("10", "10", vars -> 10, c(10))
.basic("$x", "$x", ListExpression::x, vx)
.basic("($x + 2)", "$x + 2", vars -> x(vars) + 2, new Add(vx, c(2)))
.basic(
"(2 - $x)",
"2 - $x",
vars -> 2 - x(vars),
new Subtract(c(2), vx)
)
.basic(
"(3 * $x)",
"3 * $x",
vars -> 3 * x(vars),
new Multiply(c(3), vx)
)
.basic(
"($x + $x)",
"$x + $x",
vars -> x(vars) + x(vars),
new Add(vx, vx)
)
.basic(
"($x / -2)",
"$x / -2",
vars -> -x(vars) / 2,
new Divide(vx, c(-2))
)
.basic("(2 + $x)", "2 + $x", vars -> 2 + x(vars), new Add(c(2), vx))
.basic(
"((1 + 2) + 3)",
"1 + 2 + 3",
vars -> 6,
new Add(new Add(c(1), c(2)), c(3))
)
.basic(
"(1 + (2 + 3))",
"1 + 2 + 3",
vars -> 6,
new Add(c(1), new Add(c(2), c(3)))
)
.basic(
"((1 - 2) - 3)",
"1 - 2 - 3",
vars -> -4,
new Subtract(new Subtract(c(1), c(2)), c(3))
)
.basic(
"(1 - (2 - 3))",
"1 - (2 - 3)",
vars -> 2,
new Subtract(c(1), new Subtract(c(2), c(3)))
)
.basic(
"((1 * 2) * 3)",
"1 * 2 * 3",
vars -> 6,
new Multiply(new Multiply(c(1), c(2)), c(3))
)
.basic(
"(1 * (2 * 3))",
"1 * 2 * 3",
vars -> 6,
new Multiply(c(1), new Multiply(c(2), c(3)))
)
.basic(
"((10 / 2) / 3)",
"10 / 2 / 3",
vars -> 10 / 2 / 3,
new Divide(new Divide(c(10), c(2)), c(3))
)
.basic(
"(10 / (3 / 2))",
"10 / (3 / 2)",
vars -> 10 / (3 / 2),
new Divide(c(10), new Divide(c(3), c(2)))
)
.basic(
"(10 * (3 / 2))",
"10 * (3 / 2)",
vars -> 10 * (3 / 2),
new Multiply(c(10), new Divide(c(3), c(2)))
)
.basic(
"(10 + (3 - 2))",
"10 + 3 - 2",
vars -> 10 + (3 - 2),
new Add(c(10), new Subtract(c(3), c(2)))
)
.basic(
"(($x * $x) + (($x - 1) / 10))",
"$x * $x + ($x - 1) / 10",
vars -> x(vars) * x(vars) + (x(vars) - 1) / 10,
new Add(
new Multiply(vx, vx),
new Divide(new Subtract(vx, c(1)), c(10))
)
)
.basic(
"($x * -1000000000)",
"$x * -1000000000",
vars -> x(vars) * -1_000_000_000,
new Multiply(vx, c(-1_000_000_000))
)
.basic(
"(10 / $x)",
"10 / $x",
vars -> 10 / x(vars),
new Divide(c(10), vx)
)
.basic(
"($x / $x)",
"$x / $x",
vars -> x(vars) / x(vars),
new Divide(vx, vx)
)
.advanced("(2 + 1)", "2 + 1", vars -> 2 + 1, new Add(c(2), c(1)))
.advanced(
"($x - 1)",
"$x - 1",
vars -> x(vars) - 1,
new Subtract(vx, c(1))
)
.advanced(
"(1 * 2)",
"1 * 2",
vars -> 1 * 2,
new Multiply(c(1), c(2))
)
.advanced(
"($x / 1)",
"$x / 1",
vars -> x(vars) / 1,
new Divide(vx, c(1))
)
.advanced(
"(1 + (2 + 1))",
"1 + 2 + 1",
vars -> 1 + 2 + 1,
new Add(c(1), new Add(c(2), c(1)))
)
.advanced(
"($x - ($x - 1))",
"$x - ($x - 1)",
vars -> x(vars) - (x(vars) - 1),
new Subtract(vx, new Subtract(vx, c(1)))
)
.advanced(
"(2 * ($x / 1))",
"2 * ($x / 1)",
vars -> 2 * (x(vars) / 1),
new Multiply(c(2), new Divide(vx, c(1)))
)
.advanced(
"(2 / ($x - 1))",
"2 / ($x - 1)",
vars -> 2 / (x(vars) - 1),
new Divide(c(2), new Subtract(vx, c(1)))
)
.advanced(
"((1 * 2) + $x)",
"1 * 2 + $x",
vars -> 1 * 2 + x(vars),
new Add(new Multiply(c(1), c(2)), vx)
)
.advanced(
"(($x - 1) - 2)",
"$x - 1 - 2",
vars -> x(vars) - 1 - 2,
new Subtract(new Subtract(vx, c(1)), c(2))
)
.advanced(
"(($x / 1) * 2)",
"$x / 1 * 2",
vars -> (x(vars) / 1) * 2,
new Multiply(new Divide(vx, c(1)), c(2))
)
.advanced(
"((2 + 1) / 1)",
"(2 + 1) / 1",
vars -> (2 + 1) / 1,
new Divide(new Add(c(2), c(1)), c(1))
)
.advanced(
"(1 + (1 + (2 + 1)))",
"1 + 1 + 2 + 1",
vars -> 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)",
vars -> x(vars) - (1 * 2 + x(vars)),
new Subtract(vx, new Add(new Multiply(c(1), c(2)), vx))
)
.advanced(
"($x * (2 / ($x - 1)))",
"$x * (2 / ($x - 1))",
vars -> x(vars) * (2 / (x(vars) - 1)),
new Multiply(vx, new Divide(c(2), new Subtract(vx, c(1))))
)
.advanced(
"($x / (1 + (2 + 1)))",
"$x / (1 + 2 + 1)",
vars -> x(vars) / (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",
vars -> 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)",
vars -> 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)",
vars -> (x(vars) - 1) * (x(vars) / 1),
new Multiply(new Subtract(vx, c(1)), new Divide(vx, c(1)))
)
.advanced(
"(($x - 1) / (1 * 2))",
"($x - 1) / (1 * 2)",
vars -> (x(vars) - 1) / (1 * 2),
new Divide(new Subtract(vx, c(1)), new Multiply(c(1), c(2)))
)
.advanced(
"((($x - 1) - 2) + $x)",
"$x - 1 - 2 + $x",
vars -> x(vars) - 1 - 2 + x(vars),
new Add(new Subtract(new Subtract(vx, c(1)), c(2)), vx)
)
.advanced(
"(((1 * 2) + $x) - 1)",
"1 * 2 + $x - 1",
vars -> 1 * 2 + x(vars) - 1,
new Subtract(new Add(new Multiply(c(1), c(2)), vx), c(1))
)
.advanced(
"(((2 + 1) / 1) * $x)",
"(2 + 1) / 1 * $x",
vars -> ((2 + 1) / 1) * x(vars),
new Multiply(new Divide(new Add(c(2), c(1)), c(1)), vx)
)
.advanced(
"((2 / ($x - 1)) / 2)",
"2 / ($x - 1) / 2",
vars -> 2 / (x(vars) - 1) / 2,
new Divide(new Divide(c(2), new Subtract(vx, c(1))), c(2))
);
}
private static Integer x(final List<Integer> vars) {
return vars.get(0);
}
static void main(final String... args) {
TripleExpression.SELECTOR.variant(
"List",
ExpressionTest.v(ListExpression::tester)
).main(args);
}
}

46
java/expression/Log.java Normal file
View File

@@ -0,0 +1,46 @@
package expression;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* @author Doschennikov Nikita (me@fymio.us)
*/
public class Log extends AbstractBinaryOperation {
public Log(AbstractExpression l, AbstractExpression r) { super(l, r); }
@Override protected String getOperator() { return "//"; }
@Override protected int getPriority() { return 3; }
@Override protected boolean isRightAssoc() { return true; }
@Override
protected int applyInt(int a, int b) {
if (a <= 0) throw new ArithmeticException("logarithm of non-positive number");
if (b <= 1) throw new ArithmeticException("logarithm base must be > 1");
int result = 0;
int power = 1;
while (power <= a / b) {
power *= b;
result++;
}
return result;
}
@Override
protected BigInteger applyBi(BigInteger a, BigInteger b) {
if (a.signum() <= 0) throw new ArithmeticException("logarithm of non-positive number");
if (b.compareTo(BigInteger.TWO) < 0) throw new ArithmeticException("logarithm base must be > 1");
int result = 0;
BigInteger power = BigInteger.ONE;
while (power.multiply(b).compareTo(a) <= 0) {
power = power.multiply(b);
result++;
}
return BigInteger.valueOf(result);
}
@Override
protected BigDecimal applyBd(BigDecimal a, BigDecimal b) {
throw new UnsupportedOperationException("log not supported for BigDecimal");
}
}

52
java/expression/Log2.java Normal file
View File

@@ -0,0 +1,52 @@
package expression;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
/**
* @author Doschennikov Nikita (me@fymio.us)
*/
public class Log2 extends AbstractExpression {
private final AbstractExpression operand;
public Log2(AbstractExpression operand) {
this.operand = operand;
}
private static int log2(int n) {
if (n <= 0) throw new ArithmeticException("log₂ of non-positive number: " + n);
int result = 0;
int v = n;
while (v > 1) {
v >>= 1;
result++;
}
return result;
}
@Override public int evaluate(int x) { return log2(operand.evaluate(x)); }
@Override public int evaluate(int x, int y, int z) { return log2(operand.evaluate(x,y,z)); }
@Override public int evaluate(List<Integer> vars) { return log2(operand.evaluate(vars)); }
@Override public BigInteger evaluateBi(List<BigInteger> vars) { throw new UnsupportedOperationException(); }
@Override public BigDecimal evaluateBd(List<BigDecimal> vars) { throw new UnsupportedOperationException(); }
@Override public String toString() { return "log₂(" + operand + ")"; }
@Override
public String toMiniString() {
if (operand instanceof AbstractBinaryOperation) {
return "log₂(" + operand.toMiniString() + ")";
}
return "log₂ " + operand.toMiniString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Log2)) return false;
return operand.equals(((Log2) obj).operand);
}
@Override public int hashCode() { return operand.hashCode() ^ 0x4C4F4732; }
}

41
java/expression/Low.java Normal file
View File

@@ -0,0 +1,41 @@
package expression;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
/**
* @author Doschennikov Nikita (me@fymio.us)
*/
public class Low extends AbstractExpression {
private final AbstractExpression operand;
public Low(AbstractExpression operand) {
this.operand = operand;
}
@Override public int evaluate(int x) { int n = operand.evaluate(x); return n & -n; }
@Override public int evaluate(int x, int y, int z) { int n = operand.evaluate(x,y,z); return n & -n; }
@Override public int evaluate(List<Integer> vars) { int n = operand.evaluate(vars); return n & -n; }
@Override public BigInteger evaluateBi(List<BigInteger> vars) { throw new UnsupportedOperationException(); }
@Override public BigDecimal evaluateBd(List<BigDecimal> vars) { throw new UnsupportedOperationException(); }
@Override public String toString() { return "low(" + operand + ")"; }
@Override
public String toMiniString() {
if (operand instanceof AbstractBinaryOperation) {
return "low(" + operand.toMiniString() + ")";
}
return "low " + operand.toMiniString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Low)) return false;
return operand.equals(((Low) obj).operand);
}
@Override public int hashCode() { return operand.hashCode() ^ 0x4C4F5700; }
}