Notazione prefisso alla notazione postfissa


19

Disclaimer: No, questa non è una sfida scherzosa per invertire una stringa.

Compito

C'è solo una operazione da supportare: sottrazione ( -).

Hai anche solo due atomi da supportare: zero ( 0) e uno ( 1).

Qui, la notazione del prefisso -ABequivale alla notazione postfissa AB-, dove Ae Bsono espressioni.

Il tuo compito è convertire (ricorsivamente) un'espressione in notazione prefissata nel suo equivalente in notazione postfissa.

definizioni

Un'espressione in notazione con prefisso viene generata dalla seguente grammatica:

S > -SS
S > 0
S > 1

Un'espressione nella notazione postfix viene generata dalla seguente grammatica:

S > SS-
S > 0
S > 1

Esempio

Prefix notation:  --01-0-01
Parentheses:      -(-01)(-0(-01))
Convert:          (01-)(0(01-)-)-
Postfix notation: 01-001---

Regole e libertà

  • È possibile rinominare l'operazione e gli atomi in qualunque carattere, purché sia ​​coerente.
  • Il formato di input deve essere coerente con il formato di output (a parte il fatto che l'input è in notazione prefisso e l'output è in notazione postfix).

testcase

Input       Output
1           1
0           0
-01         01-
-10         10-
--01-0-01   01-001---

Mette alla prova i crediti a Dada .


1
Puoi aggiungere qualche altro test, per favore?
Shaggy,

@Shaggy che tipo di test ti piacerebbe?
Leaky Nun,

@LeakyNun Va bene prendere l'input e l'output come iteratori, come ho fatto nell'ultima versione della mia risposta?
L3viathan,

@ L3viathan Suppongo di si ...
Leaky Nun

Risposte:


12

Brainfuck , 32 byte

,[[->++++<<+>]>[[-]<<[.[-]<]]>,]

Provalo online!

Ho usato @come operazione, perché il suo punto di codice (64) è conveniente. Uè anche possibile con lo stesso numero di byte, usando 3 * 85 + 1 = 256 = 0.

Spiegazione

Il nastro viene utilizzato come una pila. In ogni iterazione del ciclo principale, il puntatore ai dati avvia due celle a destra della parte superiore dello stack.

,[                Take input and start main loop
  [->++++<<+>]    Push input, and compute 4*input
  >[              If 4*input is nonzero (and thus input is not @):
    [-]<<           Zero out this cell and move to top of stack
    [.[-]<]         Pop from stack and output until \0 is reached
  ]
  >,              Move pointer into the correct position.  If input was @, the earlier > pushed \0 onto the stack.
]

6

Retina , 37 30 29 byte

M!`-*.
+m`^-(.*)¶(\d.*)
$1$2-

Provalo online! Ho salvato 7 byte rendendomi conto che i termini iniziano sempre con una cifra, quindi non devo più limitare la corrispondenza all'ultimo -(in precedenza era l'unico a cui seguivano due termini). Salvato 1 byte non inserendo -s sulla propria linea. Ad esempio, -01diventa -0¶1che viene quindi sostituito con 01-. Ora, se ho --010ie, --0¶1¶0allora voglio cambiare l'interno -0¶1in 01-modo da poterlo sostituire -01-¶0con 01-0-, ma in realtà non importa quale dei due -rimuovo, quindi rimuovo quello all'inizio della riga, come è più facile testarlo.


Penso che questo sia il tuo qualcosa :)
Leo,

@Leo non funziona in generale, ad esempio -0-0-00dovrebbe diventare 0000---.
Neil,

Hai ragione, scusa. Ho un'altra idea, ma è sostanzialmente diversa, quindi la posterò come una nuova risposta
Leo,

1
@Leo Ora ho trovato il mio qualcosa ...
Neil

1
@Leo Con il mio ultimo golf siamo legati!
Neil,

6

Haskell , 62 59 byte

f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
fst.f

Provalo online! Uso: fst.f $ "--01-0-01". 0e 1possono essere personaggi arbitrari che sono più grandi del personaggio -.

Modifica: -3 byte grazie a Zgarb!

La funzione fanalizza ricorsivamente un'espressione e restituisce una tupla di questa espressione nella notazione postfissa e nella stringa di riposo, seguendo la semplice grammatica da cui è possibile creare espressioni prefisso valide:

<exp> ::= - <exp> <exp> | 0 | 1

Se il primo carattere adella stringa di input è maggiore di -, ci troviamo in un'espressione atomica e restituiamo una tupla di una stringa con carattere ae il resto della stringa di input.

Se troviamo a -, è necessario analizzare due espressioni. Ciò può essere ottenuto (a,x)<-f rper ottenere la prima espressione ae quindi analizzare xnuovamente la stringa di resto (b,c)<-f xper ottenere la seconda espressione be la stringa di resto finale c. (a,(b,c))<-f<$>f rfa esattamente questo perché <$>sulle mappe di tuple una funzione due è il secondo elemento di una tupla pur essendo tre byte più corta di (a,x)<-f r,(b,c)<-f x. Dopo aver ottenuto entrambe le espressioni e la stringa resto, le espressioni sono concatenati e "-" viene aggiunto: (a++b++"-",c).


1
Puoi salvare 3 byte combinando i casi:f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
Zgarb

@Zgarb Grazie! Per qualche motivo ho considerato solo f(x:r)|x<'0',(a,(b,c))<-f<$>f r=(a++b++"-",c)|1<3=([x],r)quando ho cercato una versione con entrambi i casi combinati, che è byte più lungo.
Laikoni,

5

Haskell, 54 byte

v f""=""
v f(a:s)=last(v.v:[id|a>'-'])((a:).f)s
h=v h

La funzione vaccetta una stringa e una funzione, riorganizza la sottoespressione iniziale, quindi applica la funzione al resto della stringa fino a quando tutto non è stato riorganizzato. Lo stack di chiamate e l'argomento della funzione tengono traccia insieme dell'espressione che viene analizzata. La funzione hrisponde alla sfida e viene vchiamata con se stessa come primo argomento fittizio.


1
Wow! (1) Sono solo 53, non è necessario contare la nuova riga finale. (2) La prima riga può essere accorciata v f l=lse la si sposta in secondo luogo.
Ørjan Johansen,

1
Non penso che tu debba analizzare più di un'intera espressione, quindi puoi salvare un byte usando la funzione anonima v id.
Ørjan Johansen,

1
In realtà la prima riga non viene mai chiamata con un input valido, quindi puoi semplicemente cancellarla.
Ørjan Johansen,

1
Dividere in guardie sembra battere il lasttrucco di un byte.
Ørjan Johansen,

4

Perl 5 , 57 byte

sub f{"@_"=~s/x((?0)|.)((?0)|.)/my$n=$2;f($1).f($n).x/re}

Uso xcome operatore invece di -(vedi sotto il link TryItOnline).

Provalo online!

Spiegazioni:
/x((?0)|.)((?0)|.)/ corrisponde ricorsivamente a un'espressione completa: xa all'inizio, quindi un'espressione (?0)(è una chiamata ricorsiva) o un atomo ( .), seguito da un'altra espressione-o-atomo.
Quindi ho bisogno di salvare la seconda espressione / atom ( my$n=$2;) perché altrimenti le chiamate ricorsive la sovrascriveranno.
La funzione viene quindi chiamata in modo ricorsivo sulla prima espressione ( f($1)), quindi sulla seconda f($n), e xviene aggiunta alla fine ( .x).


4

Python 3, 117 112 105 100 98 76 62 61 59 byte

def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]

changelog:

  • interruzioni di riga rimosse ove possibile (-5 byte)
  • lambda invece di una funzione completa (-7 byte, grazie @Dada)
  • nessun altro (-5 byte, grazie @Leaky Nun)
  • annulla il golf troppo zelante (-2 byte, grazie @Leaky Nun)
  • lavora invece su un elenco globale (-22 byte)
  • in realtà, lavoriamo invece su iteratori (-14 byte)
  • cambia !=in >(-1 byte, copiato dal suggerimento di @ovs)
  • trucco di valutazione pigro (-2 byte, grazie @ovs)

Usalo in questo modo:

>>> list(p(iter("--01-0-01")))
['0', '1', '-', '0', '0', '1', '-', '-', '-']


2
lambda x:p(x)[0]potrebbe probabilmente sostituire la tua ffunzione.
Dada,

1
Non hai bisogno else, pensiamo.
Leaky Nun,

1
Avere d="-"davvero salvare byte?
Leaky Nun,

1
def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]per 59 byte
ovs

3

Pyth, 20 byte

L+&-hbTsyM.-Btbytbhb

Ciò crea una funzione yche prevede una stringa come parametro.

Provalo online: Dimostrazione o Test Suite

Spiegazione:

La funzione yanalizzerà e convertirà la prima espressione del prefisso in un'espressione postfissa. Quindi, se viene chiamato come y"10", tornerà solo 1.

L+&-hbTsyM.-Btbytbhb
L                      define a function y(b), that returns:
   -hbT                   remove the chars "10" from the first char b
                          (T=10, and - will convert a number to a string)
  &                       if this gives the empty string (a falsy value)
 +                hb         then append b[0] to it and return it
                             (so this will parse a digit 0 or 1 from the string)
  &                       otherwise (the first char is a -)
               ytb           parse the first prefix expression from b[1:]
                             (recursive call)
          .-Btb              remove this parsed expression bifurcated from b[1:]
                             this gives a tuple [b[1:], b[1:] without first expr]
        yM                   parse and convert an expression from each one
       s                     join the results
 +                hb         and append the b[0] (the minus) to it and return

2

Retina , 34 31 29 byte


;
-;
¶
+`¶(.+);(.+)
$1$2-
;

Provalo online!

;sono usati per indicare i nodi, che inizialmente sono composti da un singolo numero e poi crescono a tutto ciò che è già stato analizzato. -vengono trasformati in newline in modo che con .+noi possiamo afferrare tutto ciò che non è un non analizzato -.


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.