Correct parenthesis

时间:2015-07-31 19:19:49

标签: c parsing recursion

I came across this problem :

"It gives a string of round brackets. This string represents a parenthesis that is not necessarily correct. You have available the next move : you can change an open bracket '(' into a close brachet ')' or vice versa. You have to calculate the minimum number of moves needed to make the parenthesis to be correct."

e.g.

)())

answer : 1

First of all, I think that it would be useful to use parsing, but the program doesn't seem to work right.

void X() {
    if(first=='(') {
        firt=fgetc(fi);
        X();
        if(first!=')')
            er++;
        first=fgetc(fi);
    }
    else {
        ..
    }
}

What would be an idea of beginning?

Thanks

3 个答案:

答案 0 :(得分:2)

I would like to propose an algorithm. First the pseudo code:

For each input character C:
   If C is '(' then 
      increment counter
   else if counter is 0 then    // The closing paren has no matching opening
      increment moves           // so we "flip" it and counting as the opening
      increment counter
   else
      decrement counter        // This closing paren is balanced
   end if
end For
// Now the counter is containing the number of unbalanced opening parentheses,
// so we add half of this number to moves, as half of them have to be balanced
moves = moves + counter / 2

return moves 

Now in C:

#include <stdio.h>
#include <string.h>
int main(void) {

    char input[] = "((((";
    int len = strlen(input);
    int i;
    int moves = 0;
    int count = 0;

    for (i=0; i < len; i++)
    {
        if (input[i] == '(')
        {
            count ++;
        }
        else
        {
            if (count == 0)
            {
                count ++;
                moves ++;
            }
            else
            {
                count --;
            }
        }
    }

    moves += count / 2;
    printf("Moves: %d\n", moves);
    return 0;
}

You are invited to test it with different inputs here, prove it's correctness or disprove with a counterexample input :)

答案 1 :(得分:1)

Here's one way (in Pascal). Fixes the actual string and shows before and after.

function FixBrackets(s: string): Integer;
var
  LeftToProcess, OpenCount: Integer;
  I: Integer;
begin
  writeln('in:', S);
  Result := 0;
  LeftToProcess := length(s);
  OpenCount := 0;
  for I := 1 to LeftToProcess do begin
    case S[I] of
    '(' :
      if LeftToProcess <= OpenCount then begin
        // we must close all
          S[I] := ')';
          inc(Result);
      end else
        inc(OpenCount);
    ')' :
      if OpenCount = 0 then begin
        // we have no open pars to close, so this has to be a new open
        S[I] := '(';
        inc(Result);
        inc(OpenCount);
      end else
        dec(OpenCount);
    end;
    dec(LeftToProcess);
  end;
  writeln('out:', s);
end;

答案 2 :(得分:1)

以下是C ++的答案:

template<class T>
int count_changes(T begin, T end) {
    int offset = 0;
    int changes = 0;
    for (auto it = begin; it != end; ++it) {
        if (*it == '(') ++offset;
        else --offset;

        if (offset < 0) {
            offset = 1;
            changes++;
        }
    }

    return changes + ((offset + 1) / 2);
}

int main() {
    std::string parens { "))(()" };

    cout << parens << " : " << count_changes(parens.begin(), parens.end()) << endl;
}