/* Useful imports */ import edu.neu.ccs.*; import edu.neu.ccs.gui.*; import edu.neu.ccs.codec.*; import edu.neu.ccs.console.*; import edu.neu.ccs.filter.*; import edu.neu.ccs.jpf.*; import edu.neu.ccs.parser.*; import edu.neu.ccs.pedagogy.*; import edu.neu.ccs.quick.*; import edu.neu.ccs.util.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.font.*; import java.awt.image.*; import javax.swing.*; import javax.swing.border.*; import java.io.*; import java.util.*; import java.math.*; import java.beans.*; import java.lang.reflect.*; import java.net.URL; import java.util.regex.*; import java.text.ParseException; public class SudokuHint implements Comparable { // Static definitions // /** The bits for computing the hash. */ private static int[] bits = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 }; /** The digits for toString(). */ private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; // Member definitions // /** The cached hash that maintains the hint state. */ private int hash = 0; /** The number of hints that are true. */ private int count = 0; // Constructors // /** * Default constructor. * * All hint states are initially false. */ public SudokuHint() { } /** * Cloning constructor. */ public SudokuHint(SudokuHint h) { if (h == null) return; hash = h.hash; count = h.count; } /** * The constructor that sets one data item to true * and all other data items to false. * * @param data the single data item to set to true */ public SudokuHint(int data) { setOneHint(data); } // Methods // /** * Gets the hint state for the given data value. */ public boolean getHint(int data) { if ((data >= 1) && (data <= 9)) return ((hash & bits[data]) != 0); return false; } /** * Sets the hint state for the given data value * to the given hint state. * * Returns true if the hint was changed. */ public boolean setHint(int data, boolean state) { if ((data >= 1) && (data <= 9)) if (getHint(data) != state) { if (state) { hash += bits[data]; count++; } else { hash -= bits[data]; count--; } return true; } return false; } /** * Sets the hint state for the given data value * to false, that is, prunes that data value. * * Returns true if the hint was pruned. */ public boolean pruneHint(int data) { return setHint(data, false); } /** * Prunes this hint of all data values in the * given hint. * * Returns true if the hint was pruned. */ public boolean pruneHint(SudokuHint h) { if (h == null) return false; boolean haspruned = false; for (int data = 1; data<= 9; data++) if (h.getHint(data)) haspruned |= pruneHint(data); return haspruned; } /** * Sets all hint states to the given state. * * Returns true if the hint was changed. */ public boolean setAll(boolean state) { int oldhash = hash; if (state) { hash = 1022; count = 9; } else { hash = 0; count = 0; } return (oldhash != hash); } /** * Sets the hint state for the given data value to true * and all other hint states to false. * * Returns true if the hint was changed. */ public boolean setOneHint(int data) { int oldhash = hash; if ((data >= 1) && (data <= 9)) { hash = bits[data]; count = 1; } return (oldhash != hash); } /** * Returns the count of indices for which the hint state * is true. */ public int count() { return count; } /** * Returns true if this hint is equal to the given hint * in the sense that all corresponding hint states agree. */ public boolean isEqualTo(SudokuHint h) { if (h == null) return false; return hash == h.hash; } /** * Returns true if o is a SudokuHint and isEqualTo this * hint. */ public boolean equals(Object o) { if (o instanceof SudokuHint) return isEqualTo((SudokuHint) o); return false; } /** * Returns whether this hint contains * hint h as a subset. * * Will also return true if this hint * equals h. */ public boolean contains(SudokuHint h) { if (h == null) return false; int a = hash; int b = h.hash; return (b == (a & b)); } /** * Returns the sum of 2-to-the-power-i for all i * such that getHint(i) is true. * * Two SudokuHint objects are equal if and only if * they have the same hashCode. */ public int hashCode() { return hash; } /** * If o is a SudokuHint h, returns the difference of * this hashCode minus that of h. * * Throws ClassCastException if o is not a SudokuHint. */ public int compareTo(Object o) { if (! (o instanceof SudokuHint)) throw new ClassCastException ("Illegal argument in compareTo in SudokuHint"); SudokuHint h = (SudokuHint) o; return hash - h.hash; } /** * Returns a string with nine 1's and 0's corresponding * to the nine true-false states of the hint. */ public String toString() { StringBuffer buffer = new StringBuffer(9); for (int i = 1; i <= 9; i++) buffer.append(getHint(i) ? digits[i] : '0'); return buffer.toString(); } }