Jump to content

Word search: Difference between revisions

Add implementation in python
(Add implementation in python)
Line 1,687:
[0,0]: ski [6,3]: lack
102
</pre>
 
=={{header|Python}}==
{{trans|Java}}
{{works with|Python|3.x}}
<lang python>
import re
from random import shuffle, randint
 
dirs = [[1, 0], [0, 1], [1, 1], [1, -1], [-1, 0], [0, -1], [-1, -1], [-1, 1]]
n_rows = 10
n_cols = 10
grid_size = n_rows * n_cols
min_words = 25
 
 
class Grid:
def __init__(self):
self.num_attempts = 0
self.cells = [['' for _ in range(n_cols)] for _ in range(n_rows)]
self.solutions = []
 
 
def read_words(filename):
max_len = max(n_rows, n_cols)
 
words = []
with open(filename, "r") as file:
for line in file:
s = line.strip().lower()
if re.match(r'^[a-z]{3,' + re.escape(str(max_len)) + r'}$', s) is not None:
words.append(s)
 
return words
 
 
def place_message(grid, msg):
msg = re.sub(r'[^A-Z]', "", msg.upper())
 
message_len = len(msg)
if 0 < message_len < grid_size:
gap_size = grid_size // message_len
 
for i in range(0, message_len):
pos = i * gap_size + randint(0, gap_size)
grid.cells[pos // n_cols][pos % n_cols] = msg[i]
 
return message_len
 
return 0
 
 
def try_location(grid, word, direction, pos):
r = pos // n_cols
c = pos % n_cols
length = len(word)
 
# check bounds
if (dirs[direction][0] == 1 and (length + c) > n_cols) or \
(dirs[direction][0] == -1 and (length - 1) > c) or \
(dirs[direction][1] == 1 and (length + r) > n_rows) or \
(dirs[direction][1] == -1 and (length - 1) > r):
return 0
 
rr = r
cc = c
i = 0
overlaps = 0
 
# check cells
while i < length:
if grid.cells[rr][cc] != '' and grid.cells[rr][cc] != word[i]:
return 0
cc += dirs[direction][0]
rr += dirs[direction][1]
i += 1
 
rr = r
cc = c
i = 0
# place
while i < length:
if grid.cells[rr][cc] == word[i]:
overlaps += 1
else:
grid.cells[rr][cc] = word[i]
 
if i < length - 1:
cc += dirs[direction][0]
rr += dirs[direction][1]
 
i += 1
 
letters_placed = length - overlaps
if letters_placed > 0:
grid.solutions.append("{0:<10} ({1},{2})({3},{4})".format(word, c, r, cc, rr))
 
return letters_placed
 
 
def try_place_word(grid, word):
rand_dir = randint(0, len(dirs))
rand_pos = randint(0, grid_size)
 
for direction in range(0, len(dirs)):
direction = (direction + rand_dir) % len(dirs)
 
for pos in range(0, grid_size):
pos = (pos + rand_pos) % grid_size
 
letters_placed = try_location(grid, word, direction, pos)
if letters_placed > 0:
return letters_placed
 
return 0
 
 
def create_word_search(words):
grid = None
num_attempts = 0
 
while num_attempts < 100:
num_attempts += 1
shuffle(words)
 
grid = Grid()
message_len = place_message(grid, "Rosetta Code")
target = grid_size - message_len
 
cells_filled = 0
for word in words:
cells_filled += try_place_word(grid, word)
if cells_filled == target:
if len(grid.solutions) >= min_words:
grid.num_attempts = num_attempts
return grid
else:
break # grid is full but we didn't pack enough words, start over
 
return grid
 
 
def print_result(grid):
if grid is None or grid.num_attempts == 0:
print("No grid to display")
return
 
size = len(grid.solutions)
 
print("Attempts: {0}".format(grid.num_attempts))
print("Number of words: {0}".format(size))
 
print("\n 0 1 2 3 4 5 6 7 8 9\n")
for r in range(0, n_rows):
print("{0} ".format(r), end='')
for c in range(0, n_cols):
print(" %c " % grid.cells[r][c], end='')
print()
print()
 
for i in range(0, size - 1, 2):
print("{0} {1}".format(grid.solutions[i], grid.solutions[i+1]))
 
if size % 2 == 1:
print(grid.solutions[size - 1])
 
 
if __name__ == "__main__":
print_result(create_word_search(read_words("unixdict.txt")))
</lang>
 
{{out}}
<pre>
Attempts: 1
Number of words: 25
 
0 1 2 3 4 5 6 7 8 9
 
0 f b R u e r u l t h
1 o n o t v O e r o p
2 a S a b a x o b E m
3 l e d s h w T p e u
4 w p v a n s u c k i
5 o T u r A t u t s r
6 n s o p u m y d i t
7 t h C j a c o b i O
8 t i r e h n i m D p
9 y n o l o c E s a c
 
exhaust (6,1)(0,7) hornwort (1,7)(8,0)
btu (3,2)(3,0) jacobi (3,7)(8,7)
foal (0,0)(0,3) triumph (9,6)(9,0)
inherit (6,8)(0,8) mecum (9,2)(5,6)
colony (5,9)(0,9) curve (5,7)(1,3)
wont (0,4)(0,7) lure (7,0)(4,0)
hob (9,0)(7,2) tidy (9,6)(6,6)
suck (5,4)(8,4) san (3,3)(1,1)
sac (7,9)(9,9) put (7,3)(5,5)
led (0,3)(2,3) stu (8,5)(6,5)
have (4,3)(4,0) min (7,8)(5,8)
bob (1,0)(3,2) pup (3,6)(1,4)
dip (7,6)(9,8)
</pre>
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.