Minimiere einen Pyth-ähnlichen String

13

Pyth ist vielleicht die erfolgreichste Allzweck-Golfsprache. Obwohl es aufgrund neuer Sprachen etwas rückläufig ist, machte es von 2014 bis 2016 Pyths prägnante Syntax, ständige Aktualisierungen, Überladung und (für seine Ära) viele eingebaute Funktionen zu einem Favoriten für die meisten Fragen.

Pyth-Code ist oft schwer zu lesen. Sogar die Ausgabe des Debug-Modus (transpiliertes Python) besteht oft aus einer langen Zeile, manchmal mit zehn Klammern. Richtig formatiertes Pyth ist jedoch sehr gut lesbar.

Hier ist ein Teil des Pyth-Codes, der von @isaacg in Play the Word Chain geschrieben wurde .

.MlZfqhMtTeMPT+Lzs.pMyQ

So ist es viel besser lesbar.

.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

Für diese Herausforderung beseitigen wir den Aspekt der der Kategorisierung von Pyth-Zeichen und konzentrieren uns auf die Formatierung. Anstatt Pyth-Code zu sein, besteht die Eingabe aus Zeichen in 0123456789M. Die Ziffer nstellt eine Funktion der Arität dar nund Mrepräsentiert einen Operator. Beispielsweise wird der obige Code als dargestellt 210221M101M102M011M10. Hier sind die Schritte, um die Minimierung aufzuheben:

Teilen Sie die Zeichenfolge in Token.

Ein Token stimmt überein [0-9]M*. 0Mwird nicht in der Eingabe auftreten.

Fügen Sie nachfolgende Nullen hinzu.

Wenn nicht genügend Argumente vorhanden sind, hängt Pyth so viele implizite Variablen (Lambda-Variablen oder Qs) an den Code an, wie erforderlich sind, um die Argumente des Programms zu füllen. diese sollten durch 0s dargestellt werden.

Gruppieren Sie Token in Zeilen.

Die Arität eines Tokens ist der Wert seiner Ziffer.

  • Ein arity-0-Token (dh eine 0) beendet eine Zeile.

  • Für ein Arity-1-Token sollte sich das nächste Token in derselben Zeile befinden, die durch ein Leerzeichen getrennt ist.

  • Bei einem arity> = 2-Token werden die Argumente in verschiedenen Zeilen in der Reihenfolge aufgeführt, in der sie im Code erscheinen, gefolgt von jeweils eigenen Unterargumenten und so weiter. Argumente zu einem Token werden bis zum Ende des Tokens plus ein Leerzeichen eingerückt.

Eingang

Eine nicht leere Zeichenfolge (oder ein Zeichenfeld, ein Feld mit Zeichenfolgen der Länge 1 usw., wie es nach den Standard-E / A-Methoden zulässig ist), bestehend aus einer Zeichenfolge, die die Teilzeichenfolge 0123456789Mnicht enthält 0M.

Ausgabe

Die Zeichenfolge wurde gemäß den obigen Regeln formatiert.

Testfälle

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
Lirtosiast
quelle
Kann ich die Eingabe als Array von Ziffern / Zeichenfolgen annehmen? Beispiel 210221M101M102M011M10wäre[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 Nein, es sei denn, nach den Standard-E / A-Regeln ist dies zulässig (was meiner Meinung nach nicht der Fall ist). IMO würde die Herausforderung geringfügig ändern, wenn die Ms einen anderen Datentyp als die ganzen Zahlen haben dürfen.
Lirtosiast
@lirtosiast Also ein Array von Zeichen / Einzelzeichenketten ist in Ordnung, nur keine unterschiedlichen Datentypen zwischen Ziffern und M?
Kamil Drakari
1
@LeakyNun Leere Zeichenfolge ist jetzt undefiniertes Verhalten.
Lirtosiast

Antworten:

1

JavaScript (ES8), 160 bis 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):'')

Probieren Sie es online!

Kommentiert

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
  )                            //
Arnauld
quelle
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

Probieren Sie es online!

Es muss einen besseren Weg geben, um den Arity-1-Fall zu behandeln. Er benötigt derzeit 45 Bytes.

Bearbeitungen:

  • -2 Bytes durch Umschalten auf eine andere Methode zur Behandlung von 1, obwohl die vorherige Methode wahrscheinlich mehr Optimierungspotential hat.
  • -3 Bytes, indem Sie die Zeichen nicht in Zahlen konvertieren und predstattdessen verwenden 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

Probieren Sie es online!

Laikoni
quelle
1

Kohle , 75 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

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

Machen Sie eine Schleife über die eingegebenen Zeichen und wandeln Sie sie in eine Ziffernliste mit optionalen MSuffixen um.

≔⮌υυ

Kehren Sie diese Liste um, damit wir sie verwenden Popkönnen.

≔⟦⟧θ

Diese Variable ist ein Stapel von Token, deren Arität noch nicht erfüllt wurde.

≔⟦⟧η

Diese Variable ist ein Stapel der verbleibenden Menge der nicht erfüllten Token.

W∨υη«

Wiederholen, bis alle Token aufgebraucht und der Stapel geleert sind.

     ≔⎇υ⊟υ0ι

Holen Sie sich das nächste Token oder 0wenn keines.

     ι¿⊖Σι↘→

Drucken Sie den Token aus und bewegen Sie den Cursor dann horizontal, wenn er mit einer 1anderen Diagonale beginnt .

     ⊞θι⊞ηΣι

Fügen Sie den Token und seine Arität zu den entsprechenden Variablen hinzu.

     W∧η¬§η±¹«

Wiederholen, während der Arity-Stapel nicht leer ist, aber die oberste Arity Null ist.

              ⊟η

Verwerfen Sie die Nullstelle.

              M⊕L⊟θ←

Entferne seinen Marker und verschiebe so viele Zeichen wie möglich.

              ¿η⊞η⊖⊟η

Wenn noch Aritäten übrig sind, dekrementieren Sie die oberste Arität.

Neil
quelle