Solving variable value combination through Boolean expression - c#

I do have some boolean expressions in a file as mentioned below.
((a&&b)|(c&&a)|(r&&s) && !(c)&& (f>=5)) = false
((e&&f) !(n)&& p) = false
and so on.
My task is to find all the possible boolean combinations for the variables used in the expression , that would yield an outcome mentioned at the right hand side of the expression.
I am a beginner to c# .Kindly guide me achieve this.

You can do it for a limited number of inputs, and know input values like this:
public void CalculateExpression(Expression<Func<bool, bool, int, bool>> expr){
var compiledExpr = expr.Compile();
for(var a = false; !a; !a)
for(var b = false; !b; !b)
for(var c = 0; c < 100; c)
if(compiledExpr.Invoke(a,b,c))
//Print or do whatever you want with that parameter combination
}
//Call with any of your login sentences
CalculateExpression((a,b,c) => (a|b)&&(c>5) == false);

Related

parse string with condition to boolean

I am looking for a way to get a boolean value from a string.
I have a string, stored in a database, that is a condition to be tested with.
suppose the string = "[number] < 10000"
In my code I then plan to replace [number] with a actual number so the string would become "100 < 10000".
Is there a simple way to evaluate this string to a boolean.
In this case it would be False.
Another example: "[number] > 100 && [number] < 1000"
If number would be 200, the evaluation would be True.
What if I add code to this condition, like "if ([number] > 100 && [number] < 1000) { return true;} else {return false;}"
If there a simple way to get the return value from this string with code?
You can make use of DynamicExpression class, it is available in this nuget package. It can evaluate expressions on the fly.
Below is an example,
var expression = System.Linq.Dynamic.DynamicExpression.ParseLambda(
new System.Linq.Expressions.ParameterExpression[] { },
typeof(bool),
"100 > 1000",
new object[] { });
var compiledDelegate = expression.Compile();
var result = compiledDelegate.DynamicInvoke(null);
The result will be false as the provided expression "100 > 1000" is false.
If you need more control, you have to create expressions depending upon dynamic strings representing logical operations. For example, I have taken your first case of "[number]<1000" You can try below:
static void Main(string[] args)
{
string code = "[number] < 10000".Replace("[number]", "100");
string[] operands = code.Split('<');
var comparison = Expression.LessThan(
Expression.Constant(operands[0]),
Expression.Constant(operands[1]));
var lambda = Expression.Lambda<Func<bool>>(comparison).Compile();
bool result = lambda();
}
Or Alternatively you can use existing libraries or nuget packages for doing same thing in a more simpler way (under hood they do same though):
string code = "[number] < 10000".Replace("[number]", "100");
func = ExpressionParser.Compile<Func<bool>>(code);
bool result = func()
It makes use of Lambda parser as shown here

Combination of conditional statements

I have 2 sets of 3 conditions each.
Let a,b,c be one set of conditions and x,y,z be the other set. I need to evaluate the following
if(a && x)
.....
else if(a && y)
.....
else if(a && z)
.....
In the same way 3 conditions with b and 3 with c.
What is the best way to evaluate the conditions without writing all the combinations?
Update :
I am making a game in Unity. The conditions a,b,c check whether the x position of the player is within a certain range compared to a ball's position and conditions x,y,z do the same for y position. Based on the correct condition(from the combination ax,ay,az,bx,by,bz,cx,cy,cz) one animation state(out of 9) is selected. So each condition would produce a different result.
Update :
I ended up making two functions that evaluate the two sets of conditions and each returns an enum on which bitwise OR is done to get the final state.
My first thought would be to at least test the first group of conditions first, and then test the second group of conditions afterwards. While this is not an answer that avoids writing all nine if statements, you will on average reduce the amount of if statements being checked.
if (a)
{
if (x) { }
else if (y) { }
else if (z) { }
}
else if (b)
{
if (x) { }
else if (y) { }
else if (z) { }
}
else if (c)
{
if (x) { }
else if (y) { }
else if (z) { }
}
Generate all possible combinations. Since you deal with Booleans, each gives you 2 options. Then the simplest possible combination of 2 bools results to 2 x 2 = 4 combinations. Generally saying, K = 2^n, where n represent number of booleans you deal with.
Would I be you, I would stick to Tuple<bool, bool, bool> and nested for(var i = 0; i < 2; i++) cycles (for n parameters n cycles needed).
Then I would feed a list of Tuple<Predicate<Tuple<bool, bool, bool>>, Action> which pairs predicate with callback that should trigger when predicates equals true.
Rest could be achieved with Linq. Something alike possibleCombinationsList.Select(tripleOfBooleans => predicatesAndCallbacksList.Single(predicateAndCallback => predicateAndCallback.Item1(tripleOfBooleans) == true)).Sinle().Item2();
Have fun.
This is one way of doing it using Linq expressions, Linq expressions is a way to define expressions dynamically where you can do multiple operations on them. i used here a fake conditional expression that takes a number as an argument just for the sake of demonstration. first define each condition in a method or directly within you code. then put all those into arrays, each conditions set to an array. then two foreach that executes the expressions.
int num = 20;
ConditionalExpression[] firstSet = { ExpressionA(num), ExpressionB(num), ExpressionC(num) };
ConditionalExpression[] secondSet = { ExpressionX(num), ExpressionY(num), ExpressionZ(num) };
foreach(var firstSetExpression in firstSet)
foreach (var secondSetExpression in secondSet)
{
var result1 = Expression.Lambda<Func<bool>>(firstSetExpression.Test).Compile();
var result2 = Expression.Lambda<Func<bool>>(secondSetExpression.Test).Compile();
if (result1.Invoke() && result2.Invoke())
{
// do your thing here
}
}
Where you define expressions for each condition within a method, for example like this:
private static ConditionalExpression ExpressionA(int num)
{
return Expression.Condition(
Expression.Constant(num > 10),
Expression.Constant("num is greater than 10"),
Expression.Constant("num is smaller than 10")
);
}
this can be even optimized in many ways, but only to get you started.
Update: This is another way for who dont like to compile at runtime. using delegates:
Func<int, bool>[] firstSet = new Func<int,bool> [] { ExpressionA(), ExpressionA(), ExpressionA() };
Func<int, bool>[] secondSet = new Func<int, bool>[] { ExpressionA(), ExpressionA(), ExpressionA() };
foreach(var firstSetExpression in firstSet)
foreach (var secondSetExpression in secondSet)
{
if (firstSetExpression.Invoke(20) && secondSetExpression.Invoke(20))
{
// do your thing here
}
}
...
...
...
private static Func<int, bool> ExpressionA()
{
return (x) => x > 10;
}
Good Luck.

LINQ search / match

let assume we have an array like this:
var caps = new[] { "1512x", "001xx", "27058", "201xx", "4756x" };
(original array is huge and come from another linq query)
What I need is to create a LINQ statement accepting a value and tries to match with one of the values on the foreseen array.
For example if I use "15121" I need to match the "1512x" value on the array and return it.
Obviously, if I use "27058" it finds the exact match and simply return it.
Is it possible in LINQ?
The "wildcard" char on the array is "x", but I can change it.
Thanks in advance!
Valerio
You can use regular expressions:
var value = "15121";
var caps = new[] { "1512x", "001xx", "27058", "201xx", "4756x" };
var match = caps
.FirstOrDefault(c => new Regex("^" + c.Replace("x", "[0-9]") + "$").IsMatch(value));
if (match != null)
Console.WriteLine("{0} matches {1}", value, match);
The "pattern" 001xx is converted into the regular expression ^001[0-9][0-9]$ and so on. Then the first matching regular expressions is found.
But if the caps is huge it might not perform so well because each regular expression has to be compiled and converted into a state machine until a match is found.
Assuming you have a predicate method, something like this (or something equivalent using Regex, as described in another answer):
static bool Match(string pattern, string exact)
{
if(pattern.Length != exact.Length) return false;
for(var i = 0; i < pattern.Length; i++)
if(pattern[i] != exact[i] && pattern[i] != 'x')
return false;
return true;
}
Then the LINQ query can look like this:
var found = caps.Single(x => Match(x, yourSearch));

I am trying to understand what is happening in this variable assignment

I am trying to understand what is happening in this variable assignment.
num = forward.Data.Key >= key ? 1 : 0;
In particular this part >= key ? 1 : 0
To help out forward is a LinkedListCell<KeyValuePair<int, double>> forward = _data.Next;
key is an int parameter being passed into the method.
Also it is a program written in C#
That's the ternary operator. It takes a boolean expression, and returns one of two values depending on the result of that expression. You get it in a number of languages.
It's equivalent to:
if( forward.Data.Key >= key ) {
num = 1;
}
else {
num = 0;
}
It is called ternary conditional operator. (or the short If-Else statement)
value = condition ? truePart : falsePart;
The ternary operator tests a condition. It compares two values. It produces a third value that depends on the result of the comparison.
from MSDN,
int input = Convert.ToInt32(Console.ReadLine());
string classify;
// if-else construction.
if (input < 0)
classify = "negative";
else
classify = "positive";
// ?: conditional operator.
classify = (input < 0) ? "negative" : "positive";

Reversing an ienumerable of lambda functions

I have created an ienumerable of lambda functions using this function
static IEnumerable<Func<int>> MakeEnumerator(int[] values)
{
for (int a = 0; a < values.Length; a++)
{
yield return () => Values[a];
}
}
I cannot then reverse this using LINQ or convert into an array without all the values becoming the last function.
Example code (note this just demonstrates the problem it is not the code in the application):
int[] start = {1,2,3};
IEnumerable<Func<int>> end = MakeEnumerator(start).Reverse<Func<int>>();
foreach (Func<int> i in end)
{
Console.WriteLine(i());
}
I think the problem is in the MakeEnumerator function. How would I modify this to make it work or go about writing a working replacement reverse function.
The problem is that you're capturing the loop variable. All of your delegates are capturing the same variable, so they'll always see the latest value of a... which will be values.Length + 1 by the time you're executing the delegates, in your use cases. You can simply copy it instead:
for (int a = 0; a < values.Length; a++)
{
int copy = a;
yield return () => Values[copy];
}
Alternatively (and preferrably IMO) use a foreach loop, which currently requires the same workaround:
foreach (int value in values)
{
int copy = value;
yield return () => copy;
}
Or better yet:
return values.Select(x => (Func<int>)(() => x));
Or:
Func<int, Func<int>> projection = x => () => x;
return values.Select(projection);
See Eric Lippert's blog post "Closing over the loop variable considered harmful" for more information. Note that the behaviour of foreach may well be changing for C# 4.5.
All of your lambda expressions are sharing the same a variable.
Since you're only calling them after the loop finishes, a is always 3.
You need to give each one its own variable:
for (int dontUse = 0; dontUse < values.Length; dontUse++)
{
int a = dontUse;
yield return () => Values[a];
}
In this code, each lambda expression gets its own a variable (since it's scoped inside the loop), and these separate variables never change.

Categories

Resources