Diurutkan Partisi Leksikal dari Nomor

17

Tantangannya sangat sederhana: mengingat angka, Anda membagi angka-angkanya menjadi array angka yang lebih kecil sehingga angka yang dihasilkan tidak menurun. Tangkapannya adalah Anda harus membaginya sehingga panjang array maksimal.

Bingung?

  • Anda diberi bilangan bulat positif melalui STDIN (atau alternatif terdekat), argumen baris perintah atau argumen fungsi dalam format input apa pun yang nyaman dan tidak ambigu.
  • Anda harus mempartisi angka desimal angka menjadi kelompok-kelompok yang berdekatan dan terpisah.
  • Susunan angka yang diwakili oleh grup digit ini harus diurutkan (dalam urutan biasa, tidak menurun) tanpa menata ulang grup .
  • Dalam kasus di mana terdapat lebih dari satu partisi seperti itu, Anda harus mempartisi input menjadi angka sebanyak mungkin. Dalam kasus ikatan, kembalikan satu hasil seperti itu.
  • Anda bisa menampilkan array ke STDOUT (atau alternatif terdekat) atau sebagai nilai pengembalian fungsi. Dalam hal STDOUT (atau alternatif terdekat), array harus dicetak dalam format daftar yang nyaman dan tidak ambigu.
  • Nomor yang dipisah tidak boleh memiliki angka nol di depan. Jadi misalnya 1002003tidak dapat dicetak sebagai salah satu [1, 002, 003]atau [1, 2, 3]satu-satunya jawaban yang valid untuk itu [100, 2003].

Kasus uji:

123456 -> [1, 2, 3, 4, 5, 6]
345823 -> [3, 4, 5, 8, 23]
12345678901234567890 -> [1, 2, 3, 4, 5, 6, 7, 8, 90, 123, 456, 7890]
102 -> [102]
302 -> [302]
324142 -> [3, 24, 142] OR [32, 41, 42]
324142434445 -> [32, 41, 42, 43, 44, 45]
1356531 -> [1, 3, 5, 6, 531]
11121111111 -> [1, 1, 1, 2, 11, 11, 111]
100202003 -> [100, 202003]

Mencetak gol

Ini adalah kode-golf sehingga kode terpendek dalam byte menang.

Pengoptimal
sumber

Jawaban:

10

Pyth, 34

FNyUz#aYmv:zhdedC,+0N+NlzB)efqSTTY

Cobalah online di sini . Perhatikan, ini memiliki kompleksitas waktu (dan ruang) O (n). Karenanya test case 12345678901234567890terlalu lama dalam kompiler online. Gunakan yang offline sebagai gantinya (1 menit di laptop saya).

Ini hanya upaya pertama saya. Mungkin ada ruang untuk perbaikan.

Pertama, beberapa ide bagaimana algoritma saya bekerja.

  • Saya menafsirkan input sebagai string dan bukan sebagai angka.
  • Lalu saya membuat semua himpunan bagian yang mungkin dari [0, 1, 2, ..., len(n-1)]
  • Untuk masing-masing himpunan bagian ini (mari kita ambil [1, 4, 5]), saya membagi string input menjadi bagian menggunakan angka-angka ini. [input[0:1], input[1, 4], input[4,5], input[5,len(input)]].
  • Setelah itu saya mencoba mengubah angka-angka ini menjadi string. Mungkin ada dua masalah. Pyth (atau Python) melempar pengecualian untuk string kosong, dan untuk string angka yang dimulai dengan 0. Karena itu saya menggunakan try - catchblok (sebenarnya infinity loop dengan istirahat langsung). Jika konversi berhasil, saya menambahkan hasilnya ke daftar Y.
  • Setelah saya menangani semua himpunan bagian, saya memfilter daftar Yuntuk hasil, yang sudah diurutkan dan mencetak yang terakhir (yang terakhir memiliki kelompok terbanyak).

Sekarang penjelasan terperinci:

                            Implicit: z = input() (z is a String!)
                                      Y = empty list
FNyUz                       for each subset N of [0, 1, 2, ..., len(z)-1]:

     #                         start try-catch block (actually an infinite loop, 
                               but the Python implementation uses a try catch. 

      aY                          append to Y:
                C,+0N+Nlz            zip([0] + N, N + [len(z)])
        m                            map each element d to
          :zhded                     z[d[0]:d[-1]]
         v                           evaluated
                         B        if this didn't throw an exception already, end the infinite loop
                          ) end for loop   

 f    Y      filter Y for elements T, for which
  qSTT           sorted(T) == T
e            and print the last one (the subsets generated with yUz are sorted 
             by length, so the last one has the most groups)
Jakube
sumber
Anda dapat menggunakan aYsebagai gantinya~Y]
FryAmTheEggman
@FryAmTheEggman saya selalu lupa a. Tidak tahu kenapa
Jakube
@ Jakube Mungkin karena tidak ada dalam dokumen?
Sp3000
Saya punya solusi untuk ~ 45 karakter. Saya tidak menyadari fakta bahwa int("01")menjadi kesalahan dalam Pyth (ini tidak terjadi dengan Python).
orlp
3
@ Jakube haha, meskipun tampaknya logis, tetapi umumnya nadalah panjang input.
Pengoptimal
6

Mathematica, 134 127 byte

Ini cukup tidak efisien karena menghasilkan lebih banyak partisi daripada yang valid. Kasing 324142434445uji berjalan dalam beberapa detik, tetapi saya tidak akan mencoba 12345678901234567890.

f/@Last@Select[Needs@"Combinatorica`";f=FromDigits;SetPartitions[d=IntegerDigits@#],0<=##&@@f/@#&&Join@@#==d&&#~FreeQ~{0,__}&]&

Ini mendefinisikan fungsi tanpa nama yang mengambil integer dan mengembalikan daftar integer.

Penjelasan

Urutan pembacaan kode ini sedikit di semua tempat, jadi saya akan memecah dalam urutan yang dimaksudkan untuk dibaca (dan dievaluasi untuk sebagian besar):

  • d=IntegerDigits@#dapatkan digit desimal input dan tetapkan daftar ini d.
  • SetPartitions(yang mengharuskan Needs@"Combinatorica`";) memberi saya semua partisi ini. Namun, ia mengembalikan lebih banyak daripada yang sebenarnya saya inginkan karena memperlakukan input sebagai satu set . Inilah yang membuatnya tidak efisien, tapi saya menggunakan ini karena cara terpendek yang saya tahu untuk mendapatkan semua daftar partisi jauh lebih lama. Sebagai contoh, jika daftar itu {1, 2, 3}fungsinya akan kembali:

    {{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 2}, {3}}, {{1, 3}, {2}}, {{1}, {2}, {3}}}
    

    Perhatikan bahwa a) partisi berturut-turut semuanya dalam urutan yang benar dan b) partisi diurutkan dari kasar ke terbaik.

  • Select[...,...&] kemudian memfilter daftar ini dengan fungsi anonim yang diteruskan sebagai argumen kedua.
    • Join @@ # == d memeriksa apakah kita benar-benar mendapatkan daftar partisi daripada partisi set umum.
    • #~FreeQ~{0, __} memeriksa apakah tidak ada partisi yang dimulai dengan nol di depannya.
    • 0 <= ## & @@ f /@ #sedikit lebih tidak jelas. Pertama kita memetakan FromDigitske setiap daftar di partisi untuk memulihkan angka yang diwakili oleh digit. Kemudian kami berlaku 0 <= ##untuk angka-angka itu, di mana ##mengacu pada semua angka. Jika partisi {1, 23, 45}kemudian diperluas 0 <= 1 <= 23 <= 45, sehingga memeriksa bahwa array diurutkan.
  • Last@lalu memberi saya partisi terakhir yang tersisa setelah pemfilteran - ini berfungsi karena SetPartitionssudah mengurutkan partisi, sehingga yang terbaik ada di akhir.
  • Akhirnya, f/@memulihkan nomor dari daftar digit.
Martin Ender
sumber
5

Python 3, 134 byte

def f(s,n=0,L=[],R=[],i=0):
 while s[i:]:i+=1;m=int(s[:i]);R=max([f(s[i:],m,L+[m]),R][m<n or"1">s[i:]>"":],key=len)
 return[L,R][s>""]

Agak berantakan, tapi oh well. Program ini hanya menghasilkan semua partisi yang valid secara rekursif. Bagian yang menarik adalah bahwa untuk melarang angka nol di depan, semua yang diperlukan adalah or "1">s[i:]>""syarat tambahan .

Mengambil input suka f("12345678901234567890")dan mengembalikan daftar int.

Sp3000
sumber
4

Pyth, 62 61 60

JlzKkef&qJsml`dTqTSTolNmmibTcjKsC,z+m>Ndt>+*J]0jk2_JKNU^2-J1

Penjelasan

Algoritma ini bekerja dengan menghasilkan semua angka biner antara 0(inklusif) dan 2^(n-1)(eksklusif), di mana npanjang input.

Digit biner masing-masing kemudian dipetakan ke pemisah ( N) untuk 1 dan tidak ada untuk 0.

Karakter-karakter ini kemudian disisipkan di antara masing-masing karakter input, dan hasilnya dibagi N, menghasilkan daftar.

Nilai-nilai dalam daftar kemudian diuraikan menjadi bilangan bulat, dan daftar diurutkan berdasarkan panjangnya. Kemudian yang tersisa adalah menyaring yang tidak diurutkan dan yang telah dipisah pada nol terkemuka, setelah itu daftar terpanjang diambil.

Jlz                                                   set J to len(input)
Kk                                                    set K to ""
e                                                     take the last of:
 f&                                                    only take lists where:
   qJsml`dT                                             sum of string lengths of items
                                                        is equal to length of input and
           qTST                                         list is in order
               olN                                       sort by length
                  m                                       map k over...
                   mibT                                    convert items to int (base-10)
                       c                        N           split by N
                        jK                                   join by ""
                          s                                   sum to combine tuples
                           C,z                                 zip input with
                              +                K                append [""] for equal lengths
                               m>Nd                              replace 1 with N, 0 with ""
                                   t                              take all but first
                                    >        _J                    take len(input) last values
                                     +                              pad front of binary with
                                      *J]0                           [0] times input's length
                                          jk2                        current k in binary
                                                 U^2-J1  range 0..2^(len(input)-1)-1
PurkkaKoodari
sumber
1

(NON-COMPETING) Pyth, 25 byte

ef&&Fmnhd\0T.A<V=NsMTtN./

Cobalah online!

Bagaimana itu bekerja:

ef&&Fmnhd\0T.A<V=NsMTtN./  Q = eval(input())
                         ./  all partitions of Q
 f                       ./  filter all partitions of Q where:
  &                            both:
   &Fmnhd\0T                     neither substring starts with "0"
                               and:
            .A<V=NsMTtN          all entries are less than their proceeding ones
e                            returns the last amongst the filtered partitions
Biarawati Bocor
sumber
0

J, 109 byte

Sangat lama tetapi setidaknya memakan memori O (n * (2n)!) Dan O (n * log (n) * (2n)!) Waktu di mana n adalah panjang input. (Jadi jangan coba-coba menjalankannya dengan lebih dari 5 digit.)

f=.3 :0
>({~(i.>./)@:(((-:/:~)@(#$])*#)@>))<@".(' 0';' _1')rplc"1~(#~y-:"1' '-."#:~])(i.!2*#y)A.y,' '#~#y
)

Fungsi mengambil input sebagai string.

Contoh:

   f every '5423';'103';'1023'
  5 423
103   0
 10  23

Metode:

  • Tambahkan jumlah spasi yang sama ke input dengan panjangnya.
  • Izinkan dengan segala cara yang memungkinkan.
  • Periksa apakah string tanpa spasi sama dengan input (mis. Itu adalah partisi dari itu).
  • Ganti '0 ke' _1 untuk membatalkan solusi nol terkemuka.
  • Evaluasi setiap string.
  • Temukan daftar terpanjang yang juga diurutkan. Ini adalah nilai balik.
randomra
sumber
0

Haskell, 161 byte

(#)=map
f[x]=[[[x]]]
f(h:t)=([h]:)#f t++(\(a:b)->(h:a):b)#f t
g l=snd$maximum[(length x,x::[Int])|x<-[read#y|y<-f l,all((/='0').head)y],and$zipWith(>=)=<<tail$x]

Uji coba:

*Main> mapM_ (print . g) ["123456","345823","12345678901234567890","102","302","324142","324142434445","1356531","11121111111","100202003"]
[1,2,3,4,5,6]
[3,4,5,8,23]
[1,2,3,4,5,6,7,8,90,123,456,7890]
[102]
[302]
[32,41,42]
[32,41,42,43,44,45]
[1,3,5,6,531]
[1,1,1,2,11,11,111]
[100,202003]

Cara kerjanya: fungsi helper fmembagi daftar input menjadi setiap daftar yang mungkin dari daftar. gpertama-tama buang yang memiliki sublist yang diawali dengan 0dan kemudian yang tanpa urutan yang tepat. Pasangkan setiap daftar yang tersisa dengan panjangnya, ambil maksimum dan buang bagian panjang lagi.

nimi
sumber