-
Notifications
You must be signed in to change notification settings - Fork 0
/
recursiveBacktracking.py
133 lines (99 loc) · 3.71 KB
/
recursiveBacktracking.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 22 21:24:36 2014
@author: Ricardo Guerrero Gómez-Olmedo
"""
import numpy as np
from matplotlib.mlab import find
class recursiveBacktracking(object):
'''
The algorithm implemented in this class is based on the recursive
backtracking algorithm described in [1].
[1] http://es.wikipedia.org/wiki/Sudoku_backtracking
'''
def __init__(self):
'''
Dummy constructor. It takes no parameters. The real initialization
is done when the method `setInitialGrid` is called.
'''
self.solution = None
self.original = None
self.matbool = None
def setInitialGrid(self,original):
'''
This method sets the initial sudoku that will be used within the class.
Parameters
----------
matrix: array_like
It contains the initial sudoku matrix.
'''
self.original = original
self.matbool = original != 0
def mySquare(self, a, b):
'''
This method returns the square to which the variable in coordinates
a,b belongs.
Parameters
----------
a : int
Current row.
b : int
Current column.
Returns
-------
squares : array_like
Returns a sub array from `squares` that contains the 3x3 square
to which belongs the element located in `original`[`a`,`b`]
'''
#Converting full grid to collection of 3x3 squares
squares = np.swapaxes(self.original.reshape(3,3,3,-1),1,2)
#mapping indexes a,b in original to c,d in squares
equiv = {0: [0,1,2], 1: [3,4,5], 2: [6,7,8]}
c = [key for key in equiv if a in equiv[key]][0]
d = [key for key in equiv if b in equiv[key]][0]
return squares[c,d]
def solve(self):
'''
solve method implements Recursive Backtracking.
It initializes the recursive function that takes care of the
whole algorithm
Parameters
----------
solution: array_like
Retuns a numpy array of 9x9 that contains the solution of the
initial sudoku given in `setInitialGrid`
'''
self.solveRec(0,0)
return self.solution
def solveRec(self, i, j):
'''
This is a helper recursive function used by solver.
It stores the solved sudoku in `self.solution`
Parameters
----------
i : int
Current row.
j : int
Current column.
'''
if self.matbool[i,j] == False:
for k in range(1,10):
self.original[i,j] = k
#checking if value is plausible in row, col and square
if len(find(self.original[i,:] == k)) == 1 and \
len(find(self.original[:,j] == k)) == 1 and \
len(find(self.mySquare(i,j) == k)) == 1:
if i == 8 and j == 8:
self.solution = self.original.copy()
elif i < 8 and j == 8:
self.solveRec(i+1, 0)
else:
self.solveRec(i, j+1)
self.original[i,j] = 0
else:
if i == 8 and j == 8:
self.solution = self.original.copy()
elif i < 8 and j == 8:
self.solveRec(i+1, 0)
else:
self.solveRec(i, j+1)