Comme discuté dans le salon sur Stack Overflow:
si vous ne pouvez pas implémenter l'algorithme Quicksort donné en.wikipedia.org/wiki/Quicksort dans n'importe quelle langue que vous avez une connaissance minimale, vous voudrez peut-être envisager une profession différente. @sbi
mais SBI a également noté que BrainF *** était peut-être une exception.
Voici donc le puzzle / défi: implémentez QuickSort dans BrainF *** . La mise en œuvre doit
code-challenge
sorting
brainfuck
Ronald
la source
la source
Réponses:
BrainF * (697 octets)
Voici une version annotée. Afin de garder une trace de ce qui devait se produire lors de son développement, j'ai utilisé une notation de commentaire qui ressemble à ceci:
|a|b=0|c=A0|@d|A0|A1|```|
La mémoire est disposée avec une pile croissante de partitions à traiter à gauche, un espace de travail au centre et le tableau trié à droite. L'indexation des tableaux est gérée en déplaçant un "bus de données" contenant l'index et l'espace de travail à travers le tableau. Ainsi, par exemple, un bus à 3 voies de
|i|data|0|A0|A1|A2
, deviendra|A0|i-1|data|0|A1|A2
après un décalage d'un. Le partitionnement est effectué en gardant le bus entre les éléments haut et bas.Voici la version complète:
la source
if (i<j) {} else {}
pris plusieurs tentatives pour bien faire les choses . Et les cas marginaux sont des tueurs. Je ne sais pas combien de fois j'ai pensé "juste cette petite chose qui restait ...", puis j'ai découvert un cas de test qui a causé un autre travail de plusieurs heures. Je pense que je peux le réduire de quelques dizaines de caractères, mais je ne suis pas sûr de vouloir faire l'effort.brainfuck (178 octets)
Même si le brainfuck est lourd, cela aide à travailler avec le grain de la langue. Demandez-vous "Dois-je stocker cette valeur explicitement dans une cellule?" Vous pouvez souvent gagner en vitesse et en concision en faisant quelque chose de plus subtil. Et lorsque la valeur est un index de tableau (ou un nombre naturel arbitraire), elle peut ne pas tenir dans une cellule. Bien sûr, vous pouvez simplement accepter cela comme une limite de votre programme. Mais la conception de votre programme pour gérer de grandes valeurs l'améliorera souvent par d'autres moyens.
Comme d'habitude, ma première version de travail était deux fois plus longue que nécessaire - 392 octets. De nombreuses modifications et deux ou trois réécritures majeures ont produit cette version relativement gracieuse de 178 octets. (Bien qu'amusamment, une sorte de temps linéaire n'est que de 40 octets.)
Les valeurs d'entrée sont espacées toutes les trois cellules: pour chaque cellule de valeur (V), il y a une cellule (L) abel (utilisée pour la navigation) et une cellule de plus pour (S) l'espace de capture. La disposition générale du tableau est
0 1 0 0 0 SVLSVL ... SVL 0 0 0 0 0 0 ...
Initialement, toutes les cellules L sont définies sur 1, pour marquer les parties du tableau qui doivent encore être triées. Lorsque nous avons terminé de partitionner un sous-tableau, nous le divisons en sous-réseaux plus petits en définissant la cellule L de son pivot sur 0, puis localisons la cellule L la plus à droite qui est toujours 1 et partitionnons ce sous-tableau suivant. Curieusement, c'est toute la comptabilité dont nous avons besoin pour gérer correctement le traitement récursif des sous-réseaux. Lorsque toutes les cellules L ont été mises à zéro, l'ensemble du tableau est trié.
Pour partitionner un sous-tableau, nous tirons sa valeur la plus à droite dans une cellule S pour agir comme pivot, et l'amener (et la cellule V vide correspondante) à gauche, en le comparant aux autres valeurs du sous-tableau et en échangeant si nécessaire. À la fin, le pivot est de nouveau échangé, en utilisant le même code de swap (ce qui économise environ 50 octets). Pendant le partitionnement, deux cellules L supplémentaires sont maintenues à 0, pour marquer les deux cellules qui peuvent avoir besoin d'être échangées l'une avec l'autre; à la fin du partitionnement, le 0 gauche fusionnera avec le 0 à gauche du sous-tableau, et le 0 droit finira par marquer son pivot. Ce processus laisse également un 1 supplémentaire dans la cellule L à droite du sous-tableau; la boucle principale commence et se termine à cette cellule.
la source