Розв’яжіть математичний вираз із змінних сторін


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

Так, eval нормально.
Стюі Гріффін

Відповіді:


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>


Збережені вам байти: p < '0' ? ( c=='/' | c<'+' || ' ' )+c : c ;.
Кенні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.