Dictionary Reader

Build a dictionary reader.

Scroll down...




This assignment will require you to loosen up those file I/O and Regex muscles. You'll need to read in a dictionary file and create a simple parser that will search for words within it. This is a good chance to practice highly modular design and work with "micro classes" which can help you perform a variety of specific tasks.


Getting Started

  1. Fork and clone the project repo on Github.
  2. Add your name to the README file, commit the change, and push to your fork.
  3. Download 5desk.txt from the 12 dicts project. The zip archive of all 12 dictionaries can be downloaded here if you want it in the future.

You will need to verify that things work anyway, so why not implement a simple automated test suite..?

Application Architecture

You will build a simple word search tool on the command line in Ruby. Even though it's called a "Dictionary", to keep it simple we're actually just searching for words in a word list (which is our "dictionary").

The architecture of this is going to feel a bit strange at first. Specifically, we'll break it up into 5 highly specialized classes:

  1. DictionaryUI is the main class which handles the user interaction loop.
  2. DictionaryLoader is a helper class whose single responsibility is to load in the dictionary.
  3. Dictionary is the class which wraps the loaded dictionary.
  4. DictionarySearcher is an analysis class whose sole responsibility is to perform any analysis on the dictionary you provide it.
  5. ResultsSaver takes a batch of results and writes them to a file.

It may feel a bit strange to break out all these separate classes but this type of object orientation is quite common. Each class should only have ONE responsibility -- this is a way of enforcing this.

By having a single DictionaryLoader class to handle all the loading operations, your main DictionaryUI doesn't care where the dictionary actually comes from. Imagine you wanted to be able to load dictionaries from your local filesystem via XML or from the web via a URL... It would be the job of your DictionaryLoader to call the appropriate XMLLoader or WebLoader subclasses if the application was sufficiently complicated.

By having your DictionarySearcher in its own class, you again allow DictionaryUI to fully delegate the analysis logic and processes to a class whose sole purpose is performing those tasks. The same is true of ResultsSaver since it fully encapsulates the task of figuring out how to save your results.

Your Task

Create a simple application which loads in the dictionary file you downloaded during the setup step and allows the user to perform simple searches on it.

Load the Dictionary

  1. Create a DictionaryUI class to handle the user interaction loop. The first prompt is for the location of your dictionary file.
  2. Create a class DictionaryLoader whose purpose is to perform the loading and processing of the specified dictionary file before returning it as an instance of a Dictionary. Remember that classes don't need to be big!

    > d = DictionaryUI.new
    > d.run
    # Where is your dictionary? ('q' to quit)
    > "path/to/myfile.csv"
    > ...
  3. Return statistics about your dictionary when it is first loaded, including word count and words by starting letter:

    > "path/to/myfile.csv"
    # Dictionary successfully loaded
    # Your dictionary contains 12345 words.
    # Word frequency by starting letter:
    # A: 123
    # B: 456

Search the Dictionary

  1. Create a class DictionarySearcher which takes a dictionary and contains methods that perform searches on it.
  2. Next, allow the user to perform one of four types of searches:

    1. Exact matches
    2. Partial matches
    3. "begins with" matches
    4. "ends with" matches

    These can be done with Regex or not... you should use whatever you're least comfortable with! The results should return the full word, regardless of match type.

  3. Once the search is complete, display the number of matches and those matches:

    # What kind of search? 
    # 1: Exact
    # 2: Partial
    # 3: Begins With
    # 4: Ends With
    > 3
    # Enter the search term
    > fuz
    # Found 7 matches:
    # FUZE
    # FUZEE
    # FUZHOU
    # FUZZ
    # FUZZY

Save the Results

  1. After displaying results, prompt the user whether to save the results to a file.
  2. If saving to a file, prompt the user for the name of the file to save results to. If it already exists, ask whether to overwrite it or not. Create a ResultsSaver class which takes a batch of results and writes them to a file.

    # Found 1 match:
    # FUZZY
    # ***
    # Do you want to save results? y/n? 'q' quits.
    > y
    # What filepath should we write results to?
    > results.txt
    # That file exists, overwrite? y/n? 'q' quits.
    > y
    # File successfully overwritten!
  3. Play with this and verify that searches and saving works properly. What other search types can you come up with?

Finishing Up

  1. When you're finished with all tasks, push your changes up to your fork (aka $ git push origin master).
  2. To submit your assignment, create a pull request from your fork to the main upstream repository.

Optional Extension

Write a basic test suite which verifies that each of your classes behaves the way you expect it to. Be mindful to include edge cases!


The solution will be available here on Github once you've unlocked it.

Pull request 300 Octocat 300

Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

Sorry, comments aren't active just yet!

Next Lesson: Ruby Cheat Sheet