# Tri rapide de crêpes

Contrairement aux problèmes classiques de tri, l'opération coûteuse à économiser n'est pas la comparaison des valeurs, mais le retournement des crêpes. Dans cet exercice, nous allons explorer un autre algorithme permettant de réduire le nombre de retournements nécessaires pour trier la pile. Fait amusant, cet algorithme a été proposé pour la première fois par Bill Gates, avant qu'il n'invente Windows.

L'idée de base est de faire grandir des séquences de crêpes triées, pas forcément en commençant du bas de la pile. On dira qu'un ensemble de crêpes dans l'ordre constitue un block tandis qu'une crêpe qui n'est pas dans un bloc est dite libre. L'algorithme considère la crêpe tout en haut de la pile, dont la taille est notée `t`, et cherche les deux crêpes de taille `t-1` et `t+1` (le voisin ainsi considéré est noté `t+o`). Huit cas sont possibles alors :

- Cas a: `t` et `t+o` sont tous les deux libres. Ils sont alors fusionnés en un retournement.

- Cas b: `t` est libre, et `t+o` est le premier élément d'un bloc. Ils sont fusionnés en un bloc.

- Cas c: `t` est libre, mais `t-1` et `t+1` sont tous les deux les derniers éléments de blocs. Ces deux blocs ainsi que `t` sont tous fusionnés en 4 retournements. Prenez garde, si `t-1` ou `t+1` n'existe pas (parce que `t` est 0 ou max), seulement deux de ces retournements sont nécessaires.

- Cas d: `t` est dans un bloc, mais `t+o` est libre. Ils sont fusionnés en un retournement.

- Cas e: `t` est dans un bloc, et `t+o` est le premier élément d'un bloc. Ils sont fusionnés en un retournement.

- Cas f: `t` est dans un bloc, et `t+o` est le dernier élément d'un autre bloc. Ils sont fusionnés en trois retournements comme suit.

- Cas g: `t` est dans un bloc de taille k+1 (le dernier élément est `t+ko`), `t+(k+1)o` est soit libre soit le dernier élément d'un autre bloc. Les deux blocs sont fusionnés en deux retournements:

- Cas h: `t` est dans un bloc de taille k+1 (le dernier élément est `t+ko`), `t+(k+1)o` est le premier élément d'un autre bloc (la différence avec le cas g est que `t+(k+1)o` est maintenant le premier élément de son bloc). Les deux blocs sont fusionnés en deux retournements:

- Cas i: `t` est dans un bloc de taille `n`, qui contient donc toutes les crêpes. Si `t` n'est pas 1, toute la pile est retournée. Ensuite, l'algorithme s'arrête.

Chaque itération augmente la taille des blocs, donc la terminaison de l'algorithme est certaine. Une analyse plus fine montre qu'il prend au plus `(5n+5)/3` étapes pour trier la pile. C'est mieux que l'algorithme naïf, qui nécessite `2n-3` étapes pour cela.

## À vous de jouer

Vous avez maintenant quasi assez d'informations pour implémenter cet algorithme par vous-même. Il faut juste lever les dernières ambiguïtés pour que vous implémentiez exactement le même algorithme que la correction. Si plusieurs cas s'appliquent à la situation courante, appliquez le premier. Par exemple, si les cas a et b s'appliquent (avec `t-1` pour le cas a et `t+1` pour le cas b), vous devez appliquer les instructions du cas a. Si un cas donné s'applique à la fois pour `t+1` et `t-1`, appliquez le pour `t+1`.

Cet exercice est plus difficile que ceux que nous avons fait jusque là, et il ne serait pas choquant que vous ayez besoin d'un peu plus de temps que les autres pour le résoudre. Mais n'abandonnez pas, vous pouvez le faire !

Commencez par écrire des fonctions d'aide, comme `estLibre()` ou `estPremier()`. Cela simplifiera l'écriture de votre algorithme, qui peut être écrit sous une forme très similaire à l'énoncé si vous faites les bonnes fonctions d'aide. Factoriser ainsi votre code aide très souvent à améliorer la lisibilité du code.

Pour débugger un monde après l'autre, il est préférable d'éviter que les affichages de tous les mondes se mélangent. Le plus simple pour cela est d'utiliser la méthode `isSelected()` qui ne renvoi vrai que si le monde courant est celui sélectionné dans l'interface. Cela aidera à réduire la complexité en résolvant les problèmes les uns après les autres.
En particulier, afficher l'état du monde sous forme textuelle à chaque fois que vous rentrez dans la boucle principale peut aider.