Formatador de Explicação de Código

32

Os envios bem-sucedidos de golfe por código são, por natureza, preenchidos com símbolos malucos em todo o lugar. Para facilitar sua compreensão, muitos golfistas de código optam por incluir uma explicação de seu código. Na explicação deles, a linha de código é transformada em um diagrama explodido verticalmente.

Por exemplo, se este fosse o meu código:

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

Um dos muitos diagramas possíveis que eu poderia criar ficaria assim:

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

O objetivo

Neste desafio, você escreverá uma ferramenta de formatação automática de explicações que utiliza uma linha de código e cria um diagrama ao qual o texto explicativo pode ser facilmente adicionado.

Para tornar esse desafio mais útil , o usuário poderá especificar o conteúdo de cada linha, fornecendo uma string de formatação. A cadeia de formatação será uma segunda linha, contendo apenas letras A-Za-z, que é do mesmo tamanho que o programa. As letras mostram a ordem em que os caracteres do programa devem ser impressos na explicação.

Aqui está um exemplo de E / S sem formatação de colchete :

123423
AabcBC

1     
    2 
     3
 2    
  3   
   4  

Suportes

Se mais de um caractere no programa tiver o mesmo nível de prioridade, esse conjunto de caracteres funcionará como um único bloco de código (se formarem um grupo) ou um conjunto de colchetes (se eles contiverem outros caracteres no meio). As regras gerais são simples:

  1. Os caracteres não aparecem em uma linha do diagrama até que todos os outros caracteres de maior prioridade já apareçam nas linhas acima dele no diagrama.

  2. Caracteres de igual prioridade são sempre impressos nas mesmas linhas. Se um determinado caractere aparecer em uma linha, todos os outros caracteres de igual prioridade aparecerão na linha.

  3. Um conjunto de caracteres de igual prioridade continua a aparecer em cada linha até que todos os outros caracteres contidos nela apareçam pelo menos uma vez. Isso permite construções "entre parênteses". Se bceabforem as prioridades, os bcaracteres aparecerão na segunda linha (são a segunda maior prioridade) e continuarão a aparecer até que todos os ceacaracteres apareçam . Se a seqüência de prioridade for abcadeafga, todos bcdefgserão considerados contidos nela, e todos os 4 as continuarão a aparecer até que apareça g.

Mais requisitos de formatação

Todas as linhas de saída devem ter o mesmo comprimento (o comprimento das linhas de entrada), preenchidas com espaços conforme necessário. A linha do programa de entrada pode conter espaços, embora esses espaços também recebam uma letra prioritária. Novas linhas à direita na saída / entrada são opcionais.

Pontuação

Isso é código de golfe, o menor número de bytes vence.


Exemplos

Aqui está um exemplo comentado de um pedaço de código com formatação mais complexa.

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

Um exemplo em Perl:

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

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

Aqui estão alguns exemplos no CJam, cortesia 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$}*}/

Aqui está um exemplo maluco só para mexer com você:

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

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

Aqui está um exemplo mais explícito do que acontece quando os colchetes se sobrepõem abab. (Normalmente, não é dessa maneira que você escolheria formatar sua explicação.)

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
fonte

Respostas:

14

Pitão, 33 40 bytes

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

Experimente on-line: Compilador / Executor Pyth

Explicação:

Gerado com a sequência 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

Portanto, a primeira linha de entrada é z, a segunda linha de entrada é J.

O loop itera sobre todos os caracteres Jna ordem classificada e sem duplicatas. O caractere atual é chamado H.

Então, para cada Yde JI imprimir o caractere correspondente do zou um espaço em branco, dependendo se as duas seguintes condições:

  • Y <= H(um caractere aparece pela primeira vez na linha H)
  • existe um caractere d >= Hque aparece em um bloco começando e terminando com Y(colchetes).

Exemplos

Isto mostra como a linha de saída da entrada abcdaeb, abcdaebé impresso. A quarta linha é uma boa representação, pois a maioria dos casos possíveis acontece:

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

E outro exemplo baseado em um caso de teste, o @Optimizer me deu. (que destruiu minha solução 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

Versão antiga: 58 57 52 bytes

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

Experimente on-line: Compilador / Executor Pyth

Isso cria uma máscara, que modificarei antes e depois da impressão de cada linha. Para mais informações, consulte o histórico de edições.

Jakube
fonte
8

CJam, 82 bytes

Atualmente, há muito tempo e acho que posso economizar mais alguns bytes.

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

Algoritmo

O algoritmo básico é o seguinte:

  • leel:F]z::+ : Agrupe o código, a formatação e o índice de cada caractere
  • F$_&\f{{W=1$=},\;}: Agrupe os trigêmeos acima na prioridade de impressão usando a sequência de formatação. Esse código também garante que as prioridades sejam classificadas.
  • ]_{0f=_W=),\0=>Lf&Ra#)},: Para cada grupo prioritário de trigêmeos, obtenha o intervalo do índice delimitador e veja se algum índice ainda não foi impresso. Se houver um índice não impresso, inclua esse grupo de prioridade no grupo "a ser impresso nesta etapa".
  • F,S*\:+{~;1$L+:L;t}%oNo~}%: Depois de obter todos os grupos a serem impressos nesta etapa, preencha o código no índice correto de uma sequência de espaço vazia e imprima essa sequência. Atualize também a matriz que contém a lista de índices impressos.

Código de explicação a ser seguida quando eu terminar de jogar isso.

Exemplo

Aqui está o código executado no próprio código:

Entrada:

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

Saída:

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~}%];

Experimente online aqui

Optimizer
fonte
oNopode ser substituído por nno TIO .
Esolanging Fruit
8

CJam, 48 bytes

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

Explicação

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
fonte
6

IDL 8.4, 316 318 304 bytes

Nova versão, ainda muito longa, mas mais curta! E, no verdadeiro espírito do IDL, completamente vetorizado, o que significa (já que não há loop for) que agora eu posso fazê-lo como uma linha e executá-lo sozinho, depois que minha versão for atualizada completamente para 8.4. Isso será editado mais tarde.

Versão de uma linha:

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

Com quebras de linha (o mesmo número de bytes, subbing \ n vs &) e comentou:

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

Aqui está um detalhamento algorítmico da linha 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)

... e 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

As linhas 9 e 10 realizam o trabalho real, o restante configura as variáveis ​​necessárias para o final. Eu acho que isso é o mais golfe possível, não consigo encontrar outro lugar para fazê-lo melhor.

Versão antiga (tudo abaixo aqui está desatualizado):

Isso está longe de ser curto o suficiente para ganhar, porque essa é uma linguagem terrível para o golfe, mas ninguém nunca responde no IDL, então eu vou tentar.

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

Não tenho certeza se há alguma maneira de reduzi-lo mais ... Eu poderia chamar strmid em aeb ao mesmo tempo, mas passo mais bytes indexando d e funciona da mesma maneira. Vou continuar trabalhando nisso! (E amanhã vou editar uma explicação do algoritmo.)

sirpercival
fonte