Unminify una stringa Pythlike


13

Pyth è forse il linguaggio di golf per tutti gli usi di maggior successo. Sebbene sia in qualche modo in declino a causa di linguaggi più recenti, dal 2014 al 2016 la sintassi concisa di Pyth, gli aggiornamenti costanti, il sovraccarico e (per la sua era) molti builtin lo hanno reso uno dei preferiti per la maggior parte delle domande.

Il codice Pyth è spesso difficile da leggere. Anche l'output della modalità debug (Python traspilato) è spesso costituito da una linea lunga, a volte con parentesi nidificate a dieci profondità. Tuttavia, Pyth correttamente formattato è molto leggibile.

Ecco un pezzo di codice Pyth, scritto da @isaacg in Play the Word Chain .

.MlZfqhMtTeMPT+Lzs.pMyQ

È molto più leggibile in questo modo.

.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

Per questa sfida, eliminiamo l' aspetto della della categorizzazione dei caratteri Pyth e ci concentriamo sulla formattazione. Invece di essere codice Pyth, l'input sarà composto da caratteri in 0123456789M. La cifran rappresenta una funzione di arity ne Mrappresenta un operatore. Ad esempio, il codice sopra è rappresentato come 210221M101M102M011M10. Ecco i passaggi per annullare la minificazione:

Separare la stringa in token.

Un token corrisponde [0-9]M* . 0Mnon si verificherà in input.

Aggiungi 0 finali.

Quando non ci sono abbastanza argomenti, Pyth aggiunge Qal codice tutte le variabili implicite (variabili o s lambda ) necessarie per riempire gli argomenti del programma; questi dovrebbero essere rappresentati da0 s.

Raggruppa i token in linee.

L'arità di un token è il valore della sua cifra.

  • Un token arity-0 (ovvero uno 0) termina una linea.

  • Per un token arity-1 il token successivo dovrebbe andare sulla stessa linea, separato da uno spazio.

  • Per un token arity> = 2, i suoi argomenti vanno su righe separate, nell'ordine in cui compaiono nel codice, ciascuno seguito dai propri argomenti secondari e così via. Gli argomenti di un token sono rientrati alla fine di quel token più uno spazio.

Ingresso

Una stringa non vuota (o array di caratteri, array di stringhe di lunghezza 1, ecc. Come consentito dai metodi I / O standard) costituito da 0123456789M, che non conterrà la sottostringa 0M.

Produzione

La stringa formattata secondo le regole precedenti.

Casi test

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 prendere l'input come una matrice di cifre / stringa? L'esempio 210221M101M102M011M10sarebbe[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 No, a meno che le regole I / O standard richiedano che ti sia permesso (cosa che non credo lo facciano). IMO cambierebbe leggermente la sfida se gli Ms potessero essere un tipo di dati diverso dagli interi.
lirtosiast

@lirtosiast Quindi una serie di caratteri / stringhe di singoli caratteri va bene, semplicemente non usando tipi di dati diversi tra cifre e M?
Kamil Drakari,

1
@LeakyNun La stringa vuota ora è un comportamento indefinito.
lirtosiast

Risposte:


1

JavaScript (ES8), 160 159 byte

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

Provalo online!

Commentate

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 byte

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

Provalo online!

Deve esserci un modo migliore per gestire il caso arity-1, attualmente occupa 45 byte.

modifiche:

  • -2 byte passando a un diverso metodo di gestione 1, sebbene il metodo precedente abbia probabilmente un maggiore potenziale di ottimizzazione.
  • -3 byte non convertendo le cifre dei caratteri in numeri e usando predinvece di 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

Provalo online!


1

Carbone , 75 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

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

Scorri i caratteri di input e trasformali in un elenco di cifre con Msuffissi opzionali .

≔⮌υυ

Invertire questo elenco in modo che possiamo usarlo Popper consumarlo.

≔⟦⟧θ

Questa variabile è una pila di token la cui arità non è stata ancora adempiuta.

≔⟦⟧η

Questa variabile è una pila dell'arità rimanente dei token non completati.

W∨υη«

Ripeti fino a quando non abbiamo consumato tutti i token e svuotato la pila.

     ≔⎇υ⊟υ0ι

Ottieni il prossimo token o 0se nessuno.

     ι¿⊖Σι↘→

Stampa il token e quindi sposta il cursore in orizzontale se inizia con 1altrimenti in diagonale.

     ⊞θι⊞ηΣι

Aggiungi il token e la sua arità alle variabili appropriate.

     W∧η¬§η±¹«

Ripeti mentre lo stack arity non è vuoto ma l'arity superiore è zero.

              ⊟η

Scarta l'arità zero.

              M⊕L⊟θ←

Rimuovi il suo token e sposta tutti i personaggi rimasti.

              ¿η⊞η⊖⊟η

Se ci sono delle arità rimaste, decrementa l'arità superiore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.