Notación de prefijo a notación de prefijo

19

Descargo de responsabilidad: No, este no es un desafío de broma para invertir una cadena.

Tarea

Solo hay una operación que admitir: sustracción ( -).

También solo tiene dos átomos para soportar: cero ( 0) y uno ( 1).

Aquí, la notación de prefijo -ABes equivalente a la notación de postfix AB-, donde Ay Bson expresiones.

Su tarea es convertir (recursivamente) una expresión en notación de prefijo a su equivalente en notación de postfix.

Definiciones

La siguiente gramática genera una expresión en notación de prefijo:

S > -SS
S > 0
S > 1

La siguiente gramática genera una expresión en notación postfix:

S > SS-
S > 0
S > 1

Ejemplo

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

Reglas y libertad

  • Puede cambiar el nombre de la operación y los átomos a cualquier carácter, siempre que sea coherente.
  • El formato de entrada debe ser coherente con el formato de salida (aparte del hecho de que la entrada está en notación de prefijo y la salida está en notación postfix).

Caso de prueba

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

Créditos de casos de prueba a Dada .

Monja permeable
fuente
1
¿Puedes agregar algunos casos de prueba más, por favor?
Shaggy
@ Shaggy, ¿qué tipo de pruebas te gustaría?
Leaky Nun
@LeakyNun ¿Está bien tomar la entrada y la salida como iteradores, como lo hice en la última versión de mi respuesta?
L3viathan
@ L3viathan supongo que sí ...
Leaky Nun

Respuestas:

12

brainfuck , 32 bytes

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

Pruébalo en línea!

Utilicé @como operación, porque su punto de código (64) es conveniente. UTambién es posible con el mismo número de bytes, usando 3 * 85 + 1 = 256 = 0.

Explicación

La cinta se usa como una pila. En cada iteración del bucle principal, el puntero de datos inicia dos celdas a la derecha de la parte superior de la pila.

,[                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.
]
Nitrodon
fuente
6

Retina , 37 30 29 bytes

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

Pruébalo en línea! Ahorré 7 bytes al darme cuenta de que los términos siempre comienzan con un dígito, por lo que ya no tengo que limitar la coincidencia a la última -(anteriormente era el único garantizado para ser seguido por dos términos). Se salvó 1 byte al no poner -s en su propia línea. Por ejemplo, se -01convierte en lo -0¶1que luego se reemplaza con 01-. Ahora, si tengo, --010es decir --0¶1¶0, quiero cambiar el interior -0¶1a 01-para poder reemplazar el -01-¶0con 01-0-, pero en realidad no importa cuál de los dos -s elimino, por lo que elimino el que está al comienzo de la línea, como eso es más fácil de probar.

Neil
fuente
Creo que este es tu algo :)
Leo
@Leo no funciona en general, por ejemplo, -0-0-00debería ser 0000---.
Neil
Tienes razón, lo siento. Tengo otra idea, pero es sustancialmente diferente, así que la publicaré como una nueva respuesta
Leo
1
@Leo Ahora he encontrado algo ...
Neil
1
@Leo ¡Con mi último golf estamos empatados!
Neil
6

Haskell , 62 59 bytes

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

Pruébalo en línea! Uso: fst.f $ "--01-0-01". 0y 1pueden ser caracteres arbitrarios que son más grandes que el carácter -.

Editar: -3 bytes gracias a Zgarb!

La función fanaliza de forma recursiva una expresión y devuelve una tupla de esta expresión en notación postfix y la cadena de resto, siguiendo la gramática simple a partir de la cual se pueden construir expresiones de prefijo válidas:

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

Si el primer carácter ade la cadena de entrada es mayor que -, estamos en una expresión atómica y devolvemos una tupla de una cadena con carácter ay el resto de la cadena de entrada.

Si encontramos a -, se deben analizar dos expresiones. Esto se puede lograr (a,x)<-f robteniendo la primera expresión ay luego analizar la cadena de descanso xnuevamente (b,c)<-f xpara obtener la segunda expresión by la cadena de descanso final c. (a,(b,c))<-f<$>f rhace exactamente esto porque <$>en tuplas asigna una función dos, el segundo elemento de una tupla, mientras que es tres bytes más corta que (a,x)<-f r,(b,c)<-f x. Después de obtener las dos expresiones y la cadena de reposo, las expresiones se concatenan y un "-" se adjunta: (a++b++"-",c).

Laikoni
fuente
1
Puede guardar 3 bytes combinando los casos:f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
Zgarb
@ Zgarb ¡Gracias! Por alguna razón, solo consideré f(x:r)|x<'0',(a,(b,c))<-f<$>f r=(a++b++"-",c)|1<3=([x],r)cuando busqué una versión con ambos casos combinados, que es un byte más largo.
Laikoni
5

Haskell, 54 bytes

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

La función vtoma una cadena y una función, reorganiza la subexpresión inicial, luego aplica la función al resto de la cadena hasta que todo se haya reorganizado. La pila de llamadas y el argumento de la función juntos hacen un seguimiento de qué expresión se analiza. La función hresponde al desafío y se vllama a sí misma como un primer argumento ficticio.

faubi
fuente
1
¡Guauu! (1) Eso es solo 53, no necesita contar la nueva línea final. (2) La primera línea se puede acortar v f l=lsi la mueve en segundo lugar.
Ørjan Johansen
1
No creo que necesite analizar más de una expresión completa, por lo que puede guardar un byte utilizando la función anónima v id.
Ørjan Johansen
1
En realidad, la primera línea nunca recibe una entrada válida, por lo que puede eliminarla.
Ørjan Johansen
1
Dividirse en guardias parece superar el lasttruco en un byte.
Ørjan Johansen
4

Perl 5 , 57 bytes

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

Lo uso xcomo operador en lugar de -(ver el enlace TryItOnline a continuación).

Pruébalo en línea!

Explicaciones:
/x((?0)|.)((?0)|.)/ coincide recursivamente con una expresión completa: xa al principio, luego una expresión (?0)(es una llamada recursiva) o un átomo ( .), seguido de otra expresión o átomo.
Luego necesito guardar la segunda expresión / átomo ( my$n=$2;) porque de lo contrario las llamadas recursivas lo anularán.
La función se llama recursivamente en la primera expresión ( f($1)), luego en la segunda f($n), y xse agrega al final ( .x).

Dada
fuente
4

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

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

Registro de cambios:

  • saltos de línea eliminados donde sea posible (-5 bytes)
  • lambda en lugar de una función completa (-7 bytes, gracias @Dada)
  • no más (-5 bytes, gracias @Leaky Nun)
  • deshacer el golf excesivamente celoso (-2 bytes, gracias @Leaky Nun)
  • trabajar en una lista global en su lugar (-22 bytes)
  • en realidad, trabajemos en iteradores en su lugar (-14 bytes)
  • cambiar !=a >(-1 byte, copiado de la sugerencia de @ovs)
  • truco de evaluación perezosa (-2 bytes, gracias @ovs)

Úselo así:

>>> list(p(iter("--01-0-01")))
['0', '1', '-', '0', '0', '1', '-', '-', '-']
L3viatán
fuente
2
lambda x:p(x)[0]Probablemente podría reemplazar su ffunción.
Dada
1
No necesitas else, me parece.
Leaky Nun
1
¿Tener d="-"realmente guardar bytes?
Leaky Nun
1
def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]para 59 bytes
ovs
3

Pyth, 20 bytes

L+&-hbTsyM.-Btbytbhb

Esto crea una función yque espera una cadena como parámetro.

Pruébelo en línea: Demostración o conjunto de pruebas

Explicación:

La función yanalizará y convertirá la primera expresión de prefijo en una expresión de postfix. Entonces, si se llama así y"10", solo regresará 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
Jakube
fuente
2

Retina , 34 31 29 bytes


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

Pruébalo en línea!

;se usan para indicar nodos, que inicialmente están compuestos por un solo número y luego se convierten en algo que ya se ha analizado. -se convierten en nuevas líneas para que .+podamos tomar cualquier cosa que no se haya analizado -.

León
fuente