void AdviseFast::FactSet::addFact( Coord const &point, Fact const &fact) { if(this->count(point)) this->deleteFact(point); Fact &f = ((*this)[point] = fact); // Remove marked points CoordSet marked; set_intersection( f.pointSet.begin(), f.pointSet.end(), _marked.begin(), _marked.end(), inserter(marked, marked.begin())); CoordSet::iterator i; for(i=marked.begin(); i!=marked.end(); ++i) f.pointSet.erase(*i); f.mines -= marked.size(); // Don't insert empty fact if(f.pointSet.empty()) { this->erase(point); return;} for(i=f.pointSet.begin(); i!=f.pointSet.end(); ++i) _containingFacts[*i].insert(point); }
bool AdviseFast::FactSet::reveal( Coord point, CoordSet *affectedFacts) { // Tolerate :) if( !_field->isCovered(point) ) return true; // :) CoordList tmp; if(_field->doReveal(point, &tmp, 0) == false) // Blew up :( return false; CoordSet autorevealed; for (CoordList::const_iterator it = tmp.begin(); it!=tmp.end(); ++it) autorevealed.insert(*it); autorevealed.insert(point); affectedFacts->insert(autorevealed.begin(), autorevealed.end()); CoordSet::const_iterator i; for(i=autorevealed.begin(); i!=autorevealed.end(); ++i) { // I still think that each poing will belong to // at least one fact, but don't want to waste time // proving it :) if(_containingFacts.count(*i)){ CoordSet const &affF = _containingFacts[*i]; affectedFacts->insert( affF.begin(), affF.end()); for(CoordSet::const_iterator j=affF.begin(); j!=affF.end(); ++j) { (*this)[*j].pointSet.erase(*i); if((*this)[*j].pointSet.empty()) this->erase(*j); } _containingFacts.erase(*i); } Fact f; retrieveFact(*i, &f); this->addFact(*i, f); } return true; }
bool Solver::solveStep() { if ( _field->isSolved() ) { emit solvingDone(true); return true; } d->rules->solve(); #ifdef DEBUG PRINT_ELAPSED("fast rules") #endif if( _field->isSolved() ) { emit solvingDone(true); return true; } CoordSet surePoints; AdviseFull::ProbabilityMap probabilities; AdviseFull::adviseFull(d->facts, &surePoints, &probabilities); #ifdef DEBUG PRINT_ELAPSED("full rules") #endif if(!surePoints.empty()) { CoordSet::iterator i; for(i=surePoints.begin(); i!=surePoints.end(); ++i) { bool b = d->rules->reveal(*i); assert(b); } } else if ( !_noGuess ) { #ifdef DEBUG cout << "Applying heuristics!" << endl; cout << *_field << endl; #endif // Minimum probability logic assert(!probabilities.empty()); #ifdef DEBUG AdviseFull::ProbabilityMap::iterator i=probabilities.begin(); cout << "Probability is " << i->first << endl; #endif bool success = d->rules->reveal(probabilities.begin()->second); if ( !success ) { emit solvingDone(false); return false; } } if (_inOneStep) return solveStep(); else QTimer::singleShot(0, this, SLOT(solveStep())); return false; }
void AdviseFull::adviseFull( AdviseFast::FactSet *facts, CoordSet *surePoints, ProbabilityMap *probabilities) { EquationSet eqs(*facts); #if defined(DEBUG) && DEBUG >= 2 eqs.prettyprint(); #endif eqs.normalize(); #if defined(DEBUG) && DEBUG >= 2 eqs.prettyprint(); #endif list<EquationSet> eqss; eqs.separate(&eqss); #ifdef DEBUG {list<EquationSet>::iterator i; for(i=eqss.begin(); i!=eqss.end(); ++i) i->prettyprint(); } #endif // OK, uneffective, but simple :( surePoints->clear(); probabilities->clear(); // Get a fraction; float fraction; { BaseField const *f = facts->getField(); fraction = ((float)f->nbMines()) / (f->width() * f->height()); } /* From now on the first equation set on the list includes * the equation corresponding to "total" fact. This is the * first equation on the set. * * Give it a special treatment ;) */ if(!eqss.empty()) do { EquationSet prime = eqss.front(); EquationSet::Equation total = prime._equations.front(); prime._equations.pop_front(); list<EquationSet> prime_sep; prime.separate(&prime_sep); // Find a pool list<EquationSet::Equation>::iterator i = prime._equations.begin(); while(!prime._equations.empty()){ set<short>::iterator j; for( j = i->pointSets.begin(); j != i->pointSets.end(); ++j) prime._pointSets.erase(*j); i = prime._equations.erase(i); } assert(prime._pointSets.size() <= 1); if(prime._pointSets.size() == 0) break; short pool = prime._pointSets.begin()->first; CoordSet const &p = prime._pointSets[pool]; #ifdef DEBUG cout << "Prime equation set:" << endl << " separated into " << prime_sep.size() << endl << " pool size is " << p.size() << endl; #endif // Euristic // if( prime_sep.size () > 6 && p.size() >= prime_sep.size() * 10){ if(p.size() < (prime_sep.size()+1) * 10) // No special treatment!! break; // Actually, just substitute prime (!!!) eqss.pop_front(); eqss.insert(eqss.begin(), prime_sep.begin(), prime_sep.end()); prime._equations.clear(); EquationSet::Equation o; o.pointSets.insert(pool); // #### is the convertion right ? (NH) o.mines = (ushort)(fraction * p.size()); // A precaution if(o.mines == 0) o.mines = 1; // ;) prime._equations.push_front(o); eqss.push_front(prime); #ifdef DEBUG cout << "Specially treated:" << endl; { list<EquationSet>::iterator i; for(i=eqss.begin(); i!=eqss.end(); ++i) i->prettyprint(); } #endif } while (false); list<EquationSet>::const_iterator i; for(i=eqss.begin(); i!=eqss.end(); ++i){ CoordSet sp; ProbabilityMap pb; list<EquationSet::Solution> solutions; map<short, CoordSet> const &m = i->solve(&solutions); #ifdef DEBUG printf("Got solutions.\n"); #if defined(DEBUG) && DEBUG >= 2 { list<EquationSet::Solution>::iterator i; for( i = solutions.begin(); i != solutions.end(); ++i) { EquationSet::Solution::iterator j; for(j=i->begin(); j!=i->end(); ++j) printf("%d:\t%d\n", j->first, j->second); printf("\n"); } } #endif #endif //bool sure = AdviseFull::surePoints(m, solutions, &sp); surePoints->insert(sp.begin(), sp.end()); getProbabilities(m, solutions, &pb, fraction); probabilities->insert(pb.begin(), pb.end()); } // That's it return; }