Posté par
_Michel _Michel
Pour ne rien rater, j'ai écrit un bruteforce en C:
Citation :
/*
Triacey - bruteforce de l'énigme 126 sur Ilemaths.
Dernière modification le 12/08/2009 15h49.
*/
#include <stdio.h>
#include <windows.h>
#define NBR_COUP_MAX (6)
/*
Structure du tableau :
- octet 0 : nombre de cases coloriées
- bits 8-31 : état des cases 1-24
*/
#define CASE(Tableau, i) ( (Tableau>>(i+7))&1 )
#define SET_CASE(Tableau, i) \
Tableau |= (1<<(i+7)); \
Tableau+=1;
#define NBR_CASE(Tableau) ( (unsigned char)Tableau )
/*
Voisin - Description des correspondances entre les cases.
*/
const unsigned char Voisin[25][3] = {
{0, 0, 0},
{2, 9, 10},
{1, 3, 18},
{2, 4, 12},
{3, 5, 20},
{4, 6, 14},
{5, 7, 22},
{6, 8, 16},
{7, 9, 23},
{8, 1, 17},
{1, 17, 11},
{10, 12, 19},
{11, 13, 3},
{12, 14, 21},
{13, 15, 5},
{14, 16, 22},
{15, 23, 7},
{9, 24, 10},
{24, 2, 19},
{11, 18, 20},
{19, 21, 4},
{20, 22, 13},
{21, 15, 6},
{16, 24, 8},
{23, 17, 18}
};
/*
Reaction - Colorie les cases ayant deux voisins coloriés
Paramètres :
Tableau - Pointeur sur le tableau car il est susceptible d'être modifié.
i - Numéro de la case qui viens d'être modifiée.
*/
void Reaction (unsigned long *Tableau, int i)
{
unsigned char _Voisin, a, b, c;
_Voisin = Voisin[i][0];
if (!CASE (*Tableau, _Voisin)) {
a = CASE (*Tableau, Voisin[_Voisin][0]);
b = CASE (*Tableau, Voisin[_Voisin][1]);
c = CASE (*Tableau, Voisin[_Voisin][2]);
if ((a&&(b||c))||(b&&c)) { // Si au moins deux voisins sont cooriés
SET_CASE (*Tableau, _Voisin);
Reaction (Tableau, _Voisin);
}
}
_Voisin = Voisin[i][1];
if (!CASE (*Tableau, _Voisin)) {
a = CASE (*Tableau, Voisin[_Voisin][0]);
b = CASE (*Tableau, Voisin[_Voisin][1]);
c = CASE (*Tableau, Voisin[_Voisin][2]);
if ((a&&(b||c))||(b&&c)) { // Si au moins deux voisins sont cooriés
SET_CASE (*Tableau, _Voisin);
Reaction (Tableau, _Voisin);
}
}
_Voisin = Voisin[i][2];
if (!CASE (*Tableau, _Voisin)) {
a = CASE (*Tableau, Voisin[_Voisin][0]);
b = CASE (*Tableau, Voisin[_Voisin][1]);
c = CASE (*Tableau, Voisin[_Voisin][2]);
if ((a&&(b||c))||(b&&c)) { // Si au moins deux voisins sont cooriés
SET_CASE (*Tableau, _Voisin);
Reaction (Tableau, _Voisin);
}
}
}
/*
Jeu - Bruteforce à partir d'un tableau donné. Affiche toutes les solutions trouvées.
Paramètres :
Tableau - Tableau de départ
NbrCoup - Nombre de coup déjà effectués.
Coup - Pointeur sur l'historique des coups. Cette solution permet de ne pas passer par la pile le tableau.
*/
void Jeu (unsigned long Tableau, int NbrCoup, unsigned char (*Coup)[8])
{
int i;
unsigned TableauCopie = Tableau;
for (i=1; i<=24; i++) {
if (!CASE(Tableau, i)) { // Si la case i n'est pas coloriée
// Colorie la case
SET_CASE (Tableau, i)
(*Coup)[NbrCoup] = (unsigned char)i;
// Réaction en chaîne
Reaction (&Tableau, i);
// Vérifie si la tableau est fini
if (NBR_CASE (Tableau) == 24) {
printf ("Solution : %d, %d, %d, %d, %d, %d, %d, %d.\n",
(*Coup)[0], (*Coup)[1], (*Coup)[2], (*Coup)[3], (*Coup)[4], (*Coup)[5], (*Coup)[6], (*Coup)[7]);
}
// Joue les autres coups
if (NbrCoup != NBR_COUP_MAX-1) {
Jeu (Tableau, NbrCoup+1, Coup);
}
// Retourne à l'état initial
Tableau = TableauCopie;
(*Coup)[NbrCoup] = 0;
}
}
}
int main ()
{
unsigned char Coup[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Jeu (0, 0, &Coup);
system ("pause");
return 0;
}
Résultat :
Pas de solution pour 6 coups ou moins (9").
42477120 solutions pour 7 coups (2'30" de calcul, 2'39"d'écriture, 1,7Go de données générées pour lister toutes les solutions).
Merci pour cette énigme amusante.