Épreuve d'informatique CAPES 2017 - Problème 1: le Sudoku

by Joseph Razik, last modified on 2019-10-18
capes_2017_Pb1

Sujet du CAPES 2017, épreuve d'informatique

 Problème 1 - Sudoku

Source: http://www4.ac-nancy-metz.fr/capesmath/data/uploads/EP1_Info_2017.pdf

N.B.: Ceci ne représente ni LA solution ni LE corrigé de cette épreuve mais uniquement la façon avec laquelle je répondrais à une telle série d'exercices.

Partie A - Généralités

Question 2

Écrire une fonction ligne_complete(L,i) qui prend une liste Sudoku L et un entier i entre 0 et 8, et renvoie True si la ligne i du Sudoku L vérifie les conditions de remplissage d’un Sudoku, et False sinon.

On définit de même (on ne demande pas de les écrire) les fonctions colonne_complete(L,i) pour la colonne i et carre_complet(L,i) pour le carré i.

In [1]:
# Q.2
def ligne_complete(L, i, debug=False):
    """ Renvoie True si la ligne *i* du sudoku *L* vérifie les 
        conditions de remplissage d'un sudoku.  """
    ligne = L[i]  # la ligne qui nous intéresse
    if debug:
        print(ligne)
    if sum(ligne) == 45:
        # si la ligne rempli la condition, la somme doit faire 45
        # ce test n'est pas vraiment utile mais c'est pour faire un
        # lien avec la question 1
        for n in range(1, 10):
            if n not in ligne:
                return False
    else:
        return False
    return True
In [2]:
# fonction non demandée mais nécessaire pour tester l'ensemble
def colonne_complete(L, i, debug=False):
    """ Renvoie True si la colonne *i* du sudoku *L* vérifie les 
        conditions de remplissage d'un sudoku.  """
    col = [ligne[i] for ligne in L]  # on construit/extrait la colonne
    if debug:
        print(col)
    if sum(col) == 45:
        # si la colonne remplit la condition, la somme doit faire 45
        for n in range(1, 10):
            if n not in col:
                return False
    else:
        return False
    return True
In [3]:
# fonction non demandée mais nécessaire pour tester l'ensemble
def carre_complet(L, i, debug=False):
    """ Renvoie True si le carré *i* du sudoku *L* vérifie les 
        conditions de remplissage d'un sudoku.  """
    # on construit/extrait les valeurs du carré
    carre = [L[n][m] for n in range((i//3) * 3, (i//3) * 3 + 3) for m in range((i%3)*3, (i%3)*3 + 3)]
    # pour un carré *i*, on cherche l'indice de "méta-ligne" (ligne "d'épaisseur" 3) donné par I=i//3
    # ainsi les lignes concernées sont la I*3, la I*3 + 1 et la I*3 + 2, 
    # par exemple pour le carré 4, les lignes 3, 4 et 5
    # pour les colonnes, on fait un raisonnement similaire sauf que cette fois I est donné par I=i%3
    # dans la question 6, on autre approche a été proposée
    if debug:
        print(carre)
    if sum(carre) == 45:
        # si le carre rempli la condition, la somme doit faire 45
        for n in range(1, 10):
            if n not in carre:
                return False
    else:
        return False
    return True

Question 3

Écrire une fonction complet(L) qui prend une liste Sudoku L comme argument, et qui renvoie True si la grille est complète, False sinon.

In [4]:
# Q.3
def complet(L):
    """ Renvoie True si le sudoku *L* est entièrement remplit en respectant les contraintes 
    inhérentes au sudoku.  """
    for i in range(9):
        if not (ligne_complete(L, i) and colonne_complete(L, i) and carre_complet(L, i)):
            return False
    return True
In [5]:
# Premier exemple d'une grille incomplète
L= [
    [0,6,0,0,0,0,2,0,5],
    [4,0,0,9,2,1,0,0,0],
    [0,7,0,0,0,8,0,0,1],
    [0,0,0,0,0,5,0,0,9],
    [6,4,0,0,0,0,0,7,3],
    [1,0,0,4,0,0,0,0,0],
    [3,0,0,7,0,0,0,6,0],
    [0,0,0,1,4,6,0,0,2],
    [2,0,6,0,0,0,0,1,0]
    ]
In [6]:
# on teste les fonctions définies précédemment
In [7]:
ligne_complete(L, 1, True)
[4, 0, 0, 9, 2, 1, 0, 0, 0]
Out[7]:
False
In [8]:
colonne_complete(L, 2, True)
[0, 0, 0, 0, 0, 0, 0, 0, 6]
Out[8]:
False
In [9]:
carre_complet(L, 8, True)
[0, 6, 0, 0, 0, 2, 0, 1, 0]
Out[9]:
False
In [10]:
complet(L)
Out[10]:
False

Question 4

Compléter la fonction suivante ligne(L,i), qui renvoie la liste des nombres compris entre 1 et 9 qui apparaissent sur la ligne d’indice i.

def ligne(L,i):
    chiffre = []
    for j in ....:
        if ( ....) :
            chiffre.append(L[i][j])
    return chiffre

Ainsi, avec la grille donnée dans l’énoncé, on doit obtenir :

>>> ligne(L,0)
[6, 2, 5]

On définit alors, de la même manière, la fonction colonne(L,j) qui renvoie la liste des nombres compris entre 1 et 9 qui apparaissent dans la colonne j (on ne demande pas d’écrire son code).

In [11]:
# Q.4
def ligne(L, i):
    """ Renvoie la liste des nombres compris entre 1 et 9 qui apparaissent sur la ligne *i*
    """
    chiffre = []
    for j in range(9):
        if (0 < L[i][j] < 10):
            chiffre.append(L[i][j])
    return chiffre

# Autre façon de faire plus "pythonique"
def ligne_bis(L, i):
    return [n for n in L[i] if n != 0]
In [12]:
ligne(L, 0)
Out[12]:
[6, 2, 5]
In [13]:
# fonction non demandée mais utile pour la suite (version pythonique)
def colonne(L, i):
    """ Renvoie la liste des nombres compris entre 1 et 9 qui apparaissent sur la ligne *i*
    """
    return [l[i] for l in L if l[i] != 0]
In [14]:
colonne(L, 0)
Out[14]:
[4, 6, 1, 3, 2]

Question 6

Compléter alors la fonction carre(L,i,j), qui renvoie la liste des nombres compris entre 1 et 9 qui apparaissent dans le carré 3 × 3 auquel appartient la case (i, j).

def carre(L,i,j):
    icoin = 3*(i//3)
    jcoin = 3*(j//3)
    chiffre = []
    for i in range (....):
        for j in range (....):
            if (....):
                chiffre.append(L[i][j])
    return chiffre

On rappelle que si x et y sont des entiers, x//y renvoie le quotient de la division euclidienne de x par y. Ainsi, avec la grille donnée dans l’énoncé, on doit obtenir :

>>> carre(L,4,6)
[9, 7, 3]
>>>carre(L,4,5)
[5, 4]
In [15]:
# Q6
def carre(L, i, j, debug=False):
    """ Renvoie la liste des nombres compris entre 1 et 9 qui apparaissent dans le carré 3 × 3
    auquel appartient la case (i,j).  """
    icoin = 3 * (i // 3)
    jcoin = 3 * (j // 3)
    if debug:
        print(icoin, jcoin)
    chiffre = []
    for i in range(icoin, icoin + 3):
        for j in range (jcoin, jcoin + 3):
            if debug:
                print(i, j, L[i][j])
            if (0 < L[i][j] < 10):
                chiffre.append(L[i][j])
    return chiffre
In [16]:
carre(L, 4, 6, True)
3 6
3 6 0
3 7 0
3 8 9
4 6 0
4 7 7
4 8 3
5 6 0
5 7 0
5 8 0
Out[16]:
[9, 7, 3]
In [17]:
carre(L, 4, 5, True)
3 3
3 3 0
3 4 0
3 5 5
4 3 0
4 4 0
4 5 0
5 3 4
5 4 0
5 5 0
Out[17]:
[5, 4]

Question 7

Déduire des questions précédentes une fonction conflit(L,i,j) renvoyant la liste des chiffres que l’on ne peut pas écrire en case (i,j) sans contredire les règles du jeu. La liste renvoyée peut très bien comporter des redondances. On ne prendra pas en compte la valeur de L[i][j].

In [18]:
# Q:7
def conflit(L, i, j):
    """ Renvoie la liste des chiffres que l'on ne peut pas écrire en case (i,j). """
    conf = ligne(L, i)  # les conflits par rapport à la ligne *i*
    conf.extend(colonne(L, j))  # les conflits par rapport à la colonne *j*
    conf.extend(carre(L, i ,j))  # les conflits par rapport au carré contenant la case
    return list(set(conf))  # petit passage par les ensembles uniquement pour enleves les redondances
In [19]:
conflit(L, 5, 5)
Out[19]:
[8, 1, 4, 5, 6]

Question 8

Compléter enfin la fonction chiffres_ok(L,i,j) qui renvoie la liste des chiffres que l’on peut écrire en case (i, j).

def chiffres_ok(L,i,j):
    ok = []
    conflit = conflit(L,i,j)
    for k in ....:
        if ....:
            ok.append(k)
    return ok

Par exemple, avec la grille initiale :

>>> chiffres_ok(L,4,2)
[2, 5, 8, 9]
In [20]:
# Q.8
# Attention, ici il y avait une erreur dans le sujet: une variable locale et une fonction portait
# le même nom:
# conflit = conflit(L,i,j)
# cf. résolution de la portée des variables/fonctions, et les notions de polymorphisme/surcharge
# qui n'existent pas en Python  
def chiffre_ok(L, i ,j):
    """ Renvoie la liste des chiffres qu'il est possible de placer dans la case (i,j) """
    ok = []
    conflit_list = conflit(L, i, j)
    for k in range(1, 10):
        if k not in conflit_list:
            ok.append(k)
    return ok
In [21]:
# une autre façon de faire en passant par les ensembles
def chiffre_ok_bis(L, i, j):
    return set(range(1, 10)) - set(conflit(L, i, j))
In [22]:
# une façon de faire en gardant les listes mais plus pythonique
def chiffre_ok_ter(L, i, j):
    return [n for n in range(1, 10) if n not in conflit(L, i, j)]
In [23]:
chiffre_ok(L, 4, 2)
Out[23]:
[2, 5, 8, 9]
In [24]:
chiffre_ok_bis(L, 4 ,2)
Out[24]:
{2, 5, 8, 9}
In [25]:
chiffre_ok_ter(L, 4, 2)
Out[25]:
[2, 5, 8, 9]

 Partie B - Algorithme naïf

In [26]:
# Second exemple de grille incomplète
M= [[2, 0, 0, 0, 9, 0, 3, 0, 0],
    [0, 1, 9, 0, 8, 0, 0, 7, 4],
    [0, 0, 8, 4, 0, 0, 6, 2, 0],
    [5, 9, 0, 6, 2, 1, 0, 0, 0],
    [0, 2, 7, 0, 0, 0, 1, 6, 0],
    [0, 0, 0, 5, 7, 4, 0, 9, 3],
    [0, 8, 5, 0, 0, 9, 7, 0, 0],
    [9, 3, 0, 0, 5, 0, 8, 4, 0],
    [0, 0, 2, 0, 6, 0, 0, 0, 1]]

Question 9

A partir des fonctions annexes, écrire une fonction nb_possible(L,i,j), indiquant le nombre de chiffres possibles à la case (i, j).

In [27]:
# Q.9
def nb_possible(L, i ,j):
    """ Renvoie le nombre de chiffres possibles en case (i,j) """
    return len(chiffre_ok(L, i ,j))
In [28]:
nb_possible(L, 4, 2)
Out[28]:
4

Question 10

On souhaite disposer de la fonction un_tour(L) qui parcourt l’ensemble des cases du Sudoku et qui complète les cases dans le cas où il n’y a qu’un chiffre possible, et renvoie True s’il y a eu un changement, et False sinon. La liste L est alors modifiée par effet de bords. Par exemple, en partant de la grille initiale M :

>>> un_tour(M)
True
>>> M
[[2, 0, 0, 0, 9, 0, 3, 0, 0],
 [0, 1, 9, 0, 8, 0, 5, 7, 4],
 [0, 0, 8, 4, 0, 0, 6, 2, 9],
 [5, 9, 0, 6, 2, 1, 4, 8, 7],
 [0, 2, 7, 0, 3, 8, 1, 6, 5],
 [0, 6, 1, 5, 7, 4, 2, 9, 3],
 [0, 8, 5, 0, 0, 9, 7, 3, 0],
 [9, 3, 6, 0, 5, 0, 8, 4, 2],
 [0, 0, 2, 0, 6, 0, 9, 5, 1]]

On propose la fonction suivante :

def un_tour(L):
    changement = False
    for i in range(1,9):
        for j in range(1,9):
            if (L[i][j] = 0):
                if (nb_possible(L,i,j) = 1):
                    L[i][j] = chiffres_ok(L,i,j)[1]
    return changement

Recopier ce code en en corrigeant les erreurs.

In [29]:
# Q.10
def un_tour(L):
    """ Parcours l'ensemble des cases du sudoku et remplit les cases n'ayant qu'une seule possibilité.
    Renvoie True si au moins une case a été remplie, False sinon. 
    """
    changement = False
    for i in range(0, 9):
        for j in range(0, 9):
            if L[i][j] == 0:
                if nb_possible(L, i ,j) == 1:
                    L[i][j] = chiffre_ok(L, i ,j)[0]
                    changement = True
    return changement
    
In [30]:
un_tour(M)
Out[30]:
True
In [31]:
M
Out[31]:
[[2, 0, 0, 0, 9, 0, 3, 0, 0],
 [0, 1, 9, 0, 8, 0, 5, 7, 4],
 [0, 0, 8, 4, 0, 0, 6, 2, 9],
 [5, 9, 0, 6, 2, 1, 4, 8, 7],
 [0, 2, 7, 0, 3, 8, 1, 6, 5],
 [0, 6, 1, 5, 7, 4, 2, 9, 3],
 [0, 8, 5, 0, 0, 9, 7, 3, 0],
 [9, 3, 6, 0, 5, 0, 8, 4, 2],
 [0, 0, 2, 0, 6, 0, 9, 5, 1]]

Question 11

Écrire une fonction complete(L) qui exécute la fonction un_tour tant qu’elle modifie la liste, et renvoie True si la grille est complétée, et False sinon.

In [32]:
# Q.11
def complete(L):
    """ Essaie de compléter la grille en remplissant itérativement les cases n'ayant qu'une seule possibilité.
    Renvoie True si la grille finale est complète, False sinon.  """
    while un_tour(L):
        pass
    return complet(L)
In [33]:
complete(M)
Out[33]:
True

M

 Partie C - Backtracking

Question 12

Écrire une fonction case_suivante(pos) qui prend une liste pos du couple des coordonnées de la case, et renvoie la liste du couple d’indices de la case suivante en utilisant l’ordre lexicographique, et qui renvoie [9,0] si pos=[8,8]. Par exemple :

>>> case_suivante([1,3])
[1, 4] 
>>> case_suivante([8,8])
[9, 0]
In [34]:
# Q.12
def case_suivante(pos):
    """ Renvoie la case suivante dans la grille. """
    x = pos[0] + (pos[1] + 1) // 9
    y = (pos[1] + 1) % 9
    return [x, y]
In [35]:
case_suivante([1,3])
Out[35]:
[1, 4]
In [36]:
case_suivante([8, 8])
Out[36]:
[9, 0]

Question 13

Compléter le squelette de la fonction backtracking(L,pos) selon les règles précédentes.

def backtracking(L,pos):
    """
    pos est une liste désignant une case du sudoku,
    [0,0] pour le coin en haut à gauche.
    """
    if (pos==[9 , 0]):
        .....
    i,j = pos[0],pos[1]
    if L[i][j] != 0:
        return .....
    for k in ....:
        L[i][j] = ....
        if ....:
            return ....
    L[i][j] = ....
    return ....
In [37]:
# Q.13
nb_appel = 0  # sert uniquement pour le debuggage pour que chaque appel à la fonction ait un numéro unique

def backtracking(L, pos, debug=False):
    """
    pos est une liste désignant une case du sudoku,
    [0, 0] pour le coin en haut à gauche.
    """
    global nb_appel  # sert uniquement pour suivre le debuggage
    appel = nb_appel  # idem
    nb_appel += 1   # idem
    if debug:
        print("enter backtrack niveau " + str(appel))
        print("pos: " + str(pos) + " ", end='')
    if pos == [9, 0]:
        return True
    i, j = pos[0], pos[1]
    if debug:
        print(L[i][j])
    if L[i][j] != 0:
        return backtracking(L, case_suivante(pos), debug)
    if debug:
        print(chiffre_ok(L, i, j))
    for k in chiffre_ok(L, i, j):
        if debug:
            print(k)
        L[i][j] = k
        if backtracking(L, case_suivante(pos), debug):
            return True
    L[i][j] = 0
    if debug:
        print("exit backtrack niveau " + str(appel))
    return False
In [38]:
# juste un rappel de la seconde grille initiale
M= [[2, 0, 0, 0, 9, 0, 3, 0, 0],
    [0, 1, 9, 0, 8, 0, 0, 7, 4],
    [0, 0, 8, 4, 0, 0, 6, 2, 0],
    [5, 9, 0, 6, 2, 1, 0, 0, 0],
    [0, 2, 7, 0, 0, 0, 1, 6, 0],
    [0, 0, 0, 5, 7, 4, 0, 9, 3],
    [0, 8, 5, 0, 0, 9, 7, 0, 0],
    [9, 3, 0, 0, 5, 0, 8, 4, 0],
    [0, 0, 2, 0, 6, 0, 0, 0, 1]]
In [39]:
# Les affichages de cet appel sont long, c'est à cause du mode debuggage pour illustrer et bien comprendre
# cette fonction
backtracking(M, [0, 0], True)
enter backtrack niveau 0
pos: [0, 0] 2
enter backtrack niveau 1
pos: [0, 1] 0
[4, 5, 6, 7]
4
enter backtrack niveau 2
pos: [0, 2] 0
[6]
6
enter backtrack niveau 3
pos: [0, 3] 0
[1, 7]
1
enter backtrack niveau 4
pos: [0, 4] 9
enter backtrack niveau 5
pos: [0, 5] 0
[5, 7]
5
enter backtrack niveau 6
pos: [0, 6] 3
enter backtrack niveau 7
pos: [0, 7] 0
[8]
8
enter backtrack niveau 8
pos: [0, 8] 0
[]
exit backtrack niveau 8
exit backtrack niveau 7
7
enter backtrack niveau 9
pos: [0, 6] 3
enter backtrack niveau 10
pos: [0, 7] 0
[5, 8]
5
enter backtrack niveau 11
pos: [0, 8] 0
[8]
8
enter backtrack niveau 12
pos: [1, 0] 0
[3]
3
enter backtrack niveau 13
pos: [1, 1] 1
enter backtrack niveau 14
pos: [1, 2] 9
enter backtrack niveau 15
pos: [1, 3] 0
[2]
2
enter backtrack niveau 16
pos: [1, 4] 8
enter backtrack niveau 17
pos: [1, 5] 0
[5, 6]
5
enter backtrack niveau 18
pos: [1, 6] 0
[]
exit backtrack niveau 18
6
enter backtrack niveau 19
pos: [1, 6] 0
[]
exit backtrack niveau 19
exit backtrack niveau 17
exit backtrack niveau 15
exit backtrack niveau 12
exit backtrack niveau 11
8
enter backtrack niveau 20
pos: [0, 8] 0
[5]
5
enter backtrack niveau 21
pos: [1, 0] 0
[3]
3
enter backtrack niveau 22
pos: [1, 1] 1
enter backtrack niveau 23
pos: [1, 2] 9
enter backtrack niveau 24
pos: [1, 3] 0
[2]
2
enter backtrack niveau 25
pos: [1, 4] 8
enter backtrack niveau 26
pos: [1, 5] 0
[5, 6]
5
enter backtrack niveau 27
pos: [1, 6] 0
[]
exit backtrack niveau 27
6
enter backtrack niveau 28
pos: [1, 6] 0
[]
exit backtrack niveau 28
exit backtrack niveau 26
exit backtrack niveau 24
exit backtrack niveau 21
exit backtrack niveau 20
exit backtrack niveau 10
exit backtrack niveau 5
7
enter backtrack niveau 29
pos: [0, 4] 9
enter backtrack niveau 30
pos: [0, 5] 0
[5]
5
enter backtrack niveau 31
pos: [0, 6] 3
enter backtrack niveau 32
pos: [0, 7] 0
[1, 8]
1
enter backtrack niveau 33
pos: [0, 8] 0
[8]
8
enter backtrack niveau 34
pos: [1, 0] 0
[3]
3
enter backtrack niveau 35
pos: [1, 1] 1
enter backtrack niveau 36
pos: [1, 2] 9
enter backtrack niveau 37
pos: [1, 3] 0
[2]
2
enter backtrack niveau 38
pos: [1, 4] 8
enter backtrack niveau 39
pos: [1, 5] 0
[6]
6
enter backtrack niveau 40
pos: [1, 6] 0
[5]
5
enter backtrack niveau 41
pos: [1, 7] 7
enter backtrack niveau 42
pos: [1, 8] 4
enter backtrack niveau 43
pos: [2, 0] 0
[7]
7
enter backtrack niveau 44
pos: [2, 1] 0
[5]
5
enter backtrack niveau 45
pos: [2, 2] 8
enter backtrack niveau 46
pos: [2, 3] 4
enter backtrack niveau 47
pos: [2, 4] 0
[1, 3]
1
enter backtrack niveau 48
pos: [2, 5] 0
[3]
3
enter backtrack niveau 49
pos: [2, 6] 6
enter backtrack niveau 50
pos: [2, 7] 2
enter backtrack niveau 51
pos: [2, 8] 0
[9]
9
enter backtrack niveau 52
pos: [3, 0] 5
enter backtrack niveau 53
pos: [3, 1] 9
enter backtrack niveau 54
pos: [3, 2] 0
[3, 4]
3
enter backtrack niveau 55
pos: [3, 3] 6
enter backtrack niveau 56
pos: [3, 4] 2
enter backtrack niveau 57
pos: [3, 5] 1
enter backtrack niveau 58
pos: [3, 6] 0
[4]
4
enter backtrack niveau 59
pos: [3, 7] 0
[8]
8
enter backtrack niveau 60
pos: [3, 8] 0
[7]
7
enter backtrack niveau 61
pos: [4, 0] 0
[4, 8]
4
enter backtrack niveau 62
pos: [4, 1] 2
enter backtrack niveau 63
pos: [4, 2] 7
enter backtrack niveau 64
pos: [4, 3] 0
[3, 8, 9]
3
enter backtrack niveau 65
pos: [4, 4] 0
[]
exit backtrack niveau 65
8
enter backtrack niveau 66
pos: [4, 4] 0
[3]
3
enter backtrack niveau 67
pos: [4, 5] 0
[]
exit backtrack niveau 67
exit backtrack niveau 66
9
enter backtrack niveau 68
pos: [4, 4] 0
[3]
3
enter backtrack niveau 69
pos: [4, 5] 0
[8]
8
enter backtrack niveau 70
pos: [4, 6] 1
enter backtrack niveau 71
pos: [4, 7] 6
enter backtrack niveau 72
pos: [4, 8] 0
[5]
5
enter backtrack niveau 73
pos: [5, 0] 0
[1, 6, 8]
1
enter backtrack niveau 74
pos: [5, 1] 0
[6]
6
enter backtrack niveau 75
pos: [5, 2] 0
[]
exit backtrack niveau 75
exit backtrack niveau 74
6
enter backtrack niveau 76
pos: [5, 1] 0
[]
exit backtrack niveau 76
8
enter backtrack niveau 77
pos: [5, 1] 0
[6]
6
enter backtrack niveau 78
pos: [5, 2] 0
[1]
1
enter backtrack niveau 79
pos: [5, 3] 5
enter backtrack niveau 80
pos: [5, 4] 7
enter backtrack niveau 81
pos: [5, 5] 4
enter backtrack niveau 82
pos: [5, 6] 0
[2]
2
enter backtrack niveau 83
pos: [5, 7] 9
enter backtrack niveau 84
pos: [5, 8] 3
enter backtrack niveau 85
pos: [6, 0] 0
[1, 6]
1
enter backtrack niveau 86
pos: [6, 1] 8
enter backtrack niveau 87
pos: [6, 2] 5
enter backtrack niveau 88
pos: [6, 3] 0
[3]
3
enter backtrack niveau 89
pos: [6, 4] 0
[4]
4
enter backtrack niveau 90
pos: [6, 5] 9
enter backtrack niveau 91
pos: [6, 6] 7
enter backtrack niveau 92
pos: [6, 7] 0
[]
exit backtrack niveau 92
exit backtrack niveau 89
exit backtrack niveau 88
6
enter backtrack niveau 93
pos: [6, 1] 8
enter backtrack niveau 94
pos: [6, 2] 5
enter backtrack niveau 95
pos: [6, 3] 0
[1, 3]
1
enter backtrack niveau 96
pos: [6, 4] 0
[4]
4
enter backtrack niveau 97
pos: [6, 5] 9
enter backtrack niveau 98
pos: [6, 6] 7
enter backtrack niveau 99
pos: [6, 7] 0
[3]
3
enter backtrack niveau 100
pos: [6, 8] 0
[2]
2
enter backtrack niveau 101
pos: [7, 0] 9
enter backtrack niveau 102
pos: [7, 1] 3
enter backtrack niveau 103
pos: [7, 2] 0
[]
exit backtrack niveau 103
exit backtrack niveau 100
exit backtrack niveau 99
exit backtrack niveau 96
3
enter backtrack niveau 104
pos: [6, 4] 0
[4]
4
enter backtrack niveau 105
pos: [6, 5] 9
enter backtrack niveau 106
pos: [6, 6] 7
enter backtrack niveau 107
pos: [6, 7] 0
[]
exit backtrack niveau 107
exit backtrack niveau 104
exit backtrack niveau 95
exit backtrack niveau 85
exit backtrack niveau 82
exit backtrack niveau 78
exit backtrack niveau 77
exit backtrack niveau 73
exit backtrack niveau 72
exit backtrack niveau 69
exit backtrack niveau 68
exit backtrack niveau 64
8
enter backtrack niveau 108
pos: [4, 1] 2
enter backtrack niveau 109
pos: [4, 2] 7
enter backtrack niveau 110
pos: [4, 3] 0
[3, 9]
3
enter backtrack niveau 111
pos: [4, 4] 0
[]
exit backtrack niveau 111
9
enter backtrack niveau 112
pos: [4, 4] 0
[3]
3
enter backtrack niveau 113
pos: [4, 5] 0
[]
exit backtrack niveau 113
exit backtrack niveau 112
exit backtrack niveau 110
exit backtrack niveau 61
exit backtrack niveau 60
exit backtrack niveau 59
exit backtrack niveau 58
4
enter backtrack niveau 114
pos: [3, 3] 6
enter backtrack niveau 115
pos: [3, 4] 2
enter backtrack niveau 116
pos: [3, 5] 1
enter backtrack niveau 117
pos: [3, 6] 0
[]
exit backtrack niveau 117
exit backtrack niveau 54
exit backtrack niveau 51
exit backtrack niveau 48
3
enter backtrack niveau 118
pos: [2, 5] 0
[]
exit backtrack niveau 118
exit backtrack niveau 47
exit backtrack niveau 44
exit backtrack niveau 43
exit backtrack niveau 40
exit backtrack niveau 39
exit backtrack niveau 37
exit backtrack niveau 34
exit backtrack niveau 33
8
enter backtrack niveau 119
pos: [0, 8] 0
[]
exit backtrack niveau 119
exit backtrack niveau 32
exit backtrack niveau 30
exit backtrack niveau 3
exit backtrack niveau 2
5
enter backtrack niveau 120
pos: [0, 2] 0
[4, 6]
4
enter backtrack niveau 121
pos: [0, 3] 0
[1, 7]
1
enter backtrack niveau 122
pos: [0, 4] 9
enter backtrack niveau 123
pos: [0, 5] 0
[6, 7]
6
enter backtrack niveau 124
pos: [0, 6] 3
enter backtrack niveau 125
pos: [0, 7] 0
[8]
8
enter backtrack niveau 126
pos: [0, 8] 0
[]
exit backtrack niveau 126
exit backtrack niveau 125
7
enter backtrack niveau 127
pos: [0, 6] 3
enter backtrack niveau 128
pos: [0, 7] 0
[8]
8
enter backtrack niveau 129
pos: [0, 8] 0
[]
exit backtrack niveau 129
exit backtrack niveau 128
exit backtrack niveau 123
7
enter backtrack niveau 130
pos: [0, 4] 9
enter backtrack niveau 131
pos: [0, 5] 0
[6]
6
enter backtrack niveau 132
pos: [0, 6] 3
enter backtrack niveau 133
pos: [0, 7] 0
[1, 8]
1
enter backtrack niveau 134
pos: [0, 8] 0
[8]
8
enter backtrack niveau 135
pos: [1, 0] 0
[3, 6]
3
enter backtrack niveau 136
pos: [1, 1] 1
enter backtrack niveau 137
pos: [1, 2] 9
enter backtrack niveau 138
pos: [1, 3] 0
[2]
2
enter backtrack niveau 139
pos: [1, 4] 8
enter backtrack niveau 140
pos: [1, 5] 0
[5]
5
enter backtrack niveau 141
pos: [1, 6] 0
[]
exit backtrack niveau 141
exit backtrack niveau 140
exit backtrack niveau 138
6
enter backtrack niveau 142
pos: [1, 1] 1
enter backtrack niveau 143
pos: [1, 2] 9
enter backtrack niveau 144
pos: [1, 3] 0
[2, 3]
2
enter backtrack niveau 145
pos: [1, 4] 8
enter backtrack niveau 146
pos: [1, 5] 0
[3, 5]
3
enter backtrack niveau 147
pos: [1, 6] 0
[5]
5
enter backtrack niveau 148
pos: [1, 7] 7
enter backtrack niveau 149
pos: [1, 8] 4
enter backtrack niveau 150
pos: [2, 0] 0
[3, 7]
3
enter backtrack niveau 151
pos: [2, 1] 0
[7]
7
enter backtrack niveau 152
pos: [2, 2] 8
enter backtrack niveau 153
pos: [2, 3] 4
enter backtrack niveau 154
pos: [2, 4] 0
[1]
1
enter backtrack niveau 155
pos: [2, 5] 0
[5]
5
enter backtrack niveau 156
pos: [2, 6] 6
enter backtrack niveau 157
pos: [2, 7] 2
enter backtrack niveau 158
pos: [2, 8] 0
[9]
9
enter backtrack niveau 159
pos: [3, 0] 5
enter backtrack niveau 160
pos: [3, 1] 9
enter backtrack niveau 161
pos: [3, 2] 0
[3]
3
enter backtrack niveau 162
pos: [3, 3] 6
enter backtrack niveau 163
pos: [3, 4] 2
enter backtrack niveau 164
pos: [3, 5] 1
enter backtrack niveau 165
pos: [3, 6] 0
[4]
4
enter backtrack niveau 166
pos: [3, 7] 0
[8]
8
enter backtrack niveau 167
pos: [3, 8] 0
[7]
7
enter backtrack niveau 168
pos: [4, 0] 0
[4, 8]
4
enter backtrack niveau 169
pos: [4, 1] 2
enter backtrack niveau 170
pos: [4, 2] 7
enter backtrack niveau 171
pos: [4, 3] 0
[3, 8, 9]
3
enter backtrack niveau 172
pos: [4, 4] 0
[]
exit backtrack niveau 172
8
enter backtrack niveau 173
pos: [4, 4] 0
[3]
3
enter backtrack niveau 174
pos: [4, 5] 0
[]
exit backtrack niveau 174
exit backtrack niveau 173
9
enter backtrack niveau 175
pos: [4, 4] 0
[3]
3
enter backtrack niveau 176
pos: [4, 5] 0
[8]
8
enter backtrack niveau 177
pos: [4, 6] 1
enter backtrack niveau 178
pos: [4, 7] 6
enter backtrack niveau 179
pos: [4, 8] 0
[5]
5
enter backtrack niveau 180
pos: [5, 0] 0
[1, 8]
1
enter backtrack niveau 181
pos: [5, 1] 0
[6]
6
enter backtrack niveau 182
pos: [5, 2] 0
[]
exit backtrack niveau 182
exit backtrack niveau 181
8
enter backtrack niveau 183
pos: [5, 1] 0
[6]
6
enter backtrack niveau 184
pos: [5, 2] 0
[1]
1
enter backtrack niveau 185
pos: [5, 3] 5
enter backtrack niveau 186
pos: [5, 4] 7
enter backtrack niveau 187
pos: [5, 5] 4
enter backtrack niveau 188
pos: [5, 6] 0
[2]
2
enter backtrack niveau 189
pos: [5, 7] 9
enter backtrack niveau 190
pos: [5, 8] 3
enter backtrack niveau 191
pos: [6, 0] 0
[1]
1
enter backtrack niveau 192
pos: [6, 1] 8
enter backtrack niveau 193
pos: [6, 2] 5
enter backtrack niveau 194
pos: [6, 3] 0
[3]
3
enter backtrack niveau 195
pos: [6, 4] 0
[4]
4
enter backtrack niveau 196
pos: [6, 5] 9
enter backtrack niveau 197
pos: [6, 6] 7
enter backtrack niveau 198
pos: [6, 7] 0
[]
exit backtrack niveau 198
exit backtrack niveau 195
exit backtrack niveau 194
exit backtrack niveau 191
exit backtrack niveau 188
exit backtrack niveau 184
exit backtrack niveau 183
exit backtrack niveau 180
exit backtrack niveau 179
exit backtrack niveau 176
exit backtrack niveau 175
exit backtrack niveau 171
8
enter backtrack niveau 199
pos: [4, 1] 2
enter backtrack niveau 200
pos: [4, 2] 7
enter backtrack niveau 201
pos: [4, 3] 0
[3, 9]
3
enter backtrack niveau 202
pos: [4, 4] 0
[]
exit backtrack niveau 202
9
enter backtrack niveau 203
pos: [4, 4] 0
[3]
3
enter backtrack niveau 204
pos: [4, 5] 0
[]
exit backtrack niveau 204
exit backtrack niveau 203
exit backtrack niveau 201
exit backtrack niveau 168
exit backtrack niveau 167
exit backtrack niveau 166
exit backtrack niveau 165
exit backtrack niveau 161
exit backtrack niveau 158
exit backtrack niveau 155
exit backtrack niveau 154
exit backtrack niveau 151
7
enter backtrack niveau 205
pos: [2, 1] 0
[]
exit backtrack niveau 205
exit backtrack niveau 150
exit backtrack niveau 147
5
enter backtrack niveau 206
pos: [1, 6] 0
[]
exit backtrack niveau 206
exit backtrack niveau 146
3
enter backtrack niveau 207
pos: [1, 4] 8
enter backtrack niveau 208
pos: [1, 5] 0
[2, 5]
2
enter backtrack niveau 209
pos: [1, 6] 0
[5]
5
enter backtrack niveau 210
pos: [1, 7] 7
enter backtrack niveau 211
pos: [1, 8] 4
enter backtrack niveau 212
pos: [2, 0] 0
[3, 7]
3
enter backtrack niveau 213
pos: [2, 1] 0
[7]
7
enter backtrack niveau 214
pos: [2, 2] 8
enter backtrack niveau 215
pos: [2, 3] 4
enter backtrack niveau 216
pos: [2, 4] 0
[1]
1
enter backtrack niveau 217
pos: [2, 5] 0
[5]
5
enter backtrack niveau 218
pos: [2, 6] 6
enter backtrack niveau 219
pos: [2, 7] 2
enter backtrack niveau 220
pos: [2, 8] 0
[9]
9
enter backtrack niveau 221
pos: [3, 0] 5
enter backtrack niveau 222
pos: [3, 1] 9
enter backtrack niveau 223
pos: [3, 2] 0
[3]
3
enter backtrack niveau 224
pos: [3, 3] 6
enter backtrack niveau 225
pos: [3, 4] 2
enter backtrack niveau 226
pos: [3, 5] 1
enter backtrack niveau 227
pos: [3, 6] 0
[4]
4
enter backtrack niveau 228
pos: [3, 7] 0
[8]
8
enter backtrack niveau 229
pos: [3, 8] 0
[7]
7
enter backtrack niveau 230
pos: [4, 0] 0
[4, 8]
4
enter backtrack niveau 231
pos: [4, 1] 2
enter backtrack niveau 232
pos: [4, 2] 7
enter backtrack niveau 233
pos: [4, 3] 0
[8, 9]
8
enter backtrack niveau 234
pos: [4, 4] 0
[3]
3
enter backtrack niveau 235
pos: [4, 5] 0
[]
exit backtrack niveau 235
exit backtrack niveau 234
9
enter backtrack niveau 236
pos: [4, 4] 0
[3]
3
enter backtrack niveau 237
pos: [4, 5] 0
[8]
8
enter backtrack niveau 238
pos: [4, 6] 1
enter backtrack niveau 239
pos: [4, 7] 6
enter backtrack niveau 240
pos: [4, 8] 0
[5]
5
enter backtrack niveau 241
pos: [5, 0] 0
[1, 8]
1
enter backtrack niveau 242
pos: [5, 1] 0
[6]
6
enter backtrack niveau 243
pos: [5, 2] 0
[]
exit backtrack niveau 243
exit backtrack niveau 242
8
enter backtrack niveau 244
pos: [5, 1] 0
[6]
6
enter backtrack niveau 245
pos: [5, 2] 0
[1]
1
enter backtrack niveau 246
pos: [5, 3] 5
enter backtrack niveau 247
pos: [5, 4] 7
enter backtrack niveau 248
pos: [5, 5] 4
enter backtrack niveau 249
pos: [5, 6] 0
[2]
2
enter backtrack niveau 250
pos: [5, 7] 9
enter backtrack niveau 251
pos: [5, 8] 3
enter backtrack niveau 252
pos: [6, 0] 0
[1]
1
enter backtrack niveau 253
pos: [6, 1] 8
enter backtrack niveau 254
pos: [6, 2] 5
enter backtrack niveau 255
pos: [6, 3] 0
[2]
2
enter backtrack niveau 256
pos: [6, 4] 0
[4]
4
enter backtrack niveau 257
pos: [6, 5] 9
enter backtrack niveau 258
pos: [6, 6] 7
enter backtrack niveau 259
pos: [6, 7] 0
[3]
3
enter backtrack niveau 260
pos: [6, 8] 0
[6]
6
enter backtrack niveau 261
pos: [7, 0] 9
enter backtrack niveau 262
pos: [7, 1] 3
enter backtrack niveau 263
pos: [7, 2] 0
[6]
6
enter backtrack niveau 264
pos: [7, 3] 0
[1]
1
enter backtrack niveau 265
pos: [7, 4] 5
enter backtrack niveau 266
pos: [7, 5] 0
[7]
7
enter backtrack niveau 267
pos: [7, 6] 8
enter backtrack niveau 268
pos: [7, 7] 4
enter backtrack niveau 269
pos: [7, 8] 0
[2]
2
enter backtrack niveau 270
pos: [8, 0] 0
[7]
7
enter backtrack niveau 271
pos: [8, 1] 0
[4]
4
enter backtrack niveau 272
pos: [8, 2] 2
enter backtrack niveau 273
pos: [8, 3] 0
[8]
8
enter backtrack niveau 274
pos: [8, 4] 6
enter backtrack niveau 275
pos: [8, 5] 0
[3]
3
enter backtrack niveau 276
pos: [8, 6] 0
[9]
9
enter backtrack niveau 277
pos: [8, 7] 0
[5]
5
enter backtrack niveau 278
pos: [8, 8] 1
enter backtrack niveau 279
pos: [9, 0] 
Out[39]:
True
In [40]:
# on vérifie la grille obtenue
complet(M)
Out[40]:
True
In [41]:
M
Out[41]:
[[2, 5, 4, 7, 9, 6, 3, 1, 8],
 [6, 1, 9, 3, 8, 2, 5, 7, 4],
 [3, 7, 8, 4, 1, 5, 6, 2, 9],
 [5, 9, 3, 6, 2, 1, 4, 8, 7],
 [4, 2, 7, 9, 3, 8, 1, 6, 5],
 [8, 6, 1, 5, 7, 4, 2, 9, 3],
 [1, 8, 5, 2, 4, 9, 7, 3, 6],
 [9, 3, 6, 1, 5, 7, 8, 4, 2],
 [7, 4, 2, 8, 6, 3, 9, 5, 1]]

Question 15

Que renvoie la fonction solution_sudoku(L) si le sudoku L admet plusieurs solutions ? Et si L est le sudoku rempli de 0 ?

In [42]:
# Q.15
# on créé une grille vide
N = [[0]*9 for _ in range(9)]
N
Out[42]:
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0]]
In [43]:
backtracking(N, [0, 0])
Out[43]:
True
In [44]:
N
Out[44]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
 [4, 5, 6, 7, 8, 9, 1, 2, 3],
 [7, 8, 9, 1, 2, 3, 4, 5, 6],
 [2, 1, 4, 3, 6, 5, 8, 9, 7],
 [3, 6, 5, 8, 9, 7, 2, 1, 4],
 [8, 9, 7, 2, 1, 4, 3, 6, 5],
 [5, 3, 1, 6, 4, 2, 9, 7, 8],
 [6, 4, 2, 9, 7, 8, 5, 3, 1],
 [9, 7, 8, 5, 3, 1, 6, 4, 2]]

Question 16

Dans l’algorithme précédent, on parcourt l’ensemble des cas dans l’ordre lexicographique. Comment améliorer celui-ci pour limiter le nombre d’appels à la variable pos ?

In [45]:
# Q.16
# Sans doute en parcourant les cases d'abord par carré puis par ligne, puis par colonne