Sunday, March 21, 2010

Binary Search Tree text file word search

Here's a program I made that will accept a text file (.txt, not Microsoft word or pdf stuff, just a basic text file) as a COMMAND LINE ARGUMENT and store each word (accepting ALL punctuation as if it were a space character, including apostrophe's) in a binary tree.  Each node in the tree stores an ArrayList which holds the number of times that word occurs(first element) and each position in the text file that it occurs (all following elements).  The user is shown the total number of words, and you can search for a word to see how many times and where in the file it is stored. Enjoy!

Just copy all these code snippets into separate text files with the same name as
the headings, compile them, and then run "java A3Driver textfile.txt", and you should see a GUI pop up.


A3Driver.java
 /**  
Assignment3
@author MasudKhan
This class is a driver for a program which reads in a file,
whose name is given as a command line argument, and stores each
word as well as how many occurences of that word and the positions of
each occurence in the text file. The program then offers to allow
the user to search for any input word and produce the info for it,
if any.
*/
import java.io.*;
import java.util.*;
public class A3Driver
{
/**
main method for Binary word search program.
*/
public static void main(String[] args)
{
WordBST newTestWordBST = new WordBST(new File(args[0]));
System.out.println("Total number of words in file: " +
WordBST.wordPosition);
System.out.println("Number of unique words in file: " +
WordBST.uniqueWordCount);
System.out.print("Most used word: " + WordBST.mostUsedWord);
System.out.println(", times used: " + WordBST.highestCount);
System.out.println("\n\n");
Scanner keyboard = new Scanner(System.in);
String input = "";
while(!input.equals("n"))
{
System.out.print("Search for word (y/n)? ");
input = keyboard.nextLine();
if(input.toLowerCase().equals("y"))
{
System.out.print("Enter word: ");
newTestWordBST.searchBinaryTree(keyboard.nextLine());
}
}
System.out.println("Thank you, goodbye.");
/**
To output all tree info, uncomment this section.
newTestWordBST.inOrderTraverse();
*/
}
}


WordBST.java
 /**  
Assignment3
@author MasudKhan
This class holds a Binary search tree of WordBSTNodes.
*/
import java.io.*;
import java.util.*;
public class WordBST
{
WordBSTNode root;
static int wordPosition, uniqueWordCount = 0, highestCount;
static String mostUsedWord;
/**
Constructor: initializes the root to null.
*/
public WordBST()
{
root = null;
}
/**
Constructor: initializes root to parameter value.
@param theRoot the root of this WordBST object
*/
public WordBST(WordBSTNode theRoot)
{
root = theRoot;
}
/**
Constructor: initializes root to hold nodes containing the words and
data from the parameter file.
@param text the input file containing words
*/
public WordBST(File text)
{
try
{
BufferedReader bR = new BufferedReader(new FileReader(text));
root = readBinaryTree(bR);
}
catch(IOException e)
{
System.out.println("Error reading file. Exiting.");
System.exit(1);
}
}
/**
Wrapper method for the recursive add method.
@param item the item to add to the BST
*/
public void add(String item)
{
root = add(root, item);
}
/**
Postcondition: uses recursion to add item to the BST node in the
appropriate position, or add information to the matching node.
@param localRoot the local node being checked in the current call
@param item the item to add to the BST
*/
private WordBSTNode add(WordBSTNode localRoot, String item)
{
if(localRoot == null) // item not in tree - add it
{
uniqueWordCount++; // total distinct word count
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(1);
temp.add(wordPosition);
return new WordBSTNode(item, temp);
}
else if(item.compareTo(localRoot.word) == 0) // item == localRootData
{
localRoot.countAndPos.set(0, localRoot.countAndPos.get(0) + 1);
localRoot.countAndPos.add(wordPosition);
if(localRoot.countAndPos.get(0) > highestCount)
{
highestCount = localRoot.countAndPos.get(0);
mostUsedWord = localRoot.word;
}
return localRoot;
}
else if(item.compareTo(localRoot.word) < 0) //item < localRootData
{
localRoot.leftTree = add(localRoot.leftTree, item);
return localRoot;
}
else // item > localRootData
{
localRoot.rightTree = add(localRoot.rightTree, item);
return localRoot;
}
}
/**
Postcondition: performs an inorder traversal.
*/
public void inOrderTraverse()
{
inOrderTraverse(root);
}
/**
Perform an inorder traversal.
@param localRoot the current node being traversed
*/
private void inOrderTraverse(WordBSTNode localRoot)
{
if(localRoot.leftTree != null) // left
{
inOrderTraverse(localRoot.leftTree);
}
// middle
//output current root
System.out.print(localRoot.word);
for(int i = 0; i < localRoot.countAndPos.size(); i++)
{
System.out.print(", " + localRoot.countAndPos.get(i));
}
System.out.println();
if(localRoot.rightTree != null) // right
{
inOrderTraverse(localRoot.rightTree);
}
}
/**
Wrapper method for searchBinaryTree recursive method.
@param searchWord the String word to search for
*/
public void searchBinaryTree(String searchWord)
{
searchBinaryTree(searchWord, root);
}
/**
Postcondition: if word is found in the search, it is output along with
occurrence information, and if it is not found, not-found info is output.
@param searchWord the word to search for
@param localRoot the localRoot being checked in the current call
*/
public void searchBinaryTree(String searchWord, WordBSTNode localRoot)
{
if( (searchWord.compareTo(localRoot.word) < 0) &&
(localRoot.leftTree != null) )
{
searchBinaryTree(searchWord, localRoot.leftTree);
}
else if( (searchWord.compareTo(localRoot.word) > 0) &&
(localRoot.rightTree != null) )
{
searchBinaryTree(searchWord, localRoot.rightTree);
}
else if(searchWord.compareTo(localRoot.word) == 0)
{
System.out.println("Position number(s) of occurence(s):");
for(int i = 1; i < localRoot.countAndPos.size(); i++)
{
System.out.println("word #" + localRoot.countAndPos.get(i));
}
System.out.println("Word found.");
System.out.println("Occurences: " +
localRoot.countAndPos.get(0));
}
else
{
System.out.println("Word does not exist.");
}
}
/**
@param bR the bufferedReader to read from
@return returns a node containing the info from the file which the input
BufferedReader is reading from
*/
public WordBSTNode readBinaryTree(BufferedReader bR)
{
String data = "";
String temp;
try
{
while(bR.ready())
{
data = data.concat(bR.readLine().toLowerCase() + "\n");
}
if(data == "")
{
return null;
}
}
catch(IOException e)
{
System.out.println("Error reading file. Exiting.");
System.exit(1);
}
return readBinaryTree(
new StringTokenizer(data,
" \t\n\r\f.,!`'-\"\\:()[]{}=+_*&^%$#@?<>;|/~"));
}
/**
@param inputST the StringTokenizer to repeatedly add words from
@return returns a node containing the info from the file which the input
BufferedReader is reading from
*/
public WordBSTNode readBinaryTree(StringTokenizer inputST)
{
wordPosition = 1;
ArrayList<Integer> tempArrayList =
new ArrayList<Integer>(wordPosition++);
tempArrayList.add(1);
WordBST tempBST = new WordBST(
new WordBSTNode(inputST.nextToken(), tempArrayList));
highestCount = 1;
mostUsedWord = tempBST.root.word;
while(inputST.hasMoreTokens())
{
tempBST.add(inputST.nextToken());
wordPosition++; // current position, and total words in file
}
return tempBST.root;
}
}


WordBSTNode.java
 /**  
Assignment3
@author MasudKhan
This class holds a node for a binary search tree. The node includes
a pointer to it's left subtree and it's right subtree, as well as String
data, and an ArrayList containing the number of occurences of the
data in the user's input file in the first position, followed by the
word number in each following position.
*/
import java.util.*;
public class WordBSTNode
{
WordBSTNode leftTree;
WordBSTNode rightTree;
String word;
ArrayList<Integer> countAndPos;
/**
Constructor: no arg constructor must never be used to avoid
confusion between a null node element and a null element content.
*/
public WordBSTNode()
{
System.out.println("Cannot creat empty node, sorry.");
}
/**
Constructor: initializes parent, word, and countAndPos instance
variables.
@param theWord the word to be stored in this node
@param theCountAndPos an ArrayList containing this node's word's
count and position's
*/
public WordBSTNode(String theWord, ArrayList<Integer> theCountAndPos)
{
leftTree = null;
rightTree = null;
word = theWord;
countAndPos = theCountAndPos;
}
}


Feedback from dev's/student dev's is welcome!

Card Match program

This is a project to do that I found in Absolute Java, a textbook for learning to program in Java. It's a card match game, where there is a set of "cards" which are turned over and the user must pick one to turn over and then try to find it's match in the rest of the cards. When a match is found, those 2 cards stay face up, and the game is over when all cards are turned over. Hope it's to your liking!

Just copy all these code snippets into separate text files with the same name as the headings, compile them, and then run "java CardMatchDemo", and the program will begin.

CardMatchDemo.java
 /**     This program will run a game called CardMatch, where the user must pick  
coordinates of 'cards' and match them to their twins, until all cards have
been matched.
It uses the CardMatch class and the Card class.
@MasudKhan
Finished: July 14, 2009
Last Updated: July 14, 2009
*/
import java.util.Scanner;
public class CardMatchDemo
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
CardMatch test = new CardMatch();
System.out.println("\t\tWelcome to CARD MATCH!");
test.shuffle();
test.allFaceDown();
int rowTemp, columnTemp;
String quit = "n";
do
{
test.displayField();
test.pickCard();
test.displayField();
rowTemp = test.getRowPick();
columnTemp = test.getColumnPick();
test.pickCard();
test.displayField();
if(test.equalCardNumber(rowTemp, columnTemp,
test.getRowPick(), test.getColumnPick()))
System.out.println("\n\t\t\t MATCH!\n");
else
{
System.out.println("\n\t\t\tNO MATCH\n");
test.setFaceDown(rowTemp, columnTemp);
test.setFaceDown(test.getRowPick(), test.getColumnPick());
}
if(test.isGameDone())
{
System.out.println("\t\t\tYOU WIN!");
System.out.println("\t\t\t QUIT?");
quit = keyboard.next();
test.shuffle();
test.allFaceDown();
}
} while(!test.isGameDone() && (quit.toLowerCase()).equals("n"));
}
}


CardMatch.java
 /**     This class uses the Card class to create a card matching game.  
It's main purpose is to store and manipulate an array that serves
as the game's playing field
*/
import java.util.Scanner;
public class CardMatch
{
private static int rowPick, columnPick;
private Card[][] field;
public CardMatch()
{
field = new Card[4][4];
fillField();
}
/**
Fills the matrix field with 16 cards with values from 1-8,
two of each.
*/
private void fillField()
{
int i, j;
for(i = 0; i < field.length; i++)
for(j = 0; j < field[i].length; j++)
field[i][j] = Card.createCard();
}
/**
Precondition: field must be initialized and filled.
Postcondition: switches the cards in the 2D array around as if
to shuffle them.
*/
public void shuffle()
{
int randomRow, randomRow2;
int randomColumn, randomColumn2;
for(int i = 0; i < 10000; i++)
{// lots of switching cards, to make sure it's well shuffled
randomRow = ((int)(Math.random() * 4)); // random # between 1-4 incl.
randomColumn = ((int)(Math.random() * 4));
Card tempCard = new Card(field[randomRow][randomColumn]); //buffer card
randomRow2 = ((int)(Math.random() * 4));
randomColumn2 = ((int)(Math.random() * 4));
// switch the card places
field[randomRow][randomColumn] = new Card(field[randomRow2][randomColumn2]);
field[randomRow2][randomColumn2] = new Card(tempCard);
}
}
/**
sets all cards to faceUp = false.
used for restarting a game.
*/
public void allFaceDown()
{
for(int i = 0; i < field.length; i++)
for(int j = 0; j < field[i].length; j++)
field[i][j].setFaceDown();
}
/**
sets all cards to faceUp = true.
used to give up on a game. Currently not in use by the program.
*/
public void allFaceUp()
{
for(int i = 0; i < field.length; i++)
for(int j = 0; j < field[i].length; j++)
field[i][j].setFaceUp();
}
/**
displays the current field of cards - MUST BE FIXED TO INCORPORATE FACEDOWN CARDS
*/
public void displayField()
{
for(int i = 0; i < field.length; i++)
{
System.out.print("\t\t\t");
for(int j = 0; j < field[i].length; j++)
{
if(field[i][j].isFaceUp())
System.out.print(field[i][j].getCardNumber() + " ");
else
System.out.print("* ");
}
System.out.println("\n");
}
}
/**
Prompts user for row and column choice for which card to flip over.
*/
private int[] inputUserPick()
{
// CREATE A SENTINEL TO QUIT
Scanner keyboard = new Scanner(System.in);
do
{
System.out.println("Enter the number of the row you choose,");
System.out.println("followed by a space, and the column.");
rowPick = keyboard.nextInt() - 1;
columnPick = keyboard.nextInt() - 1;
if(field[rowPick][columnPick].isFaceUp())
System.out.println("That one's already picked. try again.");
} while(field[rowPick][columnPick].isFaceUp());
int[] temp = new int[2];
temp[0] = rowPick;
temp[1] = columnPick;
return temp;
}
/**
User inputs coordinates of pick, and that pick is turned faceUp.
*/
public void pickCard()
{
inputUserPick();
field[rowPick][columnPick].setFaceUp();
}
/**
Returns true if faceUp = true for all cards.
Returns false otherwise.
*/
public boolean isGameDone()
{
boolean temp = true;
for(int i = 0; i < field.length; i++)
for(int j = 0; j < field[i].length; j++)
if(!field[i][j].isFaceUp())
temp = false;
return temp;
}
/**
Returns the static variable rowPick.
*/
public int getRowPick()
{
return rowPick;
}
/**
Returns the static variable columnPick.
*/
public int getColumnPick()
{
return columnPick;
}
public boolean equalCardNumber(int rowTemp, int columnTemp,
int rowCurrent, int columnCurrent)
{
return(field[rowTemp][columnTemp].getCardNumber() ==
field[rowCurrent][columnCurrent].getCardNumber());
}
/**
sets the card referred to by the argument coordinates to isFaceUp() = false.
*/
public void setFaceDown(int row, int column)
{
field[row][column].setFaceDown();
}
}


Card.java
 /**     This class stores info for an object that will be used as a  
card in a card-matching game.
*/
public class Card
{
private int cardNumber;
private boolean faceUp;
public static int cardNumberIterator = 0;
/**
This constructor should never be used. Only written to follow
style guidelines of always writing a no-arg constructor.
*/
public Card()
{
setCardNumber(0);
setFaceDown();
}
public Card(int initialCardValue)
{
setCardNumber(initialCardValue);
setFaceDown();
}
public Card(Card original)
{
setCardNumber(original.getCardNumber());
setFaceDown();
}
/**
Returns a newly created card with a value between 1 and 8,
faceDown. Also iterates the value of the next card to be
created.
*/
public static Card createCard()
{
if(Card.cardNumberIterator == 8)
Card.cardNumberIterator = 0;
Card.cardNumberIterator++;
return new Card(Card.cardNumberIterator);
}
/**
Sets cardNumber to the Value associated with the argument's value
*/
public void setCardNumber(int initialCardNumber)
{
if(initialCardNumber < 1 || initialCardNumber > 8)
{
System.out.println("Invalid card number. Exiting.");
System.exit(0);
}
cardNumber = initialCardNumber;
}
/**
sets faceUp to false
*/
public void setFaceDown()
{
faceUp = false;
}
/**
sets faceUp to true
*/
public void setFaceUp()
{
faceUp = true;
}
/**
Returns cardNumber
*/
public int getCardNumber()
{
return cardNumber;
}
/**
Returns true if faceUp is true, and false otherwise
*/
public boolean isFaceUp()
{
return faceUp;
}
}


Have fun!