trackler 2.0.8.1 → 2.0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/fsharp/exercises/list-ops/Example.fs +5 -5
- data/tracks/fsharp/exercises/list-ops/ListOpsTest.fs +2 -2
- data/tracks/go/exercises/TRACK_HINTS.md +6 -2
- data/tracks/go/exercises/series/asktoomuch_test.go +4 -4
- data/tracks/go/exercises/series/example.go +2 -0
- data/tracks/go/exercises/series/first_test.go +3 -3
- data/tracks/go/exercises/series/series_test.go +10 -2
- data/tracks/java/exercises/pangram/src/test/java/PangramsTest.java +6 -0
- data/tracks/javascript/exercises/robot-simulator/example.js +8 -1
- data/tracks/javascript/exercises/robot-simulator/robot-simulator.spec.js +4 -4
- data/tracks/julia/docs/ABOUT.md +12 -0
- data/tracks/julia/docs/INSTALLATION.md +2 -0
- data/tracks/julia/docs/RESOURCES.md +6 -0
- data/tracks/ocaml/exercises/hello-world/example.ml +1 -4
- data/tracks/ocaml/exercises/hello-world/hello_world.ml +1 -2
- data/tracks/ocaml/exercises/hello-world/hello_world.mli +2 -10
- data/tracks/ocaml/exercises/hello-world/test.ml +1 -3
- data/tracks/ocaml/exercises/luhn/test.ml +14 -14
- data/tracks/ocaml/tools/test-generator/src/parser.ml +2 -1
- data/tracks/ocaml/tools/test-generator/templates/hello-world/template.ml +1 -1
- data/tracks/python/.travis.yml +1 -0
- data/tracks/python/config.json +25 -0
- data/tracks/python/exercises/all-your-base/all_your_base_test.py +82 -0
- data/tracks/python/exercises/all-your-base/example.py +23 -0
- data/tracks/python/exercises/grep/example.py +57 -0
- data/tracks/python/exercises/grep/grep_test.py +225 -0
- data/tracks/python/exercises/linked-list/example.py +14 -0
- data/tracks/python/exercises/linked-list/linked_list.py +2 -1
- data/tracks/python/exercises/linked-list/linked_list_test.py +18 -0
- data/tracks/python/exercises/word-search/example.py +57 -0
- data/tracks/python/exercises/word-search/word_search.py +27 -0
- data/tracks/python/exercises/word-search/word_search_test.py +84 -0
- data/tracks/python/requirements-travis.txt +1 -1
- data/tracks/python/test/check-exercises.py +44 -19
- data/tracks/scala/config.json +9 -0
- data/tracks/scala/exercises/perfect-numbers/build.sbt +3 -0
- data/tracks/scala/exercises/perfect-numbers/example.scala +24 -0
- data/tracks/scala/exercises/perfect-numbers/src/main/scala/PerfectNumbers.scala +0 -0
- data/tracks/scala/exercises/perfect-numbers/src/test/scala/PerfectNumbersTest.scala +62 -0
- data/tracks/typescript/Makefile +8 -0
- metadata +13 -2
@@ -0,0 +1,23 @@
|
|
1
|
+
def from_digits(digits, base):
|
2
|
+
return sum(n * base ** i for i, n in enumerate(reversed(digits)))
|
3
|
+
|
4
|
+
|
5
|
+
def to_digits(number, base_to):
|
6
|
+
result = []
|
7
|
+
while number > 0:
|
8
|
+
result.append(number % base_to)
|
9
|
+
number //= base_to
|
10
|
+
return result[::-1] # list(reversed(result))
|
11
|
+
|
12
|
+
|
13
|
+
def rebase(from_base, digits, to_base):
|
14
|
+
if (from_base < 2):
|
15
|
+
raise ValueError("Invalid input base.")
|
16
|
+
|
17
|
+
if (to_base < 2):
|
18
|
+
raise ValueError("Invalid output base.")
|
19
|
+
|
20
|
+
if any(True for d in digits if d < 0 or d >= from_base):
|
21
|
+
raise ValueError("Invalid input digit.")
|
22
|
+
|
23
|
+
return to_digits(from_digits(digits, from_base), to_base)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
def matches(line, pattern, flags):
|
2
|
+
if '-i' in flags: # case-insensitive
|
3
|
+
line = line.lower()
|
4
|
+
pattern = pattern.lower()
|
5
|
+
|
6
|
+
if '-x' in flags: # match entire lines
|
7
|
+
if len(pattern) != len(line.rstrip()):
|
8
|
+
return False
|
9
|
+
|
10
|
+
if '-v' in flags: # invert matching
|
11
|
+
return pattern not in line
|
12
|
+
|
13
|
+
return pattern in line
|
14
|
+
|
15
|
+
|
16
|
+
def format_files(matched_lines):
|
17
|
+
result = ''
|
18
|
+
|
19
|
+
for file_name, _, _ in matched_lines:
|
20
|
+
if file_name not in result:
|
21
|
+
result += file_name + '\n'
|
22
|
+
|
23
|
+
return result
|
24
|
+
|
25
|
+
|
26
|
+
def format_lines(matched_lines, files, flags):
|
27
|
+
result = []
|
28
|
+
|
29
|
+
for file_name, line_number, line in matched_lines:
|
30
|
+
line_result = ""
|
31
|
+
|
32
|
+
if len(files) > 1:
|
33
|
+
line_result += file_name + ':'
|
34
|
+
|
35
|
+
if '-n' in flags:
|
36
|
+
line_result += str(line_number) + ':'
|
37
|
+
|
38
|
+
line_result += line
|
39
|
+
|
40
|
+
result.append(line_result)
|
41
|
+
|
42
|
+
return ''.join(result)
|
43
|
+
|
44
|
+
|
45
|
+
def grep(pattern, files, flags=''):
|
46
|
+
matched_lines = []
|
47
|
+
|
48
|
+
for file_name in files:
|
49
|
+
with open(file_name) as f:
|
50
|
+
for line_number, line in enumerate(f.readlines(), start=1):
|
51
|
+
if matches(line, pattern, flags):
|
52
|
+
matched_lines.append((file_name, line_number, line))
|
53
|
+
|
54
|
+
if '-l' in flags:
|
55
|
+
return format_files(matched_lines)
|
56
|
+
|
57
|
+
return format_lines(matched_lines, files, flags)
|
@@ -0,0 +1,225 @@
|
|
1
|
+
import os
|
2
|
+
import unittest
|
3
|
+
|
4
|
+
from grep import grep
|
5
|
+
|
6
|
+
|
7
|
+
ILIADFILENAME = 'iliad.txt'
|
8
|
+
ILIADCONTENTS = '''Achilles sing, O Goddess! Peleus' son;
|
9
|
+
His wrath pernicious, who ten thousand woes
|
10
|
+
Caused to Achaia's host, sent many a soul
|
11
|
+
Illustrious into Ades premature,
|
12
|
+
And Heroes gave (so stood the will of Jove)
|
13
|
+
To dogs and to all ravening fowls a prey,
|
14
|
+
When fierce dispute had separated once
|
15
|
+
The noble Chief Achilles from the son
|
16
|
+
Of Atreus, Agamemnon, King of men.
|
17
|
+
'''
|
18
|
+
|
19
|
+
MIDSUMMERNIGHTFILENAME = 'midsummer-night.txt'
|
20
|
+
MIDSUMMERNIGHTCONTENTS = '''I do entreat your grace to pardon me.
|
21
|
+
I know not by what power I am made bold,
|
22
|
+
Nor how it may concern my modesty,
|
23
|
+
In such a presence here to plead my thoughts;
|
24
|
+
But I beseech your grace that I may know
|
25
|
+
The worst that may befall me in this case,
|
26
|
+
If I refuse to wed Demetrius.
|
27
|
+
'''
|
28
|
+
|
29
|
+
PARADISELOSTFILENAME = 'paradise-lost.txt'
|
30
|
+
PARADISELOSTCONTENTS = '''Of Mans First Disobedience, and the Fruit
|
31
|
+
Of that Forbidden Tree, whose mortal tast
|
32
|
+
Brought Death into the World, and all our woe,
|
33
|
+
With loss of Eden, till one greater Man
|
34
|
+
Restore us, and regain the blissful Seat,
|
35
|
+
Sing Heav'nly Muse, that on the secret top
|
36
|
+
Of Oreb, or of Sinai, didst inspire
|
37
|
+
That Shepherd, who first taught the chosen Seed
|
38
|
+
'''
|
39
|
+
|
40
|
+
|
41
|
+
def remove_file(file_name):
|
42
|
+
try:
|
43
|
+
os.remove(file_name)
|
44
|
+
except OSError:
|
45
|
+
pass
|
46
|
+
|
47
|
+
|
48
|
+
def create_file(name, contents):
|
49
|
+
with open(name, 'w') as f:
|
50
|
+
f.write(contents)
|
51
|
+
|
52
|
+
|
53
|
+
class GrepTest(unittest.TestCase):
|
54
|
+
|
55
|
+
@classmethod
|
56
|
+
def setUpClass(self):
|
57
|
+
create_file(ILIADFILENAME, ILIADCONTENTS)
|
58
|
+
create_file(MIDSUMMERNIGHTFILENAME, MIDSUMMERNIGHTCONTENTS)
|
59
|
+
create_file(PARADISELOSTFILENAME, PARADISELOSTCONTENTS)
|
60
|
+
|
61
|
+
@classmethod
|
62
|
+
def tearDownClass(self):
|
63
|
+
remove_file(ILIADFILENAME)
|
64
|
+
remove_file(MIDSUMMERNIGHTFILENAME)
|
65
|
+
remove_file(PARADISELOSTFILENAME)
|
66
|
+
|
67
|
+
def test_one_file_one_match_no_flags(self):
|
68
|
+
self.assertMultiLineEqual(
|
69
|
+
grep("Agamemnon", [ILIADFILENAME]),
|
70
|
+
"Of Atreus, Agamemnon, King of men.\n"
|
71
|
+
)
|
72
|
+
|
73
|
+
def test_one_file_one_match_print_line_numbers_flag(self):
|
74
|
+
self.assertMultiLineEqual(
|
75
|
+
grep("Forbidden", [PARADISELOSTFILENAME], "-n"),
|
76
|
+
"2:Of that Forbidden Tree, whose mortal tast\n"
|
77
|
+
)
|
78
|
+
|
79
|
+
def test_one_file_one_match_case_insensitive_flag(self):
|
80
|
+
self.assertMultiLineEqual(
|
81
|
+
grep("FORBIDDEN", [PARADISELOSTFILENAME], "-i"),
|
82
|
+
"Of that Forbidden Tree, whose mortal tast\n"
|
83
|
+
)
|
84
|
+
|
85
|
+
def test_one_file_one_match_print_file_names_flag(self):
|
86
|
+
self.assertMultiLineEqual(
|
87
|
+
grep("Forbidden", [PARADISELOSTFILENAME], "-l"),
|
88
|
+
PARADISELOSTFILENAME + '\n'
|
89
|
+
)
|
90
|
+
|
91
|
+
def test_one_file_one_match_match_entire_lines_flag(self):
|
92
|
+
self.assertMultiLineEqual(
|
93
|
+
grep("With loss of Eden, till one greater Man", [PARADISELOSTFILENAME], "-x"),
|
94
|
+
"With loss of Eden, till one greater Man\n"
|
95
|
+
)
|
96
|
+
|
97
|
+
def test_one_file_one_match_multiple_flags(self):
|
98
|
+
self.assertMultiLineEqual(
|
99
|
+
grep("OF ATREUS, Agamemnon, KIng of MEN.", [ILIADFILENAME], "-n -i -x"),
|
100
|
+
"9:Of Atreus, Agamemnon, King of men.\n"
|
101
|
+
)
|
102
|
+
|
103
|
+
def test_one_file_several_matches_no_flags(self):
|
104
|
+
self.assertMultiLineEqual(
|
105
|
+
grep("may", [MIDSUMMERNIGHTFILENAME]),
|
106
|
+
("Nor how it may concern my modesty,\n"
|
107
|
+
"But I beseech your grace that I may know\n"
|
108
|
+
"The worst that may befall me in this case,\n")
|
109
|
+
)
|
110
|
+
|
111
|
+
def test_one_file_several_matches_print_line_numbers_flag(self):
|
112
|
+
self.assertMultiLineEqual(
|
113
|
+
grep("may", [MIDSUMMERNIGHTFILENAME], "-n"),
|
114
|
+
("3:Nor how it may concern my modesty,\n"
|
115
|
+
"5:But I beseech your grace that I may know\n"
|
116
|
+
"6:The worst that may befall me in this case,\n")
|
117
|
+
)
|
118
|
+
|
119
|
+
def test_one_file_several_matches_match_entire_lines_flag(self):
|
120
|
+
self.assertMultiLineEqual(
|
121
|
+
grep("may", [MIDSUMMERNIGHTFILENAME], "-x"),
|
122
|
+
""
|
123
|
+
)
|
124
|
+
|
125
|
+
def test_one_file_several_matches_case_insensitive_flag(self):
|
126
|
+
self.assertMultiLineEqual(
|
127
|
+
grep("ACHILLES", [ILIADFILENAME], "-i"),
|
128
|
+
("Achilles sing, O Goddess! Peleus' son;\n"
|
129
|
+
"The noble Chief Achilles from the son\n")
|
130
|
+
)
|
131
|
+
|
132
|
+
def test_one_file_several_matches_inverted_flag(self):
|
133
|
+
self.assertMultiLineEqual(
|
134
|
+
grep("Of", [PARADISELOSTFILENAME], "-v"),
|
135
|
+
("Brought Death into the World, and all our woe,\n"
|
136
|
+
"With loss of Eden, till one greater Man\n"
|
137
|
+
"Restore us, and regain the blissful Seat,\n"
|
138
|
+
"Sing Heav'nly Muse, that on the secret top\n"
|
139
|
+
"That Shepherd, who first taught the chosen Seed\n")
|
140
|
+
)
|
141
|
+
|
142
|
+
def test_one_file_no_matches_various_flags(self):
|
143
|
+
self.assertMultiLineEqual(
|
144
|
+
grep("Gandalf", [ILIADFILENAME], "-n -l -x -i"),
|
145
|
+
""
|
146
|
+
)
|
147
|
+
|
148
|
+
def test_multiple_files_one_match_no_flags(self):
|
149
|
+
self.assertMultiLineEqual(
|
150
|
+
grep("Agamemnon", [ILIADFILENAME, MIDSUMMERNIGHTFILENAME, PARADISELOSTFILENAME]),
|
151
|
+
"iliad.txt:Of Atreus, Agamemnon, King of men.\n"
|
152
|
+
)
|
153
|
+
|
154
|
+
def test_multiple_files_several_matches_no_flags(self):
|
155
|
+
self.assertMultiLineEqual(
|
156
|
+
grep("may", ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]),
|
157
|
+
("midsummer-night.txt:Nor how it may concern my modesty,\n"
|
158
|
+
"midsummer-night.txt:But I beseech your grace that I may know\n"
|
159
|
+
"midsummer-night.txt:The worst that may befall me in this case,\n")
|
160
|
+
)
|
161
|
+
|
162
|
+
def test_multiple_files_several_matches_print_line_numbers_flag(self):
|
163
|
+
self.assertMultiLineEqual(
|
164
|
+
grep("that", ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"], "-n"),
|
165
|
+
("midsummer-night.txt:5:But I beseech your grace that I may know\n"
|
166
|
+
"midsummer-night.txt:6:The worst that may befall me in this case,\n"
|
167
|
+
"paradise-lost.txt:2:Of that Forbidden Tree, whose mortal tast\n"
|
168
|
+
"paradise-lost.txt:6:Sing Heav'nly Muse, that on the secret top\n")
|
169
|
+
)
|
170
|
+
|
171
|
+
def test_multiple_files_one_match_print_file_names_flag(self):
|
172
|
+
self.assertMultiLineEqual(
|
173
|
+
grep("who", ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"], "-l"),
|
174
|
+
ILIADFILENAME + '\n' + PARADISELOSTFILENAME + '\n'
|
175
|
+
)
|
176
|
+
|
177
|
+
def test_multiple_files_several_matches_case_insensitive_flag(self):
|
178
|
+
self.assertMultiLineEqual(
|
179
|
+
grep("TO", ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"], "-i"),
|
180
|
+
("iliad.txt:Caused to Achaia's host, sent many a soul\n"
|
181
|
+
"iliad.txt:Illustrious into Ades premature,\n"
|
182
|
+
"iliad.txt:And Heroes gave (so stood the will of Jove)\n"
|
183
|
+
"iliad.txt:To dogs and to all ravening fowls a prey,\n"
|
184
|
+
"midsummer-night.txt:I do entreat your grace to pardon me.\n"
|
185
|
+
"midsummer-night.txt:In such a presence here to plead my thoughts;\n"
|
186
|
+
"midsummer-night.txt:If I refuse to wed Demetrius.\n"
|
187
|
+
"paradise-lost.txt:Brought Death into the World, and all our woe,\n"
|
188
|
+
"paradise-lost.txt:Restore us, and regain the blissful Seat,\n"
|
189
|
+
"paradise-lost.txt:Sing Heav'nly Muse, that on the secret top\n")
|
190
|
+
)
|
191
|
+
|
192
|
+
def test_multiple_files_several_matches_inverted_flag(self):
|
193
|
+
self.assertMultiLineEqual(
|
194
|
+
grep("a", ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"], "-v"),
|
195
|
+
("iliad.txt:Achilles sing, O Goddess! Peleus' son;\n"
|
196
|
+
"iliad.txt:The noble Chief Achilles from the son\n"
|
197
|
+
"midsummer-night.txt:If I refuse to wed Demetrius.\n")
|
198
|
+
)
|
199
|
+
|
200
|
+
def test_multiple_files_one_match_match_entire_lines_flag(self):
|
201
|
+
self.assertMultiLineEqual(
|
202
|
+
grep("But I beseech your grace that I may know",
|
203
|
+
["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"],
|
204
|
+
"-x"),
|
205
|
+
"midsummer-night.txt:But I beseech your grace that I may know\n"
|
206
|
+
)
|
207
|
+
|
208
|
+
def test_multiple_files_one_match_multiple_flags(self):
|
209
|
+
self.assertMultiLineEqual(
|
210
|
+
grep("WITH LOSS OF EDEN, TILL ONE GREATER MAN",
|
211
|
+
["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"],
|
212
|
+
"-n -i -x"),
|
213
|
+
"paradise-lost.txt:4:With loss of Eden, till one greater Man\n"
|
214
|
+
)
|
215
|
+
|
216
|
+
def test_multiple_files_no_matches_various_flags(self):
|
217
|
+
self.assertMultiLineEqual(
|
218
|
+
grep("Frodo", ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"],
|
219
|
+
"-n -l -x -i"),
|
220
|
+
""
|
221
|
+
)
|
222
|
+
|
223
|
+
|
224
|
+
if __name__ == '__main__':
|
225
|
+
unittest.main()
|
@@ -9,6 +9,7 @@ class LinkedList(object):
|
|
9
9
|
def __init__(self):
|
10
10
|
self.head = None
|
11
11
|
self.tail = None
|
12
|
+
self.length = 0
|
12
13
|
|
13
14
|
def push(self, value):
|
14
15
|
new_node = Node(value)
|
@@ -18,6 +19,7 @@ class LinkedList(object):
|
|
18
19
|
new_node.prev = self.tail
|
19
20
|
self.tail.next = new_node
|
20
21
|
self.tail = new_node
|
22
|
+
self.length += 1
|
21
23
|
|
22
24
|
def pop(self):
|
23
25
|
node = self.tail
|
@@ -26,6 +28,7 @@ class LinkedList(object):
|
|
26
28
|
else:
|
27
29
|
self.tail = self.tail.prev
|
28
30
|
self.tail.next = None
|
31
|
+
self.length -= 1
|
29
32
|
return node.value
|
30
33
|
|
31
34
|
def shift(self):
|
@@ -35,6 +38,7 @@ class LinkedList(object):
|
|
35
38
|
else:
|
36
39
|
self.head = self.head.next
|
37
40
|
self.head.prev = None
|
41
|
+
self.length -= 1
|
38
42
|
return node.value
|
39
43
|
|
40
44
|
def unshift(self, value):
|
@@ -45,3 +49,13 @@ class LinkedList(object):
|
|
45
49
|
new_node.next = self.head
|
46
50
|
self.head.prev = new_node
|
47
51
|
self.head = new_node
|
52
|
+
self.length += 1
|
53
|
+
|
54
|
+
def __len__(self):
|
55
|
+
return self.length
|
56
|
+
|
57
|
+
def __iter__(self):
|
58
|
+
current_node = self.head
|
59
|
+
while (current_node):
|
60
|
+
yield current_node.value
|
61
|
+
current_node = current_node.next
|
@@ -44,6 +44,24 @@ class LinkedListTests(unittest.TestCase):
|
|
44
44
|
self.assertEqual(50, self.list.pop())
|
45
45
|
self.assertEqual(30, self.list.shift())
|
46
46
|
|
47
|
+
@unittest.skip("extra-credit")
|
48
|
+
def test_length(self):
|
49
|
+
self.list.push(10)
|
50
|
+
self.list.push(20)
|
51
|
+
self.assertEqual(2, len(self.list))
|
52
|
+
self.list.shift()
|
53
|
+
self.assertEqual(1, len(self.list))
|
54
|
+
self.list.pop()
|
55
|
+
self.assertEqual(0, len(self.list))
|
56
|
+
|
57
|
+
@unittest.skip("extra-credit")
|
58
|
+
def test_iterator(self):
|
59
|
+
self.list.push(10)
|
60
|
+
self.list.push(20)
|
61
|
+
iterator = iter(self.list)
|
62
|
+
self.assertEqual(10, next(iterator))
|
63
|
+
self.assertEqual(20, next(iterator))
|
64
|
+
|
47
65
|
|
48
66
|
if __name__ == '__main__':
|
49
67
|
unittest.main()
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import copy
|
2
|
+
|
3
|
+
|
4
|
+
class Point(object):
|
5
|
+
def __init__(self, x, y):
|
6
|
+
self.x = x
|
7
|
+
self.y = y
|
8
|
+
|
9
|
+
def __repr__(self):
|
10
|
+
return 'Point({}:{})'.format(self.x, self.y)
|
11
|
+
|
12
|
+
def __add__(self, other):
|
13
|
+
return Point(self.x + other.x, self.y + other.y)
|
14
|
+
|
15
|
+
def __sub__(self, other):
|
16
|
+
return Point(self.x - other.x, self.y - other.y)
|
17
|
+
|
18
|
+
def __eq__(self, other):
|
19
|
+
return self.x == other.x and self.y == other.y
|
20
|
+
|
21
|
+
def __ne__(self, other):
|
22
|
+
return not(self == other)
|
23
|
+
|
24
|
+
|
25
|
+
DIRECTIONS = (Point(1, 0), Point(1, -1), Point(1, 1), Point(-1, -1),
|
26
|
+
Point(0, -1), Point(0, 1), Point(-1, 1), Point(-1, 0))
|
27
|
+
|
28
|
+
|
29
|
+
class WordSearch(object):
|
30
|
+
def __init__(self, puzzle):
|
31
|
+
self.rows = puzzle.split()
|
32
|
+
self.width = len(self.rows[0])
|
33
|
+
self.height = len(self.rows)
|
34
|
+
|
35
|
+
def find_char(self, coordinate):
|
36
|
+
if coordinate.x < 0 or coordinate.x >= self.width:
|
37
|
+
return
|
38
|
+
if coordinate.y < 0 or coordinate.y >= self.height:
|
39
|
+
return
|
40
|
+
return self.rows[coordinate.y][coordinate.x]
|
41
|
+
|
42
|
+
def find(self, word, position, direction):
|
43
|
+
current = copy.copy(position)
|
44
|
+
for letter in word:
|
45
|
+
if self.find_char(current) != letter:
|
46
|
+
return
|
47
|
+
current += direction
|
48
|
+
return position, current - direction
|
49
|
+
|
50
|
+
def search(self, word):
|
51
|
+
positions = (Point(x, y) for x in range(self.width) for y in range(self.height))
|
52
|
+
for pos in positions:
|
53
|
+
for d in DIRECTIONS:
|
54
|
+
result = self.find(word, pos, d)
|
55
|
+
if result:
|
56
|
+
return result
|
57
|
+
return None
|