Desminificar una cadena Pythlike


13

Pyth es quizás el lenguaje de golf de propósito general más exitoso. Aunque está algo en declive como resultado de los idiomas más nuevos, de 2014 a 2016 la sintaxis concisa de Pyth, las actualizaciones constantes, la sobrecarga y (para su época) muchas incorporaciones lo convirtieron en el favorito para la mayoría de las preguntas.

El código Pyth es a menudo difícil de leer. Incluso la salida del modo de depuración (Python transpilado) a menudo consiste en una línea larga, a veces con paréntesis anidados de diez de profundidad. Sin embargo, Pyth formateado correctamente es muy legible.

Aquí hay un fragmento de código Pyth, escrito por @isaacg en Play the Word Chain .

.MlZfqhMtTeMPT+Lzs.pMyQ

Es mucho más legible como este.

.M                     Filter by gives-maximal-value of
   l Z                   lambda Z:length(Z) over
   f                     filter by (lambda T:
     q                     equal
       hM t T                head-map tail T
       eM P T                end-map Pop T)
     +L                    Append z to each element in
        z                        
        s .pM y Q            flattened permutations of each subset of Q

Para este desafío, eliminamos el aspecto de kolmogorov de categorizar los caracteres Pyth y centrarnos en el formateo. En lugar de ser código Pyth, la entrada consistirá en caracteres en 0123456789M. El dígito nrepresenta una función de aridad ny Mrepresenta un operador. Por ejemplo, el código anterior se representa como 210221M101M102M011M10. Estos son los pasos para desminificar:

Separa la cuerda en fichas.

Un token coincide [0-9]M*. 0Mno ocurrirá en la entrada.

Añadir ceros finales.

Cuando no hay suficientes argumentos, Pyth agrega tantas variables implícitas (variables lambda o Qs) al código como sean necesarias para completar los argumentos del programa; estos deben estar representados por 0s.

Agrupe las fichas en líneas.

La aridad de una ficha es el valor de su dígito.

  • Un token arity-0 (es decir, un 0) termina una línea.

  • Para una ficha arity-1, la siguiente ficha debe ir en la misma línea, separada por un espacio.

  • Para un token arity> = 2, sus argumentos van en líneas separadas, en el orden en que aparecen en el código, cada uno seguido de sus propios subargumentos, etc. Los argumentos de una ficha están sangrados al final de esa ficha más un espacio.

Entrada

Una cadena no vacía (o matriz de caracteres, matriz de cadenas de longitud 1, etc. según lo permitido por los métodos de E / S estándar) que consta de 0123456789M, que no contendrá la subcadena0M .

Salida

La cadena formateada de acuerdo con las reglas anteriores.

Casos de prueba

210221M101M102M011M10

2
  1 0
  2
    2
      1M 1 0
      1M 1 0
    2M
       0
       1 1M 1 0


123M4M

1 2
    3M
       4M
          0
          0
          0
          0
       0
       0
    0


2MM

2MM
    0
    0


11011100

1 1 0
1 1 1 0
0


9000000

9
  0
  0
  0
  0
  0
  0
  0
  0
  0


¿Puedo tomar la entrada como una matriz de dígitos / cadena? El ejemplo 210221M101M102M011M10sería[2,1,0,2,2,1,'M',1,0,1,'M',1,0,2,'M',0,1,1,'M',1,0]
Luis felipe De jesus Munoz el

@LuisfelipeDejesusMunoz No, a menos que las reglas estándar de E / S requieran que se le permita (lo cual no creo). IMO cambiaría ligeramente el desafío si Mse permite que los s sean un tipo de datos diferente de los enteros.
lirtosiast el

@lirtosiast Entonces, una serie de caracteres / cadenas de un solo carácter está bien, solo que no usa diferentes tipos de datos entre dígitos y M?
Kamil Drakari

1
@LeakyNun La cadena vacía ahora es un comportamiento indefinido.
lirtosiast el

Respuestas:


1

Javascript (ES8), 160 159 bytes

f=(s,a=[d=0,p=[1]])=>s.replace(/(.)M*/g,(s,c)=>(g=_=>a[d]?s+(P=p[d]-=c--&&~s.length,c?`
`.padEnd(P):' '):g(d--))(a[d]--,a[++d]=+c,p[d]=p[d-1]))+(d?f('0',a):'')

Pruébalo en línea!

Comentado

f = (                          // f = recursive function taking:
  s,                           //   s   = input string
  a = [                        //   a[] = array holding the number of expected arguments
    d = 0,                     //   d   = current depth, initialized to 0
    p = [1]                    //   p[] = array holding the padding values
  ]                            //
) =>                           //
  s.replace(                   // search in s all substrings
    RegExp('(.)M*', 'g'),      // consisting of a digit followed by 0 to N 'M' characters
    (s, c) =>                  // for each substring s beginning with the digit c:
      ( g = _ =>               //   g = recursive function
          a[d] ?               //     if we're still expecting at least one argument at
                               //     this depth:
            s + (              //       append s
              P = p[d] -=      //       update the padding value P = p[d] for this depth:
                c-- &&         //         decrement c; unless c was equal to 0,
                ~s.length,     //         add the length of s + 1 to p[d]
              c ?              //       if c is not equal to 0 (i.e. was not equal to 1):
                `\n`.padEnd(P) //         append a linefeed followed by P - 1 spaces
              :                //       else:
                ' '            //         append a single space
            )                  //
          :                    //     else (all arguments have been processed):
            g(d--)             //       decrement the depth and call g again
      )(                       //   before the initial call to g:
        a[d]--,                //     decrement the number of arguments at depth d
        a[++d] = +c,           //     set the number of arguments for the next depth
        p[d] = p[d - 1]        //     set the padding value for the next depth,
      )                        //     using a copy of the previous depth
  ) + (                        // end of replace()
    d ?                        // if we're not back at depth 0:
      f('0', a)                //   do a recursive call to f with an extra '0'
    :                          // else:
      ''                       //   stop recursion
  )                            //

1

Haskell , 192 190 187 bytes

unlines.snd.f
f(n:r)|(m,t)<-span(>'9')r,(s,l)<-n#t=(s,n?((n:m):map((' '<$(n:n:m))++)l))
f e=(e,["0"])
'1'?(a:b:r)=(a++drop(length a)b):r
_?s=s
'0'#s=(s,[])
n#s|(r,l)<-f s=(l++)<$>pred n#r

Pruébalo en línea!

Tiene que haber una mejor manera de manejar el caso arity-1, actualmente ocupa 45 bytes.

Ediciones:

  • -2 bytes cambiando a un método diferente de manejo de 1, aunque el método anterior tiene probablemente más potencial de optimización.
  • -3 bytes al no convertir los dígitos de caracteres en números y usar en predlugar de n-1.
unlines.snd.f
f(n:r)|(m,t)<-span(>'9')r,(s,l)<-read[n]#t,w<-map((' '<$(n:n:m))++)=(s,last$((n:m):w l):[(n:m++' ':h):w t|n<'2',h:t<-[l]])
f e=(e,["0"])
0#s=(s,[])
n#s|(r,l)<-f s=(l++)<$>(n-1)#r

Pruébalo en línea!


1

Carbón de leña , 75 bytes

FS⊞υ⎇⁼ιM⁺⊟υιι≔⮌υυ≔⟦⟧θ≔⟦⟧ηW∨υη«≔⎇υ⊟υ0ιι¿⊖Σι↘→⊞θι⊞ηΣιW∧η¬§η±¹«⊟ηM⊕L⊟θ←¿η⊞η⊖⊟η

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

FS⊞υ⎇⁼ιM⁺⊟υιι

Pase los caracteres de entrada y conviértalos en una lista de dígitos con Msufijos opcionales .

≔⮌υυ

Invierta esta lista para que podamos usarla Poppara consumirla.

≔⟦⟧θ

Esta variable es una pila de tokens cuyo arity aún no se ha cumplido.

≔⟦⟧η

Esta variable es una pila de la aridad restante de las fichas no cumplidas.

W∨υη«

Repite hasta que hayamos consumido todas las fichas y vaciado la pila.

     ≔⎇υ⊟υ0ι

Obtenga el siguiente token o 0si ninguno.

     ι¿⊖Σι↘→

Imprima el token y luego mueva el cursor horizontalmente si comienza de 1otra manera en diagonal.

     ⊞θι⊞ηΣι

Agregue el token y su arity a las variables apropiadas.

     W∧η¬§η±¹«

Repita mientras la pila de arity no está vacía, pero la arity superior es cero.

              ⊟η

Descarta la aridad cero.

              M⊕L⊟θ←

Elimina su ficha y mueve tantos caracteres restantes.

              ¿η⊞η⊖⊟η

Si quedan aridades restantes, disminuya la aridad superior.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.