kakuro2formula.cpp
Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <vector>
00003 #include <iostream>
00004 #include <iomanip>
00005 #include <fstream>
00006 #include <string>
00007 #include <sstream>
00008 
00009 #include "../libcnf/libcnf.h"
00010 #include "kakuro.h"
00011 
00012 using namespace cnf;
00013 
00014 
00015 
00029 void allSums(
00030         std::vector< std::vector<unsigned int> > * possibleSums,
00031         std::vector<unsigned int> * current,
00032         int nCells,
00033         int wantedSum )
00034 {
00035         if (nCells == 0) // If we reached the last cell
00036         {
00037                 if (wantedSum == 0)
00038                         possibleSums->push_back(*current);
00039                         // If we have the correct sum, we keep it
00040         }
00041         else
00042                 for (unsigned int i=1; i<=9; i++)
00043                 {
00044                         if ( 
00045                                 ((int)(wantedSum-i) >= (nCells-1)*1)
00046                              && ((int)(wantedSum-i) <= (nCells-1)*9)
00047                              && ( 
00048                                      (current->size() == 0)
00049                                      || ( (*current)[current->size()-1] < i)
00050                                 )
00051                             )
00052                         {
00053                                 std::vector<unsigned int> * newVector
00054                                         = new std::vector<unsigned int>;
00055                                 *newVector = *current;
00056                                 newVector->push_back(i);
00057                                 allSums(possibleSums,newVector,nCells-1,wantedSum-i);
00058                         }
00059                 }
00060         delete current;
00061 }
00062 
00063 
00072 void disjointClauses(Formula * form, Kakuro kak)
00073 {
00074         std::vector< std::vector<unsigned int> >  sumsAbscissa = kak.getSumsAbscissa();
00075         std::vector< std::vector<unsigned int> >  sumsOrdinate = kak.getSumsOrdinate();
00076         for (unsigned int nHints=0; nHints<sumsAbscissa.size(); nHints++)
00077                 for (unsigned int i1=0; i1<sumsAbscissa[nHints].size()-1; i1++)
00078                         for (unsigned int i2=i1+1; i2<sumsAbscissa[nHints].size(); i2++)
00079                                 for (unsigned int value=1; value<=9; value++)
00080                                 {
00081                                         form->newClause();
00082                                         form->addLit(0, false, sumsAbscissa[nHints][i1], sumsOrdinate[nHints][i1], value-1);
00083                                         form->addLit(0, false, sumsAbscissa[nHints][i2], sumsOrdinate[nHints][i2], value-1);
00084                                         form->pushClause();
00085                                 }
00086 }
00087 
00088 
00096 void oneValuePerCell(unsigned int i, unsigned int j, Formula * form)
00097 {
00098         for (unsigned int k1=0; k1<8; k1++)
00099                 for (unsigned int k2=k1+1; k2<9; k2++)
00100                 {
00101                         form->newClause();
00102                         form->addLit(0,false,i,j,k1);
00103                         form->addLit(0,false,i,j,k2);
00104                         form->pushClause();
00105                 }
00106 }
00107 
00108 
00120 void allowedValues(Formula * form,
00121                    unsigned int nHints,
00122                    unsigned int nValSets,
00123                    Kakuro kak,
00124                    std::vector< std::vector<unsigned int> > * possibleSums)
00125 {
00126         std::vector< std::vector<unsigned int> > sumsAbscissa = kak.getSumsAbscissa();
00127         std::vector< std::vector<unsigned int> > sumsOrdinate = kak.getSumsOrdinate();
00128         for (unsigned int elem=0; elem<(*possibleSums)[nValSets].size(); elem++)
00129         {
00130                 form->newClause();
00131                 form->addLit(1,false,nHints,nValSets); // not y_{nHints,nValSets}
00132                 for (unsigned int l=0; l<sumsAbscissa[nHints].size(); l++)
00133                         form->addLit(0,
00134                                      true,
00135                                      sumsAbscissa[nHints][l],
00136                                      sumsOrdinate[nHints][l],
00137                                      (*possibleSums)[nValSets][elem]-1);
00138                 form->pushClause();
00139         }
00140 }
00141 
00142 
00157 void sumAxioms(Formula * form, Kakuro kak)
00158 {
00159         std::vector<unsigned int>  sumsValue = kak.getSumsValue();
00160         std::vector< std::vector<unsigned int> >  sumsAbscissa = kak.getSumsAbscissa();
00161         std::vector< std::vector<unsigned int> >  sumsOrdinate = kak.getSumsOrdinate();
00162         std::vector< std::vector<unsigned int> > *  possibleSums = new std::vector< std::vector<unsigned int> >;
00163 
00164         for (unsigned int nHints=0; nHints<kak.getNHints(); nHints++)
00165         {
00166                 possibleSums->clear();
00167                 allSums(possibleSums,
00168                         new std::vector<unsigned int>,
00169                         sumsAbscissa[nHints].size(),
00170                         sumsValue[nHints]);
00171                 if (possibleSums->size() == 0)
00172                 {
00173                         std::cout<<"ERROR: Kakuro grid impossible, no"
00174                                  <<"way to make "<<sumsValue[nHints]
00175                                  <<"with "<<sumsAbscissa[nHints].size()
00176                                  <<"cells!"<<std::endl;
00177                         exit(100);
00178                 }
00179                 else
00180                 {
00181                         // non-emptiness
00182                         form->newClause();
00183                         for (unsigned int nValSets=0; nValSets<possibleSums->size(); nValSets++)
00184                                 form->addLit(1,true,nHints,nValSets);
00185                         form->pushClause();
00186                         // non-duplicated legal subsets
00187                         for (unsigned int nValSets1=0; nValSets1<possibleSums->size()-1; nValSets1++)
00188                         {
00189                                 form->newClause();
00190                                 for (unsigned int nValSets2=nValSets1+1; nValSets2<possibleSums->size(); nValSets2++)
00191                                 {
00192                                         form->addLit(1,false,nHints,nValSets1);
00193                                         form->addLit(1,false,nHints,nValSets2);
00194                                 }
00195                                 form->pushClause();
00196                         }
00197                         // correct sums
00198                         for (unsigned int nValSets=0; nValSets<possibleSums->size(); nValSets++)
00199                         allowedValues(form, nHints, nValSets, kak, possibleSums);
00200                 }
00201         }
00202 }
00203 
00204 
00205 
00206 
00213 int main(int argc, char ** argv)
00214 {
00215         Kakuro kak;
00216         // initialising kakuro
00217         if (argc==1)
00218         {
00219                 kak.parseGrid(&std::cin);
00220         }
00221         else
00222         {
00223                 std::string name (argv[1]);
00224                 std::ifstream input(name.c_str());
00225                 kak.parseGrid(&input);
00226                 input.close();
00227         }
00228         kak.grids2sums();
00229         // copying kakuro grid
00230         std::string currentKakuro("currentKakuro.txt");
00231         std::ofstream out(currentKakuro.c_str());
00232         kak.printToStream(out,true);
00233         out.close();
00234         // initialising the variable set
00235         VariableSet vars(kak.getNSize(), kak.getMSize(), 9);
00236         vars.addVars(kak.getNHints(),12);
00237         Formula * form = new Formula(&vars);
00238         // adding clauses to the formula
00239         disjointClauses(form,kak);
00240         for (unsigned int i=0; i<kak.getNSize(); i++)
00241                 for (unsigned int j=0; j<kak.getMSize(); j++)
00242                         oneValuePerCell(i,j,form);
00243         sumAxioms(form,kak);
00244         // outputing the formula to stdout
00245         std::string comment ("Kakuro as a CNF formula");
00246         form->toFile(&std::cout,comment);
00247         std::cout<<std::endl;
00248         return 0;
00249 }
 All Classes Files Functions Variables