// A C/D D/C B
// W-Wing ab---b===b----ab 删除ab两个数格共同看到的a候选数 属于Forcing Chain的
// 特例,也是应用强弱强的属性。
// 思路:
// 将所有的数对找出,过滤出不在同一个规则(row/col/box)中的数对(位置A,B,数字X,Y);
// 将所有的 X强链(单候选数)找出,定位关键字为候选数的值
// 如果A,B能够共同看到带X或者Y的数格,则再查找一个强链(X=X或者Y=Y)能将A,B连接
// 起来。如是,则发现 W-Wing 。
// string s52= "295000640681240500473560820049700200500920408020004190954382716000490352032000984";
struct sdPair {
int x;
int y;
bool operator < (const sdPair & rht) const {
if (x != rht.x) return x<rht.x;
return y<rht.y;
}
};
bool Sudoku::W_Wing()
{
typedef map<sdPair, list<_Point> > sdWWing;
typedef pair<sdPair, list<_Point> > sdWWingPair;
int r, c;
sdPair sdPr;
sdWWing wing;
for (r = 0; r < 9; ++r)
{
for (c = 0; c < 9; ++c)
{
ANSudokuCell &cell = m_anCell[r][c];
if (cell.n != 2)
continue;
sdPr.x = cell.candi[0];
sdPr.y = cell.candi[1];
if (sdPr.x > sdPr.y)
swap(sdPr.x, sdPr.y);
_Point pt(r, c);
sdWWing::iterator itWing = wing.find(sdPr);
if (itWing == wing.end())
{
list<_Point> lstPt;
lstPt.push_back(pt);
wing.insert(sdWWingPair(sdPr, lstPt));
}
else
{
itWing->second.push_back(pt);
}
}
}
// 候选数 和 对应的强链 集合
typedef map<int, list<list<_Point> > > xLinks;
typedef pair<int, list<list<_Point> > > xLinksPair;
xLinks wingLinks;
for (r = 0; r < 27; ++r) // 9 row and 9 col, 9 box
{
_CandiCnt_Map mapCandi; // 这里用作 候选数 与 位置信息对应表
if(r < 9)
GetLinks(HOUSE_ROW, r, true, 0, mapCandi);
else if(r < 18)
GetLinks(HOUSE_COL, r-9, true, 0, mapCandi);
else
GetLinks(HOUSE_BOX, r-18, true, 0, mapCandi);
for (_CandiCnt_Map::iterator _itCandi=mapCandi.begin(); _itCandi!=mapCandi.end(); ++_itCandi)
{
const int& nX = _itCandi->first; // 候选数
xLinks::iterator iLinks = wingLinks.find(nX);
if (iLinks==wingLinks.end())
{
list<list<_Point> > lstLinks;
lstLinks.push_back(_itCandi->second);
wingLinks.insert(xLinksPair(nX, lstLinks));
}
else
{
iLinks->second.push_back(_itCandi->second);
}
}
}
for (sdWWing::iterator itWing = wing.begin(); itWing != wing.end(); ++itWing)
{
for (list<_Point>::iterator iPt = itWing->second.begin(); iPt != itWing->second.end(); ++iPt)
{
_Point &ptA = *iPt;
list<_Point>::iterator iPt2 = iPt;
for (++iPt2; iPt2 != itWing->second.end(); ++iPt2)
{
_Point &ptB = *iPt2;
if (ptA.BoxNo()==ptB.BoxNo() || ptA.r==ptB.r || ptA.c==ptB.c)
continue; // 他们在同一个规则中,则为 Naked Pair。
int k = 0;
int arrCandi[2];
_Point arrDelPt[20];
arrCandi[0] = itWing->first.x;
arrCandi[1] = itWing->first.y;
for (int InLoop = 0; InLoop<2; ++InLoop)
{
if (InLoop == 1)
swap(arrCandi[0], arrCandi[1]);
k = GetDelPos(ptA, ptB, arrCandi, 1, arrDelPt);
if (k <= 0)
continue;
// 说明 pt 和 p 之间有关于候选数X的共同可消除数格
// 再看 pt 和 p 之间 是否有 Y 的强链
xLinks::iterator iLinks = wingLinks.find(arrCandi[1]);
for (list<list<_Point> >::iterator ilk=iLinks->second.begin(); ilk!=iLinks->second.end(); ++ilk)
{
_Point& ptC = *ilk->begin();
_Point& ptD = * ++ilk->begin();
if (ptC==ptA || ptC==ptB || ptD==ptA || ptD==ptB)
continue;
if (( (ptA.BoxNo()==ptC.BoxNo()||ptA.r==ptC.r||ptA.c==ptC.c)
&&(ptB.BoxNo()==ptD.BoxNo()||ptB.r==ptD.r||ptB.c==ptD.c) )
||
( (ptA.BoxNo()==ptD.BoxNo()||ptA.r==ptD.r||ptA.c==ptD.c)
&&(ptB.BoxNo()==ptC.BoxNo()||ptB.r==ptC.r||ptB.c==ptC.c) ) )
{
printf("W-Wing:");
printf("A(%d,%d),B(%d,%d),C(%d,%d),D(%d,%d)",
ptA.r, ptA.c, ptB.r,ptB.c, ptC.r,ptC.c,ptD.r,ptD.c);
printf(" Candi:%d, Cells to del:", arrCandi[0]);
for (int i=0; i<k; ++i)
{
printf("(%d,%d)", arrDelPt[i].r, arrDelPt[i].c);
}
printf("/n");
}
}
} // for InLoop
}
} // end of for: iPt
}
return false;
}