Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to solve a conditional equation in iOS

I want to solve a conditional equation in iOS:

The equation I get from database is in NSString format, for example:

if((height > 0), (weight+ 2 ), ( weight-1 ) )

As per our understanding, if I parse the above string and separateheight>0condition, it will be in the NSString format. But to evaluate it how do I convert the string to a conditional statement?

Once the conditional statement is obtained the equation can be solved by converting it to a ternary equation as follows:

Bool status;

NSString *condition=@” height>0”;

If(condition)    //But condition is treated as a string and not as a conditional statement.
{
    status=True;
}
else
{
    status=False;
}

Return status ? weight+ 2 : weight-1;`

Also the equations can dynamically change, so they cannot be hard coded. In short how do I solve this equation which I get as a NSString.

Thank you for your patience!

like image 994
Sagar Jadhav Avatar asked May 16 '13 10:05

Sagar Jadhav


1 Answers

DDMathParser author here...

To expand on Jonathan's answer, here's how you could do it entirely in DDMathParser. However, to parse the string as-is, you'll need to do two things.

First, you'll need to create an if function:

DDMathEvaluator *evaluator = [DDMathEvaluator sharedMathEvaluator];
[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError *__autoreleasing *error) {
    if ([args count] == 3) {
        DDExpression *condition = [args objectAtIndex:0];
        DDExpression *resultExpression = nil;
        NSNumber *conditionValue = [condition evaluateWithSubstitutions:vars evaluator:eval error:error];
        if ([conditionValue boolValue] == YES) {
            resultExpression = [args objectAtIndex:1];
        } else {
            resultExpression = [args objectAtIndex:2];
        }
        NSNumber *result = [resultExpression evaluateWithSubstitutions:vars evaluator:eval error:error];
        return [DDExpression numberExpressionWithNumber:result];
    }
    return nil;

} forName:@"if"];

This creates the if() function, which takes three parameters. Depending on how the first parameter evaluates, it either evaluates to the result of the second or third parameter.

The other thing you'll need to do is tell the evaluator what height and weight mean. Since they don't start with a $ character, they get interpreted as functions, and not variables. If they started with a $, then it would be as simple as evaluating it like this:

NSString *expression = @"if(($height > 0), ($weight+ 2 ), ( $weight-1 ) )";
NSDictionary *variables = @{@"height" : @42, @"weight" : @13};
NSNumber *result = [expression evaluateWithSubstitutions:variables evaluator:evaluator error:nil];

However, since they don't start with a $, they're functions, which means you need to tell the evaluator what the functions evaluate to. You could do this by creating functions for both height and weight, just like you did for if:

[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
    return [DDExpression numberExpressionWithNumber:@42];
} forName:@"height"];

Alternatively, you could make it a bit more dynamic and use the functionResolver block of DDMathEvaluator, which is a block that returns a block (woooooo) and would look like this:

NSDictionary *values = @{@"height": @42, @"weight": @13};
[evaluator setFunctionResolver:^DDMathFunction(NSString *name) {
    DDMathFunction f = ^(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
        NSNumber *n = [values objectForKey:name];
        if (!n) { n = @0; }
        return [DDExpression numberExpressionWithNumber:n];
    };
    return f;
}];

With those two pieces in place (registering if and providing the values of height and weight), you can do:

NSString *expression = @"if((height > 0), (weight+ 2 ), ( weight-1 ) )";
NSNumber *result = [expression evaluateWithSubstitutions:nil evaluator:evaluator error:nil];

... and get back the proper result of @15.

(I have plans to make DDMathParser allow unknown functions to fall back to provided variable values, but I haven't quite finished it yet)

like image 52
Dave DeLong Avatar answered Sep 25 '22 06:09

Dave DeLong