Reputation: 6121
I have a list of boolean conditions like == 4
, < 5
, > 1
and so on. Now what I would like to know if a series of and constraints is possible. Lets say < 5 > 1
is possible while < 5 > 9
is not. I have thought of feeding the strings into nashorn but this brings me nowhere. How can I achieve this? Or is there any library out there doing the job?
EDIT: I have exactly 3 operators ==, <= and >= and doubles not integers (yes in real life the lesser or higher means lesser/higher equals - but that should not make a difference). Maybe I could scale up doubles i.e. 1022.30 -> 10223
Upvotes: 2
Views: 113
Reputation: 140319
If all of your bounds are integers, you can convert each of your conditions into a closed range. For example:
= x
is [x, x]
< x
is [Integer.MIN_VALUE, x - 1]
> x
is [x + 1, Integer.MAX_VALUE]
etc.
You can build one of these ranges for each of your input conditions, and then take the intersection of the ranges by calculating the maximum of the lower bounds, and the minimum of the lower bounds.
If the max of the lower bounds <=
the min of the upper bounds, the condition can be satisfied.
Example for integers:
boolean canBeSatisfied(Iterable<Pair<enum, Integer>> conditions) {
int maxLower = Integer.MAX_VALUE;
int minUpper = Integer.MIN_VALUE;
for (Pair<enum, Integer> condition : conditions) {
maxLower = Math.max(maxLower, getLowerBound(condition));
minUpper = Math.min(minUpper, getUpperBound(condition));
}
return maxLower <= minUpper;
}
and then define getLowerBound
and getUpperBound
something like:
int getLowerBound(Pair<enum, Integer> condition) {
switch (condition.first) {
case EQUALS:
case GE:
return condition.second;
case GT:
return condition.second + 1;
case LT: case LE:
return Integer.MIN_VALUE;
}
}
int getUpperBound(Pair<enum, Integer> condition) {
switch (condition.first) {
case EQUALS:
case GE: case GT:
return Integer.MAX_VALUE;
case LT:
return condition.second - 1;
case LE:
return condition.second;
}
}
You can extend the same idea to double bounds, but you need to be a little bit more careful to handle the difference between closed and open bounds.
If you can use Guava, you can do all of this directly with the Range
class, using the factory methods to construct appropriate instances of the ranges, and then just taking the intersection of all range instances.
Upvotes: 1
Reputation: 5681
I would use a interface
for the operators instead of an enum
. This will make you able subclass to this interface for all operators:
// File: Main.java
import java.util.ArrayList;
import java.util.List;
class Pair<L,R> {
L left;
R right;
public Pair(L left, R right) {
this.left = left;
this.right = right;
}
}
interface Operator {
boolean calculate(double lhs, double rhs);
}
public class Main {
private static Operator equals = new Operator() {
@Override
public boolean calculate(double lhs, double rhs) {
return lhs == rhs;
}
@Override
public String toString() {
return "==";
}
};
public static void main(String[] args) {
Double x = 3.14;
List<Pair<Operator, Double>> constraints = new ArrayList<>();
constraints.add(new Pair(equals, 5.0));
constraints.add(new Pair(equals, 3.14));
for (Pair<Operator, Double> constraint : constraints) {
Operator operator = constraint.left;
double value = constraint.right;
boolean result = operator.calculate(x, value);
System.out.println(x + operator.toString() + value + "=" + result);
}
}
}
Upvotes: 0
Reputation: 9319
I don't know much about your setup, but assuming there are only three operators (>
, <
, and ==
), there are only three major cases to handle:
| > | < | ==
--+---+---+---
> | | B | A
--+---+---+---
< | B | | C
--+---+---+---
==| A | C |
(sorry for the ugly table)
First, you need to detect the case, then define methods for each one, e.g.
possibleA(int biggerThan, int equalTo) {
return equalTo > biggerThan;
}
and analogous for case B and C.
Upvotes: 0