00001 #include <stdlib.h>
00002 #include <vector>
00003 #include <iostream>
00004 #include <fstream>
00005 #include <string>
00006
00007 #include "../libcnf/libcnf.h"
00008
00009 using namespace cnf;
00010
00011
00017 #define NONE 100
00018
00019
00020
00028 void oneValuePerCell(
00029 unsigned int i, unsigned int j,
00030 Formula * form)
00031 {
00032
00033 for (unsigned int k1=0; k1<8; k1++)
00034 for (unsigned int k2=k1+1; k2<9; k2++)
00035 {
00036 form->newClause();
00037 form->addLit(0,false,i,j,k1);
00038 form->addLit(0,false,i,j,k2);
00039 form->pushClause();
00040 }
00041
00042 form->newClause();
00043 for (unsigned int k1=0; k1<9; k1++)
00044 form->addLit(0,true,i,j,k1);
00045 form->pushClause();
00046 }
00047
00048
00049
00057 void oneValuePerLine(
00058 unsigned int i,
00059 Formula * form)
00060 {
00061 for (unsigned int k=0; k<9; k++)
00062 for (unsigned int j1=0; j1<8; j1++)
00063 for (unsigned int j2=j1+1; j2<9; j2++)
00064 {
00065 form->newClause();
00066 form->addLit(0,false,i,j1,k);
00067 form->addLit(0,false,i,j2,k);
00068 form->pushClause();
00069 }
00070 }
00071
00079 void oneValuePerColumn(
00080 unsigned int j,
00081 Formula * form)
00082 {
00083 for (unsigned int k=0; k<9; k++)
00084 for (unsigned int i1=0; i1<8; i1++)
00085 for (unsigned int i2=i1+1; i2<9; i2++)
00086 {
00087 form->newClause();
00088 form->addLit(0,false,i1,j,k);
00089 form->addLit(0,false,i2,j,k);
00090 form->pushClause();
00091 }
00092 }
00093
00094
00102 void oneValuePerSquare(
00103 unsigned int i,
00104 unsigned int j,
00105 Formula * form)
00106 {
00107 for (unsigned int k=0; k<9; k++)
00108 for (unsigned int l1=0; l1<8; l1++)
00109 for (unsigned int l2=l1+1; l2<9; l2++)
00110 {
00111 form->newClause();
00112 form->addLit(0,false, i*3+l1/3, j*3+l1%3, k);
00113 form->addLit(0,false, i*3+l2/3, j*3+l2%3, k);
00114 form->pushClause();
00115 }
00116 }
00117
00118
00126 void grid2restriction(std::vector< std::vector<int> > grid, Formula * form, VariableSet * vars)
00127 {
00128 for (int i=0; i<9; i++)
00129 for (int j=0; j<9; j++)
00130 {
00131 if (grid[i][j] != NONE)
00132 for (int k=0; k<9; k++)
00133 if (k==grid[i][j]-1)
00134 {
00135 form->newClause();
00136 form->addLit(0,true,i,j,k);
00137 form->pushClause();
00138 }
00139 }
00140 }
00141
00149 std::vector< std::vector<int> > parseGrid(std::istream * input)
00150 {
00151 std::vector< std::vector<int> > grid;
00152 for (unsigned int i=0; i<9; i++)
00153 {
00154 std::vector<int> line;
00155
00156 for (unsigned int j=0; j<9; j++)
00157 {
00158 char n;
00159 (*input) >> n;
00160 if ((*input).good())
00161 {
00162
00163 if (n!='-')
00164 line.push_back(n-'0');
00165 else
00166 line.push_back(NONE);
00167 }
00168 else
00169
00170 {
00171 std::cout<<"error 403: input stream does not contain enough"
00172 <<"information !"<<std::endl;
00173 exit(403);
00174 }
00175 }
00176 grid.push_back(line);
00177 }
00178 std::cout<<"Finish parsing grid"<<std::endl;
00179 return grid;
00180 }
00181
00182
00183 int main(int argc, char ** argv)
00184 {
00185 VariableSet vars(9,9,9);
00186 Formula form(&vars);
00187
00188 for (unsigned int i=0; i<9; i++)
00189 for (unsigned int j=0; j<9; j++)
00190 oneValuePerCell(i,j,&form);
00191
00192 for (unsigned int i=0; i<9; i++)
00193 oneValuePerLine(i,&form);
00194
00195 for (unsigned int j=0; j<9; j++)
00196 oneValuePerColumn(j,&form);
00197
00198 for (unsigned int i=0; i<3; i++)
00199 for (unsigned int j=0; j<3; j++)
00200 oneValuePerSquare(i,j,&form);
00201
00202
00203 std::string comment ("CNF formula corresponding to the sudoku");
00204 if (argc==1)
00205 {
00206 grid2restriction(parseGrid(&std::cin),&form,&vars);
00207 form.toFile(&std::cout,comment);
00208 }
00209 else
00210 {
00211 std::string name (argv[1]);
00212 std::ifstream input(name.c_str());
00213 std::cout<<"Reading file "<<name<<std::endl;
00214 grid2restriction(parseGrid(&input),&form,&vars);
00215 input.close();
00216 name+=".dimacs";
00217 std::ofstream output(name.c_str());
00218 form.toFile(&output,comment);
00219 std::cout<<std::endl<<"DIMACS file written: "<<name<<std::endl;
00220 }
00221 std::cout<<std::endl;
00222 return 0;
00223 }