Code de séquence croissant le plus long le plus long

11

Le défi est d'écrire l' implémentation la plus courte pour trouver la sous- séquence croissante la plus longue .

Exemple : Soit S la séquence 1 5 7 1 8 4 3 5 [longueur de S = 8]

  • Nous avons 1 sous-séquence de longueur 0 [la considérera croissante]
  • 6 sous-séquences de longueur 1 {1,5,7,8,4,3} [toutes sont considérées comme en augmentation]
  • (7 * 8) / 2 sous-séquences de longueur 2 [mais nous allons supprimer les doublons], les sous-séquences croissantes sont en noir fort.
    { 15,17 , 11, 18,14,13,57 , 51, 58 , 54,53,55,71, 78 , 74,73,75,84,83,85,43, 45,35 }

[notez que nous ne nous intéressons qu'aux sous-séquences strictement croissantes]

[vous ne pouvez pas changer l'ordre des éléments à l'intérieur de la séquence, il n'y a donc pas de sous-séquence [37] dans l'exemple de séquence]

  • Nous avons des sous-séquences croissantes de longueur 4 qui est 1578, mais il n'y a pas de sous-séquence de longueur 5, donc nous considérons la longueur de la sous-séquence croissante la plus longue = 4.

Entrée :

a 1 a 2 ... a N (la séquence)

tous les nombres sont des entiers positifs inférieurs à 10 3
N <= 1000

Sortie :

Un entier indiquant la longueur de la sous-séquence croissante la plus longue de la séquence d'entrée.

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

Votre code doit s'exécuter en temps opportun, veuillez tester votre code sur ce cas avant de le soumettre ici (également le lien contient ma solution c ++ 11 de 290 octets)

Vous pouvez soit prendre l'entrée d'un fichier / stdin ou en tant que paramètre de fonction et vous pouvez soit imprimer la sortie dans un fichier / stdout ou simplement retourner la valeur si vous écrivez une fonction

Tableau des scores

  1. Dennis CJam - 22
  2. isaacg Pyth - 26
  3. Howard GolfScript - 35
  4. fier haskeller Haskell - 56
  5. Ray Python 3-66
  6. rubis histocrate - 67
  7. DLeh C # - 92
  8. YosemiteMark Clojure - 94
  9. faubiguy Python 3 - 113
Mostafa 36a2
la source
1
"Nous avons 1 sous-séquence de longueur 0 [la considérera comme augmentant]", Eh bien techniquement, vous avez un nombre infini de sous-séquences de longueur 0 :)
Cruncher
En fait, je dois changer la déclaration afin que tous les "Sets" doivent supprimer les doublons, par exemple {1,5,7,1,8,4,3,5} devrait être {1,5,7,8,4 , 3} et alors on peut dire qu'il y a 1 sous-séquence de longueur 0 dans le "Set". merci
Mostafa 36a2
1
Pour les fonctions, faut-il compter les octets de la fonction externe ( function f(){...}) ou de la fonction interne (juste ...)? Si nous comptons les fonctions externes, les fonctions anonymes sont-elles autorisées?
Dennis
Nous comptons la fonction externe, et les fonctions anonymes sont autorisées, mais ne manquez pas de fournir une version testable (version complète avec la gestion des entrées / sorties)
Mostafa 36a2

Réponses:

2

CJam, 22 octets

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

Essayez-le en ligne.

Exemple

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

Le programme imprime 57pour ce scénario de test après 0,25 seconde.

Comment ça fonctionne

J'ai pris l'idée générale de la réponse de @ 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
la source
5

Python 3, 66

Notez que tous les nombres sont dans la plage [1, 999], nous pouvons utiliser un tableau bpour conserver la longueur de sous-séquence la plus longue se terminant par chaque numéro. b[x] = dsignifie que la sous-séquence la plus longue se terminant par xa une longueur d. Pour chaque numéro de l'entrée, nous mettons à jour le tableau à l'aide b[x] = max(b[:x]) + 1puis nous avons fait le travail en prenant max(b)finalement.

La complexité temporelle est Sur) O (mn) , où mest toujours 1000 et nest le nombre d'éléments d'entrée.

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

Wow, on dirait déjà non golfé :) Vous pouvez le tester en utilisant stdin / stdout en ajoutant une ligne:

print(f(map(int,input().split())))
Rayon
la source
for x in a: max(b)ressemble à peu près O (n ^ 2).
Howard
@Howard It's O(1000 n)et 1000 est une constante. Vous pouvez aussi le penser comme O(m n).
Ray
3
Avec un tel argument, toute la discussion est inutile car sur une entrée limitée, la complexité est toujours O(1);-)
Howard
@Howard je viens du monde ACM-ICPC et c'est un peu une convention là-bas. Vous pouvez le penser comme O (mn). C'est toujours différent de O (n ^ 2). Quoi qu'il en soit, le temps qu'il en coûtera sera inférieur au temps de démarrage de l'interprète, donc je pense que c'est assez rapide.
Ray
Algorithme incroyablement court! Je ne peux repérer qu'un seul caractère (au moins lors du passage à Python 2): vous pouvez imprimer le résultat. printest plus court que 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
la source
Solution acceptée. Votre code a été testé ici et ici .
Mostafa 36a2
@ Mostafa36a2 Le mot "accepté" a une autre signification sur ce site. Je pense que ce que vous voulez dire est "acceptable".
Ray
Désolé, oui, je voulais dire acceptable, trop tôt pour choisir celui qui est accepté.
Mostafa 36a2
Avec la ligne a+=[i]*(a==[]or i>a[-1]);z=0et l'impression len(a)(sans crochets), vous pouvez enregistrer 4 caractères.
Falko
3

Pyth , 26 29 33 39

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

Port de la solution de @ ray. Réussit les tests officiels. Utilise maintenant une entrée STDIN séparée par des espaces, pas un appel de fonction.

Exécutez comme suit:

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

Explication:

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)

Temps illimité:

Pyth , 18

L?eS,ytbhyf>Thbbb0

Note technique: J'ai remarqué un bug dans mon complieur Pyth lors de l'écriture de ce golf. Lne fonctionnait pas. C'est pourquoi il y a eu un commit récent dans le dépôt git ci-dessus.

isaacg
la source
votre code ne s'exécute pas en temps opportun pour un cas avec une grande liste (disons 100 éléments)
Mostafa 36a2
3
@ Mostafa36a2 Si vous souhaitez faire de l'exécution une exigence, veuillez le dire dans la question et ajouter un ou deux cas de test. Si c'est juste un commentaire, je suis d'accord, c'est assez lent.
isaacg
Désolé mais j'ai mentionné que ce n'est pas le runtime mais au moins une [manière opportune], pas de problème si le code prend 10-20 minutes ou même une heure, mais les solutions O (2 ^ n) ne donneront jamais le résultat pendant notre longue vie.
Mostafa 36a2
@ Mostafa36a2 Compris, je viens de remarquer cette ligne. Je vais travailler sur une amélioration.
isaacg
1
Désolé, je vois la mise à jour maintenant, veuillez essayer ce cas et dites-moi si cela fonctionne.
Mostafa 36a2
3

Clojure, 94 caractères

En utilisant l'approche de @ Ray de mise à jour des résultats dans un vecteur de 1000 éléments:

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

Par demande, avec instruction d'impression (imprime la réponse et renvoie zéro). L'entrée doit être un vecteur (g [1 2 3]) ou une liste (g '(1 2 3)):

(defn g[s](prn(apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s))))
YosemiteMark
la source
pouvez-vous ajouter l'instruction print pour la rendre testable? Il ne sera pas compté dans le score.
Mostafa 36a2
1
Actualisé. Je l'ai exécuté sur vos deux grands exemples, et j'ai obtenu 58 et 57 comme prévu.
YosemiteMark
Je pense que vous devez toujours appeler la fonction: p, mais si vous l'avez testée, cela suffit.
Mostafa 36a2
3

Haskell, 58 57 56 caractères

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

Cela utilise un algorithme que j'ai vu une fois sur Internet, mais je ne le trouve pas. Cela prend un temps imperceptible sur le cas de test donné sur mon ordinateur avec GHCi (ce serait probablement encore plus rapide s'il était compilé).

fier haskeller
la source
L'algorithme que vous avez mentionné est le même que celui utilisé par @faubiguy.
Ray
@Ray vous avez raison
fier haskeller
2

GolfScript, 35 caractères

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

Une implémentation fonctionnant comme un programme complet avec entrée sur STDIN (sans le numéro de longueur donné). L'implémentation est relativement rapide, même pour des entrées plus longues (essayez ici ).

Exemples:

> 1 5 7 1 8 4 3 5
4

> 5 1 9 9 1 5
2
Howard
la source
1
@ MartinBüttner Cela prend environ 5 secondes pour 1000 numéros sur mon ordinateur. En supposant que $O (n log n), l'algorithme est O (n ^ 2 log n).
Howard
veuillez essayer l'entrée dans ce lien
Mostafa 36a2
@ Mostafa36a2 je l'ai déjà fait (voir commentaire avant). Après 5 secondes, il retourne 58.
Howard
c'est un autre, il devrait renvoyer 57, donc si votre code a retourné 57 alors il est accepté :) Félicitations
Mostafa 36a2
@ Mostafa36a2 Ah, maintenant je vois que ce sont deux cas de test distincts. Oui, votre deuxième lien renvoie 57, tout comme ma solution sur cette entrée.
Howard
2

Rubis, 67

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

Cela s'exécute en 30 secondes sur la grande entrée, cela compte-t-il en temps opportun? : p

C'est une récursivité brute, mais avec une certaine mémorisation.

histocrate
la source
1
Oui, c'est une manière opportune :)
Mostafa 36a2
2

C #, 172 92 caractères

Rien de spécial, mais je l'ai fait alors j'ai pensé que je pourrais aussi bien le soumettre.

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

Merci Armin et Bob pour leurs améliorations!

DLeh
la source
1
vous pouvez changer votre paramètre en int [], puis vous auriez moins de caractères car vous n'auriez pas besoin de transtyper la chaîne en int
Armin
2
Les espaces autour ne =>sont pas nécessaires. Vous pouvez également déplacer la i=0déclaration hors de la forboucle vers int c=2,m=2,i=0;for(;. Vous pouvez également déposer les accolades autour du forcorps, car vous ne disposez que d'une seule déclaration.
Bob
Et c++;if(c>m)m=c;peut l'être m=c++>m?m:c;, et vous pouvez à nouveau laisser tomber les accolades autour de cela.
Bob
1
En fait, vous pouvez également annuler la if(i>0)vérification en faisant fordémarrer la boucle à 1. Vous pouvez raccourcir davantage la int c=2,m=2,i=0;for(;i<j.Length;i++)if(i>0)suggestion précédente int c=2,m=2,i=0;for(;i++<j.Length;). Cette section entière pourrait être convertie en 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;}(en utilisant un autre ternaire pour remplacer le dernier restant if- la règle générale est que les ternaires sont plus courts si votre ifcorps est simplement une affectation.
Bob
2
Désolé - faute de frappe dans mon commentaire précédent, m=c>m?m:cdevrait être m=c>m?c:m. Et si vous ajoutez la suggestion de @ Armin, vous obtenez 92 octets, soit presque la moitié de la taille! 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 octets

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

Essayez-le en ligne!

Fonctionne en O (n log n) , en utilisant un tri de patience modifié car seule la longueur, et non la sous-séquence réelle, est nécessaire.

Explication

[:#]`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
miles
la source
1

Bash + coreutils, 131 octets

Cette solution échoue horriblement sur l' exigence de manière opportune , et n'est même pas particulièrement courte, mais j'ai aimé que ce genre de chose soit au moins théoriquement possible dans le script shell, donc je poste quand même. Cela fonctionne avec une complexité temporelle induisant l'éternité de 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

L'entrée est une liste séparée par des virgules passée comme un seul argument de ligne de commande:

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

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

L'expansion d'accolade est utilisée pour construire la liste de toutes les sous-séquences possibles.

  • La première ligne remplace les virgules par ,:},{, ce qui produit une chaîne comme1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5
  • La deuxième ligne complète cette chaîne avec des accolades, des virgules et des points-virgules pour donner ceci {1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5,:}. Ceci est une extension d'accolade bash valide, qui lorsqu'elle est evaléditée avec un echoproduit cette liste séparée par des espaces1,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,:,: ...
  • par défaut, bash sépare les chaînes avec des espaces, nous bouclons donc sur chaque élément de cette liste:
    • les virgules sont remplacées par des nouvelles lignes, puis les lignes contenant des deux-points sont supprimées, donnant des listes séparées par des nouvelles lignes pour chaque sous-séquence possible
    • nous sort -Ctestons ensuite l' ordre croissant, et si oui, utilisons wc -wpour imprimer la longueur de la liste
  • la liste résultante des longueurs de liste est triée en sens inverse et la première valeur est imprimée pour donner la longueur de sous-séquence augmentant la plus longue.
Traumatisme numérique
la source
1

Stax , 21 octets

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

Exécuter et déboguer

Celui-ci comporte deux cas de test, dont l'un est le cas à 1000 éléments. Il s'exécute en 24 secondes sur ma machine. Il utilise l'approche de programmation dynamique classique pour ce type de problème.

récursif
la source
0

J 34

Notez que je lis également l'entrée standard.

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

Sans lire l'entrée standard, la viande est de 26 caractères.

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

Je viens de remarquer que le mien tourne lentement pour une grande entrée, eh bien.

protiste
la source
0

C ++ (gcc) , 129 octets

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

Essayez-le en ligne!

Przemysław Czechowski
la source
0

C # (.NET Core) , 155 octets

A utilisé un tableau pour calculer la sous-séquence croissante la plus longue se terminant à chaque position dans le tableau d'entrée (programmation dynamique), puis a renvoyé la plus grande valeur. Par exemple, le tableau calculé pour l'entrée [1,5,7,1,8,4,3,5]serait [1,2,3,1,4,2,2,3]et la plus grande valeur 4est renvoyée.

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

Essayez-le en ligne!

jrivor
la source
0

Wolfram Language (Mathematica) , 38 octets

Length@LongestOrderedSequence[#,Less]&

Essayez-le en ligne!

Il y a bien sûr un Mathematica intégré pour trouver les séquences ordonnées les plus longues. Son nom est très long: il représente plus de la moitié de la solution, et je ne serai pas surpris si quelqu'un sur-joue cette solution.

romain
la source