#include #include #include #include // for accessing timing operations #include #include "Square.h" //#define DEBUG #define EXTRA_ACCOUNTING using namespace std; class Accounting { public: int size; unsigned long long soln; unsigned long long cand; unsigned long long recur; unsigned long long *level; Accounting(int max) : size(max), soln(0), cand(0), recur(0) { level = new unsigned long long[size+1]; for (int i=0; i<=size; i++) level[i]=0; }; ~Accounting() { delete [] level; } }; std::ostream& operator<<(std::ostream& out, const Accounting& a) { out << "There were " << a.recur << " recursive calls made.\n"; #ifdef EXTRA_ACCOUNTING for (int i=0; i<=a.size; i++) { out << " " << setw(10) << a.level[i] << " made with " << setw(2) << i << " unfilled cells.\n"; } #endif out << "There were " << a.cand << " completely filled squares considered.\n"; out << "There were " << a.soln << " solutions found.\n"; return out; } template std::ostream& operator<<(std::ostream& out, const vector& V) { out << "{"; if (V.size()>0) out << V[0]; for (size_t r=1; r& V) { counter->recur++; if (counter->recur%1000000==0) { cout << "Number of recursive calls is " << counter->recur << " and counting...\n"; cout.flush(); } if (counter->recur%10000000LL==0) { // progress report cout << "-------- Progress Report ---------\n"; cout << "Number of solutions is " << counter->soln << " and counting...\n"; cout << "Current recurisive call based on configuration\n" << S << endl << V; cout << "------------------------------------\n\n"; cout.flush(); } if (debug) cout << "--------------------------------\nRecurisive call begining with\n" << S << endl << V << "------------------------------\n\n"; int remaining = V.size(); counter->level[remaining]++; if (remaining==0) { counter->cand++; if (S.valid()) { // found a solution counter->soln++; if (counter->soln<=10) { // print it out, if one of the first ten cout << S << endl; cout.flush(); } } } else { /* * For each item of vector V, use that item to fill the chosen cell, and recurse */ for (int rank = 0; rank newV(V); // a copy of vector V newV.erase(newV.begin()+rank); // but without the used item // recurse PuzzleSolve(S,newV); } else if (debug) cout << "--------------------------------\nThe following square was considered,\nbut ruled out as (partially) invalid\n" << S << "------------------------------\n\n"; // remove the added value S.pop(); } } } int main(int argc, const char* argv[]) { /* * The first command-line argument is used to specify n */ int n = -1; if (argc>1) { n = atoi(argv[1]); } if (n<1) { cout << "Must specify a valid 'n' as first command-line argument.\n"; exit(1); } /* * If a second command-line argument is given (no matter what), we * enter debug mode */ if (argc>2) debug = true; counter = new Accounting(n*n); /* * Now we create the initially empty square, and a list of values to * be used, from 1 to n^2. */ Square S(n); vector L; for (int i=0; i