-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathBogalSolver.py
207 lines (186 loc) · 6.88 KB
/
BogalSolver.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import sys, random, string, time
rawBoard = ''
moves = 0
# size -> int
# generate board of size size x size filled with random chars
# @returns none
def generateBoard(size):
outFile = 'test.txt'
out = open(outFile, 'w')
charlist = string.ascii_uppercase
for z in range(0, size):
line = ' '.join(random.choices(charlist, k=size))
out.write((line + "\n"))
out.close()
return
# textFile -> string
# loads a board from a text file
# @returns board in 2D list form
def loadBoard(textFile):
global rawBoard
boardFile = open(textFile, 'r')
rawBoard = boardFile.read().strip()
n1 = rawBoard.count('\n') + 1
n2 = rawBoard.count(' ') + n1
assert n1**2 == n2
# convert to 2-D array of chars
board = rawBoard.replace(' ', '')
board = board.split('\n')
newBoard = []
for i in range(0,len(board)):
temp = board[i]
newBoard += [list(temp)]
boardFile.close()
return newBoard
# board -> 2D array
# prints out the bogal board
def printBoard(board):
print(rawBoard)
# coordinate -> list, board -> 2D list
# @returns list of all possible next positions
def possibleMoves(coordinate, board):
possibleMoves = []
#search for possible moves
#try down move
if coordinate[0] + 1 < len(board):
possibleMoves.append([coordinate[0] + 1, coordinate[1]])
# try up move
if coordinate[0] - 1 > -1:
possibleMoves.append([coordinate[0] - 1, coordinate[1]])
#try right move
if coordinate[1] + 1 < len(board):
possibleMoves.append([coordinate[0], coordinate[1] + 1])
# try left move
if coordinate[1] - 1 > -1:
possibleMoves.append([coordinate[0], coordinate[1] - 1])
# try upper right corner move
if coordinate[0] - 1 > -1 and coordinate[1] + 1 < len(board):
possibleMoves.append([coordinate[0] - 1, coordinate[1] + 1])
# try down right corner move
if coordinate[0] + 1 < len(board) and coordinate[1] + 1 < len(board):
possibleMoves.append([coordinate[0] + 1, coordinate[1] + 1])
# try upper left corner move
if coordinate[0] - 1 > -1 and coordinate[1] - 1 > -1:
possibleMoves.append([coordinate[0] - 1, coordinate[1] - 1])
# try down left corner move
if coordinate[0]+1<len(board) and coordinate[1]-1>-1:
possibleMoves.append([coordinate[0] + 1, coordinate[1] - 1])
return possibleMoves
# possibleMoves -> 2D list, usedPath -> 2D list
# @returns the list of all legal moves
def legalMoves(possibleMoves, usedPath):
moves = list(set(tuple(i) for i in possibleMoves) - set(tuple(j) for j in usedPath))
return moves
# Function used for setting up all prefix dictionaries.
# This is not run with my program but was created because I'm lazy and
# didn't want to create the prefix dictionaries by hand.
def prefixDict():
preFile = open('preDict.txt', 'w')
preFile3 = open('preDict3.txt', 'w')
preFile4 = open('preDict4.txt', 'w')
preFile5 = open('preDict5.txt', 'w')
dictFile = open('Dict.txt', 'r')
preTxt = dictFile.read().split('\n')
dictFile.close()
txtSet = set()
txtSet3 = set()
txtSet4 = set()
txtSet5 = set()
for word in preTxt:
txtSet.add(word[:2])
txtSet3.add(word[:3])
txtSet4.add(word[:4])
txtSet5.add(word[:5])
for word in txtSet:
preFile.write(word)
preFile.write('\n')
for word in txtSet3:
preFile3.write(word)
preFile3.write('\n')
for word in txtSet4:
preFile4.write(word)
preFile4.write('\n')
for word in txtSet5:
preFile5.write(word)
preFile5.write('\n')
# board -> 2D list, currPos -> list, path -> 2D list
# boggle board, xy pair current position, path that got to that position
# @returns tuple of the word created and whether it is a real word.
def examineState(board, currPos, path, words, dict, preDict):
global moves
moves += 1
path = path + [currPos]
word = ''
for i in range(0, len(path)):
curr = path[i]
word = (word + board[curr[0]][curr[1]]).lower()
word = word[1:]
if len(word) == 2:
if word not in preDict[0]:
return
if len(word) == 3:
if word not in preDict[1]:
return
if len(word) == 4:
if word not in preDict[2]:
return
if len(word) == 5:
if word not in preDict[3]:
return
# legalWord = (word, 'no')
if word in dict:
# legalWord = (word, 'yes')
words.append(word)
# if there is a legal move remaining, take it, otherwise return out of that level of recursion
if legalMoves(possibleMoves(curr, board), path) != []:
for i in range(0, len(legalMoves(possibleMoves(currPos, board), path))):
examineState(board, legalMoves(possibleMoves(currPos, board), path)[i], path, words, dict, preDict)
return words
else:
return words
def classifyWords(words):
classWords = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
for i in range(0, len(words)):
lengthWord = len(words[i])
classWords[lengthWord - 1].append(words[i])
return classWords
def main():
#prefixDict()
prefixDictionary = [{},{},{},{},{}]
# test run
board = loadBoard('test.txt')
# setup dictionaries from text files
dictFile = open('Dict.txt', 'r')
dict = set(dictFile.read().split('\n'))
preDictFile = open('preDict.txt', 'r')
prefixDictionary[0] = set(preDictFile.read().split('\n'))
preDictFile3 = open('preDict3.txt', 'r')
prefixDictionary[1] = set(preDictFile3.read().split('\n'))
preDictFile4 = open('preDict4.txt', 'r')
prefixDictionary[2] = set(preDictFile4.read().split('\n'))
preDictFile5 = open('preDict5.txt', 'r')
prefixDictionary[3] = set(preDictFile5.read().split('\n'))
dictFile.close()
print('OUPUT FROM FLINTSTONE CLASSIC BAM-BAM BASH-IT APPROACH:')
printBoard(board)
print("And we're off!")
print('Running with cleverness ON')
words = []
startTime = time.time()
for j in range(0,4):
for i in range(0,4):
words.extend(examineState(board, [i,j], [[i,j]], [], dict, prefixDictionary))
endTime = time.time()
searchTime = endTime - startTime
print('All done\n')
print('Searched total of ' + str(moves) + ' moves in ' + str(searchTime) + ' seconds\n')
print('Words found: ')
classifiedWords = classifyWords(words)
for i in range(0, len(classifiedWords)):
if classifiedWords[i] != []:
print(str(i + 1) + ' -letter words: ' + str(classifiedWords[i]))
print('\nFound ' + str(len(words)) + ' words total, ' + str(len(set(words))) + ' unique.')
print('Alpha-sorted list of words:')
print(str(sorted(words)))
if __name__ == "__main__":
main()