/
WordWrangler_backend.py
188 lines (169 loc) · 4.98 KB
/
WordWrangler_backend.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
'''
Word Wrangler game
Word Wrangler is a game that generates all possible words from a user's input word
'''
import urllib2
import codeskulptor
import poc_wrangler_provided as wrangler
WORDFILE = "assets_scrabble_words3.txt"
def remove_duplicates(list1):
'''
Eliminate duplicates in a sorted list.
Returns a new sorted list with the same elements in list1, but
with no duplicates.
'''
list2 = list(list1)
count_vals_dict = {}
for val in list1:
if not count_vals_dict.get(val):
count_vals_dict[val] = 1
else:
list2.remove(val)
return list2
def intersect_nonempty_list(list1, list2):
'''
Generates the intersection of two sorted non-empty lists
Returns a list
'''
same_vals = []
idx2 = 0
for val in list1:
while idx2 < len(list2) and list2[idx2] < val:
idx2 += 1
if idx2 < len(list2):
if val == list2[idx2]:
same_vals.append(val)
return same_vals
def intersect(list1, list2):
'''
Generates the intersection of two sorted lists. Lists can be empty.
Returns a list
'''
if not list1 or not list2:
return []
else:
return intersect_nonempty_list(list1, list2)
def initial_merge(list1, list2):
'''
Merge sorted list1 and list2, up to whichever list has minimum length
'''
l1_idx = 0
l2_idx = 0
merged = []
while l1_idx < len(list1) and l2_idx < len(list2):
if list1[l1_idx] < list2[l2_idx]:
merged.append(list1[l1_idx])
l1_idx += 1
else:
merged.append(list2[l2_idx])
l2_idx += 1
return {'l1_idx': l1_idx, 'l2_idx': l2_idx, 'merged': merged}
def final_merge(list1, list2):
'''
Merge remaining values of whichever list1 or list2 has maximum length
'''
initial_result = initial_merge(list1, list2)
l1_idx = initial_result['l1_idx']
l2_idx = initial_result['l2_idx']
merged = initial_result['merged']
rem_idx = max(l1_idx, l2_idx)
remaining = []
if l1_idx < len(list1):
rem_idx = l1_idx
remaining = list1
elif l2_idx < len(list2):
rem_idx = l2_idx
remaining = list2
while rem_idx < len(remaining):
merged.append(remaining[rem_idx])
rem_idx += 1
return merged
def merge(list1, list2):
'''
Merge two sorted lists.
Returns a new sorted list containing all of the elements that
are in either list1 and list2.
'''
if not list1:
return list(list2)
elif not list2:
return list(list1)
return final_merge(list1, list2)
def merge_sort(alist):
'''
Sort an unsorted list by breaking the list into sorted lists and merging
Return the sorted list
'''
if len(alist) > 1:
mid = len(alist) / 2
left = merge_sort(alist[:mid])
right = merge_sort(alist[mid:])
return merge(left, right)
else:
return alist
def gen_word_combs(first_letter, rest_strings):
'''
Generate all word combinations given the first letter of a word and a list
of words
Return a list of all possible combinations
'''
gen_comb = [first_letter]
for string in rest_strings:
for idx in range(len(string) + 1):
new_string = string[:idx] + first_letter + string[idx:]
gen_comb.append(new_string)
return gen_comb + rest_strings
def gen_all_strings_initial(word):
'''
Generate all strings that can be composed from the letters in word
in any order.
Returns a list of all strings that can be formed from the letters
in word.
'''
if len(word) <= 1:
return [word]
else:
first = word[0]
rest = word[1:]
rest_strings = gen_all_strings_initial(rest)
all_strings = gen_word_combs(first, rest_strings)
return all_strings
def gen_all_strings(word):
'''
Generates all possible strings of a word. Treats each letter as distinct, so
if the same letter appears twice in the word, then the output will have
duplicate strings.
Returns a list of strings
'''
idx = 0
has_empty_str = False
all_strings = gen_all_strings_initial(word)
while not has_empty_str and idx < len(all_strings):
if all_strings[idx] == '':
has_empty_str = True
idx += 1
if not has_empty_str:
return all_strings + ['']
else:
return all_strings
def load_words(filename):
'''
Load word list from the file named filename.
Returns a list of strings.
'''
words = []
url = codeskulptor.file2url(filename)
netfile = urllib2.urlopen(url)
for line in netfile.readlines():
words.append(line[:-1])
return words
def run():
'''
Run game.
'''
words = load_words(WORDFILE)
wrangler = wrangler.WordWrangler(words, remove_duplicates,
intersect, merge_sort,
gen_all_strings)
wrangler.run_game(wrangler)
run()