-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunctions.py
185 lines (145 loc) · 5.35 KB
/
functions.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
import sys
import matplotlib.pyplot as plt
import numpy as np
from collections import defaultdict
rows = 'ABCDEFGHI'
cols = '123456789'
boxes = [r + c for r in rows for c in cols]
def extract_units(unitlist, boxes):
"""Initialize a mapping from box names to the units that the boxes belong to
Parameters
----------
unitlist(list)
a list containing "units" (rows, columns, diagonals, etc.) of boxes
boxes(list)
a list of strings identifying each box on a sudoku board (e.g., "A1", "C7", etc.)
Returns
-------
dict
a dictionary with a key for each box (string) whose value is a list
containing the units that the box belongs to (i.e., the "member units")
"""
# the value for keys that aren't in the dictionary are initialized as an empty list
units = defaultdict(list)
for current_box in boxes:
for unit in unitlist:
if current_box in unit:
# defaultdict avoids this raising a KeyError when new keys are added
units[current_box].append(unit)
return units
def extract_peers(units, boxes):
"""Initialize a mapping from box names to a list of peer boxes (i.e., a flat list
of boxes that are in a unit together with the key box)
Parameters
----------
units(dict)
a dictionary with a key for each box (string) whose value is a list
containing the units that the box belongs to (i.e., the "member units")
boxes(list)
a list of strings identifying each box on a sudoku board (e.g., "A1", "C7", etc.)
Returns
-------
dict
a dictionary with a key for each box (string) whose value is a set
containing all boxes that are peers of the key box (boxes that are in a unit
together with the key box)
"""
# the value for keys that aren't in the dictionary are initialized as an empty list
peers = defaultdict(set) # set avoids duplicates
for key_box in boxes:
for unit in units[key_box]:
for peer_box in unit:
if peer_box != key_box:
# defaultdict avoids this raising a KeyError when new keys are added
peers[key_box].add(peer_box)
return peers
def assign_value(values, box, value):
"""You must use this function to update your values dictionary if you want to
try using the provided visualization tool. This function records each assignment
(in order) for later reconstruction.
Parameters
----------
values(dict)
a dictionary of the form {'box_name': '123456789', ...}
Returns
-------
dict
The values dictionary with the naked twins eliminated from peers
"""
# Don't waste memory appending actions that don't actually change any values
if values[box] == value:
return values
prev = values2grid(values)
values[box] = value
if len(value) == 1:
history[values2grid(values)] = (prev, (box, value))
return values
def cross(A, B):
"""Cross product of elements in A and elements in B """
return [x+y for x in A for y in B]
def values2grid(values):
"""Convert the dictionary board representation to as string
Parameters
----------
values(dict)
a dictionary of the form {'box_name': '123456789', ...}
Returns
-------
a string representing a sudoku grid.
Ex. '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3'
"""
res = []
for r in rows:
for c in cols:
v = values[r + c]
res.append(v if len(v) == 1 else '0')
return ''.join(res)
def grid2values(grid):
"""Convert grid into a dict of {square: char} with '123456789' for empties.
Parameters
----------
grid(string)
a string representing a sudoku grid.
Ex. '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3'
Returns
-------
A grid in dictionary form
Keys: The boxes, e.g., 'A1'
Values: The value in each box, e.g., '8'. If the box has no value,
then the value will be '123456789'.
"""
sudoku_grid = {}
for val, key in zip(grid, boxes):
if val == '.':
sudoku_grid[key] = '123456789'
else:
sudoku_grid[key] = val
return sudoku_grid
def plot_sudoku(val):
# Simple plotting statement that ingests a 9x9 array (n), and plots a sudoku-style grid around it.
s= values2grid(val)
n=[]
for i in range(9):
r=[]
for j in range(9):
r.append(int(s[i*9+j]))
n.append(r)
n=np.array(n)
plt.figure()
for y in range(10):
plt.plot([-0.05,9.05],[y,y],color='black',linewidth=1)
for y in range(0,10,3):
plt.plot([-0.05,9.05],[y,y],color='black',linewidth=3)
for x in range(10):
plt.plot([x,x],[-0.05,9.05],color='black',linewidth=1)
for x in range(0,10,3):
plt.plot([x,x],[-0.05,9.05],color='black',linewidth=3)
plt.axis('image')
plt.axis('off') # drop the axes, they're not important here
for x in range(9):
for y in range(9):
foo=n[8-y][x] # need to reverse the y-direction for plotting
if foo > 0: # ignore the zeros
T=str(foo)
plt.text(x+0.3,y+0.2,T,fontsize=20)
plt.show()