Batalkan Penggabungan Daftar

14

pengantar

Sebagian besar dari Anda terbiasa dengan algoritma pengurutan gabungan untuk menyortir daftar angka. Sebagai bagian dari algoritma, seseorang menulis fungsi pembantu yang disebut mergeyang menggabungkan dua daftar yang diurutkan menjadi satu daftar yang diurutkan. Dalam pseudocode mirip-Python, fungsinya biasanya terlihat seperti ini:

function merge(A, B):
  C = []
  while A is not empty or B is not empty:
    if A is empty:
      C.append(B.pop())
    else if B is empty or A[0] ≤ B[0]:
      C.append(A.pop())
    else:
      C.append(B.pop())
  return C

Idenya adalah untuk terus muncul elemen yang lebih kecil dari pertama Adan Bsampai kedua daftar kosong, dan kumpulkan hasilnya C. Jika Adan Bkeduanya diurutkan, maka begitu pula C.

Sebaliknya, jika Cdaftar diurutkan, dan kami membaginya menjadi dua urutan Adan B, kemudian Adan Bjuga diurutkan dan merge(A, B) == C. Menariknya, ini tidak selalu berlaku jika Ctidak diurutkan, yang membawa kita ke tantangan ini.

Memasukkan

Input Anda adalah permutasi dari 2*nbilangan bulat non-negatif pertama [0, 1, 2, ..., 2*n-1]untuk beberapa n > 0, diberikan sebagai daftar C.

Keluaran

Output Anda akan menjadi nilai kebenaran jika ada dua daftar Adan Bpanjang nsedemikian rupa C == merge(A, B), dan nilai palsu sebaliknya. Karena input tidak mengandung duplikat, Anda tidak perlu khawatir tentang bagaimana ikatan rusak dalam mergefungsi.

Aturan dan Bonus

Anda dapat menulis fungsi atau program lengkap. Hitungan byte terendah menang, dan celah standar tidak diizinkan.

Perhatikan bahwa Anda tidak diharuskan menghitung daftar Adan Bdalam contoh "ya". Namun, jika Anda benar-benar menampilkan daftar, Anda menerima bonus -20% . Untuk mengklaim bonus ini, Anda harus menampilkan hanya satu pasang daftar, tidak semua kemungkinan. Untuk membuat bonus ini lebih mudah diklaim dalam bahasa yang diketik dengan sangat baik, diizinkan untuk mengeluarkan sepasang daftar kosong dalam contoh "tidak".

Brute forcing tidak dilarang, tetapi ada bonus -10% untuk menghitung semua dari empat kasus uji terakhir dalam total kurang dari 1 detik.

Uji Kasus

Hanya satu output yang mungkin diberikan dalam contoh "ya".

[1,0] -> False
[0,1] -> [0] [1]
[3,2,1,0] -> False
[0,3,2,1] -> False
[0,1,2,3] -> [0,1] [2,3]
[1,4,0,3,2,5] -> False
[4,2,0,5,1,3] -> [4,2,0] [5,1,3]
[3,4,1,2,5,0] -> [4,1,2] [3,5,0]
[6,2,9,3,0,7,5,1,8,4] -> False
[5,7,2,9,6,8,3,4,1,0] -> False
[5,6,0,7,8,1,3,9,2,4] -> [6,0,8,1,3] [5,7,9,2,4]
[5,3,7,0,2,9,1,6,4,8] -> [5,3,7,0,2] [9,1,6,4,8]
[0,6,4,8,7,5,2,3,9,1] -> [8,7,5,2,3] [0,6,4,9,1]
[9,6,10,15,12,13,1,3,8,19,0,16,5,7,17,2,4,11,18,14] -> False
[14,8,12,0,5,4,16,9,17,7,11,1,2,10,18,19,13,15,6,3] -> False
[4,11,5,6,9,14,17,1,3,15,10,12,7,8,0,18,19,2,13,16] -> [4,17,1,3,15,10,12,7,8,0] [11,5,6,9,14,18,19,2,13,16]
[9,4,2,14,7,13,1,16,12,11,3,8,6,15,17,19,0,10,18,5] -> [9,4,2,16,12,11,3,8,6,15] [14,7,13,1,17,19,0,10,18,5]
Zgarb
sumber

Jawaban:

3

Pyth, 39 * 0,9 * 0,8 = 28,08

#aY->QxQeS-QsY&YsY)KfqylTlQmsdty_Y%tlKK

Program ini meng-clam semua bonus. Ini mencetak sepasang daftar, jika un-penggabungan dimungkinkan, atau daftar kosong, yang merupakan nilai palsu dalam Pyth (dan Python).

Input:  [5,3,7,0,2,9,1,6,4,8]
Output: ([9, 1, 6, 4, 8], [5, 3, 7, 0, 2])
Input:  [5,7,2,9,6,8,3,4,1,0]
Output: [] (falsy value)

Anda dapat mengujinya secara daring , tetapi mungkin sedikit lebih lambat daripada versi luring. Versi offline memecahkan setiap kasus uji dalam <0,15 detik pada laptop saya.

Mungkin (salah satu) pertama kalinya, solusi Pyth menggunakan Pengecualian aktif (menyimpan setidaknya 1 karakter). Ini menggunakan ide yang sama dengan solusi Peter Taylor.

                         preinitialisations: Q = input(), Y = []
#                 )     while 1: (infinite loop)
        eS-QsY             finds the biggest, not previous used, number
      xQ                   finds the index
    >Q                     all elements from ... to end
   -          &YsY         but remove all used elements
 aY                        append the resulting list to Y

When all numbers are used, finding the biggest number fails, 
throws an exception and the while loop ends.  
This converts [5,3,7,0,2,9,1,6,4,8] to [[9, 1, 6, 4, 8], [7, 0, 2], [5, 3]]

        msdty_Y  combine the lists each for every possible subset of Y (except the empty subset)
 fqylTlQ         and filter them for lists T with 2*len(T) == len(Q)
K                and store them in K

%tlKK        print K[::len(K)-1] (prints first and last if K, else empty list)

Pyth, 30 * 0.9 = 27.0

Saya belum benar-benar mencoba menyelesaikannya tanpa mencetak daftar yang dihasilkan. Tapi ini solusi cepat berdasarkan kode di atas.

#aY->QxQeS-QsY&YsY)fqylsTlQtyY

Saya pada dasarnya hanya menghapus pernyataan cetak. Outputnya cukup jelek.

Input:  [0,1,2,3]
Output: [[[3], [2]], [[3], [1]], [[2], [1]], [[3], [0]], [[2], [0]], [[1], [0]]] (truthy value)
Input:  [5,7,2,9,6,8,3,4,1,0]
Output: [] (falsy value)

Cobalah online .

Jakube
sumber
Anda mungkin menemukan bahwa alih-alih mencetak, (K[0], Q-K[0])Anda dapat mencetak (K[0], K[-1]). Saya tidak tahu apakah itu akan menghemat.
Peter Taylor
@PeterTaylor terima kasih, menyelamatkan 2 karakter.
Jakube
@PeterTaylor dan bahkan 2 karakter lagi, jika saya mencetak K[::len(K)-1].
Jakube
4

GolfScript (35 * 0,9 = 31,5)

{.$-1>/~,)\.}do;]1,\{{1$+}+%}/)2/&,

The demo online sangat lambat: di komputer saya, itu berjalan semua tes di bawah 0,04 detik, jadi saya mengklaim pengurangan 10%.

Penjelasan

Sufiks C yang dimulai dengan angka terbesar di C harus berasal dari daftar yang sama. Maka alasan ini dapat diterapkan ke (C - suffix), sehingga masalah berkurang menjadi subset jumlah.

Peter Taylor
sumber
2

APL, 62 50 44 * 90% = 39,6

{(l÷2)⌷↑(⊢∨⌽)/(2-/(1,⍨⍵≥⌈\⍵)/⍳l+1),⊂l=⍳l←⍴⍵}

Coba di sini.

jimmy23013
sumber