/*
* Created on Jun 23, 2004
*/
package wordFinderPuzzle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import textfile.FileOrURLInputStream;
/** Read a text file which contains a representation of a word finder puzzle.
* The format of the file is as follows:
*
Line 1 contains two integers, separated by a space. These
* are number of rows (r) and number of columns (c) of the puzzle.
*
The next r lines each contain a string of exactly c characters.
* These lines represent the rows of characters of the puzzle.
*
The next line contains a single number, which is the number (w) of
* words
* which are to be looked for in the puzzle.
*
The next w lines each contain one word to be searched for.
*
Any lines beyond this are ignored.
*
For example, the following represents a 3x3 puzzle with
* two words to be searched for:
3 3
cat
ack
rtx
2
cat
act
There is a minimum number of rows and columns that a puzzle must be.
The number of rows and columns does not have to be the same.
*
* @author dickey
*/
public class WFPuzzleReader {
/** Minimum number of rows a puzzle may have. */
public static final int MIN_ROWS = 2;
/** Minimum number of columns a puzzle may have. */
public static final int MIN_COLS = 2;
/** The 2-D array of puzzle letters. */
private char[][] matrix;
/** The words to look for in the puzzle. */
private String[] words;
/** Read in a file from a file.
*
* @param fileID Identifies a file, which may be local, or may
* be a URL of a remote file. If local, the file should be on
* the classpath, in the user directory, or someplace else likely.
*
The original case of all letters and words is preserved. There
* is no check for legality of characters or words.
* @throws IOException if there is any error reading the file.
* @throws IllegalArgumentException if the file format is illegal.
*/
public WFPuzzleReader(String fileID) throws IOException {
BufferedReader puzzfile =
// FileOrURLBufferedReader.createReader(fileID);
new BufferedReader(new InputStreamReader(
new FileOrURLInputStream(fileID)));
int lineNum = 0; //how many lines of file have been read
try {
//The first line should have two numbers: 2-D array dimensions
String firstLine = puzzfile.readLine();
lineNum++;
String[] nums = firstLine.split("\\s", -1); //split on whitespace
int rowCount = Integer.parseInt(nums[0]);
if (rowCount <= MIN_ROWS) {
throw new IllegalArgumentException(
"line #" + lineNum + ": row count " + rowCount +
" must be > " + MIN_ROWS);
}
int colCount = Integer.parseInt(nums[1]);
if (colCount <= MIN_COLS) {
throw new IllegalArgumentException(
"line #" + lineNum + ": column count " + colCount +
" must be > " + MIN_COLS);
}
//Now we know how big to expect the puzzle to be
this.matrix = new char[rowCount][colCount];
for (int row = 0; row < rowCount; row++) {
String rowLine = puzzfile.readLine();
lineNum++;
if (rowLine.length() != colCount) {
throw new IllegalArgumentException(
"line #" + lineNum + " has " + rowLine.length() +
", expected " + colCount);
}
this.matrix[row] = rowLine.toCharArray();
}
//all rows of the matrix have been read in
//next line tells how many words to expect
String wCountString = puzzfile.readLine();
lineNum++;
int wCount = Integer.parseInt(wCountString);
if (wCount < 0) {
throw new IllegalArgumentException("Line " + lineNum + ": " +
"Number of words to search for " +
" must be positive: " + wCount);
}
this.words = new String[wCount];
for (int w = 0; w < wCount; w++) {
String wLine = puzzfile.readLine();
if (wLine == null) {
throw new IllegalArgumentException("Premature end of file " +
"after line " + lineNum);
}
lineNum++;
this.words[w] = wLine.trim();
}
//all expected data has been read
String extraData = puzzfile.readLine();
while (extraData != null) {
lineNum++;
System.out.println("Line " + lineNum + ": " +
" unexpected data ignored: " + extraData);
extraData = puzzfile.readLine();
}
System.out.println("Puzzle file " + fileID + " processed completely. " +
lineNum + " lines read");
System.out.println(this);
//all done, successfully
} catch (IOException e) {
System.out.println("Error reading puzzle file, line " + lineNum +
":\n\t" + e);
throw e;
}
}
/** Get the character matrix of the puzzle that was read in.
*
* @return the character matrix.
*/
public char[][] getMatrix() {
return this.matrix;
}
/** Get the list of words which are to be looked for in the puzzle.
*
* @return an array of strings, each of which represents a word
* to be looked for.
*/
public String[] getWords() {
return this.words;
}
/** Give a short summary of the puzzle that was read in.
*
*/
public String toString() {
String retVal = this.getClass().getName() + " " +
this.matrix.length + "x" + this.matrix[0].length + " matrix, " +
this.words.length + " words to find.";
return retVal;
}
}