#include #include #define N 4 /* Taille du cube */ #define Taille N*N*N /* Nombre de petits cubes */ //#define Nb_sit 1 /* Nombre de situations de départ : pour 2, une seule */ #define Nb_sit 6 /* Nombre de situations de départ : pour 3 et 4, il y en a 3 */ /* Pour le cube d'ismael : 6 */ #define D 3 /* On travaille en 3 dimensions */ /* NB : pas adapté à faire autre chose que 3 dimensions ! Ou en tous cas pas sans un peu de boulot */ #define STOP 0 /* STOP : est-ce qu'on s'arrête après avoir trouvé une solution. Quand STOP vaut 0, il teste tout ! */ #define V 0 /* Mode verbeux (attention les zyeux) */ /* Pour changer la taille : changer N, changer la séquence des longueurs (en dessous), et changer l'initialisation (voir le main) */ // nombre de situations testées static int nb_tests = 0 ; /* La séquence des longueurs : spécifique au cube */ /* N = 3 */ //int sequence[Taille] = //{ 3, 0, 0, 1, 1, 2, 0, 1, 2, 0, 1, 1, 2, 0, 2, 0, 1, 1, 1, 2, 0, 2, 0, 2, 0, 2, 0 } ; /* N = 2 */ /*int sequence[N*N*N] = { 2, 0, 1, 1, 1, 1, 1, 1} ; */ /* N = 4 */ /* int sequence[Taille] = { 4, 0, 0, 0, 1, 1, 3, 0, 0, 3, 0, 0, 1, 2, 0, 2, 0, 1, 1, 1, 1, 3, 0, 0, 3, 0, 0, 1, 1, 1, 2, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 2, 0, 1, 3, 0, 0, 1, 1, 1, 1, 1, 2, 0 } ; */ // Cube d'Ismael int sequence[Taille] = { 3, 0, 0, 1, 2, 0, 1, 1, 3, 0, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 2, 0, 1, 1, 1, 1, 1, 2, 0, 3, 0, 0, 1, 1, 1, 3, 0, 0, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 0, 1 } ; /* La liste des orientations possibles */ int orientations[2*D][D] = { {0, 0, 1}, {0, 0, -1}, { 0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0} } ; /*** Structure ***/ typedef struct Situation { int Cube[N][N][N] ; /* Le cube, rempli d'entiers */ int X ; /* Coord du dernier cube qu'on y a mis */ int Y ; int Z ; int Orientation[D] ; /* L'orientation du dernier cube : par ex (0, +1, 0) */ int Num ; /* Le numéro du dernier cube qu'on y a mis */ } t_sit ; int taillesituation=sizeof(struct Situation) ; /*********************************************/ /*** Affichage ***/ /* Affichage du cube */ void affiche_cube(int (*cube)[N][N][N]) { int i, j, k ; for(k=0;k Cube : \n") ; affiche_cube(&situation->Cube) ; printf("-> Coordonnées du dernier cube : %i, %i, %i\n", situation->X, situation->Y, situation->Z) ; printf("-> Numéro du dernier cube : %i\n", situation->Num) ; printf("-> Orientation : %i, %i, %i\n", situation->Orientation[0], situation->Orientation[1], situation->Orientation[2]) ; return ; } /********************************************/ /*** Fonctions d'initialisation diverses ***/ /* Vérifie que la séquence a la bonne taille */ int verif_sequence(int* seq) { int somme=0 ; int i ; for(i=0; iCube[i][j][k] = 0 ; // l'orientation : rien pour le moment for(i=0; iOrientation[i] = 0 ; } // le reste situation->X = 0 ; situation->Y = 0 ; situation->Z = 0 ; situation->Num = 0 ; return situation ; } /* Effectue une copie de la situation. */ void copie_sit(t_sit *originale, t_sit *nouvelle) { int i, j, k ; // copie du cube for(i=0; iCube[i][j][k] = originale->Cube[i][j][k] ; // copie de l'orientation for(i=0; iOrientation[i] = originale->Orientation[i] ; } // copie du reste nouvelle->X = originale->X ; nouvelle->Y = originale->Y ; nouvelle->Z = originale->Z ; nouvelle->Num = originale->Num ; return; } /* Prépare une situation de départ : on donne un point de départ du cube et l'orientation, et la fonction "place" la première séquence dans le cube */ /* depart est censée être une situation déjà initialisée */ int prepare(t_sit * depart, int x, int y, int z, int* orientation) { int longueur, i, xp, yp, zp ; // la longueur de la première séquence longueur = sequence[0] ; if(V) printf("Initialisation : longueur de la première séquence : %i\n", longueur) ; // coordonnées du cube à mettre xp = x ; yp = y ; zp = z ; for(i=0; iCube[xp][yp][zp] = i+1 ; if(i != longueur -1) { xp += orientation[0] ; yp += orientation[1] ; zp += orientation[2] ; } } if(V) printf("Initialisation : cubes placés\n") ; depart->Num = longueur ; // copie de l'orientation for(i=0; iOrientation[i] = orientation[i] ; // la position du dernier cube depart->X = xp ; depart->Y = yp ; depart->Z = zp ; return 1 ; } /***********************************************/ /*** Manipulation du cube ***/ // Est-ce que les coordonnées sont hors du cube ? int hors_cube(int x, int y, int z) { return (x<0 || x>=N || y<0 || y>=N || z<0 || z>=N) ; } // Vérifie que deux orientations sont compatibles, ie si elles sont bien différentes (sans compter le sens) // ex : (1, 0, 0) et (0, -1, 0) ok, mais pas (1, 0, 0) et (-1, 0, 0) int valide_orientations(int* orient1, int* orient2) { return (abs(orient1[0]) != abs(orient2[0]) || abs(orient1[1]) != abs(orient2[1]) || abs(orient1[2]) != abs(orient2[2]) ) ; } /* teste de placer les cubes suivants selon l'orientation donnée */ /* Renvoie une situation t_sit. Si ça plante, on renvoie la situation, mais avec Num=-1 */ t_sit * tester_cas(t_sit * situation, int * nouvelle_orientation) { int i, longueur ; int x, y, z, num ; // incrémentation du nombre de tests nb_tests++ ; // copie de la situation actuelle t_sit *situation2 ; situation2 = malloc(taillesituation) ; copie_sit(situation, situation2) ; if(V) { printf("Tester_cas : situation actuelle : \n") ; affiche_situation(situation) ; printf("-----\n") ; } // quelle est la longueur de la prochaine séquence ? longueur = sequence[situation->Num] ; if(V) printf("Tester_cas : longueur de la séquence à appliquer : %i\n", longueur) ; if(longueur ==0) { printf("Tester_cas : problème >_< : la séquence à appliquer est de longueur nulle...\n") ; printf("Situation obtenue :\n") ; affiche_situation(situation) ; } x = situation2->X ; y = situation2->Y ; z = situation2->Z ; num = situation2->Num ; for(i=0; iCube[x][y][z]>0) { if(V) { printf("Tester_cas %i : l'orientation (%i, %i, %i) ne marche pas\n", i, nouvelle_orientation[0], nouvelle_orientation[1], nouvelle_orientation[2]) ; printf("Nouvelles coordonnées : %i, %i, %i\n", x, y, z) ; } situation2->Num = -1 ; return situation2 ; } // c'est bon ! if(V) printf("Tester_cas %i : l'orientation (%i, %i, %i) marche\n", i, nouvelle_orientation[0], nouvelle_orientation[1], nouvelle_orientation[2]) ; num++ ; // il ne faut pas oublier que num commence à 0 situation2->Cube[x][y][z] = num ; } if(V) printf("Tester_cas : tout bon\n") ; // tout a été bon jusque là, on remet dans la structure situation2->X = x ; situation2->Y = y ; situation2->Z = z ; situation2->Num = num ; // copier la nouvelle orientation for(i=0; iOrientation[i] = nouvelle_orientation[i] ; if(V) { printf("Nouvelle situation : \n") ; affiche_situation(situation2) ; printf("-----\n") ; } return situation2 ; } /********** La résolution **********/ int resoudre(t_sit * situation) { int i ; int reussi ; t_sit *retour ; // si on est arrivé à la fin de la séquence if(situation->Num == Taille) { printf("Solution trouvée, youhouuuu \\o/\n\n") ; affiche_cube(&(situation->Cube)) ; printf("--------------\n") ; printf("Nombre de cas testés jusque là : %i\n",nb_tests) ; if(STOP) return 1 ; else return 0 ; } for(i=0; i<6; i++) { // est-ce que cette orientation est valide ? if(valide_orientations(situation->Orientation, orientations[i])) { if(V) printf("Test de l'orientation : %i, %i, %i\n", orientations[i][0], orientations[i][1], orientations[i][2]) ; // tester ce cas précis retour = tester_cas(situation, orientations[i]) ; if(retour->Num ==-1) { if(V) printf("Test échoué ! On passe à la suite\n") ; } else { // on récurre reussi = resoudre(retour) ; if(reussi) return 1 ; // si pas réussi, il faut tester d'autres orientations ! } // libérer la situation qu'on a testée free(retour) ; } } if(V) printf("Toutes les orientations sont testées.\n") ; return 0 ; } /****************************************************/ int main(argc, argv) { int i ; if(!verif_sequence(sequence)) { printf("La séquence des cubes n'est pas valide, c'est mal barré !\n") ; return 1 ; } // Créer les situations de départ /* Situations de départ */ t_sit * situations_depart[Nb_sit] ; for(i=0; i