Desminificar uma string de tipo piton


13

Pyth é talvez a linguagem de golfe de uso geral mais bem-sucedida. Embora esteja em declínio como resultado de idiomas mais recentes, de 2014 a 2016, a sintaxe concisa do Pyth, atualizações constantes, sobrecarga e (para a época) muitos componentes internos o tornaram o favorito para a maioria das perguntas.

O código Pyth geralmente é difícil de ler. Até a saída do modo de depuração (Python transpilado) geralmente consiste em uma linha longa, às vezes com parênteses aninhados com dez profundidade. No entanto, Pyth corretamente formatado é muito legível.

Aqui está um pedaço do código Pyth, escrito por @isaacg em Play the Word Chain .

.MlZfqhMtTeMPT+Lzs.pMyQ

É muito mais legível assim.

.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 esse desafio, eliminamos o aspecto da kolmogorov da categorização de caracteres Pyth e focamos na formatação. Em vez de ser um código Pyth, a entrada será composta por caracteres 0123456789M. O dígito nrepresenta uma função da aridade ne Mrepresenta um operador. Por exemplo, o código acima é representado como 210221M101M102M011M10. Aqui estão as etapas para desinstalar:

Separe a sequência em tokens.

Um token corresponde [0-9]M*. 0Mnão ocorrerá na entrada.

Adicione 0s à direita.

Quando não há argumentos suficientes, Pyth anexa ao código tantas variáveis ​​implícitas (variáveis ​​lambda ou Qs) necessárias para preencher os argumentos do programa; estes devem ser representados por 0s.

Agrupe tokens em linhas.

A aridade de um token é o valor do seu dígito.

  • Um token arity-0 (ou seja, um 0) termina uma linha.

  • Para um token arity-1, o próximo token deve seguir a mesma linha, separado por um espaço.

  • Para um token de arity> = 2, seus argumentos seguem em linhas separadas, na ordem em que aparecem no código, cada um seguido por seus próprios subargumentos e assim por diante. Os argumentos para um token são recuados até o final desse token mais um espaço.

Entrada

Uma cadeia não vazia (ou matriz de caracteres, matriz de cadeias de comprimento 1, etc. conforme permitido pelos Métodos de E / S padrão) consistindo em 0123456789M, que não conterá a substring 0M.

Resultado

A sequência formatada de acordo com as regras acima.

Casos de teste

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


Posso considerar a entrada como uma matriz de dígitos / string? Exemplo 210221M101M102M011M10seria[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

@LuisfelipeDejesusMunoz Não, a menos que as regras de E / S padrão exijam permissão para você (o que eu acho que não.) A IMO mudaria levemente o desafio se os Ms pudessem ter um tipo de dados diferente dos números inteiros.
lirtosiast

@lirtosiast Então, um conjunto de caracteres / cadeias de caracteres únicos é bom, apenas não usando tipos de dados diferentes entre dígitos e M?
Kamil Drakari #

1
@LeakyNun A string vazia agora é um comportamento indefinido.
lirtosiast

Respostas:


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):'')

Experimente online!

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

Experimente online!

Tem que haver uma maneira melhor de lidar com o caso arity-1, que atualmente ocupa 45 bytes.

Editar% s:

  • -2 bytes alternando para um método diferente de manipulação 1, embora o método anterior tenha provavelmente mais potencial de otimização.
  • -3 bytes não convertendo os dígitos dos caracteres em números e usando em predvez 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

Experimente online!


1

Carvão , 75 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

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

Passe os caracteres de entrada e os transforme em uma lista de dígitos com Msufixos opcionais .

≔⮌υυ

Inverta esta lista para que possamos Popconsumi-la.

≔⟦⟧θ

Essa variável é uma pilha de tokens cuja aridade ainda não foi cumprida.

≔⟦⟧η

Essa variável é uma pilha da aridade restante dos tokens não preenchidos.

W∨υη«

Repita até consumirmos todos os tokens e esvaziarmos a pilha.

     ≔⎇υ⊟υ0ι

Obtenha o próximo token ou 0se não houver.

     ι¿⊖Σι↘→

Imprima o token e, em seguida, mova o cursor horizontalmente se ele começar na 1diagonal.

     ⊞θι⊞ηΣι

Adicione o token e sua aridade às variáveis ​​apropriadas.

     W∧η¬§η±¹«

Repita enquanto a pilha de arity não estiver vazia, mas a arity superior for zero.

              ⊟η

Descarte a aridade zero.

              M⊕L⊟θ←

Remova o token e mova o número de caracteres restantes.

              ¿η⊞η⊖⊟η

Se houver alguma aridade restante, diminua a aridade superior.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.