This lab uses the language, "Beginning Student with List Abbreviations". Also load the "matrix.ss" teachpack.
In this lab, you will create a program for a word-search puzzle (like Boggle), which involves searching for words in a grid of characters. If you are not familiar with the concept, look at this for a few minutes. You are given a grid and a dictionary. A word is correctly spotted if (1) the word's path through the grid is contiguous and does not repeat cells, and (2) the word is in the dictionary. You will write a set of functions culminating in a method that takes a path through the grid and returns a score for the word traced by the path.
Copy and paste the code below into your definitions window. This defines the character grid and the dictionary.
(define grid
(make-matrix 4 4 (list "A" "D" "E" "P" "E" "O" "P" "A" "K" "Z" "I" "F" "F" "T" "H" "I")))
grid
(define dictionary
(list "ADD" "ADO" "APE" "APED" "APP" "DEAF" "DOE" "DOZE" "FAITH" "FIT" "HIP" "HIT" "HOP" "HOPE" "ODE" "PAP" "PEA" "PED" "PEP" "PIT" "PITH" "POD" "POKE" "POKED" "TIP" "TOP" "ZED" "ZIP" "ZIT"))
Running the program will bring up a visualization of the character grid, which should look like this:
Now define a datatype, cell which denotes a position on the character grid. The type should have two number fields, row and col. Numbering on the grid starts from zero. To indicate the cell on the row 1, column 2 (in this case, corresponding to the letter "P"), I would type (make-cell 1 2).
(contiguous? (list (make-cell 1 3) (make-cell 1 2) (make-cell 0 2))) evaluates to true.
(contiguous? (list (make-cell 3 1) (make-cell 1 1) (make-cell 1 2))) evaluates to false.
Define a function hasnoloops? that takes a path and makes sure it does not contain repeated cells. You may use the built-in member function to check if a cell is in a list of cells.
For example:(hasnoloops? (list (make-cell 1 3) (make-cell 1 2) (make-cell 0 2))) evaluates to true.
(hasnoloops? (list (make-cell 1 3) (make-cell 1 2) (make-cell 1 3))) evaluates to false.
The word corresponding to a path (list (make-cell i1 j1) (make-cell i2 j2) ... (make-cell in jn)) is the string formed by concatenating the characters in the grid at each cell in order. Write a function path2word: list -> string which takes a path and returns the corresponding word. (You may assume that the path entered does not contain any positions outside the grid -- that is, all i, j are between 0 and 3.) You will need to make use of these two built-in methods:
(path2word (list (make-cell 1 3) (make-cell 1 2) (make-cell 0 2))) evaluates to "APE".etc.
(path2word (list (make-cell 2 3) (make-cell 2 2) (make-cell 3 1))) evaluates to "FIT".
(path2word (list (make-cell 3 1) (make-cell 1 1) (make-cell 1 2))) evaluates to "TOP".
Write a function indict?: string list -> boolean which checks if an input word is in the dictionary. Use the operation equal? to check whether two strings are equal.
Test cases:(indict? "APE" dictionary) evaluates to true
(indict? "AEK" dictionary) evaluates to false.
(indict? "ZIT" dictionary) evaluates to true.
Now write a function evalpath: list -> string which takes a path as input. If the path is contiguous without repeated cells, and the word corresponding to the path is in the dictionary, return the word. If any of these conditions are false, return the empty string "". For example,
> (evalpath (list (make-cell 1 3) (make-cell 1 2) (make-cell 0 2)))
"APE"
> (evalpath (list (make-cell 0 0) (make-cell 0 1) (make-cell 0 2)))
""
> (evalpath (list (make-cell 0 1) (make-cell 1 1) (make-cell 2 1) (make-cell 0 2)))
""
> (evalpath (list (make-cell 0 0) (make-cell 0 1) (make-cell 0 1)))
""
You will need to make use of contiguous?, hasnoloops?, path2word and indict? in your definiton.
Now that we have a mechanism to validate the path and check whether a word is correctly found, the next step is to add a scoring function.
(define letterscores
(list (list #\A 1)
(list #\D 1)
(list #\E 1)
(list #\F 2)
(list #\H 2)
(list #\I 1)
(list #\K 3)
(list #\O 2)
(list #\P 1)
(list #\T 1)
(list #\Z 3)))
letterscores is a list that assigns a score to each character of the alphabet. Write a function getscore: list character -> number which takes as input a list (in particular, letterscores) and a character, and returns the score of the character according to the list. The function should return 0 if the character is not present in the list. Use the operation char=? to compare two characters.
Test cases:
(getscore letterscores #\K) gives 3.
(getscore letterscores #\Y) gives 0.
We will define the score of a word to be the sum of the scores given to its constituent characters.
Write a function charlistscore: list -> number which takes a list of characters and returns the sum of their scores. If the list is empty, return 0. For example, (charlistscore (list #\F #\I #\T)) gives 4.
Finally, write a function pathscore: list -> number. This function takes a path and finds the score of the corresponding word. Make use of your previous function evalpath. You will also need the built-in function string->list, which breaks up a word into a list of its characters -- for example, (string->list "APE") evaluates to (list #\A #\P #\E). The definition of pathscore should be very short. Some test cases:
(pathscore (list (make-cell 1 3) (make-cell 1 2) (make-cell 0 2) (make-cell 0 1))) gives 4.Make sure you have written the contract, purpose and tests for all the functions that you write. If you do the extra credit section, write the code in the same file as the main lab. Include your name and userid as a comment at the top. Optionally, also include your feedback on the lab, and comments/suggestions. Use the handin button to submit your work.