#include "sudoku.h" #include "box.h" #include "row.h" #include "reg.h" #include #include using namespace std; const size_t box::all[n] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; void box::set(size_t i) { //cout << "set(" << i << ") at " << x << ", " << y << "\n"; assert(x < n); assert(y < n); assert(i < n); if (!(*this)[i]) { cerr << "Cannot set row " << y + 1 << ", column " << x + 1 << " to " << i + 1 << ". No solution\n."; exit(EXIT_FAILURE); } for (size_t j = 0; j < n; ++j) { if (j != i) { reset(j); } } mow_down(i); //No other box in this row can be i. mow_down(i); mow_down(i); } void box::reset(size_t i) { //cout << "reset(" << i << ") at " << x << ", " << y << "\n"; assert(x < n); #if 0 assert(y < n); #else if (y > n) { cout << "reset(" << i << ") at " << x << ", " << y << "\n"; exit(EXIT_FAILURE); } #endif assert(i < n); if (!(*this)[i]) { return; } s.erase(i); //If only one box in this row could now be i, //set that box to i. //Ditto for this column and this region. only(i); only(i); only(i); herd(i); herd(i); herd(i); herd(i); } template void box::only(size_t i) const { assert(x < n); assert(y < n); assert(i < n); const ZONE& z = *this; const binder2nd > predicate(mem_fun_ref(&box::operator[]), i); const typename ZONE::iterator::difference_type d = count_if(z.begin(), z.end(), predicate); if (d == 1) { const typename ZONE::iterator it = find_if(z.begin(), z.end(), predicate); assert(it != z.end()); if (it->size() > 1) { it->set(i); } } } template void box::mow_down(size_t i) const { assert(x < n); assert(y < n); assert(i < n); const ZONE& z = *this; for (typename ZONE::iterator it = z.begin(); it != z.end(); ++it) { if (&*it != this) { it->reset(i); } } } //If all the remaining i's in this ZONE1 are in the same ZONE2, //turn off all the i's in ZONE2 - ZONE1. template void box::herd(size_t i) const { const ZONE1& z1 = *this; const binder2nd > predicate(mem_fun_ref(&box::operator[]), i); const typename ZONE1::iterator it = find_if(z1.begin(), z1.end(), predicate); assert(it != z1.end()); const ZONE2& z2 = *it; for (typename ZONE1::iterator it = z1.begin(); it != z1.end(); ++it) { if (&static_cast(*it) != &z2) { return; } } for (typename ZONE2::iterator it = z2.begin(); it != z2.end(); ++it) { if (&static_cast(*it) != &z1) { it->reset(i); } } } //If this box belongs to set of k boxes in this ZONE //that together contain only k different possibilities, //turn off those possibilities in teh other boxes of the zone. //For example, if the set is 12 23 123, turn off 1, 2, 3 in the //other boxes in the zone. template void box::contingency() const { } ostream& operator<<(ostream& ost, const box& bo) { for (size_t i = 0; i < box::n; ++i) { if (bo[i]) { ost << i + 1; } } return ost; } box::operator row&() const {return p->rows[y];} box::operator col&() const {return p->cols[x];} box::operator reg&() const {return p->regs[y / root][x / root];}