package expression; import base.ExtendedRandom; import base.Pair; import base.Selector; import base.TestCounter; import expression.common.ExpressionKind; import expression.common.Type; import java.util.List; /** * Three-argument arithmetic expression over integers. * * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) */ @FunctionalInterface @SuppressWarnings("ClassReferencesSubclass") public interface TripleExpression extends ToMiniString { int evaluate(int x, int y, int z); // Tests follow. You may temporarily remove everything til the end. Type TYPE = new Type<>(a -> a, ExtendedRandom::nextInt, int.class); ExpressionKind KIND = new ExpressionKind<>( TYPE, TripleExpression.class, List.of( Pair.of("x", new Variable("x")), Pair.of("y", new Variable("y")), Pair.of("z", new Variable("z")) ), (expr, variables, values) -> expr.evaluate(values.get(0), values.get(1), values.get(2)) ); @SuppressWarnings("PointlessArithmeticExpression") static ExpressionTester tester(final TestCounter counter) { final Variable vx = new Variable("x"); final Variable vy = new Variable("y"); final Variable vz = new Variable("z"); return new ExpressionTester<>( counter, KIND, c -> (x, y, z) -> c, (op, a, b) -> (x, y, z) -> op.apply(a.evaluate(x, y, z), b.evaluate(x, y, z)), Integer::sum, (a, b) -> a - b, (a, b) -> a * b, (a, b) -> a / b ) .basic("10", "10", (x, y, z) -> 10, c(10)) .basic("x", "x", (x, y, z) -> x, vx) .basic("y", "y", (x, y, z) -> y, vy) .basic("z", "z", (x, y, z) -> z, vz) .basic("(x + 2)", "x + 2", (x, y, z) -> x + 2, new Add(vx, c(2))) .basic("(2 - y)", "2 - y", (x, y, z) -> 2 - y, new Subtract(c(2), vy)) .basic("(3 * z)", "3 * z", (x, y, z) -> 3 * z, new Multiply(c(3), vz)) .basic("(x / -2)", "x / -2", (x, y, z) -> -x / 2, new Divide(vx, c(-2))) .basic("((1 + 2) + 3)", "1 + 2 + 3", (x, y, z) -> 6, new Add(new Add(c(1), c(2)), c(3))) .basic("(1 + (2 + 3))", "1 + 2 + 3", (x, y, z) -> 6, new Add(c(1), new Add(c(2), c(3)))) .basic("((1 - 2) - 3)", "1 - 2 - 3", (x, y, z) -> -4, new Subtract(new Subtract(c(1), c(2)), c(3))) .basic("(1 - (2 - 3))", "1 - (2 - 3)", (x, y, z) -> 2, new Subtract(c(1), new Subtract(c(2), c(3)))) .basic("((1 * 2) * 3)", "1 * 2 * 3", (x, y, z) -> 6, new Multiply(new Multiply(c(1), c(2)), c(3))) .basic("(1 * (2 * 3))", "1 * 2 * 3", (x, y, z) -> 6, new Multiply(c(1), new Multiply(c(2), c(3)))) .basic("((10 / 2) / 3)", "10 / 2 / 3", (x, y, z) -> 10 / 2 / 3, new Divide(new Divide(c(10), c(2)), c(3))) .basic("(10 / (3 / 2))", "10 / (3 / 2)", (x, y, z) -> 10, new Divide(c(10), new Divide(c(3), c(2)))) .basic("((x * y) + ((z - 1) / 10))", "x * y + (z - 1) / 10", (x, y, z) -> x * y + (z - 1) / 10, new Add( new Multiply(vx, vy), new Divide(new Subtract(vz, c(1)), c(10)) )) .basic("(x + y)", "x + y", (x, y, z) -> x + y, new Add(vx, vy)) .basic("(y + x)", "y + x", (x, y, z) -> y + x, new Add(vy, vx)) .advanced("(1 + 1)", "1 + 1", (x, y, z) -> 1 + 1, new Add(c(1), c(1))) .advanced("(y - x)", "y - x", (x, y, z) -> y - x, new Subtract(vy, vx)) .advanced("(2 * x)", "2 * x", (x, y, z) -> 2 * x, new Multiply(c(2), vx)) .advanced("(2 / x)", "2 / x", (x, y, z) -> 2 / x, new Divide(c(2), vx)) .advanced("(z + (1 + 1))", "z + 1 + 1", (x, y, z) -> z + 1 + 1, new Add(vz, new Add(c(1), c(1)))) .advanced( "(2 - (y - x))", "2 - (y - x)", (x, y, z) -> 2 - (y - x), new Subtract(c(2), new Subtract(vy, vx)) ) .advanced( "(z * (2 / x))", "z * (2 / x)", (x, y, z) -> z * (2 / x), new Multiply(vz, new Divide(c(2), vx)) ) .advanced( "(z / (y - x))", "z / (y - x)", (x, y, z) -> z / (y - x), new Divide(vz, new Subtract(vy, vx)) ) .advanced("((2 * x) + y)", "2 * x + y", (x, y, z) -> 2 * x + y, new Add(new Multiply(c(2), vx), vy)) .advanced( "((y - x) - 2)", "y - x - 2", (x, y, z) -> y - x - 2, new Subtract(new Subtract(vy, vx), c(2)) ) .advanced("((2 / x) * y)", "2 / x * y", (x, y, z) -> 2 / x * y, new Multiply(new Divide(c(2), vx), vy)) .advanced("((1 + 1) / x)", "(1 + 1) / x", (x, y, z) -> (1 + 1) / x, new Divide(new Add(c(1), c(1)), vx)) .advanced("(1 + (2 * 3))", "1 + 2 * 3", (x, y, z) -> 7, new Add(c(1), new Multiply(c(2), c(3)))) .advanced("(1 - (2 * 3))", "1 - 2 * 3", (x, y, z) -> -5, new Subtract(c(1), new Multiply(c(2), c(3)))) .advanced("(1 + (2 / 3))", "1 + 2 / 3", (x, y, z) -> 1, new Add(c(1), new Divide(c(2), c(3)))) .advanced("(1 - (2 / 3))", "1 - 2 / 3", (x, y, z) -> 1, new Subtract(c(1), new Divide(c(2), c(3)))) .advanced( "(2 + (z + (1 + 1)))", "2 + z + 1 + 1", (x, y, z) -> 2 + z + 1 + 1, new Add(c(2), new Add(vz, new Add(c(1), c(1)))) ) .advanced( "(1 - ((2 * x) + y))", "1 - (2 * x + y)", (x, y, z) -> 1 - (2 * x + y), new Subtract(c(1), new Add(new Multiply(c(2), vx), vy)) ) .advanced( "(1 * (z / (y - x)))", "1 * (z / (y - x))", (x, y, z) -> 1 * (z / (y - x)), new Multiply(c(1), new Divide(vz, new Subtract(vy, vx))) ) .advanced( "(z / (z + (1 + 1)))", "z / (z + 1 + 1)", (x, y, z) -> z / (z + 1 + 1), new Divide(vz, new Add(vz, new Add(c(1), c(1)))) ) .advanced( "((2 * x) + (1 + 1))", "2 * x + 1 + 1", (x, y, z) -> 2 * x + 1 + 1, new Add(new Multiply(c(2), vx), new Add(c(1), c(1))) ) .advanced( "((1 + 1) - (1 + 1))", "1 + 1 - (1 + 1)", (x, y, z) -> 1 + 1 - (1 + 1), new Subtract(new Add(c(1), c(1)), new Add(c(1), c(1))) ) .advanced( "((y - x) * (2 / x))", "(y - x) * (2 / x)", (x, y, z) -> (y - x) * (2 / x), new Multiply(new Subtract(vy, vx), new Divide(c(2), vx)) ) .advanced( "((y - x) / (2 * x))", "(y - x) / (2 * x)", (x, y, z) -> (y - x) / (2 * x), new Divide(new Subtract(vy, vx), new Multiply(c(2), vx)) ) .advanced( "(((y - x) - 2) + 1)", "y - x - 2 + 1", (x, y, z) -> y - x - 2 + 1, new Add(new Subtract(new Subtract(vy, vx), c(2)), c(1)) ) .advanced( "(((2 * x) + y) - z)", "2 * x + y - z", (x, y, z) -> 2 * x + y - z, new Subtract(new Add(new Multiply(c(2), vx), vy), vz) ) .advanced( "(((1 + 1) / x) * 2)", "(1 + 1) / x * 2", (x, y, z) -> (1 + 1) / x * 2, new Multiply(new Divide(new Add(c(1), c(1)), vx), c(2)) ) .advanced( "((z / (y - x)) / x)", "z / (y - x) / x", (x, y, z) -> z / (y - x) / x, new Divide(new Divide(vz, new Subtract(vy, vx)), vx) ); } private static Const c(final Integer c) { return TYPE.constant(c); } Selector SELECTOR = ExpressionTest.SELECTOR .variant("Triple", ExpressionTest.v(TripleExpression::tester)); static void main(final String... args) { TripleExpression.SELECTOR.main(args); } }