Le tri par fusion est un algorithme de tri qui fonctionne en divisant une liste donnée en deux, en triant récursivement les deux listes plus petites et en les fusionnant à nouveau dans une liste triée. Le cas de base de la récursivité arrive à une liste singleton, qui ne peut pas être divisée davantage mais qui est par définition déjà triée.
L'exécution de l'algorithme sur la liste [1,7,6,3,3,2,5]
peut être visualisée de la manière suivante:
[1,7,6,3,3,2,5]
/ \ split
[1,7,6,3] [3,2,5]
/ \ / \ split
[1,7] [6,3] [3,2] [5]
/ \ / \ / \ | split
[1] [7] [6] [3] [3] [2] [5]
\ / \ / \ / | merge
[1,7] [3,6] [2,3] [5]
\ / \ / merge
[1,3,6,7] [2,3,5]
\ / merge
[1,2,3,3,5,6,7]
La tâche
Écrivez un programme ou une fonction qui prend une liste d'entiers de manière raisonnable en entrée et visualise les différentes partitions de cette liste tout en étant triée par un algorithme de tri par fusion. Cela signifie que vous n'avez pas besoin de générer un graphique comme ci-dessus, mais juste les listes sont bien:
[1,7,6,3,3,2,5]
[1,7,6,3][3,2,5]
[1,7][6,3][3,2][5]
[1][7][6][3][3][2][5]
[1,7][3,6][2,3][5]
[1,3,6,7][2,3,5]
[1,2,3,3,5,6,7]
De plus, toute notation de liste raisonnable est très bien, donc ce qui suit serait également une sortie valide:
1 7 6 3 3 2 5
1 7 6 3|3 2 5
1 7|6 3|3 2|5
1|7|6|3|3|2|5
1 7|3 6|2 3|5
1 3 6 7|2 3 5
1 2 3 3 5 6 7
Enfin, la façon de diviser une liste en deux listes plus petites vous appartient tant que la longueur des deux listes résultantes diffère au maximum d'une unité. Cela signifie qu'au lieu de diviser [3,2,4,3,7]
en [3,2,4]
et [3,7]
, vous pouvez également diviser en prenant des éléments à des index pairs et impairs ( [3,4,7]
et [2,3]
) ou même randomiser la division à chaque fois.
C'est le code-golf , donc le code le plus court dans n'importe quelle langue, mesuré en octets, gagne.
Cas de test
Comme indiqué ci-dessus, le format réel et la façon de diviser les listes en deux sont à vous.
[10,2]
[10][2]
[2,10]
[4,17,1,32]
[4,17][1,32]
[4][17][1][32]
[4,17][1,32]
[1,4,17,32]
[6,5,4,3,2,1]
[6,5,4][3,2,1]
[6,5][4][3,2][1]
[6][5][4][3][2][1]
[5,6][4][2,3][1] <- Important: This step cannot be [5,6][3,4][1,2], because 3 and 4 are on different branches in the the tree
[4,5,6][1,2,3]
[1,2,3,4,5,6]
la source
[[1,2],[3],[4,5],[6]]
étape est en fait la bonne solution, car le tri par fusion fonctionne récursivement. C'est-à-dire si nous commençons par le[1,2,3,4,5,6]
diviser en[1,2,3]
et[4,5,6]
, puis ces listes sont traitées indépendamment jusqu'à ce qu'elles soient fusionnées à l'étape finale.[3]
et[2,1]
, alors ceux-ci sont sur des branches différentes, donc nous ne pouvons pas fusionner[3]
et[2]
après[2,1]
est divisé en[2]
et[1]
.Réponses:
Haskell ,
137128127125121109106 octets(-2) + (- 4) = (- 6) octets grâce à nimi ! Le modifier pour collecter toutes les étapes d'une liste (à nouveau en raison de nimi) permet d'économiser 12 octets supplémentaires.
Encore 3 octets dus à Laikoni , avec une liaison de garde de modèle et une utilisation intelligente de la compréhension de liste pour coder la garde.
Essayez-le en ligne!
Le fractionnement des listes en éléments impairs et pairs est un code plus court qu'en deux moitiés séquentielles, car nous sommes épargnés d'avoir à mesurer le
length
, alors.Fonctionne en "imprimant" les listes, puis en répétant avec les listes de partage (
x >>= h
) s'il y a effectivement eu un fractionnement, et en "imprimant" les listes triées; en commençant par la seule liste d'entrée; en supposant l'entrée non vide. Et au lieu de l'impression réelle, il suffit de les rassembler dans une liste.La liste produite par
g[[6,5..1]]
, imprimée ligne par ligne, est la suivante:la source
p=print
et trois foisp
. Essayez-le en ligne!g
vous pouvez collecter toutes les étapes d'une liste et la renvoyer. Essayez-le en ligne!g x|y<-x>>=h=x:[z|x/=y,z<-g y++[sort<$>x]]
enregistre quelques octets supplémentaires.Wolfram Language (Mathematica) ,
146127111 111102 octetsEssayez-le en ligne!
Renvoie un
List
qui contient les étapes.Explication
Dans une entrée, divisez tous les
List
s contenant 2 ou plusieurs entiers en deux. La première sous-liste contient les éléments indexés impairs (indexés 1) et la seconde les éléments indexés pairs.Répétez cela jusqu'à ce que rien ne change (c'est-à-dire que toutes les sous-listes sont de longueur 1). Conservez tous les résultats intermédiaires. Stockez-le (le
List
de toutes les étapes) dansu
.Déposez le dernier élément de
u
et inversez-le.À partir du résultat ci-dessus, triez toutes les occurrences d'une liste d'entiers.
la source
Nettoyer ,
228206168157 157140121104 octetsConstruit la liste des étapes à partir des extrémités, en utilisant le fait que l'
n
élément -th à partir de la fin est la version triée de l'n
élément -th depuis le début.Idée du commentaire de JungHwan Min
Essayez-le en ligne!
la source
Charbon de bois ,
145133123122 octetsEssayez-le en ligne! Le lien est vers la version détaillée du code.
Toujours à contourner les bugs de charbon de bois ...Edit: sauvé 5 octets en utilisant un doubleMap
comme compréhension de tableau d'un pauvre. Enregistré 4 octets en utilisantPop
pour double itérer sur un tableau. Enregistré 3 octets en utilisant la concaténation au lieu dePush
. Économisé 10 octets en proposant unewhile
condition de golfeur qui évite également un bug de charbon de bois. Économisé 1 octet en découvrant que Charcoal a effectivement un opérateur de filtre. Explication:Divisez l'entrée sur des espaces, puis encapsulez le résultat dans un tableau externe, en l'enregistrant
q
.Répétez l'opération alors que le premier élément de
q
possède plusieurs éléments. (Le premier élément deq
contient toujours le plus d'éléments en raison de la façon dont les listes sont divisées en deux.)Imprimez les éléments de
q
jointure avec des espaces et des lignes verticales. (Le tableau entraîne l'impression du résultat sur sa propre ligne. Il existe d'autres façons d'y parvenir pour le même nombre d'octets.)Créez une liste en dupliquant chaque élément de
q
, puis mappez sur cette liste et prenez la moitié de chaque liste (en utilisant l'approche des éléments alternatifs), en enregistrant le résultatq
.Imprimer les éléments de
q
jointure avec des espaces et des lignes verticales. En fait, à ce stade, les éléments deq
sont des listes vides ou à un seul élément, donc les joindre les convertit simplement en chaînes vides ou en leurs éléments. Les chaînes vides ajouteraient des lignes de fin inutiles afin qu'elles soient filtrées. Un opérateur aplati aurait été plus golfeur (quelque chose comme⟦⪫Σθ|⟧
).Répéter tout en
q
ayant plusieurs éléments. (Le code suivant nécessite un nombre pair d'éléments.)Copiez
q
dansh
, mais inversé (voir ci-dessous) et réinitialisez-leq
dans une liste vide.Répétez jusqu'à ce qu'il
h
soit vide.Extrayez l'élément suivant de
h
intoe
. (Pop
extraits de la fin, c'est pourquoi je dois inverserq
.)Initialisez
z
sur une liste vide.Faites une boucle sur les éléments de l'élément suivant de
h
.Copier
e
àd
et remettree
à une liste vide.Faites une boucle sur les éléments de
d
.Poussez-les vers
z
oue
selon qu'ils sont plus petits que l'élément actuel de l'élément suivant deh
.Appuyez sur l'élément actuel de l'élément suivant de
h
toz
.Concaténer
z
avec tous les éléments restantse
et pousserq
. Ceci termine la fusion de deux éléments deh
.Imprimer les éléments de
q
jointure avec des espaces et des lignes verticales.la source
while (...Map(...)...)
bug dont je vous ai déjà parlé.Python 2 ,
145144 octetsIdée du commentaire de JungHwan Min
-1 octet grâce à Jonathan Frech
Essayez-le en ligne!
la source
<2
au lieu de==1
.JavaScript (ES6), 145 octets
Prend l'entrée comme un tableau dans un tableau, c'est-à-dire
f([[6,5,4,3,2,1]])
. Fonctionne en générant les première et dernière lignes de la sortie, puis en se divisant et en se rappelant, jusqu'à ce que chaque sous-tableau ait une longueur 1. Voici une démonstration de base de son fonctionnement:la source
Husk , 14 octets
Prend un tableau contenant un seul tableau. Essayez-le en ligne!
Explication
L'intégré
½
prend un tableau et le divise au milieu. Si sa longueur est impaire, la première partie est plus longue d'un élément. Un tableau singleton[a]
donne[[a],[]]
et un tableau vide[]
donne[[],[]]
, il est donc nécessaire de supprimer les tableaux vides avant d'appliquerU
.la source
Stax ,
116 (÷ 3>)3829 octets CP437-9 octets par commentaire de @recursive. Maintenant, l'entrée est donnée comme un singleton dont le seul élément est un tableau des nombres à trier.
Essayez-le en ligne!
Version non compressée avec 35 octets:
Explication
Le code peut être divisé en deux parties. La première partie visualise le fractionnement et la seconde visualise la fusion.
Code pour visualiser le fractionnement:
Le code pour visualiser la fusion:
Ancienne version, en train de construire la structure de liste imbriquée.
cc0+=
est utilisé trois fois dans le code pour vérifier si le haut de la pile est un scalaire ou un tableau.{{cc0+=!{x!}Mm',*:}}X
construit un bloc qui s'appelle récursivement pour sortir correctement un tableau de nombres imbriqué. (La sortie par défaut dans Stax vectorise un tableau imbriqué avant l'impression).Il y a deux autres blocs qui effectuent le fractionnement et la fusion, respectivement. Ils sont trop verbeux et je ne me soucie pas d'expliquer (il y a un peu plus d'informations dans la version historique de ce post mais ne vous attendez pas à trop).
la source
cH!
peut être utilisé à la place decH%!
.{Nd}M
peut également être remplacé parT
.