package com.madbean.kata8.readable; import java.io.File; import java.io.IOException; import java.io.BufferedReader; import java.io.FileReader; import java.util.BitSet; /** * An AbstractAlgorithm for finding pairs of words that, when * concatenated, form another word (called the 'result' word). * * @author Matt Quail */ public abstract class BaseAlg { private File wordlistFile; private boolean ignoreCase = true; /** * If bit 'i' is set, then we are interested in 'result' * words of length 'i'. */ private final BitSet resultWordLengths = new BitSet(); private int matchingWords = 0; /** the number of 'result' words */ public int getMatchingWords() { return matchingWords; } public File getWordlistFile() { return wordlistFile; } public void setWordlistFile(File aWordlistFile) { wordlistFile = aWordlistFile; } /** * Indicates that we are interested in result words of length 'length' */ public void addResultWordLength(int length) { resultWordLengths.set(length); } /** * Indicates that we are NOT interested in result words of length 'length' */ public void removeResultWordLength(int length) { resultWordLengths.clear(length); } /** * @return true if we are interested in result words of length 'length' */ public boolean isValidResultWordLength(int length) { return resultWordLengths.get(length); } /** * Reads the words in, and calls {@link #addWord} for each word */ public void readwords() throws IOException { // every line in the file is a word, just read them in BufferedReader in = new BufferedReader(new FileReader(wordlistFile)); String word; while (null != (word = in.readLine())) { if (ignoreCase) { word = word.toLowerCase(); } addWord(word); } in.close(); } /** * Subclasses must provide their own storage mechanism for words */ public abstract void addWord(String aWord); /** * Subclasses must provide a way for iterating over potential * result words. For each word, this method must call * {@link #generateSubstrings}. */ public abstract void iterateOverPotentialResultWords(); /** * @return true if both paramaters are valid words */ public abstract boolean validWords(String aLeadingWord, String aTrailingWord); /** * Generates all combinations of leading/trailing substrings, and calls * {@link #validWords} to determine if they are words themselves. * * @param word must have a length that is a valid result-word length. */ public void generateSubstrings(String word) { // look at the leading substrings of 'word' (and the // corresponding trailing substring), and see if said // leading and trailing substrings are actual words final int leadingMinLen = 1; final int leadingMaxLen = word.length() - 1; for (int leadingSize = leadingMinLen; leadingSize <= leadingMaxLen; leadingSize++) { String leadingWord = word.substring(0, leadingSize); String trailingWord = word.substring(leadingSize); if (validWords(leadingWord, trailingWord)) { // 'word' is the concatenation of 'leadingWord' and 'trailingWord' System.out.println(leadingWord + " + " + trailingWord + " = " + word); matchingWords ++; } } } }