/*
 * 2004 Utah High School Programming Contest, University of Utah
 * Take-Home Problem
 *
 * Search.java
 *
 * This file contains the implementation of the Search class.
 */

/**
 * A Search object is responsible for implementing a search strategy to find
 * the best decryption cipher for a Puzzle.  The Search `findCipher' method
 * creates Cipher objects and passes each one to a Puzzle object, which is
 * responsible for evaluating each cipher individually.  The `findCipher'
 * method keeps track of the best cipher and returns it.
 *
 * In sum, Search is responsible for deciding what ciphers to test, and in what
 * order.  Other objects are responsible for actually applying a cipher to a
 * cryptogram (this is done by a Cipher) and evaluating the quality of the
 * result (done by a Puzzle).
 */
class Search {
    /**
     * The Puzzle that describes the cryptogram we are trying to solve.
     */
    private final Puzzle puzzle;
    
    /**
     * Construct a Search object to manage the search for the cipher that
     * decrypts a given cryptogram Puzzle.
     *
     * @param thePuzzle    the Puzzle to be solved
     */
    Search(Puzzle thePuzzle) {
        this.puzzle = thePuzzle;
    }
    
    /**
     * Find and return the Cipher object that best decrypts the cryptogram
     * Puzzle.
     *
     * @return    the Cipher that best decrypts the puzzle
     */
    public Cipher findCipher() {
        Cipher bestCipher = null; // The best decryption cipher found so far.
        int bestCipherScore = 0;  // The "score" of that best cipher.
        
        // TODO: Search for SubstitutitionCiphers.
        //
        // The current search algorithm only handles rotation ciphers, but it
        // needs to handle substitution ciphers as well.  You will need to
        // design a completely new strategy for searching for substitution
        // ciphers --- there are far too many possible substitution ciphers for
        // your program to generate and test them all.
        
        // Generate and test all of the possible rotation ciphers.
        //
        for (int i = 0; i < 26; ++i) {
            Cipher thisCipher = new RotationCipher(i);
            int thisCipherScore = this.puzzle.testCipher(thisCipher);
            
            if ((bestCipher == null) || (thisCipherScore > bestCipherScore)) {
                bestCipher = thisCipher;
                bestCipherScore = thisCipherScore;
            }
        }
        return bestCipher;
    }
}

// End of file.

