Analizar un lenguaje 1D

13

Dada una cadena que contiene solo 0's 1's, 2's y corchetes, genera el árbol gramatical de la cadena.

A 2requiere 2 argumentos: uno a la izquierda y otro a la derecha

A 1requiere un solo argumento, ya sea a la izquierda o a la derecha

A 0no requiere ningún argumento y es el caso base

Un par de corchetes cuenta como un argumento y el contenido de los corchetes se evalúa por separado del resto de la cadena. Los soportes anidados son posibles

Una cadena de entrada siempre será un árbol completo sin caracteres que se caigan. La cadena también solo tendrá una única solución correcta. Tenga en cuenta que las funciones son conmutativas y cualquier arreglo de argumentos 2será aceptable. No tendrá que manejar entradas que no cumplan con estos requisitos.

El formato de la gramática de salida será en forma function(arguments)recursiva

Casos de prueba

0 --> 0
01 --> 1(0)
020 --> 2(0,0)
101 --> 1(1(0))
0120 --> 2(1(0),0)
0120210 --> 2(1(0),2(0,1(0)))
01210 --> 2(1(0),1(0))
(020)210 --> 2(2(0,0),1(0))
((020)20)1 --> 1(2(0,2(0,0)))
Azul
fuente
¿Es 10201una entrada válida?
Neil
No, podría ser 1 (2 (0,1 (0))) o 2 (1 (0), 1 (0))
Azul
En realidad estaba pensando que era 1 (2 (1 (0), 0)) ;-)
Neil
1
Todavía no veo por qué 0120210no se puede analizar también como 2[4](2[2](1[1](0[0]), 0[3]), 1[5](0[6]))donde los números entre paréntesis indican la posición en la cadena.
fiesta
101También es ambiguo.
fiesta

Respuestas:

3

Python 3.6 (prelanzamiento), 199

Guardado 6 bytes gracias a Morgan Thrapp

import re
def f(s):s=s.strip('()');i,j=[m.start()if m else-1for m in(re.search(c+'(?![^(]*\))',s)for c in'21')];return i>0and f'2({f(s[:i])},{f(s[i+1:])})'or j>=0and f'1({f(s[:j])or f(s[j+1:])})'or s

Explicación y versión sin golf:

import re

def f(s):
    s=s.strip('()')
    # Search for '2' and '1' outside of brackets
    i, j = [m.start() if m else -1
            for m in (re.search(c + '(?![^(]*\))', s) for c in '21')]

    if i > 0:
        # Call `f(s[:i])` and `f(s[i+1:])`, concatenate the results
        return f'2({f(s[:i])},{f(s[i+1:])})'
    elif j>=0:
        # Call `f(s[:j])` and `f(s[j+1:])`, choose the non-empty result
        return f'1({f(s[:j]) or f(s[j+1:])})'
    else:
        return s
vaultah
fuente