This task is part of project07 which is due at 23:00 EDT on 2025-10-28.
You have the option to work with a partner on this task if you wish. Working with a partner requires more work to coordinate schedules, but if you work together and make sure that you are both understanding the code you write, you will make progress faster and learn more.
You can download the starter code for this task using this link.
You can submit this task using this link.
Put all of your work for this task into the file
wordSearch.py
(which is provided among the starter files)
In this task, you will practice nested loops by implementing part of a program that solves word search puzzles. A word search puzzle consists of a text grid, and a list of words that are hidden in it. The goal is to find all of the words on the list.
For example, here is a list of words
cs111, science, center, wellesley, python, computer, nested, loops
that are hidden in the following puzzle. Can you find them?
d s b o s i d d e c x r
u k o p c e n t e r x v
p x k f i m n r h o j x
y e l s e l l e w q s j
t h o e n j k t z u n k
h a o q c i d u a u s 1
o k p p e d l p a y 1 w
n e s t e d n m a 1 h j
s n k p l g v o s f t j
c m w p u l l c d z p l
It's easier to see the placement of the hidden words if we replace all characters not in the hidden words by dashes:
- - - - s - - - - - - -
- - - - c e n t e r - -
p - - - i - - r - - - -
y e l s e l l e w - - -
t - o - n - - t - - - -
h - o - c - - u - - - 1
o - p - e - - p - - 1 -
n e s t e d - m - 1 - -
- - - - - - - o s - - -
- - - - - - - c - - -
In a traditional word search puzzle, words can be hidden vertically, horizontally, or diagonally. They can also be backwards in any direction. To simplify things, in this task your program will search only for words that are oriented horizontally or vertically, not diagonally.
For example, in the above puzzle, your program will find the horizontal
words center, nested , and wellesley and the vertical words
python, loops, computer, and science, but it will not find
cs111.
In this problem, two-dimensional text grids are represented
as a list of strings of the same length. Each string represents
one row of the grid, and the length of each row string is the
number of columns. For example, the above CS puzzle is
the value of the variable TEST_PUZZLE in wordSearch.py:
TEST_PUZZLE = [
"----s-------",
"----center--",
"p---i--r----",
"yelsellew---",
"t-o-n--v----",
"h-o-c--u---1",
"o-p-e--p--1-",
"nested-m-1--",
"-------os---",
"-------c----"
]
The words placed in this puzzle are the value of the
variable TEST_WORDS:
TEST_WORDS =
"cs111",
"science",
"center",
"wellesley",
"python",
"computer",
"nested",
"loops"
]
As noted above, your program is not expected to find the
word "cs111" in this puzzle.
The starter code includes a function wordPuzzle.generatePuzzle
that generates random word search puzzles from a list of words
to hide in the puzzle. To find out more, see the
section on Word Puzzle Generation at the end of these
instructions.
Note that as usual, you must include a docstring for each function you define.
Your first goal is define a function
printGrid that displays the text grid
for the word search puzzle. It takes a single argument, which is a list
of strings, where each string has the same length (the number of columns
in the grid). It uses
print to display the
letters in the grid such that
These printGrid examples
demonstrate how it should work.
Notes:
Recall that the newline character '\n' causes a printed string to
move to the next line.
Calls to print normally end with a newline, but this can be
overridden by the keyword argument end. E.g., print('hello', end=' ')
will display the five characters in hello followed by a space rather
than a newline.
Your printGrid function must use a nested
loop
You can test printGrid and the other wordSearch functions
by running the file test_wordSearch.py.
Although we have represented the text grid as a list of rows, words
may also be hidden in columns. To make it easier to find these words,
define a function getColumns that
takes a list of row strings as a parameter, and returns a list of
column strings, where the cth column string is the characters
of the cth column of the given row strings.
For example, getColumns( ["abcd", "efgh", "ijkl" ] ) should
return the list of column strings ["aei", "bfj", "cgk", dhl"].
These getColumns examples give more examples
how it should work.
getColumns basically flips the orientation of the grid across the
diagonal that goes from the upper left to the lower right, causing input
columns to become output rows and input rows to become output columns. In
mathematics, this operation is known as a transposition when applied to
matrices.
Notes:
One strategy is to first write code that gets the letters from a single column, and then add a loop around that code.
Make sure your function works with different puzzle sizes!
You can test getColumns and the other wordSearch functions
by running the file test_wordSearch.py.
Define a function
findHorizontal(rows,word) that
finds a single word that is hidden in the puzzle in a horizontal
orientation. It should find words both
in the forward and backward direction. The first parameter, rows, is a
list of strings representing the puzzle text grid, and word is the word
to find hidden in the grid.
This function returns a list of positions that indicate where the target word was found (note there might be more than one copy of it). Each location entry is a tuple with 2 components:
When there are multiple matches, they should be ordered according to their row and then column values (matches in earlier rows first, and within a row, matches in earlier columns first).
For example, for the findHorizontal(TEST_PUZZLE, 'center'),
the resulting list of tuples should be:
[(1, 4)]
because 'center' appears horizontally in TEST_PUZZLE once at row 1
starting in column 4.
If instead we had the grid:
selfish = [
'-meme',
'me---'
]
and we ran findHorizontal(selfish, 'me') we should get the following
list of matches (without the commentary):
[
(0, 1), # first 'me' in row 0. Row 0 comes before row 1.
(0, 2), # start of backwards 'em' that's part of 'meme'
(0, 3), # second 'me' in row 0
(1, 0), # the 'me' in row 1 (second row)
]
These findHorizontal examples provide more
demonstrations of how findHorizontals must work.
Notes:
If a word matches both forwards and backwards starting at a particular location (e.g., 'racecar'), we only count that as one match. Because of this, it is not possible for this function to ever return a list containing duplicate positions.
If the word is not found anywhere in the grid, return an empty list.
findHorizontal must use a nested
loop.
You can test findHorizontal and the other wordSearch functions
by running the file test_wordSearch.py.
To count as a match, the letters of a word must appear next to each other in the correct order (or exactly backwards). Letters that are spaced out with other letters in between don't count as a match, even if they all appear in the right order.
Define a function
findWords(rows, wordlist) that
finds words in wordlist that are hidden in the puzzle either in a
horizontal or a vertical orientation.. As in
findHorizontal the first parameter, rows,
is a list of strings representing the puzzle text grid. wordlist
is a list words (strings) to find.
This function returns a list of location entries that indicate
which words were found and where. Note these are not the same as the
positions findHorizontals returns. Each location entry is a tuple
with 3 components:
These location entry tuples must be ordered as follows:
findHorizontal orders them.findHorizontal will order them when applied to columns
instead of rows.For example, for findWords(TEST_PUZZLE, TEST_WORDS),
the result tuples should be:
[
('science', 0, 4),
('center', 1, 4),
('wellesley', 3, 0),
('python', 0, 2),
('computer', 2, 7),
('nested', 7, 0),
('loops', 3, 2)
]
These findWords examples provide more
demonstrations of how findWords must work.
Notes:
To find vertical matches, you can simply apply findHorizontal to
columns instead of rows. Use the getColumns function you wrote
earlier to get the columns. Your code must call getColumns at
least once and
must call findHorizontal at least
twice.
getColumns result really means you found a vertical word
in column 1 of the actual puzzle.If you order your loops correctly, no extra code is necessary to achieve correct ordering of the final result list.
You can test findWords and the other wordSearch functions
by running the file test_wordSearch.py.
The starter code includes a function wordPuzzle.generatePuzzle
that generates random word search puzzles from a list of words
to hide in the puzzle. If you're interested, you can use this
function to generate other puzzles to experiment with.
wordPuzzle.generatePuzzle takes four arguments:
the number of rows for the puzzle (defaults to 10)
the number of columns for the puzzle (defaults to 20)
a list of words to hide in the puzzle (defaults to a list of words related to tea).
a boolean that indicates whether all words should be
hidden only in the forward and downward orientation.
If True, the orientation will be restricted to
forward and downward; if False, the orientation
can be any direction, including backward, upward,
and diagonally.
By default, generatePuzzle produces a 10x20 text grid with a list of
tea-themed words hidden within it, and where all hidden words are
forward or downward. However, you can supply parameters to change the
default parameters. For instance, to create a puzzle with 5 rows, 10
columns, and some coffee-themed words that can be in any orientation,
you could call:
wordPuzzle.generatePuzzle(
numRow=5, numCols=10,
words=["latte","espresso", "bean", "mocha"],
onlyForwardOrDownward=False
)
wordPuzzle.generatePuzzle returns a tuple with three values:
numRows strings, each of length numCols
that represents the rows of a text gridwords that were successfully
placed in the puzzlewords that were not
able to be placed in the puzzle.printGrid examples
These examples demonstrate how printGrid should work.
In []:PrintsprintGrid(['abcd', 'efgh', 'ijkl'])a b c d e f g h i j k lIn []:PrintsprintGrid(['ab', 'cd', 'ef', 'gh', 'ij'])a b c d e f g h i jIn []:PrintsprintGrid( [ '----s-------', '----center--', 'p---i--r----', 'yelsellew---', 't-o-n--t----', 'h-o-c--u---1', 'o-p-e--p--1-', 'nested-m-1--', '-------os---', '-------c----', ] )- - - - s - - - - - - - - - - - c e n t e r - - p - - - i - - r - - - - y e l s e l l e w - - - t - o - n - - t - - - - h - o - c - - u - - - 1 o - p - e - - p - - 1 - n e s t e d - m - 1 - - - - - - - - - o s - - - - - - - - - - c - - - -
getColumns examples
These examples demonstrate how getColumns should work.
In []:Out[]:getColumns(['abcd', 'efgh', 'ijkl'])In []:['aei', 'bfj', 'cgk', 'dhl']Out[]:getColumns(['ab', 'cd', 'ef', 'gh', 'ij'])In []:['acegi', 'bdfhj']Out[]:getColumns( [ '----s-------', '----center--', 'p---i--r----', 'yelsellew---', 't-o-n--t----', 'h-o-c--u---1', 'o-p-e--p--1-', 'nested-m-1--', '-------os---', '-------c----', ] )[ '--python--', '---e---e--', '---loops--', '---s---t--', 'sciencee--', '-e-l---d--', '-n-l------', '-tretupmoc', '-e-w----s-', '-r-----1--', '------1---', '-----1----', ]
findHorizontal examples
These examples demonstrate how findHorizontal should work. Note how it finds both forwards and backwards matches, but NOT vertical matches.
In []:Out[]:findHorizontal(['----', 'find', '-me-'], 'find')In []:[(1, 0)]Out[]:findHorizontal(['----', 'find', '-me-'], 'me')In []:[(2, 1)]Out[]:findHorizontal(['dnif', '-e--', '-m--'], 'find')In []:[(0, 0)]Out[]:findHorizontal(['dnif', '-e--', '-m--'], 'me')In []:[]Out[]:findHorizontal(['-meme', 'me--', '-em-'], 'me')In []:[(0, 1), (0, 2), (0, 3), (1, 0), (2, 1)]Out[]:findHorizontal(['find', 'i--n', 'n--i', 'dnif'], 'find')In []:[(0, 0), (3, 0)]Out[]:findHorizontal(['find', 'i--n', 'n--i', 'dnif'], 'dnif')In []:[(0, 0), (3, 0)]Out[]:findHorizontal( [ '----s-------', '----center--', 'p---i--r----', 'yelsellew---', 't-o-n--t----', 'h-o-c--u---1', 'o-p-e--p--1-', 'nested-m-1--', '-------os---', '-------c----', ], 'wellesley' )In []:[(3, 0)]Out[]:findHorizontal( [ '----s-------', '----center--', 'p---i--r----', 'yelsellew---', 't-o-n--t----', 'h-o-c--u---1', 'o-p-e--p--1-', 'nested-m-1--', '-------os---', '-------c----', ], 'center' )In []:[(1, 4)]Out[]:findHorizontal( [ '----s-------', '----center--', 'p---i--r----', 'yelsellew---', 't-o-n--t----', 'h-o-c--u---1', 'o-p-e--p--1-', 'nested-m-1--', '-------os---', '-------c----', ], 'science' )In []:[]Out[]:findHorizontal( [ 'soacbykymduioaaiylyf', 'tghvnekchamomileztfd', 'arggfqavbkettleigedv', 'chonunnrvipeetsxzafc', 'jgbornnslrehucoqopjh', 'pcwliewixggevzdxyova', 'czpombclperkhlyeztti', 'wayoriouihiexqizxyrm', 'jmgyfngsaioryztcysax', 'ilrovurzcskenimsajny', ], 'kettle' )In []:[(2, 9)]Out[]:findHorizontal( [ 'soacbykymduioaaiylyf', 'tghvnekchamomileztfd', 'arggfqavbkettleigedv', 'chonunnrvipeetsxzafc', 'jgbornnslrehucoqopjh', 'pcwliewixggevzdxyova', 'czpombclperkhlyeztti', 'wayoriouihiexqizxyrm', 'jmgyfngsaioryztcysax', 'ilrovurzcskenimsajny', ], 'jasmine' )In []:[(9, 11)]Out[]:findHorizontal( [ 'soacbykymduioaaiylyf', 'tghvnekchamomileztfd', 'arggfqavbkettleigedv', 'chonunnrvipeetsxzafc', 'jgbornnslrehucoqopjh', 'pcwliewixggevzdxyova', 'czpombclperkhlyeztti', 'wayoriouihiexqizxyrm', 'jmgyfngsaioryztcysax', 'ilrovurzcskenimsajny', ], 'oolong' )[]
findWords examples
These examples demonstrate how findWords should work.
In []:Out[]:findWords(['----', 'find', '-me-'], ['find', 'me'])In []:[('find', 1, 0), ('me', 2, 1)]Out[]:findWords(['-f-', '-im', '-ne', '-d-'], ['find', 'me'])In []:[('find', 0, 1), ('me', 1, 2)]Out[]:findWords(['f--', 'i--', 'nme', 'd--'], ['find', 'me'])In []:[('find', 0, 0), ('me', 2, 1)]Out[]:findWords( [ '----s-------', '----center--', 'p---i--r----', 'yelsellew---', 't-o-n--t----', 'h-o-c--u---1', 'o-p-e--p--1-', 'nested-m-1--', '-------os---', '-------c----', ], [ 'cs111', 'science', 'center', 'wellesley', 'python', 'computer', 'nested', 'loops', ] )In []:[ ('science', 0, 4), ('center', 1, 4), ('wellesley', 3, 0), ('python', 2, 0), ('computer', 2, 7), ('nested', 7, 0), ('loops', 3, 2), ]Out[]:findWords( [ 'soacbykymduioaaiylyf', 'tghvnekchamomileztfd', 'arggfqavbkettleigedv', 'chonunnrvipeetsxzafc', 'jgbornnslrehucoqopjh', 'pcwliewixggevzdxyova', 'czpombclperkhlyeztti', 'wayoriouihiexqizxyrm', 'jmgyfngsaioryztcysax', 'ilrovurzcskenimsajny', ], [ 'chai', 'oolong', 'earlgrey', 'rooibos', 'saucer', 'teapot', 'chamomile', 'jasmine', 'kettle', 'steep', ] )[ ('chai', 3, 19), ('oolong', 2, 3), ('teapot', 1, 17), ('chamomile', 1, 7), ('jasmine', 9, 11), ('kettle', 2, 9), ('steep', 3, 10), ]
getColumns must return the correct result
getColumns function is run must match the solution result.findHorizontal must return the correct result
findHorizontal function is run must match the solution result.findWords must return the correct result
findWords function is run must match the solution result.printGrid must print the correct output
printGrid function is run must match the solution output.printGrid
def to define printGridprintGrid, use any kind of loop in at least one place.printGrid, use any kind of loop in at least one place.print
printGrid, call print in at least one place.getColumns
def to define getColumnsgetColumns, use any kind of loop in at least one place.return statement
getColumns, use return _ in at least one place.findHorizontal
def to define findHorizontalfindHorizontal, use any kind of loop in at least one place.findHorizontal, use any kind of loop in at least one place.return statement
findHorizontal, use return _ in at least one place.findWords
def to define findWordsgetColumns
findWords, call getColumns in at least one place.findHorizontal
findWords, call findHorizontal in at least 2 places.findWords, use any kind of loop in at least one place.return statement
findWords, use return _ in at least one place.findHorizontal must return the correct result
findHorizontal function is run must match the solution result.findWords must return the correct result
findWords function is run must match the solution result.findWords
def to define findWordsgetColumns
findWords, call getColumns in exactly one place.findHorizontal
findWords, call findHorizontal in exactly 2 places.