0

我在使用括号完成算法时遇到了一个令人沮丧的问题。我使用的数学库 DDMathParser 只处理以弧度表示的三角函数。如果想使用度数,他们必须调用dtor(deg_value). 问题是这增加了一个额外的括号,必须在最后考虑。

例如,数学表达式sin(cos(sin(x)))sin(dtor(cos(dtor(sin(dtor(x)))在我的代码中转换为。但是,请注意,我需要两个额外的括号才能使其成为完整的数学表达式。因此,创建resolve_dtor().

这是我尝试的解决方案,想法是0表示左括号,用1表示左括号 dtor(2表示右括号,从而完成01

- (NSMutableString *)resolve_dtor:(NSMutableString *)exp
{
    NSInteger mutable_length = [exp length];
    NSMutableArray *paren_complete = [[NSMutableArray alloc] init];     // NO/YES

    for (NSInteger index = 0; index < mutable_length; index++) {

        if ([exp characterAtIndex:index] == '(') {

            // Check if it is "dtor()"
            if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:@"dtor"]) {
                //dtor_array_index = [self find_incomplete_paren:paren_complete];
                [paren_complete addObject:@1];
            }
            else
                [paren_complete addObject:@0];      // 0 signifies an incomplete parenthetical expression
        }
        else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {

            // Check if "dtor("
            if (![self elem_is_zero:paren_complete]) {
                // Add right-paren for "dtor("
                [paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:@2];
                [exp insertString:@")" atIndex:index + 1];
                mutable_length++;
                index++;
            }
            else
                [paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:@2];
        }
        else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:@2]) {
            // We know that everything is complete
            [paren_complete removeAllObjects];
        }
    }

    return exp;
}

- (bool)check_dtor:(NSMutableString *)exp
{
    NSMutableArray *paren_complete = [[NSMutableArray alloc] init];     // NO/YES

    for (NSInteger index = 0; index < [exp length]; index++) {

        if ([exp characterAtIndex:index] == '(') {

            // Check if it is "dtor()"
            if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:@"dtor"]) {
                //dtor_array_index = [self find_incomplete_paren:paren_complete];
                [paren_complete addObject:@1];
            }
            else
                [paren_complete addObject:@0];      // 0 signifies an incomplete parenthetical expression
        }
        else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {

            // Check if "dtor("
            if (![self elem_is_zero:paren_complete]) {
                // Indicate "dtor(" at index is now complete
                [paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:@2];
            }
            else
                [paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:@2];
        }
        else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:@2]) {
            // We know that everything is complete
            [paren_complete removeAllObjects];
        }
    }

    // Now step back and see if all the "dtor(" expressions are complete
    for (NSInteger index = 0; index < [paren_complete count]; index++) {
        if ([[paren_complete objectAtIndex:index] isEqualToValue:@0] || [[paren_complete objectAtIndex:index] isEqualToValue:@1]) {
            return NO;
        }
    }

    return YES;
}

似乎该算法适用于sin((3 + 3) + (6 - 3))(转换为sin(dtor((3 + 3) x (6 - 3)))但不适用于sin((3 + 3) + cos(3))(转换为sin(dtor((3 + 3) + cos(dtor(3)).

底线

这个半解决方案很可能过于复杂(似乎是我的常见问题之一),所以我想知道是否有更简单的方法可以做到这一点?

解决方案

这是我对他提供的@j_random_hacker 伪代码的解决方案:

- (NSMutableString *)resolve_dtor:(NSString *)exp
{
    uint depth = 0;
    NSMutableArray *stack = [[NSMutableArray alloc] init];
    NSRegularExpression *regex_trig = [NSRegularExpression regularExpressionWithPattern:@"(sin|cos|tan|csc|sec|cot)" options:0 error:0];
    NSRegularExpression *regex_trig2nd = [NSRegularExpression regularExpressionWithPattern:@"(asin|acos|atan|acsc|asec|acot)" options:0 error:0];
    // need another regex for checking asin, etc. (because of differing index size)
    NSMutableString *exp_copy = [NSMutableString stringWithString:exp];

    for (NSInteger i = 0; i < [exp_copy length]; i++) {
        // Check for it!
        if ([exp_copy characterAtIndex:i] == '(') {

            if (i >= 4) {
                // check if i - 4
                if ([regex_trig2nd numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 4, 4)] == 1) {
                    [stack addObject:@(depth)];
                    [exp_copy insertString:@"dtor(" atIndex:i + 1];
                    depth++;
                }
            }
            else if (i >= 3) {
                // check if i - 3
                if ([regex_trig numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 3, 3)] == 1) {
                    [stack addObject:@(depth)];
                    [exp_copy insertString:@"dtor(" atIndex:i + 1];
                    depth++;
                }
            }

        }
        else if ([exp_copy characterAtIndex:i] == ')') {
            depth--;
            if ([stack count] > 0 && [[stack objectAtIndex:[stack count] - 1]  isEqual: @(depth)]) {
                [stack removeObjectAtIndex:[stack count] - 1];
                [exp_copy insertString:@")" atIndex:i + 1];
            }
        }
    }

    return exp_copy;
}

有用!让我知道是否有任何小的更正可以添加,或者是否有更有效的方法。

4

2 回答 2

1

还没有尝试阅读您的代码,但我会使用一种简单的方法,在该方法中,我们向前扫描输入字符串,同时写出第二个字符串,同时维护一个名为的变量,该变量depth记录括号的当前嵌套级别,以及记住需要额外的嵌套级别的堆栈,因为我们在输入它们时)添加了一个:dtor(

  • 设置depth为 0。
  • c对于输入字符串中的 每个字符:
    • 将其写入输出。
    • c一个(?如果是这样的话:
      • 是前面的令牌sincos吗?如果是这样,将 的当前值压入depth堆栈,并写出dtor(.
      • 增量depth
    • c一个)?如果是这样的话:
      • 减量depth
      • 栈顶是否等于depth? 如果是这样,弹出它并写出来)
于 2014-06-04T05:21:08.780 回答
1

DDMathParser 原生支持对三角函数使用度数,并将dtor为您插入相关函数。它甚至会通过执行以下操作自动插入它:

@"sin(42°)"

您可以通过angleMeasurementMode在相关DDMathEvaluator对象上设置 来做到这一点。

于 2014-06-24T02:48:05.193 回答