# Tri rapide de crêpes brûlées

L'algorithme de Gates que nous avons vu dans l'exercice précédent trie rapidement les crêpes non brûlées en augmentant constamment la taille de sous-séquences triées dans la pile. Cela va bien plus vite que l'algorithme naïf qui déplace à chaque étape la plus grande crêpe en bas de la pile non-triée. L'algorithme de Gates trie une pile de n crêpes en moins de (5n + 5)/3 étapes dans le pire des cas là où l'algorithme naïf nécessite 2n étapes. L'algorithme de Gates est donc un tiers plus rapide dans le pire des cas.

Dans cet exercice, nous allons explorer une adaptation de la même idée aux crêpes brûlées. Cet algorithme fut tout d'abord publié par David X. Cohen et Manuel Blum. Quelques années après, David Cohen lançait avec un ami la série Futurama, remplie de blagues mathématiques. Décidément, ce petit problème de crêpes a inspiré des gens intéressant...

L'algorithme de Cohen est un peu plus simple que celui de Gates, car il distingue moins de cas :

Cas 1 : Au moins une crêpe est à l'endroit dans la pile. Soit p la plus grande des crêpes à l'endroit. Notez que p + 1 est donc forcément à l'envers, à moins que p = n (auquel cas il n'y a pas de crêpe p + 1).

- Cas 1.a : p+1 est placée plus bas que p dans la pile.
- Cas 1.b : p+1 est placée plus haut que p dans la pile.
- Cas 1.c : Il n'y a pas de crêpe p + 1 car p est la plus grande crêpe de la pile (c'est à dire que p = n). Si la crêpe p est déjà en position, il n'y a rien à faire. Dans le cas contraire, on peut l'amener en bas de la pile en deux opérations :
  Le truc est que la crêpe p ne doit plus jamais être considérée après cela. Dans le cas contraire, vous allez considérer cette crêpe encore et encore puisqu'elle est à l'endroit et que c'est la plus grande des crêpes. Pour la laisser en paix, vous devez garder trace de la taille de la pile restant à trier. Tout balayage de la pile de crêpes doit se limiter aux crêpes restant à trier, sans considérer celles étant déjà en position en bas de la pile.

Cas 2 : Toutes les crêpes sont à l'envers. À nouveau, nous distinguons deux sous-cas.

- Cas 2.a : Il y a au moins une crêpe p pour laquelle p+1 est placée au dessus de p dans la pile (s'il y a plusieurs tels p, prenez le plus grand).
- Cas 2.b: Chaque crêpe p est placée plus bas que sa crêpe p+1. Dans ce cas, nous avons forcément la situation suivante :

Dans les cas 1 ou 2.a, nous pouvons fusionner deux crêpes qui doivent se suivre en deux opérations. Puisque nous devons réaliser n fusions de ce genre pour trier la pile, nous pouvons trier la pile en 2n opérations si le cas 2.b n'arrive jamais.

Ce cas 2.b nécessite un traitement particulier puisqu'il est impossible de fusionner deux crêpes qui doivent se suivre en deux étapes seulement. Fort heureusement, une seule configuration de pile rentre dans ce cas de figure. Nous pouvons alors utiliser l'algorithme suivant, conçu pour tirer partie de cette configuration. Cet algorithme trie alors toute la pile en exactement 2n opérations.

    Répéter n fois
        Inverser toute la pile de n crêpes
        Inverser les (n-1) crêpes placées au sommet de la pile

Cela peut sembler un peu magique, mais cela fonctionne. Le dessin ci-dessous montre même comment.

Donc, dans tous les cas, l'algorithme de Cohen parvient à trier une pile de crêpes brûlées en 2n étapes, dans tous les cas. C'est mieux que l'algorithme naïf pour crêpes brûlées, qui nécessite 3n étapes.

Pas de panique, cet exercice est très difficile, et il est donc normale de ne pas y parvenir du premier coup. Ajouter des affichages à votre code pour voir les différentes étapes, et ainsi comprendre le moment où votre algorithme cesse de se comporter correctement. Assurez vous d'utiliser la méthode `isSelected()` pour que vos affichages n'aient lieu que pour le monde en cours d'affichage. En particulier, cela peut aider d'afficher textuellement l'état du monde à chaque fois que vous entrez dans la boucle principale.