Problème des huit dames (3)

Aux échecs, la dame est capable de se déplacer dans toutes les directions.

![Mouvement des dames](https://codex.forge.apps.education.fr/fichiers/en_travaux/huit_dames_3/mvt_dame.svg){width="25%" } ![Disposition valide](https://codex.forge.apps.education.fr/fichiers/en_travaux/huit_dames_3/valide_1.svg){width="25%" }

Le problème des huit dames consiste à placer \(8\) dames sur un échiquier classique (\(8\) lignes et \(8\) colonnes) de façon à ce qu'aucune d'entre elles ne soit menacée par une autre. Ainsi il n'y a qu'une seule dame par ligne, colonne ou diagonale. La figure ci-dessus (à droite) illustre une disposition valide.

On considère dans cet exercice des « échiquiers » de taille \(n \ge 1\) variable. On garantit que l'échiquier est bien carré. Selon la taille de l'échiquier, on pourra placer plus ou moins de dames.

Le problème considéré dans cet exercice consiste donc à placer exactement \(n\) dames dans un échiquier de \(n \times n\) cases de façon à ce qu'aucune d'entre elles ne soit menacée par une autre.

Le but de l'exercice est de déterminer le nombre de dispositions valides pour un échiquier de taille \(n\).

Puisqu'une disposition des dames valides doit comporter exactement une dame par colonne on peut se contenter, pour chaque colonne, de ne garder trace que de la ligne sur laquelle se trouve l'unique dame de cette colonne.

Cette représentation du problème prend la forme d'une liste de n éléments dans laquelle l'élément d'indice j est égal à l'indice i de la ligne sur laquelle se trouve la dame.

Exemples de liste

La disposition valide ci-dessus sera par exemple représentée en machine par :

🐍 Script Python
# colonne  0  1  2  3  4  5  6  7
valide =  [6, 4, 2, 0, 5, 7, 1, 3]

On peut lire que la dame de la première colonne (indice 0) est située sur la \(7\)-ème ligne (indice 6).

On fournit une fonction est_coherente qui prend en paramètres la taille d'un échiquier ainsi qu'une une disposition et vérifie que cette disposition incomplète satisfait, à ce stade, le problème des huit dames. La fonction renvoie le booléen correspondant.

Cette fonction est déjà importée dans l'éditeur, vous pouvez l'utiliser directement.

Utilisation de la fonction est_coherente
>>> est_coherente(5, [0])  # une seule dame → cohérent
True
>>> est_coherente(5, [0, 0])  # deux dames sur la même ligne → incohérent
False
>>> est_coherente(5, [2, 0, 3, 1])
True
Code de la fonction est_coherente

Pour information, on fournit le code de la fonction est_coherente :

🐍 Script Python
def est_coherente(n ,disposition):
    # Vérifications des lignes
    nb_dames_placees = len(disposition)
    lignes_occupees = [False] * n
    for ligne in disposition:
        if lignes_occupees[ligne]:
            return False
        else:
            lignes_occupees[ligne] = True

    # Vérification des diagonales
    for j_1 in range(nb_dames_placees - 1):
        for j_2 in range(j_1 + 1, nb_dames_placees):
            if abs(disposition[j_2] - disposition[j_1]) == (j_2 - j_1):
                return False
    return True

La fonction récursive compte_valides prend en paramètre la taille de l'échiquier n ainsi qu'une disposition en cours de construction disposition et renvoie le nombre de dispositions valides solutions au problème de taille \(n\) construites sur la base de celle passée en argument.

Cette fonction fonctionne de la façon suivante :

  • si la taille de la disposition est égale à la taille de l'échiquier, cela signifie que l'on a déterminé une solution au problème ;

  • sinon, il reste des dames à placer . On doit compter les dispositions valides que lon peut construire à parti de la disposition actuelle :

    • pour ce faire on ajoute une nouvelle dame dans la disposition sur la première ligne ;

    • si cette disposition est valide on continue l'exploration avec un appel récursif ;

    • quel que soit le statut de cette nouvelle disposition, valide ou invalide, une fois testée, on retire la dame ajoutée et on en place une nouvelle suivante ;
    • on étudie ainsi toutes les lignes entre 0 et n (exclu).

La figure ci-dessous illustre une partie de la recherche dans le cas d'un échiquier de taille \(n=4\).

graph TD
    R{ } --- A0((0))
    R --- A1{1}
    R -.- A2((2))
    R -.- A3((3))
    A1 --- B0((0))
    A1 --- B1((1))
    A1 --- B2((2))
    A1 --- B3{3}
    B3 --- C0{0}
    B3 -.- C1((1))
    B3 -.- C2((2))
    B3 -.- C3((3))
    C0 --- D0((0))
    C0 --- D1((1))
    C0 --- D2{2}
    C0 -.- D3((3))
    style A0 stroke:#a00,stroke-width:4px
    style A1 stroke:#0a0,stroke-width:4px
    style B0 stroke:#a00,stroke-width:4px
    style B3 stroke:#0a0,stroke-width:4px
    style C0 stroke:#0a0,stroke-width:4px
    style D2 stroke:#0a0,stroke-width:4px
    style B0 stroke:#a00,stroke-width:4px
    style B1 stroke:#a00,stroke-width:4px
    style B2 stroke:#a00,stroke-width:4px
    style D0 stroke:#a00,stroke-width:4px
    style D1 stroke:#a00,stroke-width:4px
    style A2 stroke-dasharray: 5 5
    style A3 stroke-dasharray: 5 5
    style C1 stroke-dasharray: 5 5
    style C2 stroke-dasharray: 5 5
    style C3 stroke-dasharray: 5 5
    style D3 stroke-dasharray: 5 5
Exemples
>>> # Echiquier de dimension n = 3 -> aucune disposition valide
>>> compte_valides(3)
0
>>> # Echiquier de dimension n = 4 -> deux dispositions valides
>>> compte_valides(4)
2
Liste vide par défaut

Lors du premier appel de la fonction compte_valides, on n'a placé aucune dame et la disposition à passer en argument est donc vide.

Plutôt que d'utiliser la valeur par défaut [], on préfère utiliser None et faire :

🐍 Script Python
def compte_valides(n, disposition=None):
    if disposition is None:
        disposition = []

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013s3_8èufvIy n7aS1me(P24C:twi][çh)6Oo;bcdg/0làqp.r,=+Nk95Rxé050N0s0z0o0B0R0b0l0M0R0o0b0b0Y010z0B0U010406050b0g0r0r0o0W0k040p0J0R0g0~0J0m0l020o0r0U0K0l0(0s180W0T0g0s0b050P1517191b130U041z1G051J0P1J1L1G130N0B0i0?0^0`0|0F0B0O0F0R1Z0F0z11050.0L0R0s1U0_0{011Y1!1$1!0z1,1.1*0z0L0J0N1b1+0W1H0z0F0?1e0b0U0o0m0|0v011:1W010h0:0s0m1m0s1*2b2d2i1=2l1.2o0r2q040a0l0u0W0J0U0J0b0B1h1j0,290W0W0s0M2L1z2s0m1H0P272X0z2524260N2u0|1$0m2n2I1*1R1T0@1;2+0B2-0m211S1*0U2Q1H2V2X32142c1j2?2j2{0W180R110l0q2U3612352t381=3a3c3e0v3h2d3j2V2*013o0o3d040l0c3s2W133v3m0|3y3A0l0w3E3u363w3K3e0%3O3G3Q3I3x0J3b3z3e0H3V3k371V3n3!3p3B0n3)3H3,3J3.3$3B0e3=3X3@3Z3#3L0$3}3l3 3S040q0Q443+2@403/0q3g1A3i3W454d470q3r4i3t4k4c393_3A0q3D4q3F3*3R4v110q3N4z3P4l4u414E3U4H4s4C4L483(4O4B3Y4n3;4H1I301z2;2!0N2(3w0M212A0+1S1H2 0s313i3O054,0,4@4J1=0#110,0h4_3?4d0A3e543~4m0h114,1n0z0s0d0i3z0B0,1y4Z552j10040t594~3J110m5u4t1=5r0X3O0l4V46510B2b2I2K0B1i5z3w0J110Y5P3Y0#0M110!1i0s5U3 5r0G0y3V0l5,5F5p4 110B534H5.5a395I5K2J2T5@5G4d0J57045J5E602j5W5Y5!5$4d5r5*4O5-6h5^5v3x5{2H5}5N5y5 5/0|5R045T6r5_5B110D0C3V066h671=0M0q11030l0I1j0o0l0U0^0M0*0l0z0J1g1x0l1.0=0N2p5n326E5-6G0|50645?326j5A3J0L112x6c5q115t5o6y5w041R5|5M5O706k5(666s016u0Y6w6=6-6l046q347c6e5+6i5,7i6/2Q0z0g0W7l3i6?3w0r0B4E6D6F7c6I6K0l0j0R0l2Q0b5g0l5m7R6(0l0S6Q6S0s0W7p7r7c0m5x0L5i5k5m7b717d5S7.6k7C114a6g6,7c6/0h3!7=6@7j1_2-805Q632_854W6_040W2d0O5#78815r6 7m7/7(7k6|6z045)7#6i7i8n746n767y3t7i6u0V8p720o0U0U2n0N8F018j8M8n838g8l79110G8t7G7/6/5=895H041x0z0d4,0F7Z2n5g8M8O8h3R5x8;115D6x6k8w5J8y5~8T8i8V6f6*7q7q8v7)7+1$7-8|816u0Z7g7z99045e0U5g9b5l1x8_5s8P8^8?3Y5C8$4m6m5L914^7n8V8X7{8m9B6o77925Q118E9w8%2H0U9s0t8W4O6+7$8Z117u7w8A2W7A4W9a5j9c9r4U0P4{4?4!9@0P4%1z0z4)9|2$2Y20222!0o1-9_4%1F4}812Q0r0d0h0o0#5h0F0c111r1t1v6Z954^1M3j1G6N0l0s0)6R3!1/6#7R5=0h0*2Q0m5g0=6n2J0L0:2K0*0=0o5jaI7R1/2Q0i2n0B0Waw6O2P0B0f2Q7R0f0=ao6!001i0l0J0L0b7ZaY0la/0^aD752Law7P0l2_9.9q9Q1P1K040x0-7Qaf0Ea=2Nafa!1/3m0Ba/8)0l8H8J0R0*1/051s8c0-6Xa#15a#2#0o0M8gbx0l5tbx0LbF0#bE0M0#2_0O1zbI2nbq0m0O0^5J0Gb83j9`0-0/0;04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013s3_8èufvIy n7aS1me(P24C:twi][çh)6Oo;bcdg/0làqp.r,=+Nk95Rxé050N0s0z0o0B0R0b0l0M0R0o0b0b0Y010z0B0U010406050b0g0r0r0o0W0k040p0J0R0g0~0J0m0l020o0r0U0K0l0(0s180W0T0g0s0b050P1517191b130U041z1G051J0P1J1L1G130N0B0i0?0^0`0|0F0B0O0F0R1Z0F0z11050.0L0R0s1U0_0{011Y1!1$1!0z1,1.1*0z0L0J0N1b1+0W1H0z0F0?1e0b0U0o0m0|0v011:1W010h0:0s0m1m0s1*2b2d2i1=2l1.2o0r2q040a0l0u0W0J0U0J0b0B1h1j0,290W0W0s0M2L1z2s0m1H0P272X0z2524260N2u0|1$0m2n2I1*1R1T0@1;2+0B2-0m211S1*0U2Q1H2V2X32142c1j2?2j2{0W180R110l0q2U3612352t381=3a3c3e0v3h2d3j2V2*013o0o3d040l0c3s2W133v3m0|3y3A0l0w3E3u363w3K3e0%3O3G3Q3I3x0J3b3z3e0H3V3k371V3n3!3p3B0n3)3H3,3J3.3$3B0e3=3X3@3Z3#3L0$3}3l3 3S040q0Q443+2@403/0q3g1A3i3W454d470q3r4i3t4k4c393_3A0q3D4q3F3*3R4v110q3N4z3P4l4u414E3U4H4s4C4L483(4O4B3Y4n3;4H1I301z2;2!0N2(3w0M212A0+1S1H2 0s313i3O054,0,4@4J1=0#110,0h4_3?4d0A3e543~4m0h114,1n0z0s0d0i3z0B0,1y4Z552j10040t594~3J110m5u4t1=5r0X3O0l4V46510B2b2I2K0B1i5z3w0J110Y5P3Y0#0M110!1i0s5U3 5r0G0y3V0l5,5F5p4 110B534H5.5a395I5K2J2T5@5G4d0J57045J5E602j5W5Y5!5$4d5r5*4O5-6h5^5v3x5{2H5}5N5y5 5/0|5R045T6r5_5B110D0C3V066h671=0M0q11030l0I1j0o0l0U0^0M0*0l0z0J1g1x0l1.0=0N2p5n326E5-6G0|50645?326j5A3J0L112x6c5q115t5o6y5w041R5|5M5O706k5(666s016u0Y6w6=6-6l046q347c6e5+6i5,7i6/2Q0z0g0W7l3i6?3w0r0B4E6D6F7c6I6K0l0j0R0l2Q0b5g0l5m7R6(0l0S6Q6S0s0W7p7r7c0m5x0L5i5k5m7b717d5S7.6k7C114a6g6,7c6/0h3!7=6@7j1_2-805Q632_854W6_040W2d0O5#78815r6 7m7/7(7k6|6z045)7#6i7i8n746n767y3t7i6u0V8p720o0U0U2n0N8F018j8M8n838g8l79110G8t7G7/6/5=895H041x0z0d4,0F7Z2n5g8M8O8h3R5x8;115D6x6k8w5J8y5~8T8i8V6f6*7q7q8v7)7+1$7-8|816u0Z7g7z99045e0U5g9b5l1x8_5s8P8^8?3Y5C8$4m6m5L914^7n8V8X7{8m9B6o77925Q118E9w8%2H0U9s0t8W4O6+7$8Z117u7w8A2W7A4W9a5j9c9r4U0P4{4?4!9@0P4%1z0z4)9|2$2Y20222!0o1-9_4%1F4}812Q0r0d0h0o0#5h0F0c111r1t1v6Z954^1M3j1G6N0l0s0)6R3!1/6#7R5=0h0*2Q0m5g0=6n2J0L0:2K0*0=0o5jaI7R1/2Q0i2n0B0Waw6O2P0B0f2Q7R0f0=ao6!001i0l0J0L0b7ZaY0la/0^aD752Law7P0l2_9.9q9Q1P1K040x0-7Qaf0Ea=2Nafa!1/3m0Ba/8)0l8H8J0R0*1/051s8c0-6Xa#15a#2#0o0M8gbx0l5tbx0LbF0#bE0M0#2_0O1zbI2nbq0m0O0^5J0Gb83j9`0-0/0;04.