Erstellen Sie einen Omnifix-Rechner

16

Inspiration. Inverse.

Bewerten Sie einen bestimmten Omnifix-Ausdruck.

Omnifix ist wie die Infixnotation der normalen Mathematik, jedoch mit zusätzlichen Kopien jedes Symbols, das die Argumente umgibt. Die äußeren Symbole ersetzen Klammern, sodass keine zusätzlichen Klammern erforderlich sind.

Sie müssen Addition, Subtraktion, Multiplikation, Division und positive reelle Zahlen (negative können geschrieben werden -0-n-) in einem für Ihre Sprache angemessenen Bereich unterstützen.

Plus und Minus müssen +und sein -, aber Sie können *oder ×für Zeiten und /oder ÷zum Teilen verwenden. Andere sinnvolle Symbole sind auf Anfrage zulässig.

Brownie-Punkte für Erklärungen und zusätzliche Funktionen (wie zusätzliche Operationen, negative Zahlen, Zeichenfolgen usw.) Auch wenn Ihre Antwort diese Funktionen nicht enthält, können Sie zeigen, wie dies möglich ist.

Bitte geben Sie einen Link an, um Ihre Lösung zu testen, sofern dies möglich ist.

Beispiele

In den folgenden Erläuterungen werden zur Verdeutlichung ¯negative Zahlen mit einem hohen Minuszeichen ( ) angegeben. Sie können negative Zahlen in jedem vernünftigen Format zurückgeben.

-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)

Adam
quelle
1
The explanations below use high minus (`¯`) to indicate negative numbers.Sie lieben definitiv APL.
Erik der Outgolfer
@EriktheOutgolfer Hast du einen besseren Vorschlag? Außerdem verwendet TI-BASIC ein hohes Minus.
Adám
Eigentlich nicht, da -s mit -s verwechselt werden kann, während ¯s nicht mit -s verwechselt werden kann .
Erik der Outgolfer
Bah, ich habe gerade die reale Nummernanforderung bemerkt. Soviel zu meiner 290-Byte-Ganzzahl-Arithmetik-Retina-Lösung ...
Neil
@Neil Warum postest du es nicht als Antwort?
Adám

Antworten:

4

C # (.NET Core) , 198 197 188 Bytes

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;}}

Probieren Sie es online!

Verwendet *und /.

Eine rekursive Funktion. Zunächst wird versucht, die Eingabezeichenfolge als float. Wenn dies fehlschlägt, ruft es sich selbst auf und übergibt rekursiv den ersten und den zweiten Operanden als Argumente. Anschließend führt es die ausgewählte Operation für die Ergebnisse aus.

  • 1 Byte gespart dank Mr. Xcoder!
  • 9 Bytes gespart dank TheLethalCoder!
Charlie
quelle
IndefOf(f, 1)kann seinIndexOf(f,1)
Mr. Xcoder
1
Verwenden Sie floatstattdessen s und die Zeichencodes, wenn Sie sie haben, können Sie sie wahrscheinlich mit >und <an einigen Stellen kürzen .
TheLethalCoder
Sie können Golf ein Byte Wechsel i+1,s.Length-i-2zu ++i,s.Length+~i.
Kevin Cruijssen
4

Python 3, 159 158 152 144 136 135 132 Bytes

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)))

Probieren Sie es online!

Erlaubt keine negativen Zahlen (obwohl das -0-5-natürlich funktioniert) und erfordert Python-Operatoren.

Arfie
quelle
Können Sie einen TIO-Link hinzufügen?
Adám
1
while~-(l[i]in'+-*/'):i+=1;a=1und *l,=input()für 152 Bytes
Felipe Nardi Batista
1
mit allen Testfällen: Link
Felipe Nardi Batista
1
144 Bytes
Felipe Nardi Batista
1
if a:l[i]='(';i=t(t(i+1));l[i-1]=')'mit return-~ifür 135 Bytes: P
Felipe Nardi Batista
3

Retina , 290 287 286 Bytes

\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

Probieren Sie es online! Hinweis: Nur für Ganzzahlarithmetik geeignet, daher wurden einige der Testfälle entfernt. Akzeptiert negative Zahlen und gibt sie mit dem ¯Präfix zurück. Bearbeiten: 3 4 Bytes dank @Cowsquack gespeichert. Erläuterung:

\d+
¦$&$*

Ich brauchte eine Möglichkeit, mit Null umzugehen, also verwende ich ¦als positives Zahlenpräfix. Die Zahlen werden dann in unäre Zahlen umgewandelt.

¯¦
¯

Negative Zahlen benötigen jedoch nur ein ¯Präfix.

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

Zitate werden +hässlich, also mache ich Additionen zu Subtraktionen.

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

Wenn der absolute Wert der linken Hälfte einer Subtraktion kleiner als die rechte Hälfte ist, vertauschen Sie diese und negieren Sie beide Seiten.

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

Auch wenn die LHS einer Multiplikation oder Division negativ ist, negieren Sie beide Seiten.

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

Auch wenn die LHS einer Multiplikation Null ist, ist das Ergebnis Null. Auch zwei Minuspunkte sind von Vorteil.

¯¦|¦¯
¯

Aber ein Minus und ein Plus (oder umgekehrt) ergeben ein Minus.

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

Subtrahieren Sie zwei Zahlen desselben Vorzeichens. Wiederholen Sie dies, bis keine weiteren Subtraktionen mehr vorhanden sind.

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

Wenn es immer noch eine Subtraktion gibt, müssen die Vorzeichen unterschiedlich sein, also addieren Sie die Zahlen. (Tun Sie dies jedoch nur einmal, da dies möglicherweise erneut eine Subtraktion von zwei Zahlen desselben Vorzeichens ergibt.)

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

Multiplikation durch wiederholte Addition durchführen.

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

Führen Sie eine Ganzzahldivision durch. Einer der obigen Schritte hat den Ausdruck vereinfacht, also wiederholen Sie den Vorgang, bis keine Operationen mehr vorhanden sind.

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

Zurück in Dezimalzahl konvertieren.

Neil
quelle
Wow, das ist - episch. Größter Retina-Beitrag auf PPCG? In der Regel ähneln sich QuadR- und Retina-Lösungen jedoch stark. Kann ich vielleicht inspirieren?
Adám
In dieser Zeile +`-(([¯¦])1*)(1*)-\2\3-, [¯¦]kann sich¯|¦
Kritixi Lithos
@Cowsquack passiert tatsächlich dreimal, danke!
Neil
Es gibt eine, die Sie verpasst haben ([×÷]);)
Kritixi Lithos
1
@Cowsquack Du solltest besser keinen finden, sonst muss ich 4 streichen ...
Neil
2

PHP , 116 114 109 Bytes

-5 Danke an Martin Ender

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

Verwendet *zur Multiplikation und /zur Division. Negative Zahlen funktionieren, obwohl ich keine konkreten Versuche unternehme, dass dies der Fall ist.

Probieren Sie es online!

Ungolfed und erklärt

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;"); 

Ich erkläre auch den regulären Ausdruck, weil er ein bisschen magisch ist:

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


([*+/-])

Zunächst möchten wir einen der vier Operatoren zuordnen: *+/-

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

Dann müssen wir entweder einer Zahl [\d.]+oder einem anderen gültigen Omnifix-Ausdruck entsprechen (?R).

\1

Dann stimmen wir mit demselben Operator überein, der am Anfang war.

(?3)

Dann machen wir dasselbe wie in Gruppe 3: stimmen mit einer Zahl oder einem Omnifix-Ausdruck überein.

\1

Passen Sie schließlich den Anfangsoperator erneut an.

Was auch immer damit übereinstimmt, wird durch ersetzt ($2). Dadurch wird das Teil in die umgebenden Operatoren eingeschlossen und in eckige Klammern gesetzt, sodass es wie eine normale Infixnotation aussieht.

Geschäfts-Katze
quelle
2

QuadR , 33 32 27 Bytes

-1 dank Cows Quack . -5 Danke an Erik den Outgolfer .

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

mit dem Argument / flag

Probieren Sie es online!

Dies entspricht der 40-Byte-Dyalog-APL-Lösung:

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

Probieren Sie es online!

Erläuterung

(Der in Klammern gesetzte Text bezieht sich auf Dyalog APL anstelle von QuadR.)

(... ){2}\2 das folgende Muster zweimal, und das ganze Spiel zweimal zu:
  (.) jedes Zeichen
  [... ]+ gefolgt von einer oder mehrere der folgenden Gruppe von Zeichen:
   \dd igits,
   ¯ hoch minus (negatives Vorzeichen)
   \. Periode

( ⎕R Wird R eplaced mit :)

( {} Das Ergebnis der folgenden anonymen Funktion für den Namespace ⍵ :)

⍵M ( ⍵.Match) Der Text des M atchs löscht
¯1↓ das letzte Zeichen (das Symbol + - ×oder ÷) löscht
1↓ das erste Zeichen (Symbol) und
 führt es als APL-Code aus
 (  Stringify).

 ( ⍣≡) Wiederholen Sie den Austausch, bis keine Änderungen mehr vorgenommen werden

Adam
quelle
Ich denke, Sie können fallen
Kritixi Lithos
@Cowsquack Du hast Recht mit QuadR. ⎕Rkann nicht mit numerischen Daten arbeiten. Vielen Dank.
Adám
Kürzere Regex; -5 Bytes.
Erik der Outgolfer
1

Haskell , 132 Zeichen

(134 Bytes, weil ×und ÷nehmen zwei Bytes in 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"÷"=(/)

Probieren Sie es online!

fparst so viel wie möglich von der Eingabe und liefert das Ergebnis sowie die verbleibende Zeichenfolge (die in den Testfällen leer ist). Wenn dies nicht regelkonform ist, entfernen Sie den nicht analysierbaren Reststring mit

Haskell , 139 Zeichen

...
g=fst.f
hörte auf, sich gegen den Uhrzeigersinn zu drehen
quelle
0

Perl, 64 53 Bytes

Include +1für-p

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

Implementiert ,(wirft das erste Argument weg) und .fügt manchmal die Argumente an. .funktioniert jedoch nicht sehr zuverlässig, da es sowohl auf der Analyse- als auch auf der Auswertungsebene mit dem Dezimalpunkt interferiert

Tonne Hospel
quelle
0

Java 8, 205 200 Bytes

float O(String s){try{return new Float(s);}catch(Exception e){int f=s.charAt(0),i=s.indexOf(f,1);float a=O(s.substring(1,i)),b=O(s.substring(i+1,s.length()-1));return f<43?a*b:f<44?a+b:f<46?a-b:a/b;}}

Port von @Charlies C # Antwort .
-5 Bytes dank @ceilingcat .

Probieren Sie es online aus.

Kevin Cruijssen
quelle