// Sudoku.h: interface for the Sudoku class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SUDOKU_H__A3A5F740_4435_4643_A497_C7785C94B7E7__INCLUDED_)
#define AFX_SUDOKU_H__A3A5F740_4435_4643_A497_C7785C94B7E7__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#pragma warning ( disable : 4786 )
#include <string>
#include <set>
#include <map>
#include <list>
using namespace std;
struct T_MapData {
unsigned short m_usedNum; // 使用了哪些數字
unsigned short m_pos; // 哪些位置未填
};
typedef struct ANSudoku_tag {
int r;
int c;
int box_num;
} ANSudoku;
typedef struct ANSudokuCell_tag {
int candi[9]; // 候選數數組
int n; // 候選數個數
int m; // 原始候選數個數
} ANSudokuCell;
#define SD_SIZE 9
struct _Point{
int r;
int c;
};
#define HOUSE_BOX 1
#define HOUSE_ROW 2
#define HOUSE_COL 4
class Sudoku
{
public:
Sudoku(string & strSudoku);
Sudoku(int data[SD_SIZE][SD_SIZE]);
virtual ~Sudoku();
int Solve();
int TrySolve();
int SingleCandidature(int &r, int &c, bool bOnlyOne);
int HiddenSingleCandi(int & rr, int &cc, bool bOnlyOne);
int LockedCandidates();
void SetNum(int r, int c, int n);
// 顯式 數對(Naked Pair), 3數集(Naked Triple), 4數集(Naked Quad)
void NakedNumSet(int n);
void HiddenNumSet(int n);
// X-Wing
void X_Wing(int n = 2);
void Bug_1();
void XY_Wing();
void XYZ_Wing();
// Turbotfish 多寶魚(比目魚)
void Turbotfish();
// out put method
// 取(r,c) 位置的所有候選數, 通過num[]輸出這些候選數
// 返回值表示候選數的個數
int CandidatureNum(int r, int c, int num[]);
void OutPut();
void printfNum3();
// 獲取p1和p2點可以共同看到的位置
int GetInterSection(_Point &p1, _Point &p2, int n, _Point arrOut[]);
void UniqueRectangle();
private:
void SetBit(int r, int c, int num);
void ClsBit(int r, int c, int num);
void ResetFlag(int data[SD_SIZE][SD_SIZE]);
int GetCandidatureNum(int r, int c, int n);
void GetSuffix(int z, int &z1, int &z2);
void GetAllCandidature(void);
// 消除(r,c)位置的候選數n
void EliminateCandidature(int r, int c, int n);
void printfResult(_Point arrDelPt[], int k, _Point pt[], int v[], int n, bool bNaked = true);
void Merge(list<_Point> &lst1, list<_Point> & lst2, list<_Point> & lstOut);
void printfX_Wing(_Point arrDelPt[], int k, _Point pt[], int v[], int n, bool bRow);
// 多寶魚位置合併
bool MergeTurbot(bool isRow, _Point arr1[], _Point arr2[], _Point ptOut[]);
// c1 的候選數列表 是否包含c2的候選數列表
bool IsInclude(ANSudokuCell & c1, ANSudokuCell & c2);
// 取 c1 - c2 剩餘的候選數
int Subtract(ANSudokuCell & c1, ANSudokuCell & c2, int arrOut[]);
// 判斷 p3, p4所在行或者列 是否僅包含cellA中某一個候選數, 如是, 通過返回值返回
// 該候選數; 否則返回0
int UniquePair(ANSudokuCell &cellA, _Point &p3, _Point &p4);
// Unique Rectangle 3
// p1和p2點作爲一個虛擬單元格, 利用顯式數集進行候選數消除,
// 能消除候選數的位置通過 arrDelPt 輸出, 通過v輸出這個數集,
// 返回值爲可以消除位置的個數, 如果構不成數集或者無候選數消除,返回0
// ---p1和p2需要排除的兩個數字, 通過v傳入------------
int UniqueSubset(_Point &p1, _Point &p2, _Point arrDelPt[13], int v[4]);
// 取p1和p2, 共同的house, type指明 house, row or col
int GetHouse(_Point &p1, _Point &p2, _Point arrHouse[9], int type);
// 判斷點arrPt(個數爲n),是否屬於同一個house (box, row, col)
int JudgeHouse(_Point arrPt[], int n);
// 判斷A,B,C,D是否可以組成 UR5
int UR5(_Point &ptA, _Point &ptB, _Point &ptC, _Point &ptD);
int UR6(_Point &ptA, _Point &ptB, _Point &ptC, _Point &ptD);
int UR7(_Point &ptA, _Point &ptB, _Point &ptC, _Point &ptD);
int m_cell[SD_SIZE][SD_SIZE];
int m_solve[SD_SIZE][SD_SIZE];
T_MapData m_row[SD_SIZE];
T_MapData m_col[SD_SIZE];
T_MapData m_square[SD_SIZE];
ANSudokuCell m_anCell[9][9];
};
#endif // !defined(AFX_SUDOKU_H__A3A5F740_4435_4643_A497_C7785C94B7E7__INCLUDED_)
// 多寶魚位置合併
// isRow, true表示行; flase表示列合併
// arr1 和 arr2 的元素個數都爲2; ptOut 輸出數組, 個數爲4(下標0,1爲底部)
bool Sudoku::MergeTurbot(bool isRow, _Point arr1[], _Point arr2[], _Point ptOut[])
{
if (isRow)
{
if (arr1[0].c > arr1[1].c)
swap(arr1[0], arr1[1]);
if (arr2[0].c > arr2[1].c)
swap(arr2[0], arr2[1]);
if (arr1[0].c == arr2[0].c && arr1[1].c != arr2[1].c)
{
ptOut[0] = arr1[0];
ptOut[1] = arr2[0];
ptOut[2] = arr1[1];
ptOut[3] = arr2[1];
return true;
}
if (arr1[0].c != arr2[0].c && arr1[1].c == arr2[1].c)
{
ptOut[0] = arr1[1];
ptOut[1] = arr2[1];
ptOut[2] = arr1[0];
ptOut[3] = arr2[0];
return true;
}
}
else // 列 合併
{
if (arr1[0].r > arr1[1].r)
swap(arr1[0], arr1[1]);
if (arr2[0].r > arr2[1].r)
swap(arr2[0], arr2[1]);
if (arr1[0].r == arr2[0].r && arr1[1].r != arr2[1].r)
{
ptOut[0] = arr1[0];
ptOut[1] = arr2[0];
ptOut[2] = arr1[1];
ptOut[3] = arr2[1];
return true;
}
if (arr1[0].r != arr2[0].r && arr1[1].r == arr2[1].r)
{
ptOut[0] = arr1[1];
ptOut[1] = arr2[1];
ptOut[2] = arr1[0];
ptOut[3] = arr2[0];
return true;
}
}
return false;
}
// Sudoku.cpp: implementation of the Sudoku class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Sudoku.h"
#include <algorithm>
typedef set<int> _Candi_Set;
typedef map<_Candi_Set, list<_Point> > _Candi_Map;
typedef pair<_Candi_Set, list<_Point> > _Candi_Pair;
struct _PosCnt {
int r;
int c;
int cnt;
};
struct ANSetPoint
{
_Candi_Set s;
list<_Point> p;
};
typedef list<ANSetPoint> _Candi_List;
typedef map<int, list<_Point> > _CandiCnt_Map;
typedef pair<int, list<_Point> > _CandiCnt_Pair;
// 用於 X-Wing
typedef map<int, _CandiCnt_Map> _Candi_rcP_Map;
typedef pair<int, _CandiCnt_Map> _Candi_rcP_Pair;
typedef map<int, _Point> _CandiPt_Map;
typedef pair<int, _Point> _CandiPt_Pair;
typedef map<_Candi_Set, _Point> _CandiSetPt_Map;
typedef pair<_Candi_Set, _Point> _CandiSetPt_Pair;