Posté par
_Michel _Michel
Bonjour.
J'ai trouvé une solution pour 13 cases, et je crois qu'elle est unique à la symétrie près :
-X---X---
--X---X--
---X---X-
X---X---X
-X---X---
--X---X--
Preuve : j'ai fait un petit programme en C qui "brute force" le problème en testant (presque) tous les tableaux d'un nombre fixé de cases noircies. Puisqu'il ne me donne aucune réponse pour 12 cases, j'en déduit qu'il n'existe pas de solution pour moins de 13 cases.
Voila le code source, que j'ai voulu à la fois clair et rapide (il l'est : il ne met que 3h30 sur mon P4 !), bien que je ne soit doué ni pour l'un ni pour l'autre):
//Le tableau de 9*6 est représenté par un long long : les 9*6 premiers bits représentent les 9*6 cases.
//Les 112 exemplaires du T sont rangés dans des masques appliqués à chaque tableau candidat pour déterminer s'il est une solution.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Initialise le premier tableau à NbrCroix croix.
void InitialiseTableau ();
// Remplace le tableau par le tableau suivant selon un algorithme qui présente toutes les tableaux possibles.
// Initialisation avec InitiliseTableau() nécessaire.
// Retourne -1 si tous les tableaux ont été testés, 0 sinon.
// Attention : comportement indéterminé sur un tableau de 0 croix ou plus de 54.
long IncrementeTableau ();
// Informations sur le tableau
unsigned long long Tableau;
int DerniereCroix;
int TailleBloc;
int AvantDerniereCroix;
int NbrCroix;
int main()
{
int i, j;
unsigned long long ProtoT;
unsigned long long T[112];
clock_t cDebut, cFin;
int SolutionTrouvee;
// *** Initialisation des masques T : détermine les 112 formes de T ***
// Note : les bits de poids fort ne sont pas utilisés.
// Rotation de 0°
// 111
// 010
// 010 => 000000111 000000010 000000010 => ...000 00011100 00000100 00000010
ProtoT = 0x1C0402;
for (i=0; i<4; i++) {
for (j=0; j<7; j++) {
T[(i*7)+j] = ProtoT<<((9*i)+j);
}
}
// Rotation de 90°
// 100
// 111
// 100 => 000000100 000000111 000000100 => ...000 00010000 00001110 00000100
ProtoT = 0x100E04;
for (i=0; i<4; i++) {
for (j=0; j<7; j++) {
T[(4*7)+(i*7)+j] = ProtoT<<((9*i)+j);
}
}
// Rotation de 180°
// 010
// 010
// 111 => 000000010 000000010 000000111 => ...000 00001000 00000100 00000111
ProtoT = 0x080407;
for (i=0; i<4; i++) {
for (j=0; j<7; j++) {
T[(2*4*7)+(i*7)+j] = ProtoT<<((9*i)+j);
}
}
// Rotation de 270°
// 001
// 111
// 001 => 000000001 000000111 000000001 => ...000 00000100 00001110 00000001
ProtoT = 0x040E01;
for (i=0; i<4; i++) {
for (j=0; j<7; j++) {
T[(3*4*7)+(i*7)+j] = ProtoT<<((9*i)+j);
}
}
// *** Test de tous les tableaux possible avec un nombre croissant de croix ***
SolutionTrouvee = 0;
cDebut = clock ();
for (NbrCroix = 12; (NbrCroix<13)&&(SolutionTrouvee==0); NbrCroix++) {
// Teste tous les tableaux à NbrCroix croix : 54!/(NbrCroix!*(54-NbrCroix)!) tableaux
printf ("*** Test des tableaux contenant %d croix.\n", NbrCroix);
SolutionTrouvee = 0;
InitialiseTableau(NbrCroix);
do {
long boolSolution;
//// Affichage pour le débuggage
//printf ("Test du tableau : \n");
//for (i=0; i<6; i++){
// for (j=0; j<9; j++) {
// if ((Tableau>>(53-((i*9)+j))&1) == 0) {
// printf ("X");
// } else {
// printf ("-");
// }
// }
// printf ("\n");
//}
// Teste le tableau candidat.
boolSolution = 1;
for (i=0; i<112; i++) {
if ((Tableau&T[i])==T[i]) {
boolSolution = 0;
break;
}
}
if (boolSolution == 1) {
SolutionTrouvee += 1;
printf ("Solution trouvée !\n");
for (i=0; i<6; i++){
for (j=0; j<9; j++) {
if ((Tableau>>(53-((i*9)+j))&1) == 0) {
printf ("X");
} else {
printf ("-");
}
}
printf ("\n");
}
}
} while (IncrementeTableau () == 0);
printf ("\n");
}
cFin = clock ();
printf ("Fin des tests.\n");
printf ("Nombre de solutions trouvées : %d.\n", SolutionTrouvee);
printf ("Temps = %f.\n", (float)(cFin-cDebut) / CLK_TCK);
system ("PAUSE");
}
void InitialiseTableau ()
{
// Coche les NbrCroix cases (bits) de poids fort du tableau
if (NbrCroix == 0) {
exit (-1); // pour éviter un problème avec IncrementeTableau()
} else if (NbrCroix == 54) {
Tableau = 0ULL;
DerniereCroix=0;
AvantDerniereCroix=54;
} else {
Tableau = (~0ULL)>>(NbrCroix+10);
DerniereCroix=54-NbrCroix;
TailleBloc = 1;
AvantDerniereCroix=DerniereCroix+1;
}
}
long IncrementeTableau ()
{
// Determine si la case suivante de la case contenant la dernière croix existe.
if (DerniereCroix != 0)
{
// On déplace la croix d'une case.
Tableau = (Tableau | (1ULL<<DerniereCroix)) & ~(1ULL<<(DerniereCroix-1));
DerniereCroix -= 1;
} else {
int AvantDerniereCroixTmp;
int i;
// optimisation de 28% du temps d'execution !!!
if (TailleBloc == NbrCroix-1) {
if ((AvantDerniereCroix == 45) && ((Tableau>>45) == 0x01FE)) {
return -1;} // Plus de solution pour un tabbeau avec NbrCroix < 14
}
// Il faut déplacer un bloc ...
if (AvantDerniereCroix == 54) {
return -1;} // Plus de tableau
// Decoche la case
Tableau = Tableau | (1ULL<<AvantDerniereCroix);
for (i=AvantDerniereCroix+1; (i<54)&&(((Tableau>>i)&1) != 0); i++) {}
AvantDerniereCroixTmp = i;
// Coche le bloc de TailleBloc+1 cases suivantes et décoche la fin.
DerniereCroix = AvantDerniereCroix-TailleBloc-1;
if (DerniereCroix==0) {
Tableau = Tableau & ~((~0ULL)>>(63-TailleBloc));
TailleBloc += 1;
AvantDerniereCroix = AvantDerniereCroixTmp;
} else {
Tableau = Tableau & ~(((~0ULL)>>(63-TailleBloc))<<DerniereCroix);
Tableau = Tableau | ((~0ULL)>>(64-DerniereCroix));
TailleBloc = 1;
AvantDerniereCroix = DerniereCroix+1;
}
// optimisation de 23% du temps d'execution !!!
if ((Tableau & 0x01FF) == 0x1FF) { // On sait que ces tableaux ne sont pas des solution pour moins de 14 croix.
Tableau = (Tableau | (1ULL<<DerniereCroix)) & ~(1ULL<<8);
DerniereCroix = 8;
}
}
return 0;
}
Note : on ne pourrait pas définir la balise [code][/code] sur le forum pour les fous qui comme moi présentent des programmes?