我用括号完成算法遇到了令人沮丧的问题。我使用的数学库DDMathParser仅以弧度为单位处理三角函数。如果想要使用学位,他们必须致电dtor(deg_value)
。问题是,这增加了一个必须在最后加以考虑的附加括号。
例如,数学表达式sin(cos(sin(x)))
将在我的代码中转换为sin(dtor(cos(dtor(sin(dtor(x)))
。但是,请注意我需要两个额外的括号才能使它成为一个完整的数学表达式。因此,创建了resolve_dtor()
。
以下是我尝试过的解决方案,其中的想法是让0
表示左派,1
表示带有 dtor(
的左派,以及2
表示权利人,从而完成了0
或1
。
- (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;
}
有效!如果有任何微小的更正可以添加,或者是否有更有效的方法,请告诉我。
答案 0 :(得分:1)
Haven没有尝试过阅读你的代码,但是我会使用一种简单的方法,我们在输入字符串中向前扫描,写出第二个字符串,同时保持一个名为depth
的变量来记录当前嵌套的括号级别,以及一个记住需要额外)
的嵌套级别的堆栈,因为我们在输入时添加了dtor(
:
depth
设为0。c
:
c
是(
吗?如果是这样:
sin
,cos
等?如果是,请在堆栈上推送depth
的当前值,并写出dtor(
。depth
。c
是)
吗?如果是这样:
depth
。depth
?如果是,请弹出并写出)
。答案 1 :(得分:1)
DDMathParser本身支持使用三角函数度,并将为您插入相关的dtor
函数。它甚至会自动插入它:
@"sin(42°)"
您可以通过在相关angleMeasurementMode
对象上设置DDMathEvaluator
来执行此操作。