Kode Sub selanjutnya meningkat terpanjang

11

Tantangannya adalah untuk menulis implementasi terpendek untuk menemukan peningkatan berikutnya terpanjang .

Contoh : Misalkan S adalah urutan 1 5 7 1 8 4 3 5 [panjang S = 8]

  • Kami memiliki 1 sub-urutan panjang 0 [akan menganggapnya meningkat]
  • 6 sub-urutan panjang 1 {1,5,7,8,4,3} [semuanya dianggap meningkat]
  • (7 * 8) / 2 sub-urutan panjang 2 [tetapi kami akan menghapus duplikat], peningkatan sub-seq berwarna hitam pekat.
    { 15,17 , 11, 18,14,13,57 , 51, 58 , 54,53,55,71, 78 , 74,73,75,84,83,85,43, 45,35 }

[perhatikan bahwa kami hanya tertarik pada peningkatan sub-urutan]

[Anda tidak dapat mengubah urutan elemen di dalam urutan, sehingga tidak ada sub-urutan [37] dalam contoh urutan]

  • Kami memiliki sub-urutan panjang 4 yang meningkat yaitu 1578, tetapi tidak ada sub-urutan panjang 5, jadi kami mempertimbangkan panjang sub-urutan terlama yang meningkat = 4.

Masukan :

a 1 a 2 ... a N (Urutan)

semua angka adalah bilangan bulat positif kurang dari 10 3
N <= 1000

Keluaran :

Satu bilangan bulat yang menunjukkan panjang sub-urutan terpanjang dari urutan input.

sample input(1)
1 2 4 2 5
sample output(1)
4

sample input(2)
1 5 7 1 8 4 3 5
sample output(2)
4

Kode Anda harus berjalan tepat waktu, silakan uji kode Anda pada kasus ini sebelum mengirimkannya di sini (juga tautannya berisi solusi c ++ 11 290 byte saya)

Anda dapat mengambil input dari file / stdin atau sebagai parameter fungsi dan Anda dapat mencetak output ke file / stdout atau hanya mengembalikan nilai jika Anda menulis fungsi

Papan Skor

  1. Dennis CJam - 22
  2. isaacg Pyth - 26
  3. Howard GolfScript - 35
  4. bangga haskeller Haskell - 56
  5. Ray Python 3 - 66
  6. Ruby histokrat - 67
  7. DLeh C # - 92
  8. YosemiteMark Clojure - 94
  9. faubiguy Python 3 - 113
Mostafa 36a2
sumber
1
"Kami memiliki 1 sub-urutan panjang 0 [akan menganggapnya meningkat]", Yah, secara teknis Anda memiliki jumlah tak terbatas dari sub-urutan 0-panjang :)
Cruncher
Sebenarnya, saya harus mengubah pernyataan sehingga semua "Set" harus menghapus duplikat, misalnya {1,5,7,1,8,4,3,5} harus menjadi {1,5,7,8,4 , 3} dan kemudian kita dapat mengatakan bahwa ada 1 0 panjang selanjutnya dalam "Set". terima kasih
Mostafa 36a2
1
Untuk fungsi, haruskah kita menghitung byte dari fungsi luar ( function f(){...}) atau fungsi dalam (adil ...)? Jika kita menghitung fungsi luar, apakah fungsi anonim diizinkan?
Dennis
Kami menghitung fungsi luar, dan fungsi anonim diperbolehkan, Tapi jangan lewatkan untuk memberikan versi yang dapat diuji (versi lengkap dengan penanganan input / output)
Mostafa 36a2

Jawaban:

2

CJam, 22 byte

1e3,q~{_2$<$0=(t}/$0=z

Cobalah online.

Contoh

$ cjam subsequence.cjam <<< '[2 1]'; echo
1
$ cjam subsequence.cjam <<< '[1 9 2 4 3 5]'; echo
4

Program mencetak 57untuk test case ini setelah 0,25 detik.

Bagaimana itu bekerja

Saya mengambil ide umum dari jawaban @ Ray .

1e3,    " Push the array [ 0 ... 999 ] (J).        ";
q~      " Read from STDIN and evaluate.            ";
{       " For each integer (I) of the input array: ";
  _2$<  " Push [ J[0] ... J[I - 1] ] (A).          ";
  $0=(  " Compute min(A) - 1.                      ";
  t     " Update J[I] with the value on the stack. ";
}/      "                                          ";
$0=     " Compute abs(min(J)).                     ";
Dennis
sumber
5

Python 3, 66

Perhatikan bahwa semua angka berada dalam kisaran [1, 999], kita dapat menggunakan array buntuk mempertahankan panjang urutan terpanjang yang berakhir dengan setiap angka. b[x] = dberarti bahwa urutan terpanjang berakhir dengan xmemiliki panjang d. Untuk setiap angka dari input, kami memperbarui array menggunakan b[x] = max(b[:x]) + 1dan kemudian kami menyelesaikan pekerjaan dengan mengambil max(b)akhirnya.

Kompleksitas waktu adalah Di) O (mn) , di mana mselalu 1000 dan nmerupakan jumlah elemen input.

def f(a):
 b=[0]*1000
 for x in a:b[x]=max(b[:x])+1
 return max(b)

Wow, sepertinya ungolfed sudah :) Anda bisa mengujinya menggunakan stdin / stdout dengan menambahkan baris:

print(f(map(int,input().split())))
sinar
sumber
for x in a: max(b)terlihat cukup banyak O (n ^ 2).
Howard
@Howard Ini O(1000 n)dan 1000 adalah konstan. Anda juga bisa menganggapnya sebagai O(m n).
Ray
3
Dengan argumen seperti itu seluruh diskusi tidak berguna karena pada input terbatas kompleksitas selalu O(1);-)
Howard
@Howard Saya berasal dari dunia ACM-ICPC dan ini agak sebuah konvensi di sana. Anda dapat menganggapnya sebagai O (mn). Itu masih berbeda dari O (n ^ 2). Bagaimanapun, waktu yang dibutuhkan akan lebih sedikit dari waktu awal juru bahasa, jadi saya pikir itu cukup cepat.
Ray
Algoritma singkatnya mengesankan! Saya hanya dapat melihat satu karakter (setidaknya ketika beralih ke Python 2): Anda dapat mencetak hasilnya. printlebih pendek dari return.
Falko
3

Python - 113

a=[]
for i in map(int,input().split()):
 if not a or i>a[-1]:a+=[i]
 z=0
 while a[z]<i:z+=1
 a[z]=i
print(len(a))
faubi
sumber
Solusi yang diterima. Kode Anda telah diuji di sini dan di sini .
Mostafa 36a2
@ Mostafa36a2 Kata "diterima" memiliki arti lain di situs ini. Saya pikir apa yang Anda maksud adalah "dapat diterima".
Ray
Maaf, ya saya maksud diterima, terlalu dini untuk memilih yang Diterima.
Mostafa 36a2
Dengan garis a+=[i]*(a==[]or i>a[-1]);z=0dan pencetakan len(a)(tanpa tanda kurung) Anda dapat menyimpan 4 karakter.
Falko
3

Pyth , 26 29 33 39

J*]0^T3Fkyw=@JkheS:J0k)eSJ

Solusi Port of @ ray. Lulus tes resmi. Sekarang menggunakan input STDIN yang dipisahkan oleh ruang, bukan panggilan fungsi.

Jalankan sebagai berikut:

./pyth.py -c "J*]0^T3Fkyw=@JkheS:J0k)eSJ" <<< "1 5 7 2 8 4 3 5"
4

Penjelasan:

J*]0^T3                 J = [0]*10^3
Fkyw                    For k in space_sep(input()):
=@Jk                    J[k]=
heS:J0k                 max(J[0:k])+1
)                       end for
eSJ                     max(J)

Waktu tak terbatas:

Pyth , 18

L?eS,ytbhyf>Thbbb0

Catatan teknis: Saya melihat ada bug di kompiler Pyth saya saat menulis golf ini. Ltidak bekerja Itu sebabnya ada komit terbaru ke repositori git di atas.

isaacg
sumber
kode Anda tidak berjalan pada waktu yang tepat untuk kasus dengan daftar besar (katakanlah 100 elemen)
Mostafa 36a2
3
@ Mostafa36a2 Jika Anda ingin menjadikan runtime suatu persyaratan, katakan demikian dalam pertanyaan, dan tambahkan satu atau dua test case. Jika itu hanya komentar, maka saya setuju, itu sangat lambat.
isaacg
Maaf, tetapi saya telah menyebutkan bahwa itu bukan runtime tetapi setidaknya [secara tepat waktu], tidak masalah jika kodenya memakan waktu 10-20 menit atau bahkan satu jam, tetapi solusi O (2 ^ n) tidak akan pernah memberikan hasil selama umur panjang kita.
Mostafa 36a2
@ Mostafa36a2 Mengerti, saya baru saja memperhatikan garis itu. Saya akan bekerja pada perbaikan.
isaacg
1
Maaf saya melihat pembaruan sekarang, silakan coba kasing ini dan beri tahu saya jika ini berhasil.
Mostafa 36a2
3

Clojure, 94 karakter

Menggunakan pendekatan @ Ray untuk memperbarui hasil dalam vektor 1000-item:

(defn g[s](apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s)))

Per permintaan, dengan pernyataan cetak (akan mencetak jawaban dan mengembalikan nol). Input harus berupa vektor (g [1 2 3]) atau daftar (g '(1 2 3)):

(defn g[s](prn(apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s))))
YosemiteMark
sumber
dapatkah Anda menambahkan pernyataan cetak untuk membuatnya dapat diuji? Itu tidak akan dihitung dalam skor.
Mostafa 36a2
1
Diperbarui. Saya sudah menjalankannya pada kedua contoh besar Anda, dan mendapat 58 dan 57 seperti yang diharapkan.
YosemiteMark
Saya pikir Anda masih perlu memanggil fungsi: p, tetapi jika Anda sudah mengujinya maka itu sudah cukup.
Mostafa 36a2
3

Haskell, 58 57 56 karakter

(x:s)%v|v>x=x:s%v|0<1=v:s
_%v=[v]
l s=length$foldl(%)[]s

Ini menggunakan algoritma yang pernah saya lihat di internet, tetapi saya tidak dapat menemukannya. Dibutuhkan waktu yang tidak terlalu lama untuk test case yang diberikan di komputer saya dengan GHCi (mungkin akan lebih cepat jika dikompilasi).

haskeller bangga
sumber
Algoritma yang Anda sebutkan adalah sama dengan yang digunakan oleh @faubiguy.
Ray
@Ray kau benar
bangga haskeller
2

GolfScript, 35 karakter

~]]){1${~2$<*)}%1+$-1>[\+]+}/$-1=0=

Implementasi bekerja sebagai program lengkap dengan input pada STDIN (tanpa nomor panjang yang diberikan). Implementasinya cepat, bahkan untuk input yang lebih lama (coba di sini ).

Contoh:

> 1 5 7 1 8 4 3 5
4

> 5 1 9 9 1 5
2
Howard
sumber
1
@ MartinBüttner Diperlukan sekitar 5 detik untuk 1000 angka di komputer saya. Dengan asumsi $O (n log n) algoritma adalah O (n ^ 2 log n).
Howard
silakan coba masukan dalam tautan ini
Mostafa 36a2
@ Mostafa36a2 sudah saya lakukan (lihat komentar sebelumnya). Setelah 5 detik ia mengembalikan 58.
Howard
ini adalah satu lagi, itu harus mengembalikan 57, jadi jika kode Anda mengembalikan 57 maka itu Diterima :) Selamat
Mostafa 36a2
@ Mostafa36a2 Ah, sekarang saya melihat itu adalah dua test case yang berbeda. Ya, tautan kedua Anda mengembalikan 57 seperti halnya solusi saya pada input ini.
Howard
2

Ruby, 67

s=Hash.new{|s,a|f,*r=a
s[a]=f ?[1+s[r.select{|x|x>f}],s[r]].max: 0}

Ini berjalan dalam 30 detik pada input besar, apakah itu dianggap tepat waktu? : p

Ini adalah rekursi yang brutal, tetapi dengan beberapa memoisasi.

histokrat
sumber
1
Ya, ini tepat waktu :)
Mostafa 36a2
2

C #, 172 92 karakter

Tidak ada yang istimewa, tapi saya melakukannya jadi saya pikir saya mungkin juga menyerahkannya.

int a(int[] j){int c=2,m=2,i=1;for(;++i<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?c:m;}return m;}

Terima kasih Armin dan Bob atas peningkatan mereka!

DLeh
sumber
1
Anda dapat mengubah parameter Anda ke int [] dan kemudian Anda akan memiliki lebih sedikit karakter karena Anda tidak perlu membuang string ke int
Armin
2
Ruang-ruang di sekitar =>tidak perlu. Anda juga dapat memindahkan i=0deklarasi di luar forloop, ke int c=2,m=2,i=0;for(;. Anda juga dapat menjatuhkan kawat gigi di sekitar fortubuh, karena Anda hanya memiliki satu pernyataan di sana.
Bob
Dan c++;if(c>m)m=c;bisa m=c++>m?m:c;, dan Anda bisa kembali memasang kawat gigi di sekitarnya.
Bob
1
Bahkan, Anda juga dapat membuang if(i>0)centang dengan membuat forloop mulai dari 1. Anda dapat lebih pendek mempersingkat yang int c=2,m=2,i=0;for(;i<j.Length;i++)if(i>0)disarankan sebelumnya int c=2,m=2,i=0;for(;i++<j.Length;). Seluruh bagian itu dapat dikonversi menjadi int c=2,m=2,i=0;for(;i++<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?m:c;}(menggunakan terner lain untuk menggantikan yang tersisa if- aturan praktis adalah terner lebih pendek jika iftubuh Anda hanya tugas.
Bob
2
Maaf - salah ketik di komentar saya sebelumnya, m=c>m?m:cseharusnya m=c>m?c:m. Dan jika Anda menambahkan saran @ Armin, Anda mendapatkan 92 byte, hampir setengah ukurannya! int a(int[] j){int c=2,m=2,i=0;for(;i++<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?c:m;}return m;}
Bob
2

J , 19 byte

[:#]`I.`[} ::,~/@|.

Cobalah online!

Berjalan di O (n log n) , menggunakan jenis kesabaran yang dimodifikasi karena hanya panjang, bukan urutan aktual, yang diperlukan.

Penjelasan

[:#]`I.`[} ::,~/@|.  Input: array
                 |.  Reverse
               /     Reduce right-to-left
     I.                Find the index to insert while keeping it sorted
                       (uses binary search)
         }             Amend the current search array at that index with the next value
           ::          If error (when the index is not found)
             ,           Append the value at the end
 #                   Length of that array
mil
sumber
1

Bash + coreutils, 131 byte

Solusi ini gagal mengerikan pada persyaratan yang tepat waktu , dan bahkan tidak terlalu pendek, tapi saya suka bahwa hal semacam ini setidaknya secara teoritis mungkin dalam skrip shell, jadi saya tetap memposting. Ini berjalan dengan kompleksitas waktu yang menginduksi keabadian O (2 ^ n).

s=${1//,/,:\},\{}
a=`eval echo "{$s,:}"`
for s in $a;{
b="$(tr , \\n<<<$s|grep -v :)"
sort -nC<<<"$b"&&wc -w<<<$b
}|sort -nr|sed 1q

Input adalah daftar yang dipisahkan koma, dilewatkan sebagai argumen baris perintah tunggal:

$ time ./slisc.sh 1,5,7,1,8,4,3,5
4

real    0m1.240s
user    0m0.518s
sys 0m0.689s
$ 

Perluasan Brace digunakan untuk membangun daftar semua kemungkinan berikutnya.

  • Baris pertama menggantikan koma dengan ,:},{, yang menghasilkan string seperti1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5
  • Baris kedua melengkapi string ini dengan kawat gigi, koma dan titik koma untuk memberikan ini {1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5,:}. Ini adalah ekspansi bash brace yang valid, yang ketika evaldiedarkan dengan echomenghasilkan daftar yang dipisahkan oleh spasi ini1,5,7,1,8,4,3,5 1,5,7,1,8,4,3,: 1,5,7,1,8,4,:,5 1,5,7,1,8,4,:,: ...
  • secara default, bash memisahkan string dengan spasi putih, jadi kami mengulangi setiap elemen dari daftar ini:
    • koma diganti dengan baris baru, kemudian baris yang mengandung titik dua dihapus, memberikan daftar yang dipisahkan baris baru untuk setiap kemungkinan berikutnya
    • kami kemudian sort -Cmenguji peningkatan pesanan, dan jika demikian, gunakan wc -wuntuk mencetak panjang daftar
  • daftar panjang daftar yang dihasilkan diurutkan secara terbalik dan nilai pertama dicetak untuk memberikan panjang berikutnya yang paling lama bertambah.
Trauma Digital
sumber
1

Stax , 21 byte

ë/NS7Γ╥╚┌{1╤╒¬è¶²╢╦┌☼

Jalankan dan debug itu

Ini memiliki dua kasus uji, salah satunya adalah kasus 1000 elemen. Itu berjalan satu dalam 24 detik di mesin saya. Ia menggunakan pendekatan pemrograman dinamis klasik untuk jenis masalah ini.

rekursif
sumber
0

J 34

Perhatikan bahwa saya membaca input standar juga.

>./;+/@:*&.>(<*>.)/\&.><\.".1!:1]3

Tanpa membaca input standar, dagingnya 26 karakter.

>./;+/@:*&.>(<*>.)/\&.><\.

Hanya perhatikan bahwa saya berjalan lambat untuk input besar, oh well.

protista
sumber
0

C ++ (gcc) , 129 byte

int f(int*a,int n){int l[n]{},i=n,j,m=0;for(;i--;m=l[i]>m?l[i]:m)for(j=n;--j>i;)if(a[i]<a[j]&&l[i]<l[j]+1)l[i]=l[j]+1;return++m;}

Cobalah online!

Przemysław Czechowski
sumber
0

C # (.NET Core) , 155 byte

Menggunakan array untuk menghitung kenaikan terpanjang yang berakhir pada setiap posisi dalam input array (pemrograman dinamis), kemudian mengembalikan nilai terbesar. Misalnya, array yang dihitung untuk input [1,5,7,1,8,4,3,5]akan menjadi [1,2,3,1,4,2,2,3], dan nilai terbesar 4dikembalikan.

int b(int[]x){int l=x.Length,r=1,i=0,j,c;var a=new int[l];a[0]=1;while(++i<l)for(j=0;j<i;j++){c=x[j]<x[i]?a[j]+1:1;a[i]=a[i]<c?c:a[i];r=r<c?c:r;}return r;}

Cobalah online!

jrivor
sumber
0

Bahasa Wolfram (Mathematica) , 38 byte

Length@LongestOrderedSequence[#,Less]&

Cobalah online!

Tentu saja ada Mathematica built-in untuk menemukan urutan yang paling lama dipesan. Namanya sangat panjang: ini merupakan lebih dari setengah solusi, dan saya tidak akan terkejut jika ada orang yang bermain golf dengan solusi ini.

Roma
sumber