En Kısa En Uzun Artan Alt Sıra Kodu


11

Zorluk En uzun artan alt soruyu bulmak için en kısa uygulamayı yazmaktır .

Örnek : S dizisi 1 5 7 1 8 4 3 5 [S uzunluğu = 8] olsun

  • 0 uzunluğunda 1 alt dizimiz var [arttığını düşüneceğiz]
  • 1 uzunluk altı 6 alt dizi {1,5,7,8,4,3} [hepsinin arttığı düşünülmektedir]
  • (7 * 8) / 2 uzunluğunda 2 alt dizi [ancak kopyaları kaldıracağız], artan alt sıra güçlü siyah renktedir.
    { 15,17 , 11, 18,14,13,57 , 51, 58 , 54,53,55,71, 78 , 74,73,75,84,83,85,43, 45,35 }

[yalnızca kesinlikle artan alt sekanslarla ilgilendiğimizi unutmayın]

[ile sırasını değiştiremez dizisi içindeki elemanların, yani herhangi bir alt-dizisi [37], örneğin sırayla orada]

  • 1578 olan 4 uzunluğunda artan alt dizilerimiz var, ancak 5 uzunluğunda bir alt dizi yok, bu yüzden en uzun artan alt dizinin = 4 uzunluğunu düşünüyoruz.

Giriş :

a 1 a 2 ... a N (Dizi)

tüm sayılar 10 3
N <= 1000'den küçük pozitif tamsayılardır

Çıktı :

Giriş dizisinin en uzun artan alt dizisinin uzunluğunu gösteren bir tamsayı.

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

Kodunuzun zamanında çalışması gerekir, lütfen buraya göndermeden önce kodunuzu bu durumda test edin (ayrıca bağlantı benim 290 bayt c ++ 11 çözümümü içerir)

Girdiyi bir dosya / stdin'den veya bir işlev parametresi olarak alabilir ve çıktıyı bir dosya / stdout'a yazdırabilir veya bir işlev yazarsanız değeri döndürebilirsiniz

Skor Kurulu

  1. Dennis CJam - 22
  2. isaacg Pyth - 26
  3. Howard GolfScript - 35
  4. gururlu haskeller Haskell - 56
  5. Ray Python 3-66
  6. histokrat Yakut - 67
  7. DLeh C # - 92
  8. Yosemite Mark Clojure - 94
  9. faubiguy Python 3 - 113

1
"0 uzunluğunda 1 alt dizimiz var [arttığını düşünecek]", Teknik olarak sonsuz sayıda 0 uzunlukta alt
Cruncher

Aslında, tüm "Setler" in kopyaları kaldırması için ifadeyi değiştirmeliyim, örneğin {1,5,7,1,8,4,3,5} {1,5,7,8,4 , 3} ve sonra "Set" de 1 0 uzunluklu bir alt çizgi olduğunu söyleyebiliriz. teşekkürler
Mostafa 36a2

1
Fonksiyonlar için, dış fonksiyonun ( function f(){...}) veya iç fonksiyonun (sadece ...) baytlarını saymalıyız ? Dış işlevleri sayarsak, anonim işlevlere izin verilir mi?
Dennis

Dış işlevi sayıyoruz ve anonim işlevlere izin veriliyor, ancak test edilebilir bir sürüm (giriş / çıkış işleme ile tam sürüm) sağlamayı kaçırmayın
Mostafa 36a2

Yanıtlar:


2

CJam, 22 bayt

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

Çevrimiçi deneyin.

Misal

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

Program bu test durumu57 için 0,25 saniye sonra yazdırır .

Nasıl çalışır

Genel fikri @ Ray'nin cevabından aldım .

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)).                     ";

5

Python 3, 66

Tüm sayıların [1, 999] aralığında olduğuna dikkat edin, her bir sayıyla bbiten en uzun dizilim uzunluğunu korumak için bir dizi kullanabiliriz . b[x] = dile biten en uzun alt dizinin xuzunluğu olduğu anlamına gelir d. Girişteki her sayı için diziyi kullanarak güncelleriz ve sonunda b[x] = max(b[:x]) + 1işi bitirerek yaparız max(b).

Zaman karmaşıklığı O (n) O (mn) , burada mher zaman 1000 ve ngiriş elemanlarının sayısıdır.

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

Vay, zaten ungolfed gibi görünüyor :) Bir satır ekleyerek stdin / stdout kullanarak test edebilirsiniz:

print(f(map(int,input().split())))

for x in a: max(b)hemen hemen O (n ^ 2) görünüyor.
Howard

@ O(1000 n)1000 ve 1000 sabittir. Ayrıca olarak düşünebilirsiniz O(m n).
Ray

3
Böyle bir argümanla tüm tartışma işe yaramaz çünkü sınırlı girdide karmaşıklık her zaman O(1);-)
Howard

@ ACM-ICPC dünyasından geliyorum ve bu biraz bir kongre. O (mn) olarak düşünebilirsiniz. Hala O (n ^ 2) 'den farklı. Her neyse, maliyeti zaman tercüman başlangıç ​​zamanından daha az olacaktır, bu yüzden yeterince hızlı olduğunu düşünüyorum.
Ray

Etkileyici kısa algoritma! Yalnızca bir karakter belirleyebilirim (en azından Python 2'ye geçerken): Sonucu yazdırabilirsiniz. printdaha kısadır 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))

Kabul edilen çözüm. Kodunuz burada ve burada test edilmiştir .
Mostafa 36a2

@ Mostafa36a2 "Kabul edilen" kelimesinin bu sitede başka bir anlamı var. Demek istediğin "kabul edilebilir".
Ray

Üzgünüm, evet Kabul Edilebilir'i seçmek için çok erken, kabul edilebilir demek istedim.
Mostafa 36a2

Çizgi a+=[i]*(a==[]or i>a[-1]);z=0ve baskı len(a)(köşeli ayraç olmadan) ile 4 karakter kaydedebilirsiniz.
Falko

3

Pyth , 26 29 33 39

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

Port @ ray'ın çözümü. Resmi testleri geçer. Artık fonksiyon çağrısını değil, boşlukla ayrılmış STDIN girişini kullanıyor.

Aşağıdaki gibi çalıştırın:

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

Açıklama:

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)

Zaman sınırsız:

Pyth , 18

L?eS,ytbhyf>Thbbb0

Teknik not: Bu golfü yazarken Pyth karşılaştırıcımda bir hata fark ettim. Lçalışmadı. Bu yüzden yukarıdaki git deposuna yeni bir taahhüt var.


kodunuz büyük
listeli

3
@ Mostafa36a2 Çalışma zamanını bir gereksinim haline getirmek istiyorsanız, lütfen soruda belirtin ve bir veya iki test örneği ekleyin. Bu sadece bir yorumsa, o zaman katılıyorum, oldukça yavaş.
isaacg

Üzgünüz, ancak çalışma zamanı değil, en azından [zamanında bir şekilde], kod 10-20 dakika veya hatta bir saat sürerse sorun değil, ancak O (2 ^ n) çözümleri hiçbir zaman sonuç vermeyeceklerini belirttim uzun yaşamımız.
Mostafa 36a2

@ Mostafa36a2 Anladım, sadece bu çizgiyi fark ettim. İyileştirme üzerinde çalışacağım.
isaacg

1
Maalesef güncellemeyi şimdi görüyorum, lütfen bu davayı deneyin ve çalışıp çalışmadığını söyleyin.
Mostafa 36a2

3

Clojure, 94 karakter

@ Ray'ın 1000 öğe vektöründe sonuçları güncelleme yaklaşımını kullanarak:

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

İstek başına, print deyimi ile (cevap yazdırır ve sıfır döndürür). Giriş bir vektör (g [1 2 3]) veya bir liste (g '(1 2 3)) olmalıdır:

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

test ifadesini test edilebilir yapmak için ekleyebilir misiniz? Skorda sayılmaz.
Mostafa 36a2

1
Güncellenmiş. Hem büyük örnekleriniz üzerinde çalıştım, hem de beklendiği gibi 58 ve 57 aldım.
YosemiteMark

Sanırım yine de işlevi çağırmanız gerekiyor: p, ancak test ettiyseniz, bu yeterlidir.
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

Bu internette bir kez gördüğüm bir algoritma kullanıyor, ama bulamıyorum. GHCi ile bilgisayarımda verilen test durumunda göze çarpmayan bir zaman alır (muhtemelen derlenmişse daha da hızlı olurdu).


Bahsettiğiniz algoritma @faubiguy tarafından kullanılan algoritma ile aynıdır.
Ray

@Ray haklısın
gururlu haskeller

2

GolfScript, 35 karakter

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

STDIN üzerinde girdi (verilen uzunluk numarası olmadan) ile tam bir program olarak çalışan bir uygulama. Uygulama daha uzun girdiler için bile hızlıdır ( burayı deneyin ).

Örnekler:

> 1 5 7 1 8 4 3 5
4

> 5 1 9 9 1 5
2

1
@ MartinBüttner Bilgisayarımdaki 1000 numara için yaklaşık 5 saniye sürüyor. $O (n log n) olduğu varsayıldığında algoritma O (n ^ 2 log n) 'dir.
Howard

lütfen bu
linkteki

@ Mostafa36a2 Zaten yaptım (daha önce açıklamaya bakınız). 5 saniye sonra 58 döndürür.
Howard

Bu başka bir tane, 57 döndürmelidir, bu nedenle kodunuz 57 döndürdüyse Kabul Edilir :) Tebrikler
Mostafa 36a2

@ Mostafa36a2 Ah, şimdi bunların iki ayrı test örneği olduğunu görüyorum. Evet, ikinci bağlantınız bu girişteki çözümüm gibi 57 değerini döndürüyor.
Howard

2

Yakut, 67

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

Bu, büyük girişte 30 saniye içinde çalışır, zamanında sayılır mı? : p

Bu kaba özyineleme, ama bazı hatırlatma ile.


1
Evet, bu tam zamanında :)
Mostafa 36a2

2

C #, 172 92 karakter

Özel bir şey yok, ama ben de gönderebileceğimi düşündüm.

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;}

Armin ve Bob'a iyileştirmeleri için teşekkürler!


1
parametrenizi int [] olarak değiştirebilirsiniz ve daha sonra daha az karaktere sahip olursunuz çünkü int'e dizgi
Armin

2
Çevresindeki boşluklar =>gereksiz. i=0Bildirimi fordöngü dışında da taşıyabilirsiniz int c=2,m=2,i=0;for(;. Ayrıca, parantezleri forvücudun etrafına bırakabilirsiniz , çünkü orada sadece tek bir ifade var.
Bob

Ve c++;if(c>m)m=c;olabilir m=c++>m?m:c;ve parantezleri yine bunun etrafına bırakabilirsiniz.
Bob

1
Aslında, döngüyü 1'den başlatarak if(i>0)kontrolü de atabilirsiniz . Önerilen öğeyi daha önce forkısaltabilirsiniz . Bu bölümün tamamı dönüştürülebilir (kalan son yerine geçmek için başka bir üçlü kullanarak - vücudunuz basitçe bir ödev ise başparmak kuralı üçlüler daha kısadır .int c=2,m=2,i=0;for(;i<j.Length;i++)if(i>0)int c=2,m=2,i=0;for(;i++<j.Length;)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;}ifif
Bob

2
Üzgünüm - önceki yorumda yazım hatası m=c>m?m:colmalı m=c>m?c:m. Ve @ Armin'in önerisini eklerseniz, boyutu neredeyse yarıya indiren 92 bayt alırsınız! 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 bayt

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

Çevrimiçi deneyin!

Gerçek alt diziye değil, yalnızca uzunluğa ihtiyaç duyulduğundan, değiştirilmiş bir sabır sıralaması kullanarak O (n günlüğü n) içinde çalışır .

açıklama

[:#]`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

1

Bash + coreutils, 131 bayt

Bu çözüm, zamanında bir şekilde gereksinim üzerinde korkunç bir şekilde başarısız oluyor ve hatta özellikle kısa değil, ama bu tür bir şeyin en azından teorik olarak kabuk betiğinde mümkün olduğunu sevdim, bu yüzden yine de gönderiyorum. Bu, O'nun sonsuzluk indükleyici zaman karmaşıklığı ile çalışır (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

Girdi, tek bir komut satırı bağımsız değişkeni olarak iletilen virgülle ayrılmış bir listedir:

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

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

Küme ayracı genişletmesi, olası tüm alt dizilerin listesini oluşturmak için kullanılır.

  • İlk satır ile virgül değiştirir ,:},{gibi bir dize üreten,1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5
  • İkinci satır, bu dizeyi parantez, virgül ve noktalı virgüllerle tamamlar {1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5,:}. Bu geçerli bir evalbas parantez genişletmesi olup, bir echoboşlukla ayrıldığında bu boşlukla ayrılmış listeyi üretir1,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,:,: ...
  • bash varsayılan olarak dizeleri boşlukla ayırır, bu nedenle bu listenin her bir öğesi üzerinde döngü yaparız:
    • virgül yeni satırlarla değiştirilir, ardından iki nokta üst üste içeren satırlar kaldırılır ve her olası alt satır için satır satırından ayrı listeler verilir
    • Daha sonra sort -Cartan sipariş için test yaparız ve varsa wc -wlistenin uzunluğunu yazdırmak için
  • sonuçta ortaya çıkan liste uzunlukları listesi ters sıralanır ve en uzun artan alt sıra uzunluğunu vermek için ilk değer yazdırılır.

1

Stax , 21 bayt

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

Çalıştır ve hata ayıkla

Bu, biri 1000 elemanlı kasa olmak üzere iki test senaryosuna sahiptir. Bunu makinemde 24 saniyede çalıştırıyor. Bu tür bir problem için klasik dinamik programlama yaklaşımını kullanır.


0

J 34

Standart girişi de okuduğumu unutmayın.

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

Standart girdi okunmadan, et 26 karakterdir.

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

Sadece büyük girdi için benim yavaş çalıştığını fark ettim.



0

C # (.NET Core) , 155 bayt

Girdi dizisindeki (dinamik programlama) her bir konumla biten en uzun artan alt diziyi hesaplamak için bir dizi kullandıktan sonra en büyük değeri döndürdü. Örneğin, girdi için hesaplanan dizi [1,5,7,1,8,4,3,5]olur [1,2,3,1,4,2,2,3]ve en büyük değer 4döndürülür.

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;}

Çevrimiçi deneyin!


0

Wolfram Dili (Mathematica) , 38 bayt

Length@LongestOrderedSequence[#,Less]&

Çevrimiçi deneyin!

Elbette en uzun sıralı dizileri bulmak için yerleşik bir Mathematica vardır . Adı çok uzun: çözümün yarısından fazlasını oluşturuyor ve birisi bu çözümü golf sahasından çıkarsa şaşırmayacağım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.