Задача 8 Урок 22 (Задача 2 [!] Pascal.js Алгоритмическая практика)

Задача 2 [!] Pascal.js Алгоритмическая практика:

Решите на Паскале и/или JS Задачку №8 Урока 22, про расчет выражений вида:

5*(3+4)-7*9+3*(2+(2-7))

с помощью рекурсии.

Задача 8 Урок 22

"Калькулятор":
Напишите функцию, которая получает на вход произвольную строку вида:

5*(3+4)-7*9+3*(2+(2-7))

(арифметическое выражение со скобками любого уровня вложенности и операциями умножения, вычитания и сложения)

и в качестве ответа возвращает результат этого выражения.

Рекомендация: сначала убедитесь, что число открывающих скобок, равно числу закрывающих.

Решение:

function calculateExpression(s: string; var i: integer): integer;
var
  temp, num, n, code: integer;
  prevOp, currOp: char;
  close, open: boolean;
begin
  currOp := ' ';
  prevOp := '+';
  result := 0;
  temp := 0;
  num := 0;
  close := true;
  open := false;

  while((i <= length(s)) and close) do
  begin
    val(s[i], n, code);
    if (s[i] = '(') then open := true;

    if ((code = 0) and open) then
    begin
      num := calculateExpression(s, i);
      open := false;
    end else
      while (code = 0) do
      begin
        num := num * 10 + n;
        inc(i);
        val(s[i], n, code);
      end;

    if (s[i] = '*') then
    begin
      currOp := '*';
      if (temp = 0) then
        temp := num
      else
        temp *= num;
      num := 0;
    end;

    if ((s[i] = '+') or (s[i] = '-') or (s[i] = ')') or (i >= length(s))) then
    begin
      if (currOp = '*') then
        temp *= num
      else
        temp := num;

      case prevOp of
      '+': calculateExpression += temp;
      '-': calculateExpression -= temp;
      end;

      prevOp := s[i];
      temp := 0;
      num := 0;
      currOp := ' ';
      if (s[i] = ')') then close := false;
    end;
    inc(i);
  end;
end;

var s: string;
  index: integer;

begin
  s := '5*(3+4)-7*9+3*(2+(2-7))';
  index := 1;
  writeln(calculateExpression(s, index));

  readln();
end.

Вывод консоли:

Входные данные                      Результат

5*(3+4)-7*9+3*(2+(2-7))                 -37
vedro-compota's picture

function calculateExpression(s: string; var i: integer): 
  while((i <= length(s)) and close) do
  begin
    val(s[i], n, code);
    if (s[i] = '(') then open := true;
 
    if ((code = 0) and open) then
    begin
      num := calculateExpression(s, i);
      open := false;

-- если мы встречаем открывающую скобку, то это значит что мы уже может вызывать рекурсивно функцию начиная с позиции i+1

Предлагаю модифицировать решение, чтобы в нем:

  1. не использовались флаги open и close
  2. не делалась попытка сконвертировать в число символы, которые не сконвертируются

_____________
матфак вгу и остальная классика =)

1. Рекурсия вызывается с позиции i+1, если встречается открывающая скобка.
2. Убрал флаги close и open.
3. Нет попытки сконвертировать в число символы, которые не конвертируются.

function calculateExpression(s: string; var i: integer): integer;
var
  strNum, prevOp, currOp: string;
  temp, num, n, code: integer;

begin
  strNum := '';
  currOp := '';
  prevOp := '+';
  result := 0;
  temp := 0;
  num := 0;

  while(i <= length(s)) do
  begin

    if (s[i] = '(') then
    begin
      inc(i);
      num := calculateExpression(s, i);
      inc(i);
    end;

    if ((s[i] >= '0') and (s[i] <= '9')) then
    begin
      while ((s[i] >= '0') and (s[i] <= '9')) do
      begin
        strNum += s[i];
        inc(i);
      end;
      val(strNum, n, code);
      num := n;
      strNum := '';
    end;

    if (s[i] = '*') then
    begin
      currOp := '*';
      if (temp = 0) then
        temp := num
      else
        temp *= num;
      num := 0;
    end;

    if ((s[i] = '+') or (s[i] = '-') or (s[i] = ')') or (i >= length(s))) then
    begin
      if (currOp = '*') then
        temp *= num
      else
        temp := num;

      case prevOp of
      '+': calculateExpression += temp;
      '-': calculateExpression -= temp;
      end;

      if (s[i] = ')') then break;
      prevOp := s[i];
      temp := 0;
      num := 0;
      currOp := '';
    end;
    inc(i);
  end;
end;

var s: string;
  index: integer;

begin
  s := '(10 - 5) *(3+4)-7*9+3*(2+(2-7))';
  index := 1;
  writeln(calculateExpression(s, index));

  readln();
end. 

Вывод консоли:

Входные данные                      Результат
(10 - 5) *(3+4)-7*9+3*(2+(2-7))          -37
vedro-compota's picture

засчитано

_____________
матфак вгу и остальная классика =)