Crea un calcolatore omnifix


16

Ispirazione. Inverso.

Valuta una determinata espressione omnifix.

Omnifix è come la normale notazione infografica della matematica, ma con copie aggiuntive di ogni simbolo che circonda gli argomenti. I simboli esterni prendono il posto delle parentesi e pertanto non sono necessarie parentesi aggiuntive.

Devi supportare addizioni, sottrazioni, moltiplicazioni, divisioni e numeri reali positivi (quelli negativi possono essere scritti -0-n-) entro un intervallo ragionevole per la tua lingua.

Più e meno devono essere +e -, ma è possibile utilizzare *o ×per i tempi e /o ÷per la divisione. Altri simboli ragionevoli saranno ammessi su richiesta.

Brownie indica spiegazioni e funzioni aggiuntive (come operazioni aggiuntive, numeri negativi, stringhe, ecc.) Anche se la tua risposta non ha queste caratteristiche, sentiti libero di mostrare come potrebbe.

Fornisci un link per testare la tua soluzione, se possibile.

Esempi

Per chiarezza, le spiegazioni seguenti usano il segno meno ( ¯) per indicare numeri negativi. È possibile restituire numeri negativi utilizzando qualsiasi formato ragionevole.

-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.Adoro APL.
Erik the Outgolfer,

@EriktheOutgolfer Hai un suggerimento migliore? Inoltre, TI-BASIC utilizza un valore negativo elevato.
Adám,

In realtà non perché -s può essere confuso con -s mentre ¯s non può essere confuso con -s.
Erik the Outgolfer,

Bah, ho appena notato il vero numero richiesto. Questo per quanto riguarda la mia soluzione aritmetica Retina intera a 290 byte ...
Neil,

@Neil Perché non lo pubblichi come risposta?
Adám,

Risposte:


4

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

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

Provalo online!

Usi *e /.

Una funzione ricorsiva. Tenta innanzitutto di analizzare la stringa di input come a float. Se fallisce, si chiama ricorsivamente passando come argomenti il ​​primo e il secondo operando e quindi esegue l'operazione selezionata sui risultati.

  • 1 byte salvato grazie a Mr. Xcoder!
  • 9 byte salvati grazie a TheLethalCoder!

IndefOf(f, 1)può essereIndexOf(f,1)
Mr. Xcoder il

1
Usa floatinvece s, usa i codici char, quando li hai probabilmente puoi accorciarli con >e <in un paio di posti.
TheLethalCoder

È possibile giocare a golf un byte cambiando i+1,s.Length-i-2in ++i,s.Length+~i.
Kevin Cruijssen,

4

Python 3, 159 158 152 144 136 135 132 byte

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

Provalo online!

Non consente numeri negativi (anche se -0-5-funziona ovviamente) e richiede operatori Python.


Puoi aggiungere un link TIO?
Adám,

1
while~-(l[i]in'+-*/'):i+=1;a=1e *l,=input()per 152 byte
Felipe Nardi Batista,

1
con tutti i casi di test: link
Felipe Nardi Batista,


1
if a:l[i]='(';i=t(t(i+1));l[i-1]=')'con return-~iper 135 byte: P
Felipe Nardi Batista,

3

Retina , 290 287 286 byte

\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

Provalo online! Nota: è in grado di eseguire solo l'aritmetica dei numeri interi, quindi alcuni casi di test sono stati rimossi. Accetta e restituisce numeri negativi utilizzando il ¯prefisso. Modifica: salvato 3 4 byte grazie a @Cowsquack. Spiegazione:

\d+
¦$&$*

Avevo bisogno di un modo per gestire lo zero, quindi uso ¦come prefisso un numero positivo. I numeri vengono quindi convertiti in unari.

¯¦
¯

Ma i numeri negativi richiedono solo un ¯prefisso.

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

Citando +s diventa brutto, quindi trasformo le aggiunte in sottrazioni.

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

Se il valore assoluto dell'LHS di una sottrazione è inferiore all'RHS, scambiarli e annullare entrambi i lati.

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

Anche se l'LHS di una moltiplicazione o divisione è negativo, negare entrambe le parti.

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

Anche se l'LHS di una moltiplicazione è zero, il risultato è zero. Inoltre, due svantaggi fanno un vantaggio.

¯¦|¦¯
¯

Ma un meno e un più (o viceversa) creano un meno.

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

Sottrai due numeri dello stesso segno. Fallo ripetutamente fino a quando non rimangono più tali sottrazioni.

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

Se c'è ancora una sottrazione, i segni devono essere diversi, quindi aggiungi i numeri insieme. (Ma fallo solo una volta, poiché potrebbe rivelare di nuovo una sottrazione di due numeri dello stesso segno.)

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

Eseguire la moltiplicazione per aggiunta ripetuta.

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

Esegue la divisione dei numeri interi. Uno dei passaggi precedenti avrà semplificato l'espressione, quindi torna indietro fino a quando non rimangono più operazioni.

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

Converti in decimale.


Wow, questo è epico. Il più grande post Retina su PPCG? Tuttavia, in genere le soluzioni QuadR e Retina si assomigliano molto. Posso forse ispirare?
Adám,

In questa linea +`-(([¯¦])1*)(1*)-\2\3-, [¯¦]può diventare¯|¦
Kritixi Lithos il

@Cowsquack Succede tre volte, grazie!
Neil,

Ce ([×÷])
n'è

1
@Cowsquack Faresti meglio a non trovarne un altro, altrimenti dovrò cancellarne 4 ...
Neil

2

PHP , 116 114 109 byte

-5 grazie a Martin Ender

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

Utilizza *per la moltiplicazione e /per la divisione. Numeri negativi sembrano funzionare nonostante io non abbia fatto tentativi specifici per farlo.

Provalo online!

Ungolfed e spiegato

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

Spiegherò anche la regex perché è un po 'magica:

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


([*+/-])

Innanzitutto, vogliamo abbinare uno dei quattro operatori: *+/-

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

Quindi, dobbiamo abbinare un numero [\d.]+o un'altra espressione omnifix valida (?R).

\1

Quindi, abbiniamo lo stesso operatore che era all'inizio.

(?3)

Quindi facciamo la stessa cosa che abbiamo fatto nel gruppo 3: abbinare un numero o un'espressione omnifix.

\1

Infine, abbina nuovamente l'operatore iniziale.

Qualunque sia la corrispondenza, questo viene sostituito ($2). Questo prende la parte all'interno degli operatori circostanti e la mette tra parentesi, quindi sembra una normale notazione infissa.


2

QuadR , 33 32 27 byte

-1 grazie a Cows Quack . -5 grazie a Erik the Outgolfer .

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

con l'argomento / flag

Provalo online!

Ciò equivale alla soluzione Dyalog APL a 40 byte:

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

Provalo online!

Spiegazione

(il testo tra parentesi si riferisce a Dyalog APL anziché QuadR)

(... ){2}\2 il seguente schema per due volte, e tutta la partita due volte troppo:
  (.) qualsiasi carattere
  [... ]+ seguito da uno o più dei seguenti set di caratteri:
   \dD igits,
   ¯ alta meno (segno negativo)
   \. periodo

( ⎕R È R eplaced con :)

( {... } il risultato della seguente funzione anonima applicata allo spazio dei nomi ⍵ :)

⍵M ( ⍵.Match) il testo del M atch
¯1↓ rilascia l'ultimo carattere (il simbolo + - ×o ÷)
1↓ rilascia il primo carattere (simbolo)
 eseguito come codice APL
 (  stringify)

 ( ⍣≡) ripetere la sostituzione fino a quando non si verificano più modifiche


Penso che tu possa lasciar perdere
Kritixi Lithos il

@Cowsquack Hai ragione su QuadR. ⎕Rnon può operare su dati numerici. Grazie.
Adám,


1

Haskell , 132 caratteri

(134 byte, perché × e ÷prendere due byte 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"÷"=(/)

Provalo online!

fanalizza quanto più input possibile e produce il risultato e la stringa rimanente (che è vuota nei casi di test). Se ciò non è conforme alle regole, rimuovere la stringa rimanente non analizzabile con

Haskell , 139 caratteri

...
g=fst.f

0

Perl, 64 53 byte

Includi +1per-p

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

Attua accidentalmente anche ,(elimina il primo argomento) e talvolta .(accoda gli argomenti insieme). .non funziona in modo molto affidabile, poiché interferisce con il punto decimale sia a livello di analisi che a livello di valutazione


0

Java 8, 205 200 byte

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

Porta della risposta C # di @Charlie .
-5 byte grazie a @ceilingcat .

Provalo online.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.