Tri par fusion
Dans ce défi, vous allez implémenter le sous-programme de fusion de tri par fusion. Plus précisément, vous devez créer une fonction ou un programme ou un verbe ou similaire qui prend deux listes, chacune triée par ordre croissant, et les combine en une liste triée par ordre croissant. Exigences:
- Votre algorithme doit prendre un temps asymptotiquement linéaire dans la taille de l'entrée. Veuillez cesser de donner des solutions O (n ^ 2).
- Vous ne pouvez pas utiliser de fonctions intégrées capables de trier une liste, ou de fusionner une liste, ou quelque chose comme ça. Discrétion de l'auteur.
- Le code doit être capable de gérer des éléments répétés.
- Ne vous inquiétez pas des listes vides.
Exemples:
merge([1],[0,2,3,4])
[0,1,2,3,4]
merge([1,5,10,17,19],[2,5,9,11,13,20])
[1, 2, 5, 5, 9, 10, 11, 13, 17, 19, 20]
Il s'agit de code-golf , alors que le code le plus court gagne!
b=a;b=b.length
pourrait dupliquer le tableau entiera
(et entraîner un temps O (n ^ 2) s'il est exécuté pour chaque élément) ou dupliquer uniquement la référence au tableau (temps O (n)). Lequel compte?Réponses:
Rebmu (
3532 caractères)Tester
Sur
Rebmu est un dialecte de Rebol qui permet de «mushing» de code régulier pour les situations qui nécessitent de la brièveté. Insensible, le code fonctionne un peu comme:
Je crois que cela satisfait l' exigence O (n) car le bloc jusqu'à est au plus en boucle autant de fois que la longueur de l'entrée (et le
reverse
seul change l'ordre du conteneur des blocs d'entrée, pas les blocs eux-mêmes). L'utilisationtake
est peut-être une liberté, mais reste un impact d'efficacité mineur.Rebol (
8375 caractères)Un tout petit peu différent: dans Rebol, les chemins sont une expression plus courte que
first
ousecond
.a
est le bloc d'entrée contenant les deux blocs:la source
Solutions OP:
Haskell
494440Python
131105101 1019993Merci à @Evpok:
la source
a%b=a++b
après la correspondance du motif principal pour gérer les listes vides, ce qui supprimera quelques caractères.Python (79)
Python (95, si nous ne sommes pas autorisés à retourner un générateur)
Itertools est la solution à tous les problèmes du monde.
Bonus: les deux fonctionnent sur un nombre arbitraire de listes et s'inquiètent des listes vides (comme dans, ils prendront avec plaisir 2 listes vides et retourneront une liste vide, ou prendront 1 liste vide et 1 liste non vide, et ils renverront celui qui n'est pas vide. Une autre fonctionnalité ajoutée des 2 non-cédés: ils s'exécuteront également sans argument, et retourneront simplement une liste vide.)
Non golfé:
la source
r+=[...]
place der.append(...)
(enregistre 4 caractères à chaque fois)C - 75
Cela fonctionne sur des
NULL
tableaux terminés deint *
, bien que cela fonctionnerait aussi bien pour les pointeurs vers d'autres types en substituant la fonction de comparaison appropriée**b < **a
(par exemple,strcmp(*b, *a) < 0
).Non golfé:
la source
Golfscript,
2927302926 octetsou
Comment ça fonctionne
La commande
sera traité comme suit:
La sortie est:
la source
[1 1 1 ... 2]
et[1 1 1 ... 3]
), car comparer les tableaux (plutôt que leurs premiers éléments) serait très lent dans ce cas.J -
4233Version modifiée d' ici + le commentaire de @algorithmshark
k
ajoute la tête du tableau de droite aux queues fusionnées des deux tableaux.k~
est le même, mais avec des tableaux inversés.(>&{.)
compare les têtes. Le code générera une erreur si l'un des tableaux est vide, dans ce cas, nous renvoyons uniquement leur concaténation,
.la source
/:~ a,b
c'est la réponse interdite (avec[:/:~,
), que vous visez la réponse la plus courte qui ne comprend pas/:
, non?m=:k~`k@.(>&{.)`,@.(0=*&#)
enregistre 2 car.k=:(m}.),~0{]
etm=:k~`k@.(>&{.) ::,
. Nous utilisons0{
pour lancer une erreur lorsque la liste est vide, puis intercepter cette erreur et quitter avec,
.JavaScript (ES6),
6979 octetsComment ça fonctionne
la source
<
opérateur n'est pas valide car elle fait une comparaison de chaînes:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
[]
puis le convertir en chaîne nécessite O (n) de temps. Le faire une fois pour tous les n éléments du tableau prend O (n ^ 2) temps.Python
(63) (69)(71)J'ai écrit ceci avant de voir les commentaires d'OP sur les temps d'exécution d'autres réponses, c'est donc une autre solution qui est O (n) dans l'algorithme mais pas la mise en œuvre.
la source
return[a.pop(0)]+(a and m(a,b)or b)
Haskell, 35 octets
Haskell, 30 octets (non concurrent)
Cette version non concurrente ne garantit que l'exécution linéaire si
a
etb
ont des éléments disjoints; sinon, il fonctionne toujours correctement mais peut utiliser le temps quadratique.la source
PHP
91 9891 octetsedit # 1: Vide
$b
nécessite une condition supplémentaire dans les accolades (+7).modifier # 2: golfs mineurs
modifier # 3: ajouté une deuxième version
assez simple. La plus belle partie est le ternaire à l'intérieur du
array_shift
(qui échoue si vous l'essayez sans les curlys)
ou
non golfé
tester
la source
$a&(!$b|$a[0]<$b[0])?$a:$b
au lieu de${$a&(!$b|$a[0]<$b[0])?a:b}
array_shift
paramètre est utilisé par référence. Ce doit être une variable; une expression ne fonctionnera pas.Aller, 124 caractères
la source
JavaScript - 133
Même type d'approche que les PO.
la source
perl, 87 caractères / perl 5.14, 78 + 1 = 79 caractères
Cette implémentation encombre les références de tableau d'entrée. En dehors de cela, c'est assez simple: alors que les deux tableaux ont quelque chose, désactivez le bas des deux. Retournez ensuite le bit fusionné joint à tous les bits restants (il ne restera qu'un seul parmi @ $ x ou @ $ y). Perl5 droit, 87 caractères:
En utilisant Perl 5.14.0 et son nouveau décalage de référence de tableau: 78 caractères + 1 pénalité de caractère = 79 caractères:
la source
*
au lieu d'&&
enregistrer un octet. Et encore plus sisub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
Java: 144
C'est assez simple. Une fonction qui prend deux tableaux et renvoie un, la version fusionnée, golfée et sans wrapper de compilation:
Non golfé (avec un wrapper compilable et exécutable):
Exemples d'exécutions:
Tout conseil à raccourcir serait apprécié.
la source
Scala, 97 octets
Solution récursive avec O (n). Pour raccourcir le code, une opération est parfois effectuée en commutant les 2 paramètres interchangeables, c'est-à-dire que f (a, b) appelle f (b, a).
Non golfé:
la source
APL (32)
Explication:
la source
LISP, 117 octets
L'algorithme se termine par des
n + 1
itérations, oùn
est la longueur de la liste la plus courte en entrée.la source
PYG (50)
PYG (64, encore une fois, si aucun générateur n'est autorisé.):
Une adaptation de ma réponse Python .
la source
Python - 69 octets
Si l'ordre d'entrée et de sortie décroissait, cela pourrait être raccourci à 61 octets :
Et plus loin jusqu'à 45 octets si les générateurs sont autorisés:
la source
pop(0)
peuvent être implémentées dans O (1) et+=
peuvent au moins être implémentées mieux que O (n) (voir le lien). Soit dit en passant, votre solution utilise+=
(c'est-à-direappend
etextend
) aussi souvent que la mienne. Quoi qu'il en soit, tout cela est une question d'implémentation (pour autant que je sache), donc dans une implémentation (fictive) de Python, où les listes sont implémentées comme des listes, ma fonction est O (n). Enfin, votre question exigeait que l' algorithme soit O (n), et le mien l'est.Perl 6:53 caractères
Passez de la valeur la plus petite
a
oub
la plus petite jusqu'à ce quea
XORb
(a^b
) soit vrai. Retournez ensuite tout ce qui reste, flattening ([]
) les tableaux dans la liste (a[],b[]
).En supposant que le décalage depuis le début d'un tableau est O (n), le pire des cas est deux comparaisons et un décalage par élément, donc l'algorithme est O (n).
la source
JavaScript (ES5)
908690 octetsedit: (90 -> 86) Déplacement du ternaire dans la condition de boucle for. Idée volée à Dennis.
edit: (86 -> 90) Suppression du tableau en chaîne, car cela rompt l' exigence O (n) .
la source
Mathematica,
137135Contribution:
Production:
Non golfé:
Pourrait probablement faire mieux.
la source
m[a:{x___,y_},b:{___,z_}]:=If[y<z,b~m~a,{x}~m~b~Join~{y}];{}~m~b_=b;
R, 80
Même solution que dans Scala et dans d'autres langues. Je ne suis pas sûr que x [-1] soit O (1).
la source
Mathematica, 104 octets
Fonction anonyme, stocke la longueur des deux listes d'entrée dans les variables
m
puisn
, à chaque itération de laDo
boucle,Sow
un élément de l'une des listes incrémentant le compteur de cette liste (i
pour la première,k
pour la seconde) d'une unité . Si l'un des compteurs dépasse la longueur de la liste, l'If
instruction sera toujoursSow
l'élément de l'autre liste. Après lesn+m
opérations, tous les éléments ont été pris en charge.Reap
ou plutôt une partie[[2,1]]
de sa sortie est une liste d'éléments dans l'ordre où ils ont étéSow
n.Je ne suis pas sûr des internes (accède à une partie d'une liste, une
O(1)
opération ou non), mais les délais semblaient assez linéaires sur ma machine en ce qui concerne la longueur de la liste d'entrée.la source