Sunday, October 30, 2011

Program to Test if a Word is a Palindrome.

Problem: "A palindrome is a word that reads identically backward and forward, such as level or noon. Write a predicate method isPalindrome(str) that returns true if the string str is a palindrome. In addition, design and write a test program that calls isPalindrome to demonstrate that it works. In writing the program, concentrate on how to solve the problem simply rather than how to you make your solution more efficient." (Roberts ch 10, problem 6.)

What it looks like:
/* File: PalindromeTester
 * ----------------------------
 * This program lets a user enter in a string, and will respond with confirmation that the word is
 * or is not a palindrome. It uses a private boolean method isPalindrom(). This method goes 
 * halfway down each character of the word and compares to see whether that character and the
 * character at the mirror position on the string equal each other. If they don't, then break and 
 * returnn false, but if they do for all letters in the first half of the string, then return true.
 */

import acm.program.*;
 
public class PalindromeTester extends ConsoleProgram {
    public void run(){
        String str = readLine("Is it a palindrome? Enter string to test here:");
        if (isPalindrome(str)) {
            println("Yes it is!");
        }
        else println("No it isn't.");
    }
  

    private boolean isPalindrome(String str) {
        for (int i = 0; i < str.length()/2; i++) {          
            if (str.charAt(i) != str.charAt(str.length()-i-1)) {          
                return false;
            }                  
        }
        return true;
    }
}

What made it tough:

When I first wrote this, I had a bug. When checking to see if a word is a palindrome, the general approach is, for all charachters "i", to compare the "ith" character with its mirror character and see if they are equal, for all characters "i". So if your word is "kook", you'd compare the first last one to see if the characters are not the same (break if they're not), see if the two middle ones are the same, and so on.

In my buggy version, this is how I did the mirror check:
"if (str.charAt(i) != str.charAt(str.length()-i))"


This is the right version:
"if (str.charAt(i) != str.charAt(str.length()-i-1))"


Why do you have to subtract the extra 1 when you're trying inspect "i"'s mirror? In short because the "str.length" method counts starting at 1 when it returns how many characters a string contains, and meanwhile the charAt(i) method returns the "ith" character in a string, but counting as if the first letter of that string is 0. So because of this, the character at the second half of the word was actually always one after it should have been.

The funny thing is, when I wrote this and ran into the error, it didn't manifest itself via a warning in the Eclipse editor, or as red text showing up in my program's response. Instead the problem killed my program completely. I'd click to run the program, it would let me load up the interface for the user and enter in a word to test, and then instead of returning a result it would abort.

I'm sure there's a reason why my program reacted to the error in that particular way, but I'm not sure what that is. Thoughts?

Sunday, October 16, 2011

Class definition to represent playing cards


Problem:

Implement a new class called Card that includes the following entries:
* Named constants for the four suits (CLUBS, DIAMONDS, HEARTS, SPADES) and the four ranks that are traditionally represented in words (ACE, JACK, QUEEN, KING). The values of the rank constants should be 1, 11, 12, and 13, respectively.
* A constructor that takes a rank and a suit and returns a Card with those values. • Accessor methods getRank and getSuit to retrieve the rank and suit components
of a card.
* An implementation of the toString method that returns the complete name of the card as in exercise 1. Remember that you can use the + operator to connect the different parts of the string together, as shown in the toString implementation for the Rational class in Figure 6-9.

Roberts ch 6, problem 7.

/* File: Card class
 * ----------------------------
 * Class to represent a playing card. There are named constants for suit and face card values to translate integers into respective values,
 * so a client of this class can represent this information with either the integer or the constant.
 * 
 * How you'd use this class:
 * a) Create a new playing card: "myCard = new Card (12, 2)" or "myCard = new Card (Card.QUEEN, Card.HEARTS)"
 * b) Get the rank or suit of cards: "myCardSuit = myCard.getSuit()" or "myCardRank = myCard.getRank()"
 */

public class Card {
    
    public Card (int rank, int suit){ //Constructor
        cardRank = rank; // A real program would check whether "rank" is between 1 and 13, and if not, raise an illegal arguments exception
        cardSuit = suit; // A real program would check whether "rank" is between 1 and 4, and if not, raise an illegal arguments exception
    }
 
    public String getRank() {
        switch (cardRank) {
            case ACE: return "Ace";
            case JACK: return "Jack";
            case QUEEN: return "Queen";
            case KING: return "King";
            default: return Integer.toString(cardRank); 
        }
    }
   
    public String getSuit() {
        switch (cardSuit) {
            case SPADES: return "Spades";
            case HEARTS: return "Hearts";
            case CLUBS: return "Clubs";
            case DIAMONDS: return "Diamonds";
            default: return "no suit."; // Won't actually happen but Java needs it or it thinks the switch statement is incomplete
        }
    }
    
    public String toString() {
        return ("The" + getRank() + " of " + getSuit() + ".");
    }
    
    // Instance variables keep track of the suit and rank values for the lifetime of the card object
    private int cardSuit; // Keeps track of the Card object's suit
    private int cardRank; // Keeps track of the object's rank
    
    // Named Constants to establish int values for each of the suits -- Static variables are class variables
    public static final int SPADES = 1; //does this need to be "void"...?
    public static final int HEARTS = 2;
    public static final int CLUBS = 3;
    public static final int DIAMONDS = 4;
  
    // Named constants to establish int values for each of the suits 
    public static final int ACE = 1; //How does this named constant interact w/ the rest of the program? This part is a little messed up
    public static final int JACK = 11;
    public static final int QUEEN = 12;
    public static final int KING = 13;
}
This problem came before the "Employee" class problem in the book, but I definitely think it's more confusing than writing the Employee class and only really understood it after doing problem 8. At heart, the main point of both classes is to store information about an employee instance or playing card instance and let clients of the class access the information via public methods.

This one had an extra wrench thrown in because we needed to associate integers with suit or facecard values. I completed the class definition and I get now that the benefit of having the named constants is that, even though the constructor method is expecting integers for the suit and number values, you can pass the constants instead so it's a bit more human-readable.

For example, suit information for any particular card is represented in four different places:
1) In the constructor method, the client passes the suit value through as a parameter that instantly gets stored to the instance variable.
2) The instance variable that keeps track of the suit for the lifetime of the object
3) The named constants series translates suit integers into strings. ** Question: Why do we have this level of translation instead of having the constructor look for a string instead of an integer for the "suit" argument? ** From my understanding it's because it's easier to check whether ints are between 1 and 4 than to check all the different casings and spellings people might use to input a string, so it's more bug-tolerant.
4) The getSuit() method returns the current value of the cardSuit instance variable, so a client of the class can store that information in a variable of their own.

Class to represent employees

Problem:

"Write the definition for a new class named Employee that stores the following data for a single employee:
 * The name of the employee (a String)
 * The name of the employee’s supervisor (also a String)
 * The employee’s annual salary (a double)

As with the other classes defined in this book, you should make sure that the instance variables containing these values are private and instead provide get and set methods to retrieve or change any of the values." (Roberts ch 6, problem 8)

/* File: Employee
 * ----------------------------
 * Class to store information about employees, retrieve that information, and reset the information.
 * How you'd use this class:
 * a) Enter in a new employee, ie " emp = new Employee('Bob Cratchit', 'Ebenezer Scrooge', 25.00) "
 * b) get information, ie " name = emp.getName() "
 * c) set information, ie " emp.setSupervisor('Mickey Mouse') "
 */

public class Employee {
    public Employee (String name, String supervisor, double salary) { 
        //LOCAL variables. Exist just for the run of this constructor method. The client passes name/suvervisor/salary information
        // in initially and it immediately gets used to set the instnace variable value.
        employeeName = name;
        supervisorName = supervisor;
        employeeSalary = salary;
    }
    
    //Getter methods:
    
    public String getName() { 
        return employeeName;
    }
    public String getSupervisor() {
        return supervisorName;
    }
    public double getSalary() {
        return employeeSalary;
    }
    
    //Setter methods: These have no return type, they just reset the instance variables
    
    public void setName(String newName) { 
        employeeName = newName;
    }
    
    public void setSupervisor(String newSupervisor) { 
        supervisorName = newSupervisor; 
    }
    
    public void setSalary(double newSalary) { 
        employeeSalary = newSalary;
    }
    
    // INSTANCE variables: Stuff that we're keeping track of for the lifetime of the object. 
    // It gets set using the temp (aka local) variables in the constructor
    
    private String employeeName;
    private String supervisorName;
    private double employeeSalary;

}

This chapter in the book gets students started with writing their own classes. The problem was very simple, but it's good refresher on how objects work see the difference between instance variables and local variables in action.

 It took me a while to get used to the fact that each piece of information is represented 3 times:
* In the constructor method, the client of this class creates a new instance of the "Employee" class and sets the initial name, supervisor and salary values. These are passed through as local variables that exist just for the life of the constructor method and instantly get stored to the instance variable.
* Instance variables that store the name, supervisor and salary values for the lifetime of the object.
* The getter method returns the name/supervisor/salary information from the current value of the instance variable, so clients of the class can store the information in a variable of their own. The setter methods update the instance variable based on new values that the client of the class passes (using a local value that exists just for the life of the setter method).

 Once I got a firm hold on why name/supervisor/salary information is distinct when represented in the local variables versus the instance variables, I got a better understanding of how classes work and how you'd write a class that other programs can use.