CS101 - Lab 5

In this lab you will do more problems involving arrays and strings in Java.

As you read and try to figure out each problem, look over the examples that we did in class. They will answer many of the questions you may have. Also, there will be things which we did not explicitly discuss in class, and which I'll expect you to figure out by yourselves.

Always start by thinking of the problem top-down. Split it into logical steps, and write one step at a time. Then compile it, and check if it does what you want. Write your code incrementally! This will save you much trouble.

As a computer scientist the goal is not to memorize the details of how you do things (actually, many computer scientists have very bad memories), but rather to develop your problem solving skills. Keep all your documentation close by, check all the files and all the handouts that you want, check the web for documentation if you like, whatever (which does not violate the honor code); the goal is to solve the problems, learn how to think, and be able to do it faster next time around! And, last but not least, I hope you have fun!!

Before you raise your hand for help, try to understand what happens with your program. If it is a compile problem, read the messages on the screen; the compiler tries to give you a hint of what went wrong; can you figure out what it's telling you?

Don't forget to pay attention to issues of programming style: indentation, comments, descriptive names, spaces (see handouts). If you develop a good programming style, programming will come easier to you (plus, I wont take points off). And it will be easier for others to help you.

As usual, work individually, and call me if you need help. You are encouraged to discuss ideas and techniques broadly with other class members, but not specifics. Discussions should be limited to questions that can be asked and answered without using any written medium (e.g. pencil and paper or email). You should at no point look at the screen of your colleagues.

Enjoy!


String warm-up

To check the length of a string you can use a method on strings called length:

 int length()

Returns the length of the string.
Example:
String s = "strings";

int l = s.length(); //this assigns value 7 to l

We have seen readString, which reads a word. To read a whole line, use readLine:

ReadStream r = new ReadStream();
String s;
s = r.readLine();     // read a whole line from input

To test whether a letter occurs in a string you can use another method on Strings, called charAt. This is a method that returns a character (letter) of a string, at a specified position.

char charAt(int index) 

Returns the char value at the specified index.
Example: consider the string s = "computers". Then s.charAt(0) will return the first character of "computers", namely c. Similarly, s.charAt(1) will return the second character, namely o, and so on.

Since the method returns a chracter, you can assign the value returned to a variable of type char. Check out the example below.

String s; 
char c;
int i; 
... 
i  = 10; 
c = s.charAt(i); 
if (c == 'a')
     System.out.println("The letter at position " + i + " is a"); 
...

To ignore upper v.s. lower case, you can use a method on Strings called toLowerCase(). This converts the string to a new string, in which all characters are lower case.

String	toLowerCase() 
          
Converts all of the characters in this String to lower case.
For example, if s = "HeLlo.", then s.toLowerCase() returns a new string "hello.". Here is an example:
String name, lowerCaseName; 

//set a value for name
...

lowerCaseName =	name.toLowerCase(); 
//now the string lowerCaseName is the lower-case version of the string name

...

  1. Cryptology using Caesar's cypher. Cryptology is the science of "secret codes". Messages are encoded before they are sent out to keep their content secret if they are intercepted by the wrong parties; they are decoded when they are received to retrieve the original information.

    The most famous instances of cryptology occur in military history, beginning with Julius Caesar of the Roman Empire, who developed the Caesar Cypher, and certainly including the German Enigma code cracked by the Allies during World War II (by Alan Turing, a British mathematician and computer scientist).

    Transmitting information securely has taken a modern turn with electronic commerce on the Internet and concerns over protection of consumer credit card information and other personal data.

    A Caesar cypher, also called a shift cypher, involves shifting each character in the message to another character some fixed distance farther along in the alphabet. Specifically, let s be some integer between 1 and 25 that represents the amount of the shift. Each letter in the message is encoded as the letter that is s units farther along in the alphabet, with the last s letters of the alphabet shifted in a cycle to the first s letters.

    For example, if s=3, then a is encoded as d, b is encoded as e, etc. Notice that you have to wrap-around the end of the alphabet so that x is encoded as a, and z is encoded as c.

    On a computer characters are represented internally as numbers, each character being assigned a number (called its code). Moreover, the codes of characters are chosen such that two letters that are neighbors in the alphabet have neighboring codes: for example, the code of a is 90, and the code of b is 91, the code of c is 92,... and so on. Because of this you can compare characters and use arithmetic just as if you were using numbers (examples below).

    To shift a character you can simply use +, that is, 'a' + 1 is 'b'. However, 'z'+1 is not 'a', but the character that comes after 'z'; to see what that is, you could try to print System.out.print("z+1 is " + (char)('z'+1))). Thus you will need to take care of rolling-over.

    Decoding a message requires knowing s. For example, knowing that s=3, the code word dupb is decoded as army.

    Write a program that reads a whole line (consisting of words separated by spaces) and encodes it using Caesar cypher with s=3; afterwards it decodes it making sure it gets the original word. You will encode only lower-case letters of the alphabet, and leave everything else as is; in particular, spaces are not to be encoded. To check whether a character c is a space, you can use if (c == ' '). To test whether a character c is a letter of the alphabet you can use

    if ((c >= 'a') && (c <= 'z')) {
           //this is true if c is a letter between 'a' and 'z'
    
    

    I suggest that you use a constant variable for s, for instance final int SHIFT = 3;.

    You have already seen Strings, and some methods that you can use on them. In this program you will need to modify a word, that is, the cypher; you will need to ability to set the characters in the cypher, one by one, to the desired coded value. Strings do not offer this functionality; that is to say, are imutable, they cannot be modified.

    In this program you will see a new class StringBuffer. A StringBuffer is like a String, but it lets you change the contents. One of the basic methods of StringBuffer is append:

    void append(char ch) // appends ch to the string buffer 
    Example:
    StringBuffer sb = new StringBuffer(); 
    sb.append('x');
    sb.append('y'); 
    sb.append('z'); 
    System.out.println(sb); // prints xyz
    

    Use the following skeleton for your program:

    /* 
    ...
    */
    public class Crypto {
            
        public static void main (String args[]) {
    
    	       //print welcoming message and describe the program to user
    		System.out.println("Welcome to cryptomaster!");
    		...
    	
    		//declare the variables
    		ReadStream r = new ReadStream();
    		String original;  //original message 
    		StringBuffer cypher;    //encrypted message
    		StringBuffer decypher; //decrypted message
    
    		//read the message
    		System.out.print("Enter the message..... ");
    		original = r.readLine();
    	
    		...
    
    
    		/* ENCODE the message: that is, examine every character
    		   of message in order, shift it, and append it in
    		   order into cypher. 
                    */
    		cypher = new StringBuffer();
    		int i = 0; 
    		while (i < original.length()) {
    		     ...
    		}				
    
    
    		//print out the cypher, character by character
    		System.out.print("Encrypted message: ");
    		...
    
    
    		/* DECODE the encrypted message */
    		...
    
    	} //end of main
    } //end of class
    
    What does the following translate to? frpsxwhuvflhqfh lv vr frro

  2. The palindrome problem. A palindrome is a word that reads the same forward and backward, like
    abba 
    ala
    Campus motto: Bottoms up, Mac.
    Madam, in Eden, I'm Adam.
    Naomi, sex at noon taxes, I moan.
    Never odd or even.
    
    For examples of more involved palindromes check out this.

    Write a program that checks whether a string entered by the user is a palindrome, or not. The program should start by printing a welcome, explanatory message. Then it should ask the user to enter a string. Then it should check whether the string is a palindrome, and finally print the result.

    Don't worry about punctuation and spaces in the input (extra credit).

    Your program should make no distinction between lower and upper case letters.

    As always, use a top-down, incremental approach. I suggest that you start by assuming that the string input by the user has no spaces, is all lower case, and contains no punctuation or dot at the end. Once you get this to work well, refine your code to ignore upper v.s. lower case difference.

    Extra challenge (and extra credit :)): Make your program ignore spaces and punctuation. To check whether a character is not an alphabet letter, you can use character arithmetic:

    char ch; 
    ...
    if ((ch < 'a') || (ch > 'z')) {
           //this will be true if ch is not an alphabet letter between 'a' and 'z'
    
    }
    
    


What to turn in: