-
Notifications
You must be signed in to change notification settings - Fork 1
/
crossword.py
142 lines (108 loc) · 4.56 KB
/
crossword.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
class Crossword():
def __init__(self,structure,word):
with open(structure) as f:
contents = f.read().splitlines()
self.height = len(contents)
self.width = max(len(line) for line in contents)
self.structure = []
for i in range(self.height):
row = []
for j in range(self.width):
if j >= len(contents[i]):
row.append(False)
elif contents[i][j] == '_':
row.append(True)
else:
row.append(False)
self.structure.append(row)
with open(word) as f:
self.words = set(f.read().upper().splitlines())
self.variables = set()
for i in range(self.height):
for j in range(self.width):
if self.structure[i][j]:
#Horizontal Words
word_start = (
self.structure[i][j] and
(i == 0 or not self.structure[i-1][j])
)
if word_start:
length = 1
for k in range(i+1,self.height):
if self.structure[k][j]:
length += 1
else:
break
if length > 1:
self.variables.add(
Variable(i = i, j = j, direction = Variable.DOWN,length = length)
)
#Vertical Words
word_start = (
self.structure[i][j] and
(j == 0 or not self.structure[i][j-1])
)
if word_start:
length = 1
for k in range(j + 1, self.width):
if self.structure[i][k]:
length += 1
else:
break
if length > 1:
self.variables.add(
Variable(i,j,Variable.ACROSS,length)
)
self.overlaps = dict()
for v1 in self.variables:
for v2 in self.variables:
if v1 == v2:
continue
cells1 = v1.cells
cells2 = v2.cells
# print("cells1 : ",cells1)
# print("cells2 : ",cells2)
intersection = set(cells1).intersection(set(cells2))
if intersection:
intersection = intersection.pop()
# print("intersection : ",intersection)
self.overlaps[v1,v2] = (
cells1.index(intersection),
cells2.index(intersection)
)
else:
self.overlaps[v1,v2] = None
def neighbors(self, var):
"""Given a variable, return set of overlapping variables."""
return set(
v for v in self.variables
if v != var and (self.overlaps[v, var])
)
class Variable():
ACROSS = "across"
DOWN = "down"
def __init__(self, i, j, direction, length):
self.i = i
self.j = j
self.direction = direction
self.length = length
self.cells = []
for k in range(self.length):
self.cells.append((
self.i + (k if self.direction == Variable.DOWN else 0),
self.j + (k if self.direction == Variable.ACROSS else 0)
))
def __hash__(self):
return hash((self.i, self.j, self.direction, self.length))
def __str__(self):
return f"({self.i}, {self.j}) {self.direction} : {self.length}"
def __eq__(self, other):
return (
isinstance(other, Variable) and
(self.i == other.i) and
(self.j == other.j) and
(self.direction == other.direction) and
(self.length == other.length)
)
def __str__(self):
return f"({self.i},{self.j}){self.direction} : {self.length}"