Kürzester längster zunehmender Folgecode

11

Die Herausforderung besteht darin, die kürzeste Implementierung zu schreiben , um die am längsten zunehmende Teilsequenz zu finden .

Beispiel : Sei S die Folge 1 5 7 1 8 4 3 5 [Länge von S = 8]

  • Wir haben 1 Teilsequenz der Länge 0 [wird als ansteigend betrachtet]
  • 6 Teilsequenzen der Länge 1 {1,5,7,8,4,3} [alle gelten als ansteigend]
  • (7 * 8) / 2 Subsequenzen der Länge 2 [aber wir werden Duplikate entfernen], die zunehmenden Subsequenzen sind in starkem Schwarz.
    { 15,17 , 11, 18,14,13,57 , 51, 58 , 54,53,55,71, 78 , 74,73,75,84,83,85,43, 45,35 }

[Beachten Sie, dass wir nur an streng zunehmenden Teilsequenzen interessiert sind]

[Sie können die Reihenfolge der Elemente innerhalb der Sequenz nicht ändern , daher gibt es in der Beispielsequenz keine Teilsequenz [37].]

  • Wir haben zunehmende Teilsequenzen der Länge 4, die 1578 beträgt, aber es gibt keine Teilsequenz der Länge 5, daher betrachten wir die Länge der am längsten zunehmenden Teilsequenz = 4.

Eingabe :

a 1 a 2 ... a N (Die Sequenz)

Alle Zahlen sind positive ganze Zahlen unter 10 3
N <= 1000

Ausgabe :

Eine ganze Zahl, die die Länge der am längsten ansteigenden Teilsequenz der Eingabesequenz angibt.

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

Ihr Code sollte rechtzeitig ausgeführt werden. Bitte testen Sie Ihren Code in diesem Fall, bevor Sie ihn hier einreichen (auch der Link enthält meine 290-Byte-C ++ 11-Lösung).

Sie können die Eingabe entweder aus einer Datei / stdin oder als Funktionsparameter übernehmen und die Ausgabe entweder in eine Datei / stdout drucken oder einfach den Wert zurückgeben, wenn Sie eine Funktion schreiben

Anzeigetafel

  1. Dennis CJam - 22
  2. isaacg Pyth - 26
  3. Howard GolfScript - 35
  4. stolzer Haskeller Haskell - 56
  5. Ray Python 3 - 66
  6. Histokrat Ruby - 67
  7. DLeh C # - 92
  8. YosemiteMark Clojure - 94
  9. faubiguy Python 3 - 113
Mostafa 36a2
quelle
1
"Wir haben 1 Teilsequenz der Länge 0 [wird als steigend angesehen]", technisch gesehen haben Sie eine unendliche Anzahl von Teilsequenzen der Länge 0 :)
Cruncher
Eigentlich muss ich die Anweisung so ändern, dass alle "Sets" die Duplikate entfernen müssen, zB {1,5,7,1,8,4,3,5} sollte {1,5,7,8,4 sein , 3} und dann können wir sagen, dass es in der "Menge" eine Teilsequenz mit einer Länge von 1 0 gibt. danke
Mostafa 36a2
1
Sollten wir für Funktionen die Bytes der äußeren Funktion ( function f(){...}) oder der inneren Funktion (nur ...) zählen? Sind anonyme Funktionen zulässig, wenn wir äußere Funktionen zählen?
Dennis
Wir zählen die äußere Funktion und anonyme Funktionen sind zulässig. Verpassen Sie jedoch nicht, eine testbare Version (vollständige Version mit Eingabe- / Ausgabebehandlung)
bereitzustellen

Antworten:

2

CJam, 22 Bytes

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

Probieren Sie es online aus.

Beispiel

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

Das Programm druckt 57für diesen Testfall nach 0,25 Sekunden.

Wie es funktioniert

Ich habe die allgemeine Idee aus @ Rays Antwort übernommen .

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
quelle
5

Python 3, 66

Beachten Sie, dass alle Zahlen im Bereich [1, 999] liegen. Wir können ein Array verwenden b, um die längste Teilsequenzlänge beizubehalten, die mit jeder Zahl endet. b[x] = dbedeutet, dass die längste Teilsequenz, die mit endet, xLänge hat d. Für jede Zahl aus der Eingabe aktualisieren wir das Array mit b[x] = max(b[:x]) + 1und erledigen dann die Aufgabe, indem wir max(b)endlich nehmen.

Die zeitliche Komplexität ist Auf) O (mn) , wobei mimmer 1000 ist und ndie Anzahl der Eingabeelemente ist.

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

Wow, sieht aus wie schon ungolfed :) Du kannst es mit stdin / stdout testen, indem du eine Zeile hinzufügst:

print(f(map(int,input().split())))
Strahl
quelle
for x in a: max(b)sieht ziemlich O (n ^ 2) aus.
Howard
@ Howard Es ist O(1000 n)und 1000 ist eine Konstante. Sie können es auch so denken O(m n).
Ray
3
Mit solchen Argumenten ist die ganze Diskussion nutzlos, weil bei begrenzten Eingaben die Komplexität immer ist O(1);-)
Howard
@Howard Ich komme aus der ACM-ICPC-Welt und dies ist dort eine Art Konvention. Sie können es als O (mn) denken. Es ist immer noch anders als O (n ^ 2). Wie auch immer, die Zeit, die es kostet, wird geringer sein als die Startzeit des Dolmetschers, also denke ich, dass es schnell genug ist.
Ray
Beeindruckend kurzer Algorithmus! Ich kann nur ein Zeichen erkennen (zumindest beim Wechsel zu Python 2): Sie können das Ergebnis drucken. printist kürzer als 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
quelle
Akzeptierte Lösung. Ihr Code wurde hier und hier getestet .
Mostafa 36a2
@ Mostafa36a2 Das Wort "akzeptiert" hat auf dieser Seite eine andere Bedeutung. Ich denke, was du meinst, ist "akzeptabel".
Ray
Entschuldigung, ja, ich meinte akzeptabel, zu früh, um die akzeptierte zu wählen.
Mostafa 36a2
Mit der Zeile a+=[i]*(a==[]or i>a[-1]);z=0und dem Drucken len(a)(ohne Klammern) können Sie 4 Zeichen speichern.
Falko
3

Pyth , 26 29 33 39

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

Port of @ ray Lösung. Besteht offizielle Tests. Verwendet jetzt einen durch Leerzeichen getrennten STDIN-Eingang, keinen Funktionsaufruf.

Führen Sie Folgendes aus:

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

Erläuterung:

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)

Zeit unbegrenzt:

Pyth , 18

L?eS,ytbhyf>Thbbb0

Technischer Hinweis: Beim Schreiben dieses Golfs ist ein Fehler in meinem Pyth-Complier aufgetreten. Lfunktionierte nicht. Aus diesem Grund wurde kürzlich ein Commit für das oben genannte Git-Repository durchgeführt.

isaacg
quelle
Ihr Code wird für einen Fall mit einer großen Liste (z. B. 100 Elemente) nicht rechtzeitig ausgeführt
Mostafa 36a2
3
@ Mostafa36a2 Wenn Sie die Laufzeit zur Anforderung machen möchten, geben Sie dies bitte in der Frage an und fügen Sie ein oder zwei Testfälle hinzu. Wenn es nur ein Kommentar ist, dann stimme ich zu, es ist ziemlich langsam.
isaacg
Tut mir leid, aber ich habe erwähnt, dass dies nicht die Laufzeit ist, sondern zumindest eine [rechtzeitige] Methode. Kein Problem, wenn der Code 10 bis 20 Minuten oder sogar eine Stunde dauert, aber die O (2 ^ n) -Lösungen werden währenddessen niemals das Ergebnis liefern unser langes Leben.
Mostafa 36a2
@ Mostafa36a2 Verstanden, ich habe gerade diese Zeile bemerkt. Ich werde an einer Verbesserung arbeiten.
isaacg
1
Entschuldigung, ich sehe das Update jetzt. Bitte versuchen Sie diesen Fall und sagen Sie mir, ob es funktioniert.
Mostafa 36a2
3

Clojure, 94 Zeichen

Verwenden des Ansatzes von @ Ray zum Aktualisieren der Ergebnisse in einem Vektor mit 1000 Elementen:

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

Auf Anfrage mit Druckanweisung (Antwort wird gedruckt und Null zurückgegeben). Die Eingabe sollte ein Vektor (g [1 2 3]) oder eine Liste (g '(1 2 3)) sein:

(defn g[s](prn(apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s))))
YosemiteMark
quelle
Können Sie die print-Anweisung hinzufügen, um sie testbar zu machen? Es wird nicht in der Punktzahl berücksichtigt.
Mostafa 36a2
1
Aktualisiert. Ich habe es auf Ihren beiden großen Beispielen ausgeführt und wie erwartet 58 und 57 erhalten.
YosemiteMark
Ich denke, Sie müssen die Funktion noch aufrufen: p, aber wenn Sie sie getestet haben, ist das genug.
Mostafa 36a2
3

Haskell, 58 57 56 Zeichen

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

Dies verwendet einen Algorithmus, den ich einmal im Internet gesehen habe, aber ich kann ihn nicht finden. Es dauert nicht merklich lange, bis der angegebene Testfall auf meinem Computer mit GHCi ausgeführt wird (wahrscheinlich wäre er sogar noch schneller, wenn er kompiliert würde).

stolzer haskeller
quelle
Der von Ihnen erwähnte Algorithmus ist der gleiche wie der von @faubiguy verwendete.
Ray
@ Ray du hast recht
stolzer Haskeller
2

GolfScript, 35 Zeichen

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

Eine Implementierung, die als vollständiges Programm mit Eingabe auf STDIN arbeitet (ohne die angegebene Längennummer). Die Implementierung ist auch bei längeren Eingaben relativ schnell (versuchen Sie es hier ).

Beispiele:

> 1 5 7 1 8 4 3 5
4

> 5 1 9 9 1 5
2
Howard
quelle
1
@ MartinBüttner Es dauert ungefähr 5 Sekunden für 1000 Zahlen auf meinem Computer. Angenommen, $O (n log n) ist der Algorithmus O (n ^ 2 log n).
Howard
Bitte versuchen Sie die Eingabe in diesem Link
Mostafa 36a2
@ Mostafa36a2 habe ich schon gemacht (siehe Kommentar vorher). Nach 5 Sekunden kehrt es 58 zurück.
Howard
Dies ist eine andere, es sollte 57 zurückgeben, also wenn Ihr Code 57 zurückgegeben hat, dann ist es akzeptiert :) Herzlichen Glückwunsch
Mostafa 36a2
@ Mostafa36a2 Ah, jetzt sehe ich, dass dies zwei verschiedene Testfälle sind. Ja, Ihr zweiter Link gibt 57 zurück, ebenso wie meine Lösung für diese Eingabe.
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}

Dies läuft bei der großen Eingabe in 30 Sekunden. Zählt das als rechtzeitige Methode? : p

Es ist eine brutale Rekursion, aber mit etwas Auswendiglernen.

Histokrat
quelle
1
Ja, das ist eine rechtzeitige Art :)
Mostafa 36a2
2

C #, 172 92 Zeichen

Nichts Besonderes, aber ich habe es getan, also dachte ich mir, ich könnte es genauso gut einreichen.

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

Vielen Dank an Armin und Bob für ihre Verbesserungen!

DLeh
quelle
1
Sie können Ihren Parameter in int [] ändern und dann hätten Sie weniger Zeichen, weil Sie keinen String in int
Armin
2
Die Leerzeichen =>sind unnötig. Sie können die i=0Deklaration auch außerhalb der forSchleife nach verschieben int c=2,m=2,i=0;for(;. Sie können die Klammern auch um den forKörper legen , da Sie dort nur eine einzige Anweisung haben.
Bob
Und c++;if(c>m)m=c;kann sein m=c++>m?m:c;, und Sie können wieder die Klammern um das fallen lassen.
Bob
1
Tatsächlich können Sie die if(i>0)Prüfung auch verwerfen , indem Sie die forSchleife bei 1 beginnen lassen. Sie können die int c=2,m=2,i=0;for(;i<j.Length;i++)if(i>0)zuvor vorgeschlagene Prüfung weiter verkürzen int c=2,m=2,i=0;for(;i++<j.Length;). Dieser gesamte Abschnitt könnte konvertiert werden 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;}(indem ein anderes Ternär verwendet wird, um das letzte verbleibende zu ersetzen if- Faustregel ist, dass Ternäre kürzer sind, wenn Ihr ifKörper nur eine Aufgabe ist.
Bob
2
Entschuldigung - Tippfehler in meinem vorherigen Kommentar m=c>m?m:csollten sein m=c>m?c:m. Und wenn Sie den Vorschlag von @ Armin hinzufügen, erhalten Sie 92 Bytes, was die Größe fast halbiert! 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 Bytes

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

Probieren Sie es online aus!

Läuft in O (n log n) unter Verwendung einer modifizierten Geduldssortierung, da nur die Länge und nicht die tatsächliche Teilsequenz benötigt wird.

Erläuterung

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

Bash + Coreutils, 131 Bytes

Diese Lösung scheitert schrecklich an der rechtzeitigen Art und Weise und ist nicht einmal besonders kurz, aber ich fand es gut, dass so etwas zumindest theoretisch in Shell-Skripten möglich ist, also poste ich trotzdem. Dies läuft mit einer ewigkeitsinduzierenden Zeitkomplexität von O (2 ^ n) ab.

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

Die Eingabe ist eine durch Kommas getrennte Liste, die als einzelnes Befehlszeilenargument übergeben wird:

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

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

Die Klammererweiterung wird verwendet, um die Liste aller möglichen Teilsequenzen zu erstellen.

  • Die erste Zeile ersetzt Kommas durch ,:},{, wodurch eine Zeichenfolge wie erzeugt wird1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5
  • Die zweite Zeile vervollständigt diese Zeichenfolge mit geschweiften Klammern, Kommas und Semikolons {1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5,:}. Dies ist eine gültige Bash-Klammer-Erweiterung, die, wenn sie evalmit einem echobearbeitet wird, diese durch Leerzeichen getrennte Liste erzeugt1,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,:,: ...
  • Standardmäßig teilt bash Zeichenfolgen mit Leerzeichen, sodass wir jedes Element dieser Liste durchlaufen:
    • Kommas werden durch Zeilenumbrüche ersetzt, dann werden Zeilen mit Doppelpunkten entfernt, wodurch durch Zeilenumbrüche getrennte Listen für jede mögliche Teilsequenz erstellt werden
    • Wir sort -Ctesten dann , ob die Reihenfolge erhöht ist, und wc -wdrucken in diesem Fall die Länge der Liste
  • Die resultierende Liste der Listenlängen wird umgekehrt sortiert und der erste Wert gedruckt, um die am längsten zunehmende Teilsequenzlänge zu erhalten.
Digitales Trauma
quelle
1

Stax , 21 Bytes

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

Führen Sie es aus und debuggen Sie es

Dies hat zwei Testfälle, von denen einer der 1000-Elemente-Fall ist. Es läuft in 24 Sekunden auf meinem Computer. Es verwendet den klassischen dynamischen Programmieransatz für diese Art von Problem.

rekursiv
quelle
0

J 34

Beachten Sie, dass ich auch die Standardeingabe lese.

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

Ohne Standardeingabe zu lesen, besteht das Fleisch aus 26 Zeichen.

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

Ich habe gerade bemerkt, dass meine für große Eingaben langsam läuft, na ja.

Protist
quelle
0

C ++ (gcc) , 129 Bytes

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

Probieren Sie es online aus!

Przemysław Czechowski
quelle
0

C # (.NET Core) , 155 Byte

Verwendete ein Array, um die am längsten ansteigende Teilsequenz zu berechnen, die an jeder Position im Eingabearray endet (dynamische Programmierung), und gab dann den größten Wert zurück. Das berechnete Array für die Eingabe [1,5,7,1,8,4,3,5]wäre beispielsweise [1,2,3,1,4,2,2,3], und der größte Wert 4wird zurückgegeben.

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

Probieren Sie es online aus!

jrivor
quelle
0

Wolfram Language (Mathematica) , 38 Bytes

Length@LongestOrderedSequence[#,Less]&

Probieren Sie es online aus!

Natürlich ist eine Mathematica integriert, um die am längsten geordneten Sequenzen zu finden. Sein Name ist sehr lang: Er macht mehr als die Hälfte der Lösung aus, und ich bin nicht überrascht, wenn jemand diese Lösung übertrifft.

römisch
quelle