fun

And there we go, took an example from a website and lo and behold, my sudoku solver freaking works. I'll get to some cleanup later today :D

Author
Vngngdn
Date
July 20, 2016, 12:58 p.m.
Hash
306409c3d126fdff16a950a002086c145771267a
Parent
e5efc74698b5f3d9409cb8a5e64528ef649b0d1c
Modified file
sudoku-solver.py

sudoku-solver.py

73 additions and 26 deletions.

View changes Hide changes
1
1
sudoku-solver.py - A simple program that can solve any (solvable) sudoku puzzle.
2
2
Copyright 2016 Maarten 'Vngngdn' Vangeneugden
3
3
4
4
Licensed under the Apache License, Version 2.0 (the "License");
5
5
you may not use this file except in compliance with the License.
6
6
You may obtain a copy of the License at
7
7
8
8
    https://www.apache.org/licenses/LICENSE-2.0
9
9
10
10
Unless required by applicable law or agreed to in writing, software
11
11
distributed under the License is distributed on an "AS IS" BASIS,
12
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
"""
16
16
17
17
# I don't think I need to explain this, do I? Although I will explain how the
18
18
# program works:
19
19
# One is supposed to give an array of arrays, which will each contain a series
20
20
# of integer values in range [1,9]. Some of them may be 0, these will then stand
21
21
# for an empty value.
22
22
# This program's goal is to remove all 0's (blank spaces) and fill them so, that
23
23
# the sudoku is considered solved. After that, it prints the sudoku to the
24
24
# terminal.
25
25
26
26
# Prints the given sudoku to the terminal in a readable way:
27
27
def print_sudoku(sudoku):
28
28
    print(sudoku)
29
-
    """for x in sudoku:
30
-
        print(sudoku[x])
31
-
        for y in x:
+
29
        #print(sudoku[x])
+
30
        for y in x:
32
31
            pass
33
-
            #print(str(sudoku[x][y]) + " ", end="")
+
32
            #print(str(sudoku[x][y]) + " ", end="")
34
33
        print()  # Start a new line.
35
34
        """
36
-
37
35
# Given an empty sudoku, the solution is very simple.
38
36
def solve_empty_sudoku(sudoku): 
39
37
    n = 3
40
38
    for i in range(0, n*n):
41
39
        for j in range(0, n*n):
42
40
            sudoku[i][j] = (i*n + i/n + j) % (n*n) + 1;
43
41
    return sudoku
44
42
45
43
# Creates a table of 9x9 in the form of an array containing arrays.
46
44
def create_sudoku():
47
45
    x = []
48
46
    for i in range(0,9):
49
47
        x.append([0, 0, 0, 0, 0, 0, 0, 0, 0])
50
48
    return x
51
49
52
50
EMPTY = 0
53
51
54
52
# Checks if the given sudoku qualifies as a root solution.
55
53
def is_possible_root_solution(sudoku):
56
54
    root_solution = solve_empty_sudoku()
57
55
    for i in range(0, len(root_solution)):
58
56
        for j in range(0, len(root_solution[i])):
59
57
            if sudoku[i][j] != root_solution[i][j] and sudoku[i][j] != 0:
60
58
                return False
61
59
    # When here, all the sudoku can be filled as a root solution.
62
60
    return True
63
61
64
62
# Checks whether the given number already exists in the given array.
65
63
def exists_in_array(x, y, sudoku):
66
-
    value = sudoku[x][y]
67
-
    for i in range(len(sudoku)):
68
-
        if sudoku[i][y] == value and i != x and sudoku[i][y] != 0:
69
-
            return True
+
64
    #value = sudoku[x][y]
+
65
    for i in range(0, len(sudoku)):
+
66
        if sudoku[i][y] == value and sudoku[i][y] != EMPTY:
+
67
            return True
70
68
    return False
71
69
72
70
# Checks whether the number on the given location is unique in its column.
73
71
def exists_in_column(x, y, sudoku):
74
-
    value = sudoku[x][y]
75
-
    for i in range(0, len(sudoku[x])):
+
72
    #value = sudoku[x][y]
+
73
    for i in range(0, len(sudoku[x])):
76
74
        if sudoku[x][i] == value and i != y and sudoku[x][i] != 0:
77
-
            return True
+
75
            return True
78
76
    return False
79
77
80
78
# Checks whether the number on the given location is unique in its (3x3) grid.
81
79
def exists_in_grid(x, y, sudoku):
82
-
    value = sudoku[x][y]
83
-
    # We're going to find out now in which part of the grid the (x,y) is put.
+
80
    #value = sudoku[x][y]
+
81
    # We're going to find out now in which part of the grid the (x,y) is put.
84
82
    # We'll increment x and y by 1 in order to have some 1-indexed math:
85
83
86
84
    # The idea I'm going for now:
87
85
    # I'll first try to find out in which segment of the sudoku the value is in.
88
86
    # When I've found it, I trim the data to that segment, after I'll be
89
87
    # checking on that segment only.
90
88
    # Chart:
91
89
    """
92
90
    +-----+
93
91
    |A B C|
94
92
    |D E F|
95
93
    |G H I|
96
94
    +-----+
97
95
    """
98
96
    n = 3
99
97
    
100
98
101
99
    A = x%n
102
100
    B = y%n
103
101
    for i in range(0, n):
104
102
        for j in range(0, n):
105
103
            C = x - A + i
106
104
            D = y - B + j
107
105
            if sudoku[C][D] == value and (C != x and D != y):
108
106
                return True
109
107
    return False
110
108
111
109
def is_filled_sudoku(sudoku):
112
110
    for i in range(0, len(sudoku)):
113
111
        for j in range(0, len(sudoku[i])):
114
112
            if sudoku[i][j] == 0:
115
113
                return False
116
114
    return True
117
115
118
116
def find_first_empty_grid(sudoku):
119
117
    for i in range(0, len(sudoku)):
120
118
        for j in range(0, len(sudoku[i])):
121
119
            if sudoku[i][j] == 0:
122
120
                return i, j
123
121
124
122
def is_valid_assignment(x, y, value, sudoku):
125
123
    sudoku[x][y] = value
126
-
    if exists_in_array(x, y, sudoku):
127
-
        print("Exists in array!")
128
-
        return False
+
124
    if exists_in_array(x, y, value, sudoku):
+
125
        #print("Exists in array!")
+
126
        return False
129
127
    if exists_in_column(x, y, sudoku):
130
-
        print("Exists in column!")
131
-
        return False
+
128
        #print("Exists in column!")
+
129
        return False
132
130
    if exists_in_grid(x, y, sudoku):
133
-
        print("Exists in grid!")
134
-
        return False
+
131
        #print("Exists in grid!")
+
132
        return False
135
133
    return True
136
134
137
135
# Makes a deep copy of the given sudoku, and returns that copy.
138
136
def make_copy(sudoku):
139
137
    newSudoku = []
140
138
    for array in sudoku:
141
139
        newSudoku.append(array.copy())
142
140
    return newSudoku
143
141
144
142
145
143
sudokuA = create_sudoku()
146
144
147
145
def recursive_solution(sudoku):
148
146
    if is_filled_sudoku(sudoku):
149
147
        return True  # The sudoku is solved.
150
148
    else:
151
149
        x, y = find_first_empty_grid(sudoku)
152
150
        print(str(x) + "-" + str(y))
153
-
        for i in range(1, 10):
+
151
        for i in range(1, 10):
154
152
            # We're going to fill in numbers from 1 to 9, to find a solution
155
153
            # that works.
156
154
            sudoku[x][y] = i
157
-
            if is_valid_assignment(x, y, i, sudoku):
158
155
                oldSudoku = make_copy(sudoku)
159
-
                if recursive_solution(sudoku) is False:
+
156
                #oldSudoku = make_copy(sudoku)
+
157
                if recursive_solution(sudoku) is False:
160
158
                    sudoku = oldSudoku
161
-
                else:
+
159
                else:
162
160
                    return True
163
161
        return False
164
162
165
163
# MAIN
+
164
    discovered = []
+
165
    # Rows:
+
166
    for column in sudoku:
+
167
        discovered.clear()
+
168
        for loc in column:
+
169
            if loc in discovered:
+
170
                return False
+
171
            else:
+
172
                discovered.append(loc)
+
173
+
174
    #Columns:
+
175
    for i in range(0, len(sudoku)):
+
176
        discovered.clear()
+
177
        for y in range(0, len(sudoku[i])):
+
178
            if y in discovered:
+
179
                return False
+
180
            else:
+
181
                discovered.append(y)
+
182
+
183
    discovered.clear()
+
184
+
185
    #Grids:
+
186
    for k in [0, 3, 6]:
+
187
        discovered.clear()
+
188
        for x in range(0,3):
+
189
            for y in range(0,3):
+
190
                if sudoku[x+k][y+k] in discovered:
+
191
                    return False
+
192
                else:
+
193
                    discovered.append(sudoku[x+k][y+k])
+
194
+
195
    return True
+
196
+
197
+
198
+
199
# MAIN
166
200
+
201
        [8, 4, 0, 0, 0, 0, 0, 0, 0],
+
202
        [0, 0, 5, 7, 0, 1, 0, 3, 4],
+
203
        [9, 0, 7, 0, 0, 0, 0, 0, 0],
+
204
        [5, 9, 0, 2, 0, 0, 0, 0, 0],
+
205
        [0, 0, 0, 3, 8, 6, 0, 0, 0],
+
206
        [0, 0, 0, 0, 0, 4, 0, 8, 2],
+
207
        [0, 0, 0, 0, 0, 0, 3, 0, 1],
+
208
        [7, 3, 0, 5, 0, 9, 6, 0, 0],
+
209
        [0, 0, 0, 0, 0, 0, 0, 7, 5]
+
210
        ]
+
211
167
212
if recursive_solution(sudokuA):
168
213
    print_sudoku(sudokuA)
169
-
else:
+
214
        print_sudoku(sudokuA)
+
215
else:
170
216
    print("Failed!")
171
217
    print_sudoku(sudokuA)
172
218
                
173
219