Unminify a Pythlike String

13

Pyth mungkin bahasa tujuan serba guna yang paling sukses. Meskipun agak menurun karena bahasa yang lebih baru, dari 2014 hingga 2016 sintaksis Pyth yang ringkas, pembaruan terus-menerus, kelebihan beban, dan (untuk zamannya) banyak bawaan membuatnya menjadi favorit bagi sebagian besar pertanyaan.

Kode Pyth seringkali sulit dibaca. Bahkan output dari mode debug (transpiled Python) sering terdiri dari garis panjang, kadang-kadang dengan tanda kurung bersarang sepuluh dalam. Namun, Pyth yang diformat dengan benar sangat mudah dibaca.

Berikut adalah sepotong kode Pyth, yang ditulis oleh @isaacg di Play the Word Chain .

.MlZfqhMtTeMPT+Lzs.pMyQ

Jauh lebih mudah dibaca seperti ini.

.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

Untuk tantangan ini, kami menghilangkan aspek dari pengkategorian karakter Pyth dan fokus pada pemformatan. Alih-alih menjadi kode Pyth, input akan terdiri dari karakter dalam 0123456789M. Digit nmewakili fungsi arity n, dan Mmewakili operator. Misalnya, kode di atas direpresentasikan sebagai 210221M101M102M011M10. Berikut adalah langkah-langkah untuk menghapuskan:

Pisahkan string menjadi token.

Token cocok [0-9]M*. 0Mtidak akan terjadi pada input.

Tambahkan trailing 0s.

Ketika tidak ada cukup argumen, Pyth menambahkan sebanyak mungkin variabel implisit (variabel lambda atau Qs) ke kode sebagaimana diperlukan untuk mengisi argumen program; ini harus diwakili oleh 0s.

Grup token menjadi beberapa baris.

Arity dari token adalah nilai digitnya.

  • Token arity-0 (yaitu a 0) mengakhiri garis.

  • Untuk toity-1 token, token berikutnya harus berada pada baris yang sama, dipisahkan oleh spasi.

  • Untuk arity> = 2 token, argumennya pergi pada baris yang terpisah, dalam urutan mereka muncul dalam kode, masing-masing diikuti oleh sub-dokumen mereka sendiri dan seterusnya. Argumen untuk token dimasukkan ke akhir token itu ditambah satu spasi.

Memasukkan

String nonempty (atau array char, array string panjang-1, dll. Sebagaimana diizinkan oleh Metode I / O Standar) yang terdiri dari 0123456789M, yang tidak akan mengandung substring 0M.

Keluaran

String diformat sesuai dengan aturan di atas.

Uji kasus

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
sumber
Pertanyaan terkait: codegolf.stackexchange.com/questions/47798/…
lirtosiast
Bisakah saya mengambil input sebagai array angka / string? Contohnya 210221M101M102M011M10adalah[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 Tidak, kecuali aturan I / O standar mengharuskan Anda diizinkan (yang menurut saya tidak.) IMO itu akan sedikit mengubah tantangan jika Ms diizinkan untuk menggunakan tipe data yang berbeda dari bilangan bulat.
lirtosiast
@ lirtosiast Jadi array karakter / string karakter tunggal baik-baik saja, hanya saja tidak menggunakan tipe data yang berbeda antara digit dan M?
Kamil Drakari
1
@LeakyNun String kosong sekarang perilaku tidak terdefinisi.
lirtosiast

Jawaban:

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

Cobalah online!

Berkomentar

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
sumber
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

Cobalah online!

Harus ada cara yang lebih baik untuk menangani kasus arity-1, saat ini membutuhkan 45 byte.

Suntingan:

  • -2 byte dengan beralih ke metode penanganan 1 yang berbeda, meskipun metode sebelumnya mungkin memiliki potensi optimisasi yang lebih besar.
  • -3 byte dengan tidak mengubah digit karakter ke angka dan menggunakan predbukan 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

Cobalah online!

Laikoni
sumber
1

Arang , 75 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

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

Ulangi karakter input dan ubah menjadi daftar digit dengan Msufiks opsional .

≔⮌υυ

Balikkan daftar ini sehingga kami dapat menggunakannya Pop untuk mengkonsumsinya.

≔⟦⟧θ

Variabel ini adalah tumpukan token yang aritynya belum terpenuhi.

≔⟦⟧η

Variabel ini adalah tumpukan arity yang tersisa dari token yang tidak terpenuhi.

W∨υη«

Ulangi sampai kami menghabiskan semua token dan mengosongkan tumpukan.

     ≔⎇υ⊟υ0ι

Dapatkan token berikutnya atau 0 jika tidak ada.

     ι¿⊖Σι↘→

Cetak token dan kemudian gerakkan kursor secara horizontal jika dimulai dengan 1 sebaliknya.

     ⊞θι⊞ηΣι

Tambahkan token dan aritynya ke variabel yang sesuai.

     W∧η¬§η±¹«

Ulangi sementara tumpukan arity adalah kosong tapi arity atas adalah nol.

              ⊟η

Buang nol arity.

              M⊕L⊟θ←

Hapus tokennya dan pindahkan banyak karakter yang tersisa.

              ¿η⊞η⊖⊟η

Jika ada arities yang tersisa maka kurangi arity atas.

Neil
sumber