Converti un'espressione in notazione Panfix


19

Stavo navigando su esolangs e ho provato questa lingua: https://github.com/catseye/Quylthulg .

Una cosa interessante di questo linguaggio è che non usa prefisso, postfisso o infisso, li usa tutti e tre , chiamandolo notazione "panfix".

Ecco un esempio Per rappresentare normale infisso 1+2in panfix, diventa: +1+2+. Notare come si trova l'operatore prima, tra e dopo gli operandi. Un altro esempio è (1+2)*3. Questo diventa *+1+2+*3*. Notare di nuovo come si *trova in tutti e tre i punti rispetto agli operandi +1+2+e 3.

La sfida

Come avrai intuito, il tuo compito in questa sfida è convertire un'espressione da infix a panfix.

Alcuni chiarimenti:

  • Devi solo affrontare le quattro operazioni di base: +-*/
  • Non dovrai avere a che fare con le versioni unarie di quelle, solo binarie
  • Devi fare i conti con la parentesi
  • Assumi le normali regole di precedenza di */allora +-e associa la sinistra a tutte.
  • I numeri saranno numeri interi non negativi
  • Opzionalmente puoi avere uno spazio sia in input che in output

Casi test

1+2  ->  +1+2+
1+2+3  ->  ++1+2++3+
(1+2)*3  ->  *+1+2+*3*
10/2*5  ->  */10/2/*5*
(5+3)*((9+18)/4-1)  ->  *+5+3+*-/+9+18+/4/-1-*

Questo è , quindi vince il codice più breve in byte !

Risposte:


3

JavaScript (ES6), 160 byte

f=(s,t=s.replace(/[*-/]/g,"'$&'"),u=t.replace(/^(.*?)([*-9]+)'([*/])'([*-9]+)|([*-9]+)'([+-])'([*-9]+)|\(([*-9]+)\)/,"$1$3$2$3$4$3$6$5$6$7$6$8"))=>t==u?t:f(s,u)

Funziona citando tutti gli operatori (che in precedenza danno loro i codici carattere *), quindi cerca disponibili '*'o '/'operazioni, '+'o '-'operazioni o se ()sostituisce il primo con la sua notazione panfix. Esempio:

(5+3)*((9+18)/4-1)
(5'+'3)'*'((9'+'18)'/'4'-'1)
(+5+3+)'*'((9'+'18)'/'4'-'1)
+5+3+'*'((9'+'18)'/'4'-'1)
+5+3+'*'((+9+18+)'/'4'-'1)
+5+3+'*'(+9+18+'/'4'-'1)
+5+3+'*'(/+9+18+/4/'-'1)
+5+3+'*'(-/+9+18+/4/-1-)
+5+3+'*'-/+9+18+/4/-1-
*+5+3+*-/+9+18+/4/-1-*

3

JavaScript (ES6), 285 282 281 267 251 243 241 238 234 232 231 byte

~ 15 byte grazie a Neil .

f=(I,E=I.match(/\d+|./g),i=0)=>(J=T=>T.map?T.map(J).join``:T)((R=(H,l=(P=_=>(t=E[i++])<")"?R(0):t)(),C,F)=>{for(;(C=P())>")"&&(q=C>"*"&&C<"/")*H-1;)F=q+H?l=[C,l,C,P(),C]:F?l[3]=[C,l[3],C,R(1),C]:l=R(1,l,i--)
i-=C>")"
return l})(0))

In JavaScript questo è un po 'più difficile che in Mathematica. Questo è fondamentalmente un parser di precedenza dell'operatore troppo specializzato e golfista .

Provoca overflow dello stack su input non validi.

dimostrazione

Ungolfed

convert = input => {
  tokens = input.match(/\d+|./g);
  i = 0;
  parse_token = () => (token = tokens[i++]) == "(" ? parse_tree(false) : token;
  parse_tree = (mul_div_mode, left = parse_token()) => {
    while ((oper = parse_token()) != ")" && !((is_plus_minus = oper == "+" || oper == "-") && mul_div_mode)) {
      if (is_plus_minus || mul_div_mode)
        left = [oper, left, oper, parse_token(), oper];
      else if (non_first)
        left[3] = [oper, left[3], oper, parse_tree(true), oper];
      else
        left = parse_tree(true, left, i--);
      non_first = true;
    }
    if (oper != ")")
      i--;
    return left;
  };
  format_tree = tree => tree.map ? tree.map(format_tree).join("") : tree;
  return format_tree(parse_tree(false));
}

S.split``dovrebbe essere [...S], anche se in realtà potrebbe essere utile abbinare in /\d+|./ganticipo e lavorare invece su quello.
Neil,

@ Grazie Grazie. Lo esaminerò.
PurkkaKoodari,

2

Matematica, 203 195 byte

Questo è probabilmente meno efficiente, ma sembra fare il lavoro.

Function[f,ReleaseHold[(Inactivate@f/._[Plus][a_,b_/;b<0]:>a~"-"~-b//Activate@*Hold)//.a_/b_:>a~"/"~b/.{a_Integer:>ToString@a,Plus:>"+",Times:>"*"}]//.a_String~b_~c_String:>b<>a<>b<>c<>b,HoldAll]

Questa è una funzione anonima che accetta un'espressione effettiva e restituisce una stringa con notazione panfix. Mathematica ordina la precedenza degli operatori al momento dell'analisi, piuttosto che al momento della valutazione, quindi l'annidamento dovrebbe essere automagicamente corretto. Almeno i casi di test funzionano come previsto.

Spiegazione: È abbastanza facile interpretare l'intera espressione come un albero, in questo modo:

albero

In questa fase gli operatori (ogni nodo che non è una foglia) non sono più operatori, in realtà sono stati convertiti in stringhe come "+". Anche i numeri interi vengono espressi in stringhe. Quindi una regola di sostituzione ripetuta converte ogni nodo che ha esattamente due foglie nel panfix parent-leaf1-parent-leaf2-parent. Dopo alcune iterazioni l'albero si riduce a una singola stringa.

La perdita principale nel conteggio dei byte è che Mathematica interpreta

5 - 4 -> 5 + (-4)
9 / 3 -> 9 * (3^(-1))

E questo accade anche al momento dell'analisi.

Abbassato un po ', poiché anche il modello a_/b_è interpretato come a_ * (b_)^(-1). Anche alcune piccole ottimizzazioni altrove.


1

Prolog, 87 byte

x(T)-->{T=..[O,A,B]}->[O],x(A),[O],x(B),[O];[T].
p:-read(T),x(T,L,[]),maplist(write,L).

Questa è una funzione (principalmente perché la scrittura di un programma completo ha livelli da incubo di plateplate in Prolog; normalmente, anche se si compila un programma, produce un REPL quando eseguito), chiamato p. Prende input da stdin e output su stdout. Si noti che è necessario aggiungere un punto all'input, che è una sfortunata conseguenza del modo in cui funzionano le routine di input di Prolog (usano i periodi nell'input più o meno allo stesso modo in cui le altre lingue usano le nuove righe); che potrebbe o meno squalificare la risposta.

Spiegazione

Gli operatori aritmetici, in Prolog, vengono normalmente interpretati come costruttori di tuple . Tuttavia, obbediscono alle stesse regole di precedenza degli effettivi operatori aritmetici su cui si basano; puoi formare tuple con notazione infissa +e -legarti meno strettamente di *e /, con la precedenza presa da sinistra a destra all'interno di un gruppo. Questo è esattamente ciò che la domanda chiede; quindi, possiamo leggere un'intera tupla nidificata dall'input e ha già la struttura giusta. Questo è quello che pfa.

Successivamente, dobbiamo convertirlo in notazione panfix. xconverte l'ingresso in una lista panfixed dei costruttori e numeri interi, e può essere letto come una frase in inglese quasi direttamente: " xdi Tè: se Tè una tupla con il costruttore Oe gli argomenti A, Bpoi O, xdi A, O, xdi B, O, altra cosa T". Infine, non ci resta che stampare l'elenco senza separatori (ad esempio utilizzando maplistper chiamare writeciascun elemento dell'elenco).

Ho usato SWI-Prolog per testare questo, perché la mia versione di GNU Prolog non ha maplistancora (apparentemente è stata aggiunta a una versione più recente), ma dovrebbe generalmente essere abbastanza portatile tra le implementazioni di Prolog.

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.