CS151 – Fall 2007: Programming Project 2

Due: Friday, September 28, 11:59:59:999 EST

 

In this project you will gain more experience with defining your own classes.  You will specify both the public interfaces and the implementation behind those interfaces. 

 

To practice your specification and implementation skills, you will create a class that models a kind of word puzzle called a cryptogram.  Cryptograms are single letter substitution ciphers or codes.  For example,

         "L DP KHUH, DQG BRX DUH WKHUH."

is a cryptogram of the phrase

         "I am here, and you are there."

The substitution scheme used in the above example is called a Caesar Shift: every letter of he message is replaced with the third letter after it in the alphabet.  However, cryptograms need not employ such regular substitutions.  The choice of letters to substitute can be completely random and has no effect on the difficulty of the resulting cryptogram.  One of the things your class will do is generate a key that produces such a random cryptogram.

 

One solves cryptograms using properties of the English language such as letter frequencies, punctuation marks, etc.  You can usually tell if you have the correct answer because it should make sense as an English phrase.   You can find daily cryptograms in some newspapers and on a variety of web sites.  On these web sites they also sometimes have cryptogram solver applications.  The applications don't solve the puzzle, rather they facilitate the interactive solving process.

 

Cryptogram Class

Create a project called username-proj2, where username is your login/email address, e.g. srussell-proj2.  In that project create a class called Cryptogram.  Please do not deviate from these naming conventions, since it makes more work for the grader and cranky graders aren't a good thing for you or me.  Your Cryptogram class will model and produce cryptograms. You can then torture friends, family, one another, and me with the puzzles you produce. 

 

Recall, that each class consists of constructors, methods, and instance field/variables.  Constructors describe how to create a new object or instance of the class, methods are actions that objects of the class can perform, and instance fields/variables store information specific to each object or instance of the class. 

 

Your class should have:

1.    Three private instance fields in your class, all strings: one for the plaintext, one for the ciphertext, and one for the key.  What you call them is up to you since users of your class will access them with get and set methods (see below).

 

2.    Three constructors

a)    one that takes no parameters and creates a "blank" cryptogram

b)    one that takes a single parameter: a plaintext string and creates a cryptogram instance with that plaintext

c)    one that takes two parameters: a plaintext string and a key string, and creates a cryptogram instance with the specified plaintext and key string (again for ease of testing please make plaintext the first argument and the key the second parameter)

 

3.    Three get methods all of which take no parameters and return a String.

a)  getPlaintext

b)  getKey

c)    getCiphertext (return an upper case String, i.e. all capitals).

 

4.    Three set methods all of which take a single String parameter and return nothing.

a)  setPlaintext

b)  setKey

c)    setCiphertext

 

5.    [Strongly suggested but not mandatory]

a)    A public class constant of type String using the syntax
public static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

b)    An public class constant of type int using the syntax
public static final int ALPHABET_SIZE = ALPHABET.length();
(why is this preferable to explicitly setting it to 26?)

 

These two things will appear multiple times in your methods and are fixed across all instances of the class you create.  Hence, it's good practice to make them class constants (like the Calendar class constants we used in the last project).  Doing this also makes your code more readable. See section 4.2 of your textbook for a discussion of constants and the syntax used to declare them (focus on the "In a class" variety).  We will talk more about constants soon.

 

 

6.    A method called encrypt that takes two parameters: the first a String is a plaintext, and the second also a String is a key (again, please don't change the order of the arguments).  The method should also return a String.  It should create a cryptogram (also called a ciphertext) using the plaintext and key parameters.

 

To encrypt, you replace all instances of "A" or "a" in the plaintext with the first letter of the key, all instances of "B" or "b" with the second letter of the key, and so on.  Rather than writing a statement to explicitly search and replace each letter of the alphabet, you should use "for loop".  We haven't discussed them yet, but I will talk about them enough for you to use them in the project.  You can also look ahead in the book for information.  The following code snippet assumes you defined the suggested constants and is an example of a "for loop" in action:

 

         //prints every letter of the alphabet on a separate line

     String myAlphabet = Cryptogram.ALPHABET;

     for (int index = 0; index < 26; index++)

     {

          System.out.println(myAlphabet.charAt(index));

     }

 

(It would be better to use ALPHABET_SIZE instead of 26, but I didn't want to make the example more confusing.)  The loop counts from 0 to 26 and stores the value in variable called index that only exists inside the body of the loop, denoted by {}.  Each time the test index<26 is performed, and if true, the body of the loop (it can be more than one statement) is executed after which index is incremented by 1 and the process is repeated.  The shorthand index++ is equivalent to index=index+1.  You can change the lower bound, 0, the upper bound, 26, or the < sign to other things if you want, but you shouldn't need to.


String methods you will probably want to use in the encrypt (and decrypt and generateRandomKey methods too) include: substring(), replaceAll(), toUpperCase(), toLowerCase(), length(), replaceFirst(), split().  You may not need all of these, and you may use any String methods not in this list.  No classes other than String and Random are needed to implement the required functionality.

 

7.    A method called generateRandomKey that takes no parameters and outputs a random key in the form of a String.  Again, a key is a string of 26 letters (preferably upper case) with each letter appearing exactly once.

 

8.    [Optional/extra credit choices]

a)    A method called decrypt that takes two parameters: the first a String is a ciphertext, and the second also a String is a key (again, please don't change the order of the arguments).  The method returns a plaintext "guess" by applying the key to the ciphertext.  Note that key used to encrypt is different from the key used to decrypt. 

b)    Try to figure out how to convert an encryption key into a decryption key and write a method called ecryptionToDecryptionKey that does this. It takes a single String parameter representing an encryption key and returns a String which is the decryption key.

c)    Modify the constructor that takes two parameters to also encrypt the plaintext parameter using the key parameter and assign the result to the object's ciphertext instance variable.

d)    Other useful or fun extensions.

Strategy and Hints

First implement the get and set methods and constructors and make sure they work before moving on to the more challenging encode method.  No additional classes are needed to implement the encode method other than the String class methods.  Before trying to write the code, try to work out an algorithm for encoding on a piece of paper.  First, understand what you want to do, then figure out how to accomplish it.  There is a small issue you will have to deal with.  Suppose your key starts with BA so that A gets replaced with B, B with A, and Y with I. For the plaintext of BABY, make sure your encrypt algorithm outputs ABAI and not AAAI.  I may give hints if this proves too difficult.  If you figure it out DO NOT tell anyone else.  Help them to come up with the solution themselves.  Once you get encrypt working, then decrypt should be easy: just reverse the process. 

 

Leave generateRandomKey for last.  I may make this method extra credit, rather than required depending on how people do.  You can test your encrypt method using the sample keys provided below or generate your own key by hand.  Remember, the key is just a string with each letter of the alphabet appearing exactly once.

 

Start early and try to make a little progress each day.  Test early and often.  You can test interactively with BlueJ or write a CryptogramTester class to help with testing.  Make use of the online documentation, TAs, and me.  Don't put it off until the last minute.

Style and Documentation

All constructors, methods, and public instance variables should be commented using @param and @return tags to facilitate the generation of .html documentation similar to the Java Class Libraries on the Web via the Javadoc utility.  BlueJ automatically generates this documentation for your class when you switch from "Implementation" to "Interface" in the class editor window.  We've discussed the use of these tags in class and additional information is in section 3.3 of your textbook. 

 

Your code should adhere to the stylistic guidelines we have been discussing and which are in Appendix A of your textbook as much as possible.  Try to use meaningful variable names and internally comment your code liberally (with // or /*   */ pairs).

Sample Keys

For simplicity we will treat our keys as strings of 26 letters.  This will allow us to implement all the desired functionality using methods from the String class.  So, using Key 1, A is replace by D, B by E, and so on.  No substitution is performed for punctuation marks or spaces.  Key 1 is the key used to produce the example described at the beginning of this project description.  Key 3 is randomly generated.

 

Plaintext:     ABCDEFGHIJKLMNOPQRSTUVWXYZ

Key 1:     DEFGHIJKLMNOPQRSTUVWXYZABC

Key 2:     ZYXWVUTSRQPONMLKJIHGFEDCBA

Key 3:     BGQEOCPHTFXWJSKUDRNMALYIZV

Project Submission

Please remove any additional classes you create while working on the project for testing before you submit your final solution.  However, if you create a CryptogramTester class feel free to submit the source (.java file) for it.

 

You will again submit your projects electronically.  To do so

1.    Connect to the Academics volume of the server called fileserver1.  From a Mac choose "Connect to Server ..." from the "Go" menu in the Finder, type afp://fileserver1 in the dialog box, and select Academics from the volume list.  From Windows machine open Windows Explorer, select "Map Network Drive" from the tools menu, pick a free drive letter and type \\fileserver1\Academics.  When prompted for your user name and password, type COLBY\username, where username is your Colby username and enter your password.  These instructions are adapted from http://www.colby.edu/administration_cs/its/support/fileserver1.cfm. 
NOTE:  At this time only Mac (afp: ) connections are possible.

2.    On the Academics volume inside of the COMP/CS151 folder/directory you will see a folder with your Colby e-mail/login name.  Copy your Cryptogram.java file from your project directory to that folder.  If you have want to submit other classes, copy the .java files for those classes too.  Also, please include a brief readme.txt file explaining the additional classes and how to use them.

 

Sample Cryptogram

By convention, cryptograms are printed in capital letters which are easier to read and double-spaced so that you can pencil in your solution above the puzzle.  Single letters, punctuation, words with special patters, etc. are all clues.  The following cryptogram pertaining to procrastination is from the February 2002 edition of "Dell Easy Fast 'N' Fun Variety Puzzles":

 

X'T YTOHR WAFGCI RF ZAFL RF OQLOJY SGR FBB GARXQ RFTFHHFL LIOR X'T YGHW X LFGQV TOZW O TWYY FB RFVOJ.

Acknowledgement

Mr. Steves, my fifth grade teacher, first introduced me to cryptograms.  He used to give us 15 – 20 minutes to solve them and we usually worked in pairs.  It is probably one of the reasons I got interested in cryptography and ended up here.  I hope you enjoy them as the basis for your assignment.  Thanks again Mr. Steves!