Homework 8
CS1210 Computer Science 1 - Fall 2021
Due Thursday, Nov. 18, by 8:00pm
6 points

1. Implement function q1(numerator, denominator) that uses the greedy strategy presented in slides 7 and 8 of Lecture 32 (Nov. 5) to determine a set of distinct (i.e. all different) Egyptian fractions that sum to numerator/denominator. You may assume numerator and denominator are positive integers and that numerator is less than or equal to denominator. Your function should both 1) print a readable "equation" showing the result (see examples below) and 2) return a list of Egyptian fraction denominators

```Examples:
>>> q1(4,5)
4/5 = 1/2 + 1/4 + 1/20
[2, 4, 20]
>>> q1(2,11)
2/11 = 1/6 + 1/66
[6, 66]
>>> q1(761, 1000)
761/1000 = 1/2 + 1/4 + 1/91 + 1/91000
[2, 4, 91, 91000]
```
Important note: you MAY NOT use division or modulus in your function. All calculations should be done with integers. In particular, computing the difference (n/d) - (1/c) is a key step (see slide 8). You can calculate an integer numerator and integer denominator for this difference using only multiplication and subtraction.

2. Complete a program to find word ladders (for 5-letter words) by finishing/modifying the functions in wordLadderStart.py. (Note: you'll also need these files: bfs.py and basicgraph.py since wordLadderStart.py imports them)

A fully working user-interaction loop has already been provided in function "wordLadders(wordsFile)". You do not need to modify that function. But read the comments contained in it to fully understand what the program is doing. The wordLadders function first reads the specified word list and build a corresponding graph. The graph will have one vertex for each word, and an edge between nodes whose words differ in exactly letter at one position. Next, the program enters an interactive a loop that
• asks the user to enter either two words (start and end word) or one word (start word) or 'q' (to quit)
• checks that the give word or words are in the dictionary
• execute (a modified version of) breadth first search from the start word's node.
• if an end word was not given, find the node in the graph with the largest distance value and extract the ladder between the start node and that node.
• if an end word was given, extract a word ladder from start to the end word
• print appropriate information - the extracted ladder and its length.
Things you need to do: (and this is the strongly recommended order - test carefully after each step before going on to the next. You did the first two steps in DS8.)
1. Complete function "shouldHaveEdge" so that it correctly returns True when two length-5 words differ at exactly one character position. (You did this in DS9 - just copy it into this assignment's file)
2. Complete function "buildWordGraph" to create and return a graph with one node for each word and an edge for each pair (w1, w2) of words where shouldHaveEdge(w1, w2) is True. (You also did this in DS9 - use it!)
3. Modify the Node class in basicgraph.py to include distance and parent properties and getDistance, setDistance, getParent, and setParent methods.
4. Modify function bfs in bfs.py to correctly initialize the distance and parent properties and update them appropriately during the bread-first search.
5. Complete function "extractWordLadder" to return a list of words representing a shortest path between the start and end words. See detailed comment on the provided "extractWordLadder" stub function.
Sample interaction and output:
```>>> wordLadders()
Created word graph with 2415 nodes and 2740 edges
Enter start and end words OR start word OR 'q' to quit: adore scorn
Enter start and end words OR start word OR 'q' to quit: sleep arise
Shortest ladder from sleep to arise is length 15:
sleep sheep sheer cheer cheek check chick chink chine shine shone phone prone prose arose arise
Enter start and end words OR start word OR 'q' to quit: sound
court is maximally distant (4 steps) from sound:
sound found fount count court
Enter start and end words OR start word OR 'q' to quit: quack
typic is maximally distant (45 steps) from quack:
quack quark quart quirt quilt guilt guile guide glide elide elite elate plate place peace peach leach leash lease tease terse verse verge serge surge purge purse parse passe paste pasty party parry harry hardy handy candy canny canna manna mania manic monic tonic topic typic
Enter start and end words OR start word OR 'q' to quit: bbbbb
The start word is not in the dictionary.  Please try again.
Enter start and end words OR start word OR 'q' to quit: sleep bbbbb
The end word is not in the dictionary.  Please try again.
Enter start and end words OR start word OR 'q' to quit: q
>>>
```
The wordLadders program takes one argument, the name of a text file containing the word list to be considered. You may assume all words in the dictionary are five letters long, all lower case. Each word appears on a separate line in the file. A test file with a few thousand five-letter words is here: words5.txt. NOTE: Test your code first on a small file (e.g. wordsTest.txt) before running your program on words5.txt; debugging will be easier!

Note: if you finish this early, here's something extra you can do for fun. Modify your algorithm to try to find long word ladders rather than short ones. E.g. can you find a ladder from black to white that's longer than 100 steps? Longer than 648 steps? (Hint: even just switching the graph traversal algorithm from bfs to dfs often gives you fairly long ladders - it's super easy to try this ...)
IMPORTANT SUBMISSION NOTE: Submit via ICON exactly ONE ZIP FILE of a folder containing four files: q1.py (containing Q1's q1 function), wordLadderStart.py, bfs.py, and basicgraph.py.