Создать калькулятор омнификса


16

Вдохновение. Inverse.

Оцените данное выражение омнификса.

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

Вы должны поддерживать сложение, вычитание, умножение, деление и положительные действительные числа (можно записать отрицательные -0-n-) в разумных пределах для вашего языка.

Плюс и минус должны быть +и -, но вы можете использовать *или ×для раз и /или ÷для деления. Другие разумные символы будут разрешены по запросу.

Брауни указывает на пояснения и дополнительные функции (такие как дополнительные операции, отрицательные числа, строки и т. Д.) Даже если в вашем ответе нет этих функций, не стесняйтесь показать, как это возможно.

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

Примеры

Для ясности нижеприведенные пояснения используют высокий минус ( ¯) для обозначения отрицательных чисел. Вы можете вернуть отрицательные числа, используя любой разумный формат.

-5-2-3

+2+×3×2×+8 ( +2+×3×2×++2+6+8)

-14--3-1--12 ( -4--3-1---14-2-12)

+2.1+×3.5×2.2×+9.8 ( +2.1+×3.5×2.2×++2.1+7.7+9.8)

×3×÷-0-6-÷2÷×-9 ( ×3×÷-0-6-÷2÷××3×÷¯6÷2÷××3ׯ3ׯ9)

÷4÷-3-÷1÷2÷-÷1.6 ( ÷4÷-3-÷1÷2÷-÷÷4÷-3-0.5-÷÷4÷2.5÷1.6)


1
The explanations below use high minus (`¯`) to indicate negative numbers.Вы определенно любите APL.
Эрик Outgolfer

@EriktheOutgolfer У вас есть лучшее предложение? Также TI-BASIC использует высокий минус.
Адам

На самом деле нет, поскольку -s можно спутать с -s, а ¯s нельзя спутать с -s.
Эрик Outgolfer

Бах, я только что заметил требование к реальному номеру. Так много для моего 290-байтового целочисленного арифметического решения Retina ...
Нил

@Neil Почему бы тебе не опубликовать это как ответ?
Адам

Ответы:


4

C # (.NET Core) , 198 197 188 байт

float O(string s){try{return float.Parse(s);}catch{var f=s[0];int i=s.IndexOf(f,1);float a=O(s.Substring(1,i-1)),b=O(s.Substring(i+1,s.Length-i-2));return f<43?a*b:f<44?a+b:f<46?a-b:a/b;}}

Попробуйте онлайн!

Использует *и /.

Рекурсивная функция. Сначала он пытается проанализировать входную строку как float. Если происходит сбой, он вызывает себя рекурсивно, передавая в качестве аргументов первый и второй операнды, а затем выполняет выбранную операцию с результатами.

  • 1 байт сохранен благодаря мистеру Xcoder!
  • 9 байтов сохранено благодаря TheLethalCoder!

IndefOf(f, 1)может бытьIndexOf(f,1)
г-н Xcoder

1
Используйте floats вместо этого, используйте коды полукокса, когда вы их , вероятно , может сократить их >и <в нескольких местах.
TheLethalCoder

Вы можете играть в гольф, изменяя байты i+1,s.Length-i-2на ++i,s.Length+~i.
Кевин Круйссен

4

Python 3, 159 158 152 144 136 135 132 байта

def t(i,a=1):
 while'-'<l[i]!='/':i+=1;a=0
 if a:l[i]='(';i=t(t(i+1));l[i-1]=')'
 return-~i
*l,=input()
t(0)
print(eval(''.join(l)))

Попробуйте онлайн!

Не допускает отрицательных чисел (хотя -0-5-работает, конечно) и требует операторов Python.


Можете ли вы добавить ссылку TIO?
Адам

1
while~-(l[i]in'+-*/'):i+=1;a=1и *l,=input()для 152 байтов
Фелипе Нарди Батиста

1
со всеми тестами: ссылка
Фелипе Нарди Батиста,


1
if a:l[i]='(';i=t(t(i+1));l[i-1]=')'с return-~i135 байтами: P
Фелипе Нарди Батиста

3

Сетчатка , 290 287 286 байт

\d+
¦$&$*
¯¦
¯
{`\+([¯¦]1*)\+([¯¦]1*)\+
-$1-¯$2-
-(¯|¦)(1*)-([¯¦]+1*\2)-
-¯$3-¯$1$2-
(×|÷)¯(1*\1)([¯¦]1*\1)
$1¦$2¯$3
צ×[¯¦]1*×|¯¯¦?
¦
¯¦|¦¯
¯
+`-((¯|¦)1*)(1*)-\2\3-
$1
-([¯¦]1*)-[¯¦](1*)-
$1$2
צ1(1*)×([¯¦]1*)×
+צ$1×$2×+$2+
}`÷¦(?=1*÷(¯|¦)(1+)÷)(\2)*1*÷\1\2÷
$1$#3$*
((¯)|¦)(1*)
$2$.3

Попробуйте онлайн! Примечание: допускается только целочисленная арифметика, поэтому некоторые тестовые примеры были удалены. Принимает и возвращает отрицательные числа, используя ¯префикс. Изменить: Сохранено 3 4 байта благодаря @ Cowsquack. Объяснение:

\d+
¦$&$*

Мне нужен был способ обработки нуля, поэтому я использую ¦префикс положительного числа. Числа затем конвертируются в одинарные.

¯¦
¯

Но отрицательным числам нужен только ¯префикс.

{`\+([¯¦]1*)\+([¯¦]1*)\+
-$1-¯$2-

Цитирование +s становится уродливым, поэтому я превращаю дополнения в вычитания.

-(¯|¦)(1*)-([¯¦]+1*\2)-
-¯$3-¯$1$2-

Если абсолютное значение LHS вычитания меньше, чем RHS, поменяйте их и отрицайте обе стороны.

(×|÷)¯(1*\1)([¯¦]1*\1)
$1¦$2¯$3

Также, если LHS умножения или деления отрицателен, отрицайте обе стороны.

צ×[¯¦]1*×|¯¯¦?
¦

Также, если LHS умножения равно нулю, то результат равен нулю. Также два минуса составляют плюс.

¯¦|¦¯
¯

Но минус и плюс (или наоборот) составляют минус.

+`-((¯|¦)1*)(1*)-\2\3-
$1

Вычтите два числа одного знака. Повторяйте это до тех пор, пока не останется таких вычитаний.

-([¯¦]1*)-[¯¦](1*)-
$1$2

Если все еще есть вычитание, знаки должны отличаться, так что сложите числа вместе. (Но делайте это только один раз, так как это может снова выявить вычитание двух чисел одного знака.)

צ1(1*)×([¯¦]1*)×
+צ$1×$2×+$2+

Выполните умножение путем повторного сложения.

}`÷¦(?=1*÷(¯|¦)(1+)÷)(\2)*1*÷\1\2÷
$1$#3$*

Выполните целочисленное деление. Один из вышеперечисленных шагов упростит выражение, поэтому выполняйте цикл до тех пор, пока не останется никаких операций.

((¯)|¦)(1*)
$2$.3

Конвертировать обратно в десятичную.


Вау, это - эпично. Крупнейший пост сетчатки на PPCG? Однако обычно решения QuadR и Retina очень похожи друг на друга. Могу ли я вдохновить?
Адам

В этой линии +`-(([¯¦])1*)(1*)-\2\3-, [¯¦]может стать¯|¦
Kritixi Lithos

@ Cowsquack Бывает три раза на самом деле, спасибо!
Нил

Есть один, который вы пропустили ([×÷]);)
Kritixi Lithos

1
@ Cowsquack Тебе лучше не искать другого, иначе мне придется вычеркнуть 4 ...
Нил

2

PHP , 116 114 109 байт

-5 спасибо Мартину Эндеру

for($s=$argv[$o=1];$o!=$s;)$s=preg_replace('#([*+/-])(([\d.]+|(?R))\1(?3))\1#','($2)',$o=$s);eval("echo$s;");

Используется *для умножения и /деления. Отрицательные числа работают, несмотря на то, что я не предпринимал никаких конкретных попыток, чтобы это имело место.

Попробуйте онлайн!

Неуправляемый и объясненный

for($s=$argv[$o=1];   # Initialize with $s = input and $o = 1;
    $o!=$s;)          # While $o != $s
    # Set $o to $s and set $s to be $s after this regex replacement:
    $s=preg_replace('#([*+/-])(([\d.]+|(?R))\1(?3))\1#','($2)',$o=$s);
    # i.e., continue to do this replacement until the result is the same on two consecutive
    # steps (no replacement was made)
# Once $o == $s (i.e. no more replacement can be made), eval the result and print
eval("echo$s;"); 

Я также объясню регулярное выражение, потому что это немного волшебно:

([*+/-])(([\d.]+|(?R))\1(?3))\1


([*+/-])

Сначала мы хотим сопоставить любой из четырех операторов: *+/-

([\d.]+|(?R))

Затем нам нужно сопоставить число [\d.]+или другое допустимое выражение омнификса (?R).

\1

Затем мы сопоставляем тот же оператор, который был в начале.

(?3)

Затем мы делаем то же самое, что и в группе 3: сопоставляем число или выражение омнификса.

\1

Наконец, снова сопоставьте начальный оператор.

Все, что соответствует этому, заменяется ($2). Это берет часть внутри окружающих операторов и помещает ее в скобки, так что это выглядит как обычная инфиксная запись.


2

QuadR , 33 32 27 байт

-1 спасибо Корове Кря . -5 спасибо Эрику Аутгольферу .

((.)[\d¯\.]+){2}\2
⍎¯11↓⍵M

с аргументом / флагом

Попробуйте онлайн!

Это эквивалентно 40-байтовому решению Dyalog APL:

'((.)[\d¯\.]+){2}\2'R{⍕⍎1↓¯1↓⍵.Match}⍣≡

Попробуйте онлайн!

объяснение

(текст в скобках относится к Dyalog APL вместо QuadR)

(... ){2}\2 следующий рисунок дважды, и весь матч в два раза тоже:
  (.) любой символ
  [... ]+ следует один или более из следующего набора символов:
   \dд igits,
   ¯ большой минус (отрицательный знак)
   \.  период

( ⎕R В R eplaced с :)

( {} Результат применения следующей анонимной функции к пространству имен ⍵ :)

⍵M ( ⍵.Match) текст M atch
¯1↓ отбрасывает последний символ (символ + - ×или ÷)
1↓ отбрасывает первый символ (символ),
 выполняемый как код APL
 (  stringify)

 ( ⍣≡) повторяйте замену до тех пор, пока больше не произойдет никаких изменений


Я думаю, что вы можете сбросить
Kritixi Lithos

@ Cowsquack Вы правы насчет QuadR. ⎕Rне может работать с числовыми данными. Благодарю.
Адам


1

Haskell , 132 символа

(134 байта, потому что ×и ÷взять два байта в UTF-8)

f y|(n@(_:_),r)<-span(`elem`['.'..'9'])y=(read n,r)
f(c:d)|(l,_:s)<-f d,(m,_:r)<-f s=(o[c]l m,r)
o"+"=(+)
o"-"=(-)
o"×"=(*)
o"÷"=(/)

Попробуйте онлайн!

fанализирует как можно большую часть входных данных и выдает результат, а также оставшуюся строку (которая пуста в тестовых примерах). Если это не соответствует правилам, удалите непарсируемую строку остатка с помощью

Haskell , 139 символов

...
g=fst.f

0

Perl, 64 53 байта

Включить +1для-p

perl -pe 's%([*-/])(([\d.]+|(?0))\1(?3))\1%($2)%&&redo;$_=eval' <<< "/4/-3-/1/2/-/"

Случайно также реализует ,(отбрасывает первый аргумент) и иногда .(добавляет аргументы вместе). .не работает очень надежно, хотя, поскольку он мешает десятичной запятой как на уровне анализа, так и на уровне оценки


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.