Modélisation du cube
Objectif
- modéliser l'état du cube
- être économe en mémoire
- permettre une économie d'opérations lors des rotations
- implémenter les rotations sur le cube
Les choix
Modélisation des petits cube.
Idée : data['FRU'] = ['R', 'B', 'G']
pour signaler que le cube front-right-up est rouge-bleu-vert
Ainsi, lors d'une rotation, on économise quelques opérations par rapport au stockage des 48 face de couleurs.
Par exemple : lors de la rotation d'une face, il y a rotation d'un coin.
Pour ce coin, dans la méthode des 48 faces, il faut effectuer modifications (pour les 3 faces du coin), là où la méthode des petits cubes permet une unique affectation.
De même pour une arrête : 2 modifications pour la méthodes des faces contre une modification unique pour la méthodes des petits cubes.
Mais un coin peut effectuer une rotation sur lui même (par exemple pour FRU, faire les rotations R puis U).
On doit donc également stocker l'état de rotation du cube par rapport à son état initial.
Pour une arrête : 2 états. Pour un coin : 3 états.
Ainsi :
cubes[<coin>] = [<couleur>, <couleur>, <couleur>, <état>] #un coin
cubes[<arête>] = [<couleur>, <couleur>, <état>] #une arête
Exemple : actions R puis U sur le cube FRU
start : FRU = [W, B, O, 0] #état de rotation initial = 0
R : RBU = FRU;
RBU[3] += 1 #le cube a tourné
On voudrait avoir RBU = [B, O, W]
mais ça nous oblige à faire 3 opérations.
U : FRU = RBU #ici, le cube n'a pas tourné
Donc, get_facette('FRU', 0)
(on demande la facette F) ne doit pas renvoyer W
, mais B
. Et cela est rendu possible par l'information d'état de rotation.
Calcul du nombre d'opérations pour une rotation d'une face :
- option des 54 facettes 19 facettes à bouger, donc 19 opérations d'affectation
- options des cubes
- 4 coins à bouger (4 affectations, 4 incrémentation/décrémentation dans le pire des cas)
- 4 arêtes à bouger (idem)
= 16 opérations (seulement 3 de moins que l'option des 54 facettes, mais la situation où touts les cubes de la face tournent sur eux même n'arrive que 1/3 des fois)
Avantages de l'option des cubes :
- un peu moins d'opérations
- un concept plus proche de la réalité pour les développeurs
- modélise la relation d'appartenance des facettes à un petit cube
- plus facile de vérifier la validité du rubik's cube donné (pas de couleurs opposées dans un petit cube)
Inconvénients :
- impact en mémoire plus lourd ? (dictionnaire ou tableau de tableau)
- opérations plus coûteuses sur un dictionnaire ou sur un tableau de tableau ?
Modélisation des couleurs
On code le stockage des couleurs. Pas de chaînes de caractères mais un entier. Gain de place en mémoire.
White (W) = 0
Blue (B) = 1
Red (R) = 2
Green (G) = 3
Orange (0) = 4
Yellow (Y) = 5
Implémentation
Dans un premier temps :
- on choisi d'utiliser un dictionnaire pour stocker chaque petit cube
- chaque petit cube pointe sur un tableau
numpy
(plus léger qu'une liste Python)
Utiliser un tableaunumpy
pour stocker les couleurs d'un petit cube.
Exemple :[0, 5]
pour blanc-jaune (arête impossible).
Implémentation rapide pour lancer le projet (lecture, résolution).
cube.data = {
'FRU' : [0, 2]
...
}
Dans un second temps, envisager :
-
abandon du dictionnaire
Coder chaque cube comme un entier dans [0, 20] et utiliser un tableaunumpy
.
exemple :[<listes des couleurs de FRU>, <liste des couleurs de FU>, ...]
-
abandon du tableau
numpy
pour le stockage des couleurs d'un coin et utiliser des entiers (gain de place). exemple :523
code un coincoin = 523 a = coin // 100 // 5 b = coin // 10 % 10 // 2 c = coin % 10 // 3
À voir si c'est plus rapide lors de l'accès aux couleurs.