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)
00036 {
00037 if (wantedSum == 0)
00038 possibleSums->push_back(*current);
00039
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);
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
00182 form->newClause();
00183 for (unsigned int nValSets=0; nValSets<possibleSums->size(); nValSets++)
00184 form->addLit(1,true,nHints,nValSets);
00185 form->pushClause();
00186
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
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
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
00230 std::string currentKakuro("currentKakuro.txt");
00231 std::ofstream out(currentKakuro.c_str());
00232 kak.printToStream(out,true);
00233 out.close();
00234
00235 VariableSet vars(kak.getNSize(), kak.getMSize(), 9);
00236 vars.addVars(kak.getNHints(),12);
00237 Formula * form = new Formula(&vars);
00238
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
00245 std::string comment ("Kakuro as a CNF formula");
00246 form->toFile(&std::cout,comment);
00247 std::cout<<std::endl;
00248 return 0;
00249 }