CS111, Wellesley College, Fall 2007

Problem Set 7

Due on Wednesday, November 7 at the start of lab

Reading

  • IntList Contract
  • StringList Contract
  • String Contract
  • Study the code in the file StringListOps.java in the ps07_programs/Unjumbler folder.
  • Study the code in the file LabOps.java in the ps07_programs/Unjumbler folder.
  • Notes on invoking instance methods vs. class methods.
  • About this Problem Set

    The purpose of this problem set is to give you experience with strings, lists, and recursion.

    How to turn in this Problem Set

    You are required to turn in both a hardcopy and a softcopy. For general guidelines on problem set submission, including how to submit a softcopy and how to check if you softcopy submission was successful, click here. Please make sure to keep a copy of your work, either on a zip disk, or in your private directory (or, to play it safe, both).

    Hardcopy Submission

    Your hardcopy packet should consist of:
    1. The cover page;
    2. The paper with your JEM/box-and-pointer diagram;
    3. Your modified Unjumbler.java file.
    4. Transcripts illustrating that methods from Task 2 work correctly.
    Staple these together, and submit them at the start of class on the due date.

    Softcopy Submission

    You should submit your final version of your ps07_programs folder. In particular, the Unjumbler subfolder should contain your final version of Unjumbler.java.

    Task 1: A JEM with Box-and-Pointer Diagrams

    Suppose that the following methods are defined in a subclass of the IntList class:

    public static IntList F (IntList L) {
        return tail(G(0, L));
    }
    
    public static IntList G (int n, IntList L) {
        if (isEmpty(L))
            return prepend(0, L);
        else {
            IntList subResult = G(n + head(L), tail(L));
            return prepend(head(L) + head(subResult),
                           prepend(head(L) * (n + head(subResult)),
                                   tail(subResult)));
         }
    }

    Suppose that L1 is an integer list whose printed representation is [5,7,4]. For this task you are to draw a Java Execution Model (JEM) diagram that models the execution of F(L1). Your JEM diagram should consist of two parts:

    1. An Execution Land that shows all of the execution frames for F and G created by the invocation F(L1). Your diagram should depict the point in time when this invocation returns. Although Java can discard an execution frame when control returns from it, you should not discard any frames when drawing your diagram.
    2. An Object Land that shows the initial IntList L1, whose printed representation is [5,7,4], along with any new IntList nodes that are created during the execution. You may draw a reference to an IntList node as either a pointer that points to the node or a reference label in an oval; you may use both notations if you find this convenient. For an example of a JEM with a list, study the JEM for append in the Lectutre 15 slides.

    Task 2: Word Unjumbler

    Overview

    Word Jumble is a popular game that appears in many newspapers. There is an on-line version of Word Jumble. You may want to play this game a few times before continuing with the assignment.

    The game involves “unjumbling” English words whose letters have been reordered. For instance, the jumbled word ytikt can be unjumbled to kitty. The game can be challenging; even relatively short jumbles can be tricky to unjumble. For instance, here are the words that appeared on the October 31, 2007 version of the on-line game; can you unjumble them?:

    yandd, hubys, stapol, ungole

    In this problem, you will create a Java program that acts as an "unjumbling assistant". Given a string, your program will first generate all possible reorderings of the letters in the string. Such reorderings are called permutations. For example, there are six reorderings of the letters in the string tra:

    [tra,rta,rat,tar,atr,art]

    In general, a string with n distinct letters has n! (pronounced "n factorial") permutations. For instance, a 4-letter string has 4! = 24 permutations, a 5-letter string has 5! = 120 permutations, a 6-letter string has 6! = 720 permutations, and so on.

    Next, the assistant will determine which of the permutations is an English word by looking them up in a dictionary. You do not have to worry about how to construct such a dictionary; this has been done for you. Notes on how to use the dictionary as a "black box" can be found later in this problem description. In the case of "tra", filtering out the English words leaves:

    [rat,tar,art]

    When the string you are unjumbling contains duplicate letters, a simple permutations generator will yield some duplicate permutations. For instance, the permutations of "dda" will generate the 3! = 6 permutations:

    [dda,dda,dad,dad,add,add]

    Filtering out the English words yields:

    [dad,dad,add,add]

    In such cases, the unjumbling assistant should also filter out duplicates to yield the final list:

    [dad,add]

    To get a feel for what the unjumbling assistant does, you should experiment with the UnjumblerAnswers.class file in the Unjumbler folder, which contains working methods for unjumbling. For this assignment, we have provided this file (instead of a test folder), as an example of how your solution should execute. For example, if you want to see how your program should behave, you can run the main() method from the UnjumblerAnswers.class by entering the following in the Dr. Java Interaction pane:

    java UnjumblerAnswers string-to-unjumble

    where string-to-unjumble is a string you wish to unjumble. For example:

    java UnjumblerAnswers argle
    [glare,large,regal,lager]

    You can use this application to help you solve the on-line Word Jumble puzzles!

    Important Note: With its default settings, DrJava is only able to unjumble words of at most 6 characters. Attempts to unjumble words longer than 6 characters will encounter a StackOverflowError, indicating that there is a chain of execution frames that is too long for Java Virtual Machine to handle. Longer words can be handled by modifying the default stack size used by DrJava for program execution. This can be done via the following steps:

    1. In the DrJava window, select Edit>Preferenences to display the Preferences window.
    2. In the Preferences window, select the Miscellaneous category.
    3. In the input line labeled JVM Args for Interactions JVM, type -Xss10000k (no spaces). This tells the Java Virtual Machine (JVM) to use a stack with size 10000 kilobytes (about 10 megabytes), which is sufficient for unjumbling 8-character words.
    4. At the bottom of the Preferences window, press the OK button.
    5. A pop-up window will appear warning you that "Specifying Interactions JVM Args is an advanced option ..." and will ask you if you're sure you want to do this. Press the Yes button.
    6. In the DrJava window, select Tools>Reset Interactions to make the change take effect.

    Your Task

    Your task is to create your own unjumbler program, mostly from scratch. To do this, you need to do is to write definitions for the nine class methods specified below.

    Here are some things you need to know:

    1. public static StringList remove (String s, StringList L)
      Returns a new list in which all occurrences of s in L have been removed. The other strings in the list should have the same relative order in the resulting list as in the given list.

      Examples:
      remove("I", fromString("[I,know,that,I,said,that,I,did]"))
            returns the string list [know,that,said,that,did].

      remove("that", fromString("[I,know,that,I,said,that,I,did]"))
            returns the string list [I,know,I,said,I,did].

      remove("said", fromString("[I,know,that,I,said,that,I,did]"))
            returns the string list [I,know,that,I,that,I,did].

      remove("you", fromString("[I,know,that,I,said,that,I,did]"))
            returns the string list [I,know,that,I,said,that,I,did].

      Note: Use the equals() instance method from the String class to compare two strings. For instance, "cat".equals("cat") returns true but "cat".equals("dog") returns false. You should not use == to compare two strings because it may not return what you expect. For instance, while "cat" == "dog" is guaranteed to return false, "cat" == "cat" and "cat" == ("c" + "at") are not guaranteed to return true. They may return true in some implementations and some circumstances, but you cannot rely on this behavior.

    2. public static StringList removeDuplicates (StringList L)
      Returns a list containing each string in L exactly once. The order of the elements in the returned list should be the relative order of the first occurrence of each element in L.

      Examples:
      removeDuplicates(fromString("[I,know,that,I,said,that,I,did]"))
            returns the string list [I,know,that,said,did].

      removeDuplicates(fromString("[you,say,what,you,mean,and,mean,what,you,say]"))
            returns the string list [you,say,what,mean,and].

      removeDuplicates(fromString("[lists,are,cool]"))
            returns the string list [lists,are,cool].

      Note: The remove method from above is helpful here!

    3. public static StringList mapConcat (String s, StringList L)
      Given a list L with n strings, returns a new list with n strings in which the ith string of the resulting list is the result of concatenating s to the ith element of L.

      Examples:
      mapConcat("com", fromString("[puter,plain,municate,pile]"))
            returns the string list [computer,complain,communicate,compile].

      mapConcat("I ", fromString("[came,saw,conquered]"))
            returns the string list [I came,I saw,I conquered].

    4. public static StringList insertions (String s1, String s2)
      Given two strings s1 and s2, where s2 has n characters, returns a list of n + 1 strings that result from inserting s1 at all possible positions within s2, from left to right.

      Examples:
      insertions("*", "split")
            returns the string list [*split,s*plit,sp*lit,spl*it,spli*t,split*]

      insertions("a", "bcd")
            returns the string list [abcd,bacd,bcad,bcda]

      insertions("com", "pile")
            returns the string list [compile,pcomile,picomle,pilcome,pilecom]

      insertions("abc", "")
            returns the string list [abc]

      Note: The LabOps class contains two helper methods that are useful for defining insertions:

      1. public static String first (String s)
        Returns a string consisting of the first character of s. For example, first("computer") returns the string "c".

      2. public static String butFirst (String s)
        Returns a string consisting of all but the first character of s. For example, butFirst("computer") returns the string "omputer".

    5. public static StringList insertionsList (String s, StringList L)
      Returns a list that contains all the strings that result from inserting s at all possible positions in all the strings of L.

      Examples:
      insertionsList("a", fromString("[bc,cb]"))
            returns the string list [abc,bac,bca,acb,cab,cba]

      insertionsList("*", fromString"[I,am,Sam]"])
            returns the string list [*I,I*,*am,a*m,am*,*Sam,S*am,Sa*m,Sam*]

      insertionsList("abc", fromString("[]"))
            returns the string list []

      Note: The StringListOps class contains a helper method append that is useful for defining insertionsList:

      public static StringList append (StringList L1, StringList L2)
      Returns a new string list containing all the elements of L1 followed by all of the elements of L2. For example,
      • append(fromString("[I,do]"), fromString("[not,like,green,eggs]")) returns [I,do,not,like,green,eggs]
      • append(fromString("[I,do]"), fromString("[]")) returns [I,do]
      • append(fromString("[]"), fromString("[not,like,green,eggs]")) returns [not,like,green,eggs]

    6. public static StringList permutations (String s)
      Returns a list of all permutations of the string s. A permutation of a string s is any string that is formed by reordering the letters in the string s (without duplicating or deleting any letters). For a string with n distinct characters, there are exactly n! (i.e., "n factorial") permutations. If some characters in s are repeated, there are still n! permutations, but the permutations contain duplicates. The elements in the list returned by permutations may be in any order.

      Examples:
      permutations("d") returns the string list [d].

      permutations("cd") returns the string list [cd,dc] or the string list [dc,cd].

      permutations("bcd") returns (any permutation of) the string list [bcd,cbd,cdb,bdc,dbc,dcb].

      permutations("abcd") returns (any permutation of) the string list

            [abcd,bacd,bcad,bcda,
             acbd,cabd,cbad,cbda,
             acdb,cadb,cdab,cdba
             abdc,badc,bdac,bdca,
             adbc,dabc,dbac,dbca,
             adcb,dacb,dcab,dcba].

      permutations("121") returns (any permutation of) the string list [121,211,211,112,112,121]. Note that when the given string contains duplicate characters, the permutation list will contain duplicates.

      permutations("1231") returns (any permutation of) the string list
            [1231,2131,2311,2311,
             1321,3121,3211,3211,
             1312,3112,3112,3121,
             1213,2113,2113,2131,
             1123,1123,1213,1231,
             1132,1132,1312,1321].

      Note: There are many ways to define the permutations method, but a particularly elegant way uses the first, butFirst, and insertionsList methods from above. Be very careful in defining your base case!

    7. public static StringList filterWords (StringList L)
      Returns a list of all strings in L that are English words. The resulting strings should be in the same relative order as in L.

      Examples:
      filterWords(fromString("[the,dog,barked,at,the,cat]")) returns the string list [the,dog,barked,at,the,cat].

      filterWords(fromString("[the,dog,barkd,ate,hte,cat]")) returns the string list [the,dog,ate,cat].

      filterWords(fromString("[tra,rta,rat,tar,atr,art]")) returns the string list [rat,tar,art].

      Note: To determine if a string is an English word, you should use the class method isWord() that is already defined for you in the Unjumbler class:

      public static boolean isWord (String s)
      Returns true if s is a word in the default English dictionary, and false otherwise.

      The default dictionary (which can be changed within the Unjumbler class) contains 22641 English words (all lower case, no proper nouns) of up to 8 characters in length. It is not a "perfect" dictionary: there are some perfectly acceptable English words that are not in the dictionary.

      You can change the default dictionary to one that contains 45425 English words without a length restriction, but this takes longer to load. For details on how to do this, see the comments near the end of Unjumbler.java.

    8. public static StringList unjumble (String s)
      Returns a list of all the permutations of s that are English words (as determined by the default dictionary). The order of elements in the resulting list does not matter, but each word in the resulting list should be listed only once.

      Examples:
      unjumble("tra") returns the string list [rat,tar,art].

      unjumble("tras") returns the string list [rats,arts,star]
            (the default dictionary doesn't recognize tars or tsar as words).

      unjumble("argle") returns the string list [glare,large,lager,regal].

      unjumble("sbso") returns the string list [sobs,boss].

      unjumble("xzzy") returns the string list [].

      Note: You should only remove duplicates after performing filterWords. It turns out that performing removeDuplicates on a large lists (such as the output of permutations) can take a very long time. (To understand why this is so, take CS230!)

    9. public static void main (String[ ] args)
      Assume that args contains one string argument (denoted args[0]). Displays the list of unjumbled English words for that string argument. For example:
      > java UnjumblerAnswers argle
      Constructing dictionary from file /Users/fturbak/Desktop/ps7/Unjumbler/dicts/dict8.bin.
      This may take a little while...
      Done! Dictionary constructed with 22641 words.
      [glare,large,regal,lager]
      
      > java UnjumblerAnswers crptmeou
      [computer]
      
      > java UnjumblerAnswers sbso
      [sobs,boss]
      
      > java UnjumblerAnswers xyzzy
      []

      In the above example, the following text is automatically displayed when the dictionary is loaded, which automatically happens when the isWord() method is invoked for the first time.

      Constructing dictionary from file [some-directory-name-goes-here]Unjumbler/dicts/dict8.bin.
      This may take a little while...
      Done! Dictionary constructed with 22641 words.