Thursday, December 29, 2011

Program to Make the Plural of a Word

Problem:

Write a method regularPluralForm(word) that returns the plural of word formed by following these standard English rules:

a) If the word ends in s, x, z, ch, or sh, add es to the word. 
b) If the word ends in y and the y is preceded by a consonant, change the y to ies. 
c) In all other cases, add just an s.
Write a test program and design a set of test cases to verify that your program works.

(Roberts ch 10, problem 7).

What it looks like:

/*File: MakePlural.java
 * ---------------------
 * This program lets the user enter in any word and it will print out the plural form according to the basic,
 * not totally comprehensive rules outlined in the problem from ch. 10. It makes use of the private methods
 * makePlural (which take in a string and returns another string, the plural form of the word).
 */
import acm.program.ConsoleProgram;
public class MakePlural extends ConsoleProgram {
    public void run() {
       while (true){
           String word = readLine("Enter word and we'll make it plural. Enter '0' to stop: ");
           if (word.equals("0")){
               break;
           }
       print(makePlural(word) + " ");
       }
    }
    
    //Takes the submitted string, inspects the last letter (or last 2 letters in case of "ch" and "sh"),
    //and returns the appropriate plural form.
    private String makePlural (String singularWord){
        String pluralWord = "";
        String strippedWord = singularWord.substring(0, singularWord.length()-1);
        char lastLetter = singularWord.charAt(singularWord.length()-1);
        switch (lastLetter){
            case 's':
            case 'x':
            case 'z':
                pluralWord = singularWord + "es";
                break;
            case 'h': // checking for if the word ends with "ch" or "sh"
                if ((singularWord.charAt(singularWord.length()-2)== 'c') || (singularWord.charAt(singularWord.length()-2)== 's')) {
                    pluralWord = singularWord + "es";
                    break;
                } 
            case 'y':
                if (isEnglishConsonant(singularWord.charAt(singularWord.length()-2))) {
                    pluralWord = strippedWord + "ies";
                    break;
                }
            default: pluralWord = singularWord + "s";
            break;
        }
        return pluralWord;
    }
    private boolean isEnglishConsonant(char ch) {
        switch (Character.toLowerCase(ch)) {
            case 'a': case 'e': case 'i': case 'o': case 'u': 
                return false;
            default: 
                return true;
        }
    }
}





What made it tricky:


The program is structured to work well as a "switch" statement, and I had wanted to create a neat table that took a substring "lastLetter" (last 2 letters in the case of "ch" and "sh") and neatly return the proper plural form.  However you can't switch on a string as I learned-- damn! So had to use the character only and switch on that, which made checking for "ch" and "sh" slightly less convenient.


Come to think of it, why *can't* you switch on a string? You'd think that it's a similar situation to comparing strings via "if (s1 == s2)", namely that it would often give you the wrong answer since they're comparing actual objects, not values. However I got an error when I attempted...anyone know why?


Another bug I ran into came from attempting to inspect the last letter and second-to-last-letter by doing charAt(-1) or charAt(-2) and making a substring of all but the last letter of the original word by doing "singularWord.substring(0, -1)". Those were throwing out-of-bounds errors. Oops-- sure would have been convenient.


The main bug I got stuck on before it worked is that it kept giving me the default case. So "sky" gave me "skys", "box" gave me "boxs" etc. I didn't know why and whether the non-default case was even getting run so I added debugging lines to print out the plural form as soon as it gets run.






It appeared that the special cases were getting run, but the default was getting run every time. Why?


I suppose I needed to add "break" statements to my special cases in the "switch" statement. I looked up confirmation for this in the text and this is what it said:


"Java is defined so that if the break statement is missing, the program starts executing statements from the next clause after it finishes the selected one. While this design can be useful in some cases, it tends to cause more problems than it solves. To reinforce the importance of remembering to include the break statement, every case clause in this text ends with an explicit break statement (or sometimes with a return statement, as discussed in Chapter 5)."


That kind of makes sense... depending on what the syntax means when it checks for "default," it's posible that "default" means every single case *in addition to* the special cases that do apply. So yes, once I did add a "break" statement to each case, the problem worked correctly.


It's weird though because one example in the book does a simple switch statement with a default, but does not have a break statement after the special cases:

private boolean isEnglishVowel(char ch) {
     switch (Character.toLowerCase(ch)) {
         case 'a': case 'e': case 'i': case 'o': case 'u':
            return true;
         default: 
            return false;
    }
}   
I can confirm that this private method works correctly since I used it in my own program. So I'm not quite sure when a break statement is required. I do realize that the author may not have meant to include a confusing example in the final version of the book, so I'll check this PDF against my hard copy when I'm back home. Any ideas on this switch statement conundrum however?

Wednesday, December 28, 2011

Program to Determine the Ordinal Value of a Number

Problem:
Like most other languages, English include two types of numbers: cardinal numbers (such as one, two, three, and four) that are used in counting, and ordinal numbers (such as first, second, third, and fourth) that are used to indicate a position in a sequence. In numeric form, ordinals are usually indicated by writing the digits in the number, followed by the last two letters of the English word that names the corresponding ordinal. Thus, the ordinal numbers first, second, third, and fourth often appear in print as 1st, 2nd, 3rd, and 4th.
The general rule for determining the suffix of an ordinal can be defined as follows:
Numbers ending in the digit 1, 2, and 3, take the suffixes "st", "nd", and "rd", respectively, unless the number ends with the two- digit combination 11, 12, or 13. Those numbers, and any numbers not ending with a 1, 2, or 3, take the suffix "th".
Your task in this problem is to write a function ordinalForm(n) that takes an integer n and returns a string indicating the corresponding ordinal number.  (Roberts ch 10, problem 9).


What it looks like:

/* File: ordinalForm.java
 * -----------------
 *This console program lets the user enter in any integer and will print out the ordinal form of that number. For example
 *the ordinal form of 1 is "1st," 2 is "2nd" etc. The user enters the sentinel value "-1" to stop running the program.
 *
 *The program and the method of the same name takes an integer as the entered value and returns a string. We use the ACM library's (?)
 *built-in Integer class and its toString method. Because the suffix of an ordinal value depends on the last digit
 *of a number our program has to strip out and inspect the last digit of the supplied integer so we use the method 
 *"getLastDigit" to inspect the last digit. In the case of numbers ending with "11", "12" and "13" we need to see the last
 **two* digits so we also use a similiarly-constructed getSecondToLastDigit.
 */
import acm.program.ConsoleProgram;
public class ordinalForm extends ConsoleProgram {
    public void run() {
       while (true){
       int cardinal = readInt("Enter number and we'll give you the ordinal form: ");
       if (cardinal == -1){
           break;
       }
       print(makeOrdinal(cardinal));
       }
    }
    private String makeOrdinal(int n) {
        String ordinal = "";
        int lastDigit = getLastDigit(n);
        int secondToLastDigit = getSecondToLastDigit(n);
        if ((lastDigit == 1) && secondToLastDigit !=(1)){
            ordinal = Integer.toString(n) + "st"; //Not sure why it's "Integer.toString(n)" instead of "n.toString" or "toString(n)"
        }
        else if (lastDigit ==2 && secondToLastDigit !=(1)) {
            ordinal = Integer.toString(n) + "nd"; 
        }
        else if (lastDigit == 3 && secondToLastDigit !=(1)) {
            ordinal = Integer.toString(n) + "rd";
        }
        else ordinal = Integer.toString(n) + "th";
        return ordinal;
    }
    private int getLastDigit(int n) {
        int remainder = n % 10;
        return remainder;
    }
    
    private int getSecondToLastDigit(int n) {
        int remainder = 0;
        for (int i = 0; i < 2; i++){
            remainder = n % 10;
            n /= 10;
        }
        return remainder;
    }
}
}








What made it tricky:


My first version of this was running just fine....it just kept returning the wrong answer. Have a look at this sample run when the bug existed and guess what the problem was:



Here's a clue: this is what my private methods getSecondToLastDigit(n) and getLastDigit(n) looked like:

    private int getLastDigit(int n) {
        int remainder = 0;
        while (n > 0) {
            remainder = n % 10;
            n /= 10;
        }
        return remainder;
    }

    private int getSecondToLastDigit(int n) {
        int remainder = 0;
        while (n > 10) {
            remainder = n % 10;
            n /= 10;
        }
        return remainder;
    }
So while getLastDigit(n) should have just divided by n *once* and returned the remainder, instead it kept dividing by n until there was nothing left. So it was really stripping off and returning the *first* digit, not the last! getSecondToLastDigit(n) was behaving the same way, except it stopped one iteration sooner so it returned the second digit, not the second-to-last. Ugh, so embarrassing, blame it on the Christmas food abundance.

I didn't see the pattern or understand what was wrong for a while so I made this quick debugging program that printed out the results of just getLastDigit(n):

import acm.program.ConsoleProgram;
public class testLastDigit extends ConsoleProgram {
    public void run() {
       int n = readInt("Enter an int and we'll give you the last digit");
       print (getLastDigit(n));
    }
    private int getLastDigit(int n) {
        int remainder = 0;
        while (n > 0) {
            remainder = n % 10;
            n /= 10;
        }
        return remainder;

    }
}
I ran it a bunch of times and saw that indeed, testLastDigit  was giving me the wrong answer. Once I saw that it was wrong and predictably wrong, the fix was easy.


Saturday, December 17, 2011

Program to Search for a Substring inside a String

Problem: If the designers of the String class had not defined the version of indexOf that takes a string argument, you could implement it using the other methods available in the library. Without calling indexOf directly, implement a method myIndexOf that behaves in exactly the same way.


What it looks like:




/* File: myIndexOfTester.java
 * ---------------
 * This program has a run method that lets the user enter in a (supposed to be) big string and a
 * little string. Then it uses the private method myIndexOf to see whether the little string exists
 * inside the big string and if so, return the index within the big string that the little string
 * exists at.
 * 
 * There is already an indexOf method in Java's standard String class, but the Stanford folks 
 * thought it would be good for us to try implementing it ourselves with other methods in the
 * String class.
 */
import acm.program.*;
public class myIndexOfTester extends ConsoleProgram {
    public void run() {
       String enteredString = readLine("Enter a string: ");
       String searchedForString = readLine("Enter the string you're searching for inside it: ");
       print(myIndexOf(searchedForString, enteredString));
    }
    private int myIndexOf(String littleString, String bigString) {
//"Real" program would check that littleString is longer than bigString & raise and exception of it weren't

//For every letter in bigString MINUS the length of littleString (to guard against out-of-bounds
//errors), check if littleString equals the segment of bigString that starts at that index.
        for (int i = 0; i < bigString.length()-1-littleString.length()-1; i++) {      
            if (littleString.equals(bigString.substring(i, i+littleString.length() ))) {
                return i;
            }           
        }
        return -1; //Signifies that littleString doesn't exist inside bigString         
    }
}




The basic gist of this problem, or at least my approach to it, is you want to take your little string and compare it to substrings inside the big string. In particular, you want to iterate through each letter of the big string and carve out a substring starting at that index and of an equal length to the little string. If they are equivalent, then return the index. If you never get an equivalency, then return -1 (as is the existing convention).


What made it tricky: Two things! 1) Off-by-one errors, and 2) Out-of-bounds errors.


** Off-by-one Errors **


Let's say your big string is "HELLO WORLD". This string has 11 characters, including the space, so the method bigString.length() would return 11. If you iterated from 0 to 11, however, your last iteration would be looking at nothing since there's no character at space "11"! Therefore, you have to make the outer bound of your loop is the length of the big string minus one.




** Out-of-bounds Errors **


Let's say your big string is "HELLO", and the little string you're inspecting "HELLO" for is "HI." You go thru every letter in "HELLO," seeing if the 2-letter substring at that letter is equivalent to "HI".


However, what happens on the last couple of iterations of your loop? If your index is the letter "O" in "HELLO", you're comparing "HI" with "O" and then nothing! To keep this from happening, you need to stop your comparisons so that all the letters in "HI" have something in the string "HELLO" to get compared to.






The last tricky thing is, the problem specified that the method has to behave the *same* way as the existing indexOf. That takes in just one argument (the little string) and you apply it to the big string. My implementation takes in both the big string and the little string as arguments, so I had been worried that I hadn't actually solved the requirement. 


However, how is it possible to write your own implementation as a method by itself without "knowing" the length of the big string? Not sure whether this is do-able.... I checked the textbook to see whether the authors printed this problem. (I have to confess that I've been studying with a PDF of the pre-print copy of the textbook since it's easier to have on hand, and I leave the heavy text at home). I saw that the printed version omitted this problem, so I'm assuming that the editors decided that it wasn't quite a perfectly designed problem because of that mismatch. Thoughts?

Monday, December 12, 2011

Program to Calculate the Scrabble Score of a Word

Problem:
In most word games, each letter in a word is scored according to its point value, which is inversely proportional to its frequency in English words. In ScrabbleTM, the points are allocated as follows:

For example, the Scrabble word "FARM" is worth 9 points: 4 for the F, 1 each for the A and the R, and 3 for the M. Write a ConsoleProgram that reads in words and prints out their score in Scrabble, not counting any of the other bonuses that occur in the game. You should ignore any characters other than uppercase letters in computing the score. In particular, lowercase letters are assumed to represent blank tiles, which can stand for any letter but which have a score of 0. (Robers ch 9, problem 5)

What it looks like:


/* File: ScrabbleCalc
 * -----------------
 * This program takes in an arbitrary word from the end-user and calculates its value according to the points alloted
 * to each letter by the game Scrabble. Characters must be upper-case; lowercase letters are ignored.
 * 
 * The program makes use of the private method 'scabbleScore' that takes in the input string and iterates through
 * each charcter. The method also establishes the integer 'score,' an instance variable that keeps track of the
 * accumulating points for the word. In each loop, it asses character via a switch statement and adds the appropriate 
 * points value for the character to 'score.'
 */
import acm.program.*;
public class ScrabbleCalc extends ConsoleProgram {
    public void run() {
       String word = readLine("Enter Scrabble word (all in uppercase) and we'll calculate your score: ");
       print(scrabbleScore(word));
    }
    private int scrabbleScore(String scrabbleWord) {
        int score = 0;
        for (int i = 0; i < scrabbleWord.length(); i++){
            char calculatedLetter = scrabbleWord.charAt(i);
            switch (calculatedLetter) {
                case 'A':
                case 'E':
                case 'I':
                case 'L':
                case 'N':
                case 'O':
                case 'R':
                case 'S':
                case 'T':
                case 'U': //Jesus this is fugly
                    score +=1; break;
                case 'D':
                case 'G':
                    score +=2; break;
                case 'B':
                case 'C':
                case 'M':
                case 'P':
                    score +=3; break;
                case 'F':
                case 'H':
                case 'V':
                case 'W':
                case 'Y':
                    score +=4; break;
                case 'K':
                    score +=5; break;
                case 'J':
                case 'X':
                    score +=8; break;
                case 'Q':
                case 'Z':
                    score +=10; break;
                default: break;
            }
        }
        return score;
    }
}

What made it tricky:

Whenever I tell other programmers I'm learning programming with Java, they express much exasperation about the language, and I begin to see why. The statement that I had wanted to express was,  "If the letter at increment "i" is A, E, I, L, etc, then add 1 to the instance variable "score." I was looking for the switch statement to support an "or" statement (ie "case 'A' || 'E' || 'I' || 'L' ") but alas, the syntax isn't that neat. I had to list all the separate cases individually, though fortunately I didn't have to do the action block repeatedly for cases with identical points! I don't exactly know how you'd handle this in Python or Ruby but I expect it would be more succinct.
I think if building a Scrabble calculator in the "real world," you'd want to use a hash table  to easily turn the letter:points match into key:value pairs. We haven't gotten to hashes and arrays yet, so the tools for this problem were either a) switch statements or b) cascading "if" statements.

Saturday, November 12, 2011

Program to Create Five Random "Words"

Problem: Write a method randomWord that returns a randomly constructed “word” consisting of randomly chosen letters. The number of letters in the word should also be chosen randomly by picking a number between the values of the named constants MIN_LETTERS and MAX_LETTERS. Write a ConsoleProgram that tests your method by displaying five random words. (Roberts ch 10, problem 2).

What it looks like:



/* File: fiveRandomWords
 * --------------
 * This program generates random "words," just random letters stuck together. The characters of the word are 
 * random, but must be an upcase letter-- these are integers that correspond to the ASCII characters of the 
 * upcase alphabet. The length of the word is also random, but bounded by the constants MIN_LETTERS and
 * MAX_LETTERS.
 * 
 * The run method of the program simply starts of with blank String instance and keeps pulling random letters
 * out of the random generator until the word length is reached. It relies on a private method to generate the 
 * random characters and to set the word length.
 */

import acm.program.*;
import acm.util.RandomGenerator;

public class FiveRandomWords extends ConsoleProgram { 
    public void run() {
        for (int i = 0; i < 5; i++) {
            int wordLength = rgen.nextInt(MIN_LETTERS, MAX_LETTERS);
            String myRandomWord = " ";
            for (int j = 0; j < wordLength; j++) {
                myRandomWord += randomLetter();
            }
            println(myRandomWord);
        }
    }
    
    private char randomLetter() { 
        return (char) rgen.nextInt((int) 'A', (int) 'Z');
    }
    private RandomGenerator rgen = RandomGenerator.getInstance();
    private static final int MIN_LETTERS = 3;
    private static final int MAX_LETTERS = 10;
}
What made it tough:

This simple problem is all about getting comfortable with scalar types: data values that can be represented as numbers. The key snippet in the program is this:

 private char randomLetter() { 
        return (char) rgen.nextInt((int) 'A', (int) 'Z');
    }

How do you return a *character* that's random but bounded by the *integers* A and Z? Because the "char" data type in Java maps directly to Unicode and ASCII. Unicode and ASCII are both systems that match characters (letters, punctuations marks, etc) to integers so that it's easier for the computer to understand. 

Fun facts I learned: 
  • Precursors to ASCII literally mapped 'A' to 1, 'Z' to 26, and everything in-between, but ASCII didn't do so since there are additional characters that precede letters. 
  • The ASCII system came first, Unicode second. ASCII characters don't encode most non-Western characters, so Unicode was created with thousands of new characters to account for these.
  • Unicode contains everything that's in ASCII, and to be completely backwards-compatible, the first 128 digits of Unicode map directly to ASCII


Because characters are mapped this way, you can perform some numeric operations on *letters* as specifying a range like I did above, or taking a letter 'A' and adding 5 to get 'F.'  When specifying the range of characters, you could either provide the character or the number equivalent-- the computer can handle each one and in fact the (int) cast isn't necessary- it's there to make things clearer for humans so they don't think, "Why are you bounding nextInt with characters?" You must specify the (char) cast however to make sure that when you do rgen.nextInt, you get a letter back, not a number.


Program to Create Acronyms

This came from the book as an example, but I wanted to make it better :)

This program, taken from the unit in the book that deals with characters and string manipulation, lets the user input a string (usually a sentence of multiple words) and get an acronym back. The method that builds the acronym works by taking the very first character, and after that, hunting for space characters. It looks at the character right *after* each space and slices that following character to add to the acronym.

There is a bug however-- what happens if the user enters in "hello**world" (say that "*" is a space here)? The acronym SHOULD be "hw", but instead you get "h*w." No good.

I wrote a program, first to test out the buggy method to verify what the acronym for "hello**world" would be, and then to fix that edge case.

What it looks like:



/* File: acronymBuilder
* --------------------
* This program takes a string and returns the acronym, or, a string made up of the first character of each
* word. It works via a private method that takes the first character and saves it to the instance variable
* "result." Then it finds each space, takes the character directly after the space, and takes that following 
* character and appends it to "result" until there are no spaces left.
* 
* This method originally appeared in ch 10 of Roberts' "The Art and Science of Java," but the original method
* didn't account for inputs where there were 2 spaces in a row, so I'm making the modification and writing a
* run method to use it.
 */
import acm.program.*;
 
public class acronymBuilder extends ConsoleProgram {
    public void run(){
        String initialString = readLine("Enter a string you want to generate the acronym for:");
        String result = acronym(initialString);
        println(result);
    }
    
    private String acronym(String str) {
        String result = str.substring(0, 1); 
        int pos = str.indexOf(' '); 
        while (pos != -1) {
            if (str.charAt(pos + 1) != ' ') { 
                result += str.substring(pos + 1, pos + 2); 
            }
            pos = str.indexOf(' ', pos + 1); //Finds the next space sign           
        } 
    return result;
    }
}
What made it tough: There were a couple bugs that stumped me along the way.
First, I wanted to write an "if" statement checking to see if there are two space signs in a row. Specifically, you look at a space sign and see if the character after it is also a space sign. The "if" statement looked like this:

if (str.charAt(pos + 1) != " ");

Eclipse highlighted this statement in red and did not like it. Why?

My first thought was because of that problem that you can't compare strings with each other. The "==" and "!=" operators are mathematical comparisons that you can only use on primitives like ints, whereas for strings that operator will examine the underlying object in memory that stores the string; it won't examine the value.

But wait a minute, that can't be it. First of all, comparing strings is technically a valid argument...it will just usually return an inaccurate result. Like if there were two strings "hello" and "hello" that pointed to two different objects, it will return "False" when the developer probably wanted it to return "True". 

Also, str.charAt(pos + 1)is actually a char, not a string, and chars are primitives, so it should be OK to use the "!=" on it.

The problem was that the second part of my comparison, " ", is a string, so I was comparing a char against a string which isn't ok. All I had to do to fix it was put the space sign in single quotes, since Java denotes chars with single quotes. Easy :)

The second bug came up as I tried to run the program. This is what the code looked like at that point:

import acm.program.*;
 
public class acronymBuilder extends ConsoleProgram {
    public void run(){
        String initialString = readLine("Enter a string you want to generate the acronym for:");
        String result = acronym(initialString);
        println(result);
    }
    
    private String acronym(String str) {
        String result = str.substring(0, 1); 
        int pos = str.indexOf(' '); 
        while (pos != -1) {
            if (str.charAt(pos + 1) != ' ') { 
                result += str.substring(pos + 1, pos + 2); 
                pos = str.indexOf(' ', pos + 1); //Finds the next space sign
            }
        } 
    return result;
    }
}
When I ran the code, it compiled and I input the string "ne**s****w". (There were no "*" signs really, I just used them to demonstrate) where spaces were. When I hit "return", the program didn't print anything! Why?

At first I thought there was an unclosed loop or something, but then I realized: I had inserted an "if" statement checking for if the character following the space sign is NOT another space, but I didn't tell the program what to do if that following character WAS a space! The direction to move on to the next space sign (ie "pos = str.indexOf(' ', pos + 1)" was inside the new "if" statement! Once I adjusted the stuff in my loops I was fine.

Strange though-- on that second bug, my return statement WAS outside the "if" statement, and I had already initiated "result", so why didn't my program atleast print the first character...?

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?