/
096.py
190 lines (167 loc) · 7.26 KB
/
096.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!python
"""
Su Doku (Japanese meaning number place) is the name given to a popular puzzle concept. Its origin is unclear, but credit must be attributed to Leonhard Euler who invented a similar, and much more difficult, puzzle idea called Latin Squares. The objective of Su Doku puzzles, however, is to replace the blanks (or zeros) in a 9 by 9 grid in such that each row, column, and 3 by 3 box contains each of the digits 1 to 9. Below is an example of a typical starting puzzle grid and its solution grid.
0 0 3
9 0 0
0 0 1 0 2 0
3 0 5
8 0 6 6 0 0
0 0 1
4 0 0
0 0 8
7 0 0
0 0 6 1 0 2
0 0 0
7 0 8 9 0 0
0 0 8
2 0 0
0 0 2
8 0 0
0 0 5 6 0 9
2 0 3
0 1 0 5 0 0
0 0 9
3 0 0
4 8 3
9 6 7
2 5 1 9 2 1
3 4 5
8 7 6 6 5 7
8 2 1
4 9 3
5 4 8
7 2 9
1 3 6 1 3 2
5 6 4
7 9 8 9 7 6
1 3 8
2 4 5
3 7 2
8 1 4
6 9 5 6 8 9
2 5 3
4 1 7 5 1 4
7 6 9
3 8 2
A well constructed Su Doku puzzle has a unique solution and can be solved by logic, although it may be necessary to employ "guess and test" methods in order to eliminate options (there is much contested opinion over this). The complexity of the search determines the difficulty of the puzzle; the example above is considered easy because it can be solved by straight forward direct deduction.
The 6K text file, sudoku.txt (right click and 'Save Link/Target As...'), contains fifty different Su Doku puzzles ranging in difficulty, but all with unique solutions (the first puzzle in the file is the example above).
By solving all fifty puzzles find the sum of the 3-digit numbers found in the top left corner of each solution grid; for example, 483 is the 3-digit number found in the top left corner of the solution grid above.
"""
puzzles = """003020600900305001001806400008102900700000008006708200002609500800203009005010300
200080300060070084030500209000105408000000000402706000301007040720040060004010003
000000907000420180000705026100904000050000040000507009920108000034059000507000000
030050040008010500460000012070502080000603000040109030250000098001020600080060020
020810740700003100090002805009040087400208003160030200302700060005600008076051090
100920000524010000000000070050008102000000000402700090060000000000030945000071006
043080250600000000000001094900004070000608000010200003820500000000000005034090710
480006902002008001900370060840010200003704100001060049020085007700900600609200018
000900002050123400030000160908000000070000090000000205091000050007439020400007000
001900003900700160030005007050000009004302600200000070600100030042007006500006800
000125400008400000420800000030000095060902010510000060000003049000007200001298000
062340750100005600570000040000094800400000006005830000030000091006400007059083260
300000000005009000200504000020000700160000058704310600000890100000067080000005437
630000000000500008005674000000020000003401020000000345000007004080300902947100080
000020040008035000000070602031046970200000000000501203049000730000000010800004000
361025900080960010400000057008000471000603000259000800740000005020018060005470329
050807020600010090702540006070020301504000908103080070900076205060090003080103040
080005000000003457000070809060400903007010500408007020901020000842300000000100080
003502900000040000106000305900251008070408030800763001308000104000020000005104800
000000000009805100051907420290401065000000000140508093026709580005103600000000000
020030090000907000900208005004806500607000208003102900800605007000309000030020050
005000006070009020000500107804150000000803000000092805907006000030400010200000600
040000050001943600009000300600050002103000506800020007005000200002436700030000040
004000000000030002390700080400009001209801307600200008010008053900040000000000800
360020089000361000000000000803000602400603007607000108000000000000418000970030014
500400060009000800640020000000001008208000501700500000000090084003000600060003002
007256400400000005010030060000508000008060200000107000030070090200000004006312700
000000000079050180800000007007306800450708096003502700700000005016030420000000000
030000080009000500007509200700105008020090030900402001004207100002000800070000090
200170603050000100000006079000040700000801000009050000310400000005000060906037002
000000080800701040040020030374000900000030000005000321010060050050802006080000000
000000085000210009960080100500800016000000000890006007009070052300054000480000000
608070502050608070002000300500090006040302050800050003005000200010704090409060701
050010040107000602000905000208030501040070020901080406000401000304000709020060010
053000790009753400100000002090080010000907000080030070500000003007641200061000940
006080300049070250000405000600317004007000800100826009000702000075040190003090600
005080700700204005320000084060105040008000500070803010450000091600508007003010600
000900800128006400070800060800430007500000009600079008090004010003600284001007000
000080000270000054095000810009806400020403060006905100017000620460000038000090000
000602000400050001085010620038206710000000000019407350026040530900020007000809000
000900002050123400030000160908000000070000090000000205091000050007439020400007000
380000000000400785009020300060090000800302009000040070001070500495006000000000092
000158000002060800030000040027030510000000000046080790050000080004070100000325000
010500200900001000002008030500030007008000500600080004040100700000700006003004050
080000040000469000400000007005904600070608030008502100900000005000781000060000010
904200007010000000000706500000800090020904060040002000001607000000000030300005702
000700800006000031040002000024070000010030080000060290000800070860000500002006000
001007090590080001030000080000005800050060020004100000080000030100020079020700400
000003017015009008060000000100007000009000200000500004000000020500600340340200000
300200000000107000706030500070009080900020004010800050009040301000702000000008006""".split()
digits = set(map(int, list("123456789")))
def get_pos(p, r, c):
return int(p[9*r+c])
def set_pos(p, r, c, v):
x = 9*r+c
return p[:x]+str(v)+p[x+1:]
def get_digits_in_row(p, r):
return set(map(int, list(p[:10])))
def get_digits_in_column(p, c):
return set(map(int, list(p[c::9])))
def get_digits_in_box(p, r, c):
br = r//3
bc = c//3
box = []
for i in range(3):
for j in range(3):
box.append(get_pos(p, br+i, bc+j))
return set(box)
def is_complete(p):
for i in range(9):
if get_digits_in_row(p,i) != digits:
return False
if get_digits_in_column(p,i) != digits:
return False
if i%3==0:
for j in range(1,3):
if get_digits_in_box(i, 3*j)!= digits:
return False
return True
def solve(p):
pp = p[:]
if is_complete(pp):
return pp
for i in range(9):
for j in range(9):
if get_pos(pp,i,j) == 0:
for d in (digits & get_digits_in_row(pp,i)&get_digits_in_column(pp,j)&get_digits_in_box(pp,i,j)):
pp = set_pos(pp,i,j,d)
ppp = solve(pp)
if ppp is not None:
return ppp
pp = set_pos(pp,i,j,0)
return None
from sudokulib.grid import StringGrid
from sudokulib.solver import SudokuSolver
x = 0
for grid in puzzles:
s = SudokuSolver(grid, grid_class=StringGrid)
s.run()
r = list(grid[:3])
for i in range(3):
if r[i]=='0':
r[i]=s.grid.data_solution[i]
x+=int("".join(r))
print([x,r])
#file parsers
def get_sudoku_from_file(fn):
with open(fn, "rtU") as f:
puzzle=""
for line in f:
if line[0]=='G':#start of a new puzzle
if len(puzzle)==81:
yield puzzle
puzzle = ""
else:
puzzle += line
if len(puzzle)==81:
yield puzzle