Алгоритмическая практика. Базовая алгоритмическая подготовка. Задачи 1, 2.

Задача 1. Решите на Паскале и/или JS Задачку №10 Урока 17, про расчет выражений вида за один проход строки:

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

5+2               7
1-2*5+2          -7
5*6+7-3*2+11      42
5*6+7-3*2*3+11    30

Решение

var i, int, acc_sum, acc_mul, o, l: integer;
  s, prev, num: string;
begin
  s := '-7-8*5*6+7-33*2*3-11*2';
  l := length(s);
  for i := 1 to l do
   begin
    val(s[i], int, o);
    if o = 0 then num += s[i]
    else
     begin
      val(num, int);
      if prev = '-' then int := -int;
      if prev = '*' then acc_mul *= int
      else
       if s[i] = '*' then acc_mul := int
       else acc_sum += int;
      if s[i] <> '*' then
       begin
        acc_sum += acc_mul;
        acc_mul := 0;
       end;
      prev := s[i];
      num := '';
     end;
   end;
  if prev = '*' then acc_sum += acc_mul * int
  else
   if prev = '+' then acc_sum += int
   else acc_sum -= int;
  writeln('Ожидается: ', -7-8*5*6+7-33*2*3-11*2);
  writeln('Ответ: ', acc_sum);
  readln();
end.


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

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

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

Решение

Вариант 1. Функция возвращает массив.

type
  arr = array [1..2] of integer;
function calc_recurse(s: string; i: integer = 1): arr;
var int, acc_sum, acc_mul, o, l: integer;
  prev, num: string;
begin
  acc_sum := 0;
  acc_mul := 0;
  l := length(s);
  while i <= l do
   begin
    val(s[i], int, o);
    if o = 0 then num += s[i]
    else
     begin
      val(num, int, o);
      if s[i] = '(' then
       begin
        result := calc_recurse(s, i + 1);
        int := result[1];
        i := result[2];
       end;
      if prev = '-' then int := -int;
      if prev = '*' then acc_mul *= int
      else
       if s[i] = '*' then acc_mul := int
       else acc_sum += int;
      if s[i] <> '*' then
       begin
        acc_sum += acc_mul;
        acc_mul := 0;
       end;
      if s[i] = ')' then
       begin
        result[1] := acc_sum;
        result[2] := i + 1;
        exit;
       end;
      prev := s[i];
      num := '';
     end;
    i += 1;
   end;
  val(num, int);
  if prev = '*' then acc_sum += acc_mul * int
  else
   if prev = '+' then acc_sum += int
   else acc_sum -= int;
  result[1] := acc_sum;
  result[2] := i - 1;
end;

var c: string;
begin
  c := '(-((7-8*(5*6+7-33)*2)*3-11*2)+15*5)*7-7*88';
  writeln('Ожидается: ', (-((7-8*(5*6+7-33)*2)*3-11*2)+15*5)*7-7*88);
  writeln('Ответ: ', calc_recurse(c)[1]);
  readln();
end.

Вариант 2. Функция получает переменную по ссылке.

function calc_recurse(s: string; var i: integer): integer;
var int, acc_sum, acc_mul, o, l: integer;
  prev, num: string;
begin
  acc_sum := 0;
  acc_mul := 0;
  l := length(s);
  while i <= l do
   begin
    val(s[i], int, o);
    if o = 0 then num += s[i]
    else
     begin
      val(num, int, o);
      if s[i] = '(' then
       begin
        i += 1;
        int := calc_recurse(s, i);
        i += 1;
       end;
      if prev = '-' then int := -int;
      if prev = '*' then acc_mul *= int
      else
       if s[i] = '*' then acc_mul := int
       else acc_sum += int;
      if s[i] <> '*' then
       begin
        acc_sum += acc_mul;
        acc_mul := 0;
       end;
      if s[i] = ')' then
       begin
        result := acc_sum;
        exit;
       end;
      prev := s[i];
      num := '';
     end;
    i += 1;
   end;
  val(num, int);
  if prev = '*' then acc_sum += acc_mul * int
  else
   if prev = '+' then acc_sum += int
   else acc_sum -= int;
  result := acc_sum;
end;

var c: string;
  i: integer = 1;
begin
  c := '(-((7-8*(5*6+7-33)*2)*3-11*2)+15*5)*7-7*88';
  writeln('Ожидается: ', (-((7-8*(5*6+7-33)*2)*3-11*2)+15*5)*7-7*88);
  writeln('Ответ: ', calc_recurse(c, i));
  readln();
end.