Post on 24-Dec-2015
Crossword Puzzle Solver
Michael Keefe
PuzzleClass
public
BinaryConstraintsPuzzleVariables
CSPUtilityStatic Class
public
AddConstraintSolve
private
aC3arcReducegetConstraintgetNeighbors
ConstraintClass
public
CellACellBConstraintContainsEqualsInvertedToString
CellClass
public
CellEqualsIndexToStringVariable
VariableTypeEnum
NoneAcrossDown
VariableClass
public
DomainEqualsLabelPositionToStringVariable (+ 2 overloads)VariableTypeWidth
Solver structure
UI structure
CrosswordCell
UserControl
Class
Fields
CellNumbercomponentsLetterLabel
Properties
IsBlackLetterNumberPosition
Methods
BlackoutCrosswordCellDisposeInitializeComponent
Main
Form
Class
Fields
boardLayoutPanelcellscomponentsDictionaryheaderpanel3puzzlessolve
Methods
DisposegetConstraintsgetRangegetVariablesinitCellsInitializeComponentMainpaintSolutionrenderBoardsolve_Click
Let Q be a copy of puzzle constraints
Let arc be a binary constraint
Let xi,xj,xk be Variables with domains initialized to all words that fit
void AC3(Puzzle p)
{While Q not empty
Remove an arc (xi xj) from Q;
If arc-reduce(xi, xj) then
If the domain of xi is empty
return failure;
else
Add to Q all arcs (xk xi), with k different than
i and j, that are in the CS-Problem;
return success;
}
ARC Reduction and backtracking
Arc reduce
private static bool arcReduce(Puzzle p, Variable xi, Variable xj)
bool change = false;
var c = getConstraint(p, xi, xj);
string word = string.Empty;
// if the constraint was inverted
var swapped = c.CellA.Variable != xi;
var y = swapped ? c.CellA.Index - 1 : c.CellB.Index - 1;
var x = swapped ? c.CellB.Index - 1 : c.CellA.Index - 1;
//For each value u in the domain of xi
for (int i = xi.Domain.Count - 1; i >= 0; i--)
{
bool exists = false;
word = xi.Domain[i];
exists = xj.Domain.Any(w => w[y] == word[x]);
if (!exists)
//If there is no such v, remove u from the domain of xi & set Change to true;
xi.Domain.RemoveAt(i); change = true;
}
return change;
}