mightyscape-1.2/extensions/fablabchemnitz/sudoku/qqwing.hpp

241 lines
6.8 KiB
C++

/*
* qqwing - A Sudoku solver and generator
* Copyright (C) 2006-2014 Stephen Ostermiller http://ostermiller.org/
* Copyright (C) 2007 Jacques Bensimon (jacques@ipm.com)
* Copyright (C) 2011 Jean Guillerez (j.guillerez - orange.fr)
* Copyright (C) 2014 Michael Catanzaro (mcatanzaro@gnome.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef QQWING_HPP
#define QQWING_HPP
#include <string>
#include <vector>
namespace qqwing {
using namespace std;
class LogItem;
const int GRID_SIZE = 3;
const int ROW_COL_SEC_SIZE = GRID_SIZE*GRID_SIZE;
const int SEC_GROUP_SIZE = ROW_COL_SEC_SIZE*GRID_SIZE;
const int BOARD_SIZE = ROW_COL_SEC_SIZE*ROW_COL_SEC_SIZE;
const int POSSIBILITY_SIZE = BOARD_SIZE*ROW_COL_SEC_SIZE;
/**
* The version of QQwing, e.g. 1.2.3
*/
string getVersion();
/**
* The board containing all the memory structures and
* methods for solving or generating sudoku puzzles.
*/
class SudokuBoard {
public:
enum PrintStyle {
ONE_LINE,
COMPACT,
READABLE,
CSV
};
enum Difficulty {
UNKNOWN,
SIMPLE,
EASY,
INTERMEDIATE,
EXPERT
};
enum Symmetry {
NONE,
ROTATE90,
ROTATE180,
MIRROR,
FLIP,
RANDOM
};
SudokuBoard();
bool setPuzzle(int* initPuzzle);
const int* getPuzzle();
const int* getSolution();
void printPuzzle();
void printSolution();
bool solve();
/**
* Count the number of solutions to the puzzle
*/
int countSolutions();
/**
* Count the number of solutions to the puzzle
* but return two any time there are two or
* more solutions. This method will run much
* falter than countSolutions() when there
* are many possible solutions and can be used
* when you are interested in knowing if the
* puzzle has zero, one, or multiple solutions.
*/
int countSolutionsLimited();
/**
* return true if the puzzle has a solution
* and only a single solution
*/
bool hasUniqueSolution();
bool isSolved();
void printSolveHistory();
void setRecordHistory(bool recHistory);
void setLogHistory(bool logHist);
void setPrintStyle(PrintStyle ps);
bool generatePuzzle();
bool generatePuzzleSymmetry(SudokuBoard::Symmetry symmetry);
int getGivenCount();
int getSingleCount();
int getHiddenSingleCount();
int getNakedPairCount();
int getHiddenPairCount();
int getBoxLineReductionCount();
int getPointingPairTripleCount();
int getGuessCount();
int getBacktrackCount();
void printSolveInstructions();
SudokuBoard::Difficulty getDifficulty();
string getDifficultyAsString();
~SudokuBoard();
private:
/**
* The 81 integers that make up a sudoku puzzle.
* Givens are 1-9, unknowns are 0.
* Once initialized, this puzzle remains as is.
* The answer is worked out in "solution".
*/
int* puzzle;
/**
* The 81 integers that make up a sudoku puzzle.
* The solution is built here, after completion
* all will be 1-9.
*/
int* solution;
/**
* Recursion depth at which each of the numbers
* in the solution were placed. Useful for backing
* out solve branches that don't lead to a solution.
*/
int* solutionRound;
/**
* The 729 integers that make up a the possible
* values for a Sudoku puzzle. (9 possibilities
* for each of 81 squares). If possibilities[i]
* is zero, then the possibility could still be
* filled in according to the Sudoku rules. When
* a possibility is eliminated, possibilities[i]
* is assigned the round (recursion level) at
* which it was determined that it could not be
* a possibility.
*/
int* possibilities;
/**
* An array the size of the board (81) containing each
* of the numbers 0-n exactly once. This array may
* be shuffled so that operations that need to
* look at each cell can do so in a random order.
*/
int* randomBoardArray;
/**
* An array with one element for each position (9), in
* some random order to be used when trying each
* position in turn during guesses.
*/
int* randomPossibilityArray;
/**
* Whether or not to record history
*/
bool recordHistory;
/**
* Whether or not to print history as it happens
*/
bool logHistory;
/**
* A list of moves used to solve the puzzle.
* This list contains all moves, even on solve
* branches that did not lead to a solution.
*/
vector<LogItem*>* solveHistory;
/**
* A list of moves used to solve the puzzle.
* This list contains only the moves needed
* to solve the puzzle, but doesn't contain
* information about bad guesses.
*/
vector<LogItem*>* solveInstructions;
/**
* The style with which to print puzzles and solutions
*/
PrintStyle printStyle;
/**
* The last round of solving
*/
int lastSolveRound;
bool reset();
bool singleSolveMove(int round);
bool onlyPossibilityForCell(int round);
bool onlyValueInRow(int round);
bool onlyValueInColumn(int round);
bool onlyValueInSection(int round);
bool solve(int round);
int countSolutions(bool limitToTwo);
int countSolutions(int round, bool limitToTwo);
bool guess(int round, int guessNumber);
bool isImpossible();
void rollbackRound(int round);
bool pointingRowReduction(int round);
bool rowBoxReduction(int round);
bool colBoxReduction(int round);
bool pointingColumnReduction(int round);
bool hiddenPairInRow(int round);
bool hiddenPairInColumn(int round);
bool hiddenPairInSection(int round);
void mark(int position, int round, int value);
int findPositionWithFewestPossibilities();
bool handleNakedPairs(int round);
int countPossibilities(int position);
bool arePossibilitiesSame(int position1, int position2);
void addHistoryItem(LogItem* l);
void shuffleRandomArrays();
void print(int* sudoku);
void rollbackNonGuesses();
void clearPuzzle();
void printHistory(vector<LogItem*>* v);
bool removePossibilitiesInOneFromTwo(int position1, int position2, int round);
};
}
#endif