Решите математическое выражение с чередующихся сторон

9

Создайте программу, которая решает математическое выражение, используя элементы с чередующихся сторон выражения. Таким образом, вместо чтения слева направо, вы читаете первый символ, затем последний, затем второй, затем второй до последнего и т. Д. Это даст вам новое выражение, которое вы должны оценить и вывести.

a*b/c+d-e
135798642  <-- Order you read the expression in
ae*-bd/+c  <-- Order of operation. 

Пример:

1*3/2+4-5
15*-34/+2 = -255

Если выражение не «работает», его 1необходимо вставить в необходимые позиции, чтобы оно работало.

Несколько примеров, вероятно, проиллюстрируют это лучше:

Input: 1+1+1+1+1
Result: 23     // Because 1+1+1+1+1 -> 11++11++1 -> 23

Input: 1+2-3+12-5
Result: -19    // Because 1+2-3+12-5 -> 15+-22-13+ -> 15+-22-13+1 -> -19
               //                                 |
               //                                 Not valid expression

Input: 2*2*2*2*2
Result: 968    // Because 2*2*2*2*2 -> 22**22**2 -> 22*1*22*1*2 -> 968
               //                        ||  ||
               //                        Not valid, 1 must be inserted

Input: 17/2
Output: 127    // Because 17/2 = 127/ -> 127/1 -> 127

Операторы , которые должны поддерживаться в + - * /. Там не будет скобок. Используются нормальные математические правила и «синтаксис», например **, не означает возведения в степень. a++++1эквивалентно a+1(т.е. стиль MATLAB, а не C ++).

В случае каких-либо сомнений, некоторые допустимые операции:

-a
+a
a++b
a+-b
a*-b
a*+b
a*++b
a/b
a/-b
a/+b
-a/--b

Пока все перечисленное не действует. Показано, что они должны быть заменены:

a+      | a+1
a-      | a-1
a++++   | a++++1   (This is equivalent to a+1)
a*+++   | a*+++1   (This is equivalent to a*1)
a**b    | a*1*b
a*/b    | a*1/b
a/*b    | a/1*b
a*      | a*1
*a      | 1*a
***a    | 1*1*1*a

Правила:

  • Код может быть функцией или полной программой
  • Ввод может быть STDIN или аргумент функции
  • Входные данные должны быть допустимым математическим выражением без кавычек ''или"" .
  • Выходные данные должны быть ответом на новое выражение в виде целого числа, десятичной или упрощенной дроби.
  • Должно поддерживаться не менее трех цифр после десятичной точки. Так что 1/3 = 0.333нет 0.33. 0.333333333принято
  • ans = ... принято
  • Начальные и конечные переводы строки и пробелы принимаются.
  • На входе будут только целые числа
  • Деление на ноль может привести к ошибке, NaN, Inf и т. Д. Вывод числа не допускается.

Как всегда, самый короткий код в байтах побеждает. Победитель будет выбран через неделю со дня объявления конкурса. Ответы, опубликованные позже, могут все же выиграть, если они короче, чем текущий лидер.

Стьюи Гриффин
источник
максимальная длина входной строки или количество операторов / целых чисел? также, должен ли я поддерживать математику до 2^64, и должна ли она быть ошибкой или переносом, если вы перейдете?
кот
«результат должен быть ответом [...] упрощенной дроби ...», так что я могу просто вернуться, 0/0если выражение вырастет до целочисленного деления или по модулю на ноль?
кот
2
Если ответ дает деление на ноль, то x/0это действительный вывод. Пока он не выводит неправильный ответ, все в порядке. Ошибка и «не число» по определению верны, а бесконечность «достаточно правильна»,
Стьюи Гриффин
Просто чтобы быть уверенным - eval можно использовать, верно?
orlp
Да, Эвал в порядке.
Стьюи Гриффин

Ответы:

3

Perl, 108 100 байт

$_="";while(@F){$_.=shift@F;$_.=pop@F}s@(\*|/)\1+@\1@g;s@^[*/]@1$&@;s@\D$@$&1@;s@\D@$&@g;$_=eval

Код 96 байтов, плюс 4 для аргумента командной строки -pF//, где

  • -pвставки while (<>) { .. } continue { print }и
  • -F//разбивает ввод и вставляет его @F.

Обратите внимание, что у ввода не должно быть завершающей строки, поэтому используйте /bin/echo -n 'formula' | perl ...

Менее гольф:

$_='';              # reset $_
while(@F) {         # reorder input
   $_.=shift @F;    # take first element off of @_
   $_.=pop @F       # idem for last; if @F is empty, undef is appended
}

s@(\*|/)\1+@\1@g;   # replace 2 or more '*' or '/' with just one: *1 and /1 = nop
s@^[*/]@1$&@;       # if expression starts with * or / prepend a 1
s@\D$@$&1@;         # if expression doesn't end with a number, append 1
s@\D@$& @g;         # eval doesn't like '++1': add spaces after operators
$_ = eval           # set $_ to 3v1l, so the `-p` will print the new value

тестирование

Поместите вышесказанное в файл с именем 114.pl, а нижеприведенный тестовый скрипт в файл рядом с ним:

%test = (
    '1+1+1+1+1' =>   23,
    '1*3/2+4-5' => -255,
    '1+2-3+12-5'=>  -19,
    '2*2*2*2*2' =>  968,
    '17/2'      =>  127,
    '--/-1-2-'  =>   -2,
    '**2*'      =>    2,
    '++1++'     =>    1,
    '/2/'       =>  0.5,
    '10/'       =>   '',
);

printf "%-20s -> %5s: %5s\n", $_, $test{$_}, `/bin/echo -n '$_' | perl -pF// 114.pl`
for keys %test;

Запуск его выводит:

++1++                ->     1:     1
**2*                 ->     2:     2
17/2                 ->   127:   127
10/                  ->      :
1+1+1+1+1            ->    23:    23
1*3/2+4-5            ->  -255:  -255
2*2*2*2*2            ->   968:   968
1+2-3+12-5           ->   -19:   -19
--/-1-2-             ->    -2:    -2
/2/                  ->   0.5:   0.5

Обратите внимание, что 1/0вызывает ошибку деления на ноль: evalвыходные данные undef, которые представлены пустой строкой.

Кинни
источник
Еще несколько тестовых случаев! Я собираюсь использовать их
edc65
3

JavaScript ES6, 105 106

Редактировать Сохранено 1 байт thx @Kenney

t=>eval("for(t=[...t],p=o='';c=t.reverse().pop();p=c)o+=p<'0'?(c=='/'|c<'+'||' ')+c:c;eval(p<'0'?o+1:o)")

// Less golfed
t=>{
  for(t = [...t], p = o = '';
      c = t.reverse().pop();
      p = c)
    o += p<'0' 
     ? (c=='/' | c=='*' || ' ')+c  // '1' or ' '
     : c;
  return eval(p<'0' ? o+1 : o)
}

Тестовый фрагмент

f=t=>eval("for(t=[...t],p=o='';c=t.reverse().pop();p=c)o+=p<'0'?(c=='/'|c<'+'||' ')+c:c;eval(p<'0'?o+1:o)")

console.log=x=>O.innerHTML+=x+'\n'

function test() { console.log(I.value + ' -> '+f(I.value)) }

;['1+1+1+1+1', '1*3/2+4-5', '1+2-3+12-5', '2*2*2*2*2',
  '17/2', '--/-1-2-', '**2*', '++1++', '/2/', '10/' ]
.forEach(t=>console.log(t+' -> '+f(t)))
Your test <input id=I><button onclick="test()">-></button>
<pre id=O></pre>

edc65
источник
Спас тебя байт p < '0' ? ( c=='/' | c<'+' || ' ' )+c : c ;.
Кенни