Formateador de explicaciones de código

32

Las presentaciones exitosas de códigos de golf están, por naturaleza, llenas de símbolos locos por todo el lugar. Para que su presentación sea más fácil de entender, muchos golfistas de código deciden incluir una explicación de su código. En su explicación, la línea de código se convierte en un diagrama en despiece vertical.

Por ejemplo, si este fuera mi código:

1_'[3:~2@+]`

Uno de los muchos diagramas posibles que podría crear se vería así:

1           
 _'         
   [      ] 
   [3:    ] 
   [  ~   ] 
   [   2@ ] 
   [     +] 
           `

La meta

En este desafío, escribirá una herramienta de formateo automático de explicación que toma una línea de código y crea un diagrama al que se puede agregar fácilmente texto explicativo.

Para hacer de este un desafío más útil , el usuario podrá especificar el contenido de cada línea, proporcionando una cadena de formato. La cadena de formato será una segunda línea, que contiene solo letras A-Za-z, que tiene la misma longitud que el programa. Las letras muestran el orden en que los caracteres del programa deben imprimirse en la explicación.

Aquí hay un ejemplo de E / S sin ningún formato tipo corchete :

123423
AabcBC

1     
    2 
     3
 2    
  3   
   4  

Soportes

Si más de un carácter en el programa tiene el mismo nivel de prioridad, ese conjunto de caracteres actúa como un solo bloque de código (si forman un grupo) o un conjunto de paréntesis (si contienen otros caracteres intermedios). Las reglas generales son simples:

  1. Los caracteres no aparecen en una línea del diagrama hasta que todos los demás caracteres de mayor prioridad ya hayan aparecido en las líneas sobre el diagrama.

  2. Los caracteres de igual prioridad siempre se imprimen en las mismas líneas. Si un determinado carácter aparece en una línea, todos los demás caracteres de igual prioridad aparecen en la línea.

  3. Un conjunto de caracteres de igual prioridad continúa apareciendo en cada línea hasta que todos los demás caracteres encerrados por ella hayan aparecido al menos una vez. Esto permite construcciones tipo "corchete". Si bceabson las prioridades, los bcaracteres aparecerán en la segunda línea (son la segunda prioridad más alta) y continuarán apareciendo hasta que todos los ceacaracteres hayan aparecido. Si la cadena de prioridad es abcadeafga, entonces todos bcdefgse consideran contenidos dentro de ella, y los 4 as continuarán apareciendo hasta que aparezca g.

Más requisitos de formato

Todas las líneas de salida deben tener la misma longitud (la longitud de las líneas de entrada), rellenadas con espacios según sea necesario. La línea del programa de entrada puede contener espacios, aunque esos espacios también recibirán una letra de prioridad. Las nuevas líneas finales en la salida / entrada son opcionales.

Tanteo

Este es el código de golf, menos bytes gana.


Ejemplos

Aquí hay un ejemplo comentado de un fragmento de código con un formato más complejo.

1_'[3:~2@+]`
abbcddeffgch

1            #highest priority is denoted by the lowercase letter a
 _'          #priority b
   [      ]  #all characters with priority c
   [3:    ]  #priority d, but priority c still printed because it encloses more
   [  ~   ]  #priority e
   [   2@ ]  #priority f
   [     +]  #priority g, last line of c because all enclosed characters have appeared
           ` #priority h

Un ejemplo en Perl:

$_=<>;s/[^aeiou\W]/$&o$&/gi;print
aaaaaabbccccccccccbdddddbbbbeeeee

$_=<>;                           
      s/          /     /gi;     
      s/[^aeiou\W]/     /gi;     
      s/          /$&o$&/gi;     
                            print

Aquí hay algunos ejemplos en CJam, cortesía de Martin Büttner:

l~2*{_2%{3*)}{2/}?_p_(}g;
aabbcdddefffeeggeehhiiccj

l~                       
  2*                     
    {                 }g 
    {_2%              }g 
    {   {   }{  }?    }g 
    {   {3*)}{  }?    }g 
    {   {   }{2/}?    }g 
    {             _p  }g 
    {               _(}g 
                        ;

q{_eu'[,66>"EIOU"-#)g{'o1$}*}/
abcccddddddeeeeeeefgghiijjhhbb

q                             
 {                          }/
 {_eu                       }/
 {   '[,66>                 }/
 {         "EIOU"-          }/
 {                #         }/
 {                 )g       }/
 {                   {    }*}/
 {                   {'o  }*}/
 {                   {  1$}*}/

Aquí hay un ejemplo loco solo para meterse contigo:

1_'[3:~2@+]`
azTABACBDCAT

   [ :    ] 
   [3: 2  ] 
   [3:~2 +] 
   [ :~ @+] 
  '        `
1           
 _          

Aquí hay un ejemplo más explícito de lo que sucede cuando los corchetes se superponen abab. (Normalmente, esta no es la forma en que elegiría formatear su explicación).

aabbccddaaeebb
aabbccddaaeebb

aa      aa    
aabb    aa  bb
aabbcc  aa  bb
aabb  ddaa  bb
  bb      eebb #"aa" no longer appears because all of "bbccdd" have already appeared.
PhiNotPi
fuente

Respuestas:

14

Pyth, 33 40 bytes

JwFHS{Js.e?@zk&gHYsm&gdH}d>_>JxJYx_JYJdJ

Pruébelo en línea: Pyth Compiler / Executor

Explicación:

Generado con la cadena aabbbbbzccdeeegfffqhjiiikkpnmmllloooohec:

                                          implicit: z = first input line
Jw                                        J = second input line
  FHS{J                                   for H in sorted(set(J)):
        .e                             J    map each k,Y of enumerate(J) to:
        .e?                            J      .... if ... else ...
        .e @zk                        dJ      z[k] if ... else " "
                                              condition: 
        .e @zk gHY                    dJ        H >= Y
        .e @zk&                       dJ        and
        .e @zk     m                 JdJ        map each d of J to:
        .e @zk     m gdH             JdJ          d >= H
        .e @zk     m&                JdJ          and
        .e @zk     m    }d           JdJ          d in ...
        .e @zk     m          xJY    JdJ          index of Y in J
        .e @zk     m        >J       JdJ          substring of J (from index to end)
        .e @zk     m       _         JdJ          reverse substring
        .e @zk     m             x_JYJdJ          index of Y in reversed J
        .e @zk     m      >          JdJ          substring of reversed (from index to end)
        .e @zk    s                   dJ       sum up the booleans (acts as any)
       s                                    sum up the chars and print

Entonces, la primera línea de entrada es z, la segunda línea de entrada es J.

El ciclo itera sobre todos los caracteres Jen orden ordenado y sin duplicados. Se llama al personaje actual H.

Luego, para cada Yde Jque imprimir el carbón corresponsal zo un espacio en blanco, dependiendo de si se dan las siguientes condiciones:

  • Y <= H(un personaje aparece primero en la línea H)
  • hay un carácter d >= Hque aparece en un bloque que comienza y termina con Y(paréntesis).

Ejemplos

Esto muestra cómo la cuarta línea de la entrada abcdaeb, abcdaebestá impresa. La cuarta línea es una buena representación, ya que la mayoría de los casos posibles suceden:

code input:  "abcdaeb"
order input: "abcdaeb"

printing the fourth line, H = "d":

   "a" is printed, because "a" <= "d" and ("d" >= "d" and "d" is in "abcda")
   "b" is printed, because "b" <= "d" and ("d" >= "d" and "d" is in "bcdaeb")
   "c" are not printed, because neither "d" nor "e" (chars >= "d") are not in "c"
   "d" is printed, because "d" <= "d" and ("d" >= "d" and "d" is in "d")
   "a" is printed, because "a" <= "d" and ("d" >= "d" and "d" is in "abcda")
   "e" is not printed, because "e" > "d"
   "b" is printed, because "b" <= "d" and ("d" >= "d" and "d" is in "bcdaeb")

therefore the fourth line is: aabb__ddaa__bb

Y otro ejemplo basado en un caso de prueba, @Optimizer me dio. (que destruyó mi solución 33).

code input:  "acab"
order input: "acab"

printing the second line, H = "b":

   "a" is printed, because "a" <= "b" and ("c" >= "b" and "c" is in "aca")
   "c" is not printed, because "c" > "b"
   "a" is printed, because "a" <= "b" and ("c" >= "b" and "c" is in "aca")
   "b" is printed, because "b" <= "b" and ("b" >= "b" and "b" is in "b")

therefore the second line is: a_ab

Versión anterior: 58 57 52 bytes

JwKNFHS{J=K.e?eS>_>[email protected]?@zknYNdK=KXKHN

Pruébelo en línea: Pyth Compiler / Executor

Esto crea una máscara, que modificaré antes y después de imprimir cada línea. Para obtener más información, consulte el historial de edición.

Jakube
fuente
8

CJam, 82 bytes

Actualmente es bastante largo y creo que puedo eliminar algunos bytes más.

leel:F]z::+F$_&\f{{W=1$=},\;}{]_{0f=_W=),\0=>Lf&Ra#)},F,S*\:+{~;1$L+:L;t}%oNo~}%];

Algoritmo

El algoritmo básico es el siguiente:

  • leel:F]z::+ : Agrupe el código, el formato y el índice de cada carácter.
  • F$_&\f{{W=1$=},\;}: Agrupe los tripletes anteriores en prioridad de impresión utilizando la cadena de formato. Este código también asegura que las prioridades estén ordenadas.
  • ]_{0f=_W=),\0=>Lf&Ra#)},: Para cada grupo prioritario de tripletes, obtenga el rango del índice delimitador y vea si todavía no se imprime algún índice. Si hay un índice sin imprimir, incluya este grupo de prioridad en el grupo "para imprimir en este paso".
  • F,S*\:+{~;1$L+:L;t}%oNo~}%: Después de imprimir todos los grupos en este paso, complete el código en el índice correcto de una cadena de espacio vacío y luego imprima esa cadena. También actualice la matriz que contiene la lista de índices impresos.

Explicación del código a seguir cuando termine de jugar golf.

Ejemplo

Aquí está el código ejecutado en el código mismo:

Entrada:

leel:F]z::+F$_&\f{{W=1$=},\;}{]_{0f=_W=),\0=>Lf&Ra#)},F,S*\:+{~;1$L+:L;t}%oNo~}%];
aaabbbcccccdddddeefgghhiffggejkklmmmnoooopppqrrrssssllttttuuuvwwxxxxxxxyvvzzzzjjjj

Salida:

lee                                                                               
   l:F                                                                            
      ]z::+                                                                       
           F$_&\                                                                  
                f{          }                                                     
                f{{     },  }                                                     
                f{{W=   },\;}                                                     
                f{{W=1$ },\;}                                                     
                f{{W=  =},\;}                                                     
                             {                                                }%];
                             {]_                                              }%];
                             {  {                   },                        }%];
                             {  {0f=                },                        }%];
                             {  {   _               },                        }%];
                             {  {    W=),           },                        }%];
                             {  {        \0=        },                        }%];
                             {  {           >       },                        }%];
                             {  {            Lf&    },                        }%];
                             {  {               Ra#)},                        }%];
                             {                        F,S*                    }%];
                             {                            \:+                 }%];
                             {                               {          }%    }%];
                             {                               {~;        }%    }%];
                             {                               {  1$L+:L; }%    }%];
                             {                               {         t}%    }%];
                             {                                            oNo~}%];

Pruébalo en línea aquí

Optimizador
fuente
oNopuede ser reemplazado con nen TIO .
Esolanging Fruit
8

CJam, 48 bytes

ll:i:T.{___T#TW%@#~T<>+:e>)1$-@*123Se]m>}z_|(;N*

Explicación

l                                                Code.
 l                                               Priority.
  :i                                             Convert priority to integer.
    :T                                           Save to T.
      .{                                }        For corresponding items:
      .{___                             }        Copy the current priority 3 times.
      .{   T#                           }        First position with this priority.
      .{     TW%                        }        Reverse T.
      .{        @#                      }        First (last) position with this priority.
      .{          ~T<                   }        Cut T at the end of this priority.
      .{             >                  }        Cut at the beginning of this priority.
      .{              +                 }        Insert the current priority to
                                                 prevent the array being empty.
      .{               :e>              }        Array maximum.
      .{                  )1$-          }        Count of integers between the current
                                                 priority and the maximum, inclusive.
      .{                      @*        }        That number of the current character.
      .{                        123Se]  }        Fill irrelevant priorities with spaces.
      .{                              m>}        Rotate the array to make non-spaces
                                                 starting at the current priority.
                                                 Returns a column containing 123 items.
                                         z       Zip to get the rows from columns.
                                          _|     Remove duplicate rows, including
                                                 unused priorities and all-space rows.
                                            (;   Remove the first row (an all-space row).
                                              N* Insert newlines.
jimmy23013
fuente
6

IDL 8.4, 316 318 304 bytes

¡Nueva versión, todavía demasiado larga, pero más corta! Y, en el verdadero espíritu de IDL, completamente vectorizado, lo que significa (ya que no hay bucle for) que ahora puedo hacerlo como una línea y ejecutarlo en sí mismo, una vez que obtenga mi versión completamente actualizada a 8.4. Eso será editado más tarde.

Versión de una línea:

c=(f='')&read,c,f&l=[0:strlen(f)-1]&c=strmid(c,l,1)&s=strmid(f,l,1)&u=s.uniq()&k=value_locate(u,s)&n=[0:max(k)]&d=hash(n,u.map(lambda(x,y,z:max(z[(r=stregex(y,'('+x+'(.*))?'+x,len=w)):r+w-1])),f,k))&print,n.map(lambda(n,l,c,d,i:i.reduce(lambda(x,i,l,c,d,n:x+(d[l[i]]ge n?c[i]:' ')),l,c,d,n)),k,c,d,l)&end

Con saltos de línea (mismo número de bytes, subbing \ n vs &), y comentó:

c=(f='') ;initialize code and format as strings
read,c,f ;read two lines of input from the prompt
l=[0:strlen(f)-1] ;index array for the strings
c=strmid(c,l,1) ;split the code string into an array, via substrings of length 1
s=strmid(f,l,1) ;same for the format string, saving f for regex later
u=s.uniq() ;get the sorted unique values in the format string (sorts A->a)
k=value_locate(u,s) ;assign layer values to the format characters
n=[0:max(k)] ;index array for the unique format characters
d=hash(n,u.map(lambda(x,y,z:max(z[(r=stregex(y,'('+x+'(.*))?'+x,len=w)):r+w-1])),f,k))
print,n.map(lambda(n,l,c,d,i:i.reduce(lambda(x,i,l,c,d,n:x+(d[l[i]]ge n?c[i]:' ')),l,c,d,n)),k,c,d,l)
end ;end the script

Aquí hay un desglose algorítmico para la línea 9:

r=stregex(y,'('+x+'(.*))?'+x,len=w) ; r, w = starting position & length of substring in y {format string} bracketed by x {character} (inclusive)
z[(r=...):r+w-1] ; grab a slice of z {layer array} from r to r+w-1 -> layer values for each character in the substring
max(z[...]) ; max layer (depth) of any characters in that slice
u.map(lambda(x,y,z:max(...)),f,k) ;map an inline function of the above to every element of the unique-formatting-character array
d=hash(n,u.map(...)) ; create a hash using the unique indices, the result is a hash of (character:max_substring_depth)

... y 10:

x+(d[l[i]]ge n?c[i]:' ')) ; ternary concatenation: if maxdepth for this character >= current depth, add the character, otherwise add ' '
i.reduce(lambda(x,i,c,d,l,n:...)),,l,c,d,n) ;accumulate elements of i {code/format index array} by passing them through the inline ternary concatenation function
print,n.map(lambda(n,l,c,d,i:i.reduce(...)),k,c,d,l) ;map the depth index through the reduction, ending up with a string for each depth layer, then print it

Las líneas 9 y 10 hacen el trabajo real, el resto configura las variables que necesita para el final. Creo que esto es tan golfístico como va a ser, no puedo encontrar ningún otro lugar para hacerlo mejor.

Versión anterior (todo lo siguiente aquí está desactualizado):

Esto no es lo suficientemente corto como para ganar, porque este es un lenguaje de golf terrible, pero nadie responde en IDL, así que voy a buscarlo.

a=(b='')
read,a,b
c=[0:strlen(b)-1]
d=strmid(b,c,1)
a=strmid(a,c,1)
e=d[uniq(d,sort(d))]
f=list(value_locate(e,d),/e)
s=hash()
for i=0,max(f)do begin
g=stregex(b,'('+e[i]+'(.*))?'+e[i],l=l)
s[i]=max(f[g:g+l-1])
print,f.reduce(lambda(x,y,z:x+(s.haskey(y)?z[y]:' '),s,a)
s=s.filter(lambda(x,y:x[1]gt y),i)
endfor
end

No estoy seguro de si hay alguna forma en que pueda reducirlo más ... Podría llamar a strmid en ayb al mismo tiempo, pero luego gasto más bytes indexando d y funciona igual. ¡Pero seguiré trabajando en ello! (Y mañana editaré una explicación del algoritmo).

Sirpercival
fuente