import java.io.*; import java.util.*; // Programmer: Erik Krohn // Please report errors to Erik or the professor // Date: 3-31-2006 public class SpellCheck { //private Dictionary dict=new Dictionary(10501); private Dictionary smallDict = new Dictionary(5003); private Dictionary largeDict = new Dictionary(10000); public SpellCheck() throws Exception { getWords(); //puts words in dictionary check(promptUser()); //prompts user for file name and does work } public void getWords() throws Exception { //try{ BufferedReader fin = new BufferedReader(new FileReader("words.dat")); String word; for(int i = 0; i < 500; i++) { if( (word=fin.readLine()) != null ) smallDict.insert(new Record(word)); //insert word into dictionary } while((word=fin.readLine())!=null){ largeDict.insert(new Record(word)); //insert word into dictionary } //} catch(Exception e){ // System.out.println(e); //} //insert a and i into dictionary smallDict.insert(new Record("a")); smallDict.insert(new Record("i")); } //read in file names public String getInput(){ try{ BufferedReader fin = new BufferedReader(new InputStreamReader(System.in)); return fin.readLine(); } catch(Exception e){ System.out.println(e); } return null; } //ask user for files public String promptUser(){ System.out.print("Enter source file to spell check: "); return getInput(); } public Record searchDictionary(String word) { Record result = null; if( (result = smallDict.search(word)) != null ) return result; else return largeDict.search(word); } public void check(String file) throws Exception { try{ BufferedReader fin = new BufferedReader(new FileReader(file)); PrintWriter fout = new PrintWriter(new FileWriter(file+".out")); String line; String word = ""; String newLine = ""; char ch; //Get each line of file while((line=fin.readLine())!=null){ /*************** * The basic algorithm for this is: * 0. Keep track of the newLine to print out * 1. Read in a character until you have a word. Check if word is in the dictionary, if in the dictionary * but needs a replacement, add replacement to newLine otherwise add work to newLine along with ch (to correspond to ' or , or . etc.) * 2. If word is not in dictionary. * a. replace - add replaced word to newLine * b. replaceAll - add replacement to dictionary with word (as a lower case) as the key * c. ignore - add original word to newLine * d. ignoreAll - add word to dictionary and add to newLine * e. abort - delete file and quit * 3. Print off newLine and repeat until no new lines ******************/ for (int i = 0; i <= line.length(); i++) { ch = ' '; if(i < line.length()) ch = line.charAt(i); // word is being constructed if (Character.isLetter(ch) || (ch == '\047' && word.length() != 0)) { word = word + ch; } else if (word.length() != 0) { //word not found in dictionary as is, need to change to lowercase and search Record found = searchDictionary(word.toLowerCase()); if (found != null) { if (found.replacement == null) { //add work to line newLine += word; } else { //add replacement to newline newLine += found.replacement; } } else { //word not in dictionary at all int redo = 0; while (redo == 0) { String x = alert(word).toLowerCase(); if (x.length() > 0) { char toDo = x.charAt(0); redo = 1; //only for incorrect input switch (toDo) { case 'r': //replace word //System.out.print("Please enter a replacement > "); // Sriram: word needs to be turned into lower case // before we get replacement words word = getReplacementWord(word.toLowerCase()); newLine += word; //replace wrong word break; case 'i': //do nothing, simply ignoring word newLine += word; break; case 'n': //ignore all //add word to our dictionary Record temp = new Record(word.toLowerCase()); largeDict.insert(temp); newLine += word; break; case 'a': //aborting fout.close(); fin.close(); new File(file + ".out").delete(); System.out.println("Aborted"); System.exit(0); case 'p': //replace all, add to dictionary String replace; //System.out.print("Please enter a replacement > "); // Sriram: word needs to be turned into lower case // before we get replacement word replace = getReplacementWord(word.toLowerCase()); temp = new Record(word.toLowerCase()); temp.replacement = replace; //create a new record with word as the key largeDict.insert(temp); newLine += replace; break; default: System.out.println("Invalid input, please choose correctly!"); redo = 0; } } else System.out.println("Invalid input, please choose correctly!"); } // end of while-redo } // end of if-word-not-found //reset word and add character that followed the word word = ""; if(i < line.length()) newLine += ch; } else { //add character to newLine. for example, "I went to the store, and bought a beverage." //This is so we include the space after the comma if(i < line.length()) newLine += ch; } } //print off our line fout.print(newLine); fout.print("\n"); newLine = ""; } fout.close(); fin.close(); } catch(Exception e){ System.out.println(e); } } public String alert(String word){ //Offer options for unknown word System.out.println("\nThe word: \""+word+"\" is unknown."); System.out.print("Do you want to replace (R), replace all (P), ignore (I), ignore all (N), or abort (A)? > "); try{ return getInput(); } catch(Exception e){}; return null; } public String getReplacementWord(String word) { String [] words = getWords(word); int i; for(i = 0; i < words.length; i++) { if(words[i] == null) break; System.out.println("("+i+") "+words[i]); } System.out.println("("+i+") Use my replacement"); boolean done = false; int num = 0; while(!done) { String reply = getInput(); // Sriram: reply could be 0 through 10. So reading a char // is not enough - an int has to be read num = Integer.parseInt(reply); if( num >= 0 && num <= i) { done = true; } else { System.out.println("Invalid entry: try again."); } } // Sriram: If num equals i then the user is going to enter // her own rerplacement; otherwise we pick a replacement from // the generated replacement String result; if(num == i) { System.out.println("Enter your replacement word: "); result = getInput(); } // Added by Sriram else result = words[num]; return result; } public boolean isWord(String s) { if( smallDict.search(s) == null ) if( largeDict.search(s) == null ) return false; return true; } public boolean contains(String [] array, String s) { for(int i = 0; i < array.length; i++) { if(array[i] == null) return false; if(s.equals(array[i])) return true; } return false; } public String [] getWords(String word) { int replacementCount = 0; String [] replacements = new String[10]; String [] onehop = new String[numNeighbors(word.length())]; String [] twohop; fillArray(onehop, word, 0); // Scan the one hops array before wasting time on two hops for(int i = 0; i < onehop.length; i++) { if( isWord(onehop[i]) && !contains(replacements, onehop[i])) { replacements[replacementCount++] = onehop[i]; if(replacementCount == 10) return replacements; } } // for each word in the one hops array, get its neighbors and // check them before getting the neighbors of any other words. for(int i = 0; i < onehop.length; i++) { twohop = new String[numNeighbors(onehop[i].length())]; fillArray(twohop, onehop[i], 0); for(int j = 0; j < twohop.length; j++) { if( isWord(twohop[j]) && !contains(replacements, twohop[j])) { replacements[replacementCount++] = twohop[j]; if(replacementCount == 10) return replacements; } } } return replacements; } public int fillArray(String [] S, String word, int index) { String [] S1 = extraLetter(word); String [] S2 = swapLetter(word); String [] S3 = substituteLetter(word); String [] S4 = missingLetter(word); for(int i = 0; i < S1.length; i++) S[index++] = S1[i]; for(int i = 0; i < S2.length; i++) S[index++] = S2[i]; for(int i = 0; i < S3.length; i++) S[index++] = S3[i]; for(int i = 0; i < S4.length; i++) S[index++] = S4[i]; return index; } public int numNeighbors(int n) { //n-1 + n + (n+1)*26 + n*26; return 54*n + 25; } public String [] extraLetter(String word) { String [] result = new String[(word.length()+1)*26]; for(int i = 0; i < word.length()+1; i++) { for(int j = 0; j < 26; j++) { result[(i*26)+j] = word.substring(0,i) + (char)(j + 'a') + word.substring(i); } } return result; } public String [] swapLetter(String word) { String [] result = new String[word.length()-1]; for(int i = 0; i < word.length()-1; i++) { result[i] = word.substring(0,i) + word.charAt(i+1) + word.charAt(i) + word.substring(i+2); } return result; } public String [] substituteLetter(String word) { String [] result = new String[26 * word.length()]; for(int i = 0; i < word.length(); i++) { for(int j = 0; j < 26; j++) { result[26*i + j] = word.substring(0,i) + (char)('a' + j) + word.substring(i+1); } } return result; } public String [] missingLetter(String word) { String [] result = new String[word.length()]; for(int i = 0; i < word.length(); i++) { result[i] = word.substring(0,i) + word.substring(i+1); } return result; } public static void main(String[] args) throws Exception { new SpellCheck(); } }