-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmodels.py
134 lines (95 loc) · 3.03 KB
/
models.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
from StringIO import StringIO
from copy import deepcopy
PVALS = set(range(1, 10))
PIDXS = set(range(0, 9))
class Index (object):
def __init__(self, row, col):
self.row, self.col = row, col
def id(self):
return self.row*100+self.col
def __eq__(self, other):
return self.row == other.row and self.col == other.col
def __str__(self):
return "<%s,%s>" % (self.row, self.col)
def __repr__(self):
return "<%s,%s>" % (self.row, self.col)
def __hash__(self):
return self.id()
def __cmp__(self, other):
# so we can sort
return self.id().__cmp__(other.id())
def __iter__(self):
yield self.row
yield self.col
def square_idxs(i):
r = i / 3
return range(r*3, r*3+3)
def square(idx):
return cross(square_idxs(idx.row), square_idxs(idx.col))
def share_a_row(*idxs):
return all(idx.row == idxs[0].row
for idx in idxs[1:])
def share_a_col(*idxs):
return all(idx.col==idxs[0].col
for idx in idxs[1:])
def share_a_square(*idxs):
return all(idx.col/3==idxs[0].col/3 and idx.row/3==idxs[0].row/3
for idx in idxs[1:])
def cross(l1, l2):
return [Index(i, j)
for i in l1
for j in l2]
puzzle_range = cross(PIDXS, PIDXS)
class PosCount(object):
def __init__(self, val=None, idxs=None):
self.val, self.idxs = val, idxs or []
def __len__(self):
return len(self.idxs)
def __repr__(self):
return "|%d|" % len(self)
def __str__(self):
return "|%d|" % len(self)
def __iter__(self):
return iter(self.idxs)
class Box (object):
def __init__(self, idx, val):
self.idx,self.val = idx,val
def __len__(self):
if isinstance(self.val,int): return 1
elif not self.val: return 0
return len(self.val)
def __str__(self):
return "Box(%s,%s)"%(self.idx,self.val)
class Ref (object):
def __init__(self,**kws):
for k,v in kws.items():
setattr(self, k, v)
class Stats (object):
def __init__(self,**kws):
for k,v in kws.items():
setattr(self, k, v)
def inc(self,k,v=1):
if isinstance(k, Stats):
for k,v in vars(k).items():
self.inc(k,v)
else:
return setattr(self, k, getattr(self,k,0)+v)
def __str__ (self):
s = StringIO()
stats = deepcopy(vars(self))
del stats['constraint_steps']
del stats['puzzle_branches']
s.write(" %s - Constraint Cycles\n" % self.constraint_steps)
s.write(" %s - Branches\n\n" % self.puzzle_branches)
items = stats.items()
items.sort()
for k,v in items:
s.write(' %s : %s \n' % (k,v))
return s.getvalue()
class ConstrainedThisCycle(Exception):
pass
class NoPossibleValues(Exception):
def __init__(self, idx=None, data=None):
self.idx,self.data = idx,data
def __str__(self):
return "NoPossibleValues for %s:%r" % (self.idx, self.data)