Guest User

Untitled

a guest
Jan 23rd, 2018
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.20 KB | None | 0 0
  1. /*
  2.  * Title: Assignment four (Sudoku Solver)
  3.  * Author: Andrey Gavel
  4.  * Function:
  5.  * Input:
  6.  * Output:
  7.  *
  8.  * Created on October 02, 2011, 12:53 PM
  9.  * Last modified on October 08, 2011, 12:53 PM, by Andrey Gavel
  10.  * Copyright Andrey Gavel 2011
  11.  */
  12.  
  13. #include <iostream>
  14. #include <fstream>
  15. #include <vector>
  16.  
  17. using namespace std;
  18.  
  19. void set_cell_contents(vector<short>&, short);
  20. string get_cell_char(vector<short>);
  21. bool try_read_file(string, string&);
  22. bool is_single_digit(char);
  23. string cells_to_str(vector<short>[9][9]);
  24. static int vector_contains_short(vector<short>, short);
  25. static bool vector_remove_short(vector<short>&, short);
  26. static bool vector_remove_cell(vector<vector<short>>&, vector<short>);
  27. static vector<short> vector_remove_shorts(vector<short>, vector<short>);
  28. static vector<vector<short>> vector_remove_cells(vector<vector<short>>, vector<short>);
  29. bool ReadData(vector<short>[9][9]);
  30. void PrintData(vector<short>[9][9]);
  31. bool CheckColumn(vector<short>[9][9], int, int);
  32. bool CheckRow(vector<short>[9][9], int, int);
  33. bool CheckSubSquare(vector<short>[9][9], int, int);
  34. void SolvePuzzle(vector<short>[9][9]);
  35.  
  36. int main(int argc, char** argv)
  37. {
  38.     int i, j;
  39.     vector<short> oCells[9][9];
  40.     for (i = 0; i < 9; ++i) //for each row
  41.     {
  42.         for (j = 0; j < 9; j++) //set each cell to "0" content
  43.         {
  44.             set_cell_contents(oCells[i][j], 0);
  45.         }
  46.     }
  47.     if (ReadData(oCells))
  48.     {
  49.         SolvePuzzle(oCells);
  50.         PrintData(oCells);
  51.     }
  52.     else
  53.     {
  54.         cout << "Could not open the file!" << endl;
  55.     }
  56.     system("PAUSE");
  57.  
  58.     return 0;
  59. }
  60.  
  61. void set_cell_contents(vector<short>& oVector, short iValue)
  62. {
  63.     if (iValue < 1 || iValue > 9)
  64.     {
  65.         for (int i = 1; i < 10; i++)
  66.         {
  67.             oVector.push_back(i);
  68.         }
  69.     }
  70.     else
  71.     {
  72.         oVector.push_back(iValue);
  73.     }
  74. }
  75.  
  76. string get_cell_char(vector<short> oValues)
  77. {
  78.     string sOut = "0";
  79.     if (oValues.size() == 1)
  80.     {
  81.         char oChar[2];
  82.         sOut = itoa(oValues[0], oChar, 10);
  83.         sOut = sOut;
  84.     }
  85.     return sOut;
  86. }
  87.  
  88. bool try_read_file(string sFileName, string &sContent) //function used for testing on Windows 7; now obsolete
  89. {
  90.     int iLength;
  91.     char * oBuffer;
  92.  
  93.     ifstream is;
  94.     is.open(sFileName, ios::binary);
  95.  
  96.     //get length of file
  97.     is.seekg (0, ios::end);
  98.     iLength = is.tellg();
  99.  
  100.     if (iLength < 0)
  101.     {
  102.         delete[] oBuffer;
  103.         return false;
  104.     }
  105.     else if (iLength == 0)
  106.     {
  107.         sContent = "";
  108.         delete[] oBuffer;
  109.         return true;
  110.     }
  111.  
  112.     is.seekg (0, ios::beg);
  113.  
  114.     //allocate memory
  115.     oBuffer = new char[iLength];
  116.  
  117.     //read data as a block
  118.     is.read(oBuffer, iLength);
  119.     is.close();
  120.  
  121.     sContent = oBuffer;
  122.  
  123.     delete[] oBuffer;
  124.  
  125.     return true;
  126. }
  127.  
  128. bool is_single_digit(char oChar)
  129. {
  130.     return (oChar >= '0' && oChar <= '9');
  131. }
  132.  
  133. string cells_to_str(vector<short> oCells[9][9])
  134. {
  135.     string sOut = "";
  136.     int i, j;
  137.     for (i = 0; i < 9; i++)
  138.     {
  139.         for (j = 0; j < 9; j++)
  140.         {
  141.             sOut += get_cell_char(oCells[i][j]);
  142.             if (j + 1 < 9)
  143.             {
  144.                 sOut += " ";
  145.             }
  146.         }
  147.         sOut += "\n";
  148.     }
  149.     return sOut;
  150. }
  151.  
  152. static int vector_contains_short(vector<short> iInput, short iValue)
  153. {
  154.     for (int i = 0; i < iInput.size(); i++)
  155.     {
  156.         if (iInput[i] == iValue)
  157.         {
  158.             return i;
  159.         }
  160.     }
  161.     return -1;
  162. }
  163.  
  164. static bool vector_remove_short(vector<short>& oVector, short iValue)
  165. {
  166.     for (int i = 0; i < oVector.size(); i++)
  167.     {
  168.         if (oVector[i] == iValue)
  169.         {
  170.             oVector.erase(oVector.begin() + i);
  171.             return true;
  172.         }
  173.     }
  174.     return false;
  175. }
  176.  
  177. static bool vector_remove_cell(vector<vector<short>>& oVector, vector<short> oValue)
  178. {
  179.     for (int i = 0; i < oVector.size(); i++)
  180.     {
  181.         if (oVector[i] == oValue)
  182.         {
  183.             oVector.erase(oVector.begin() + i);
  184.             return true;
  185.         }
  186.     }
  187.     return false;
  188. }
  189.  
  190. static vector<short> vector_remove_shorts(vector<short> iInput, vector<short> iPositions)
  191. {
  192.     vector<short> oOut;
  193.     for (int i = 0; i < iInput.size(); i++)
  194.     {
  195.         if (vector_contains_short(iPositions, i) < 0)
  196.         {
  197.             oOut.push_back(iInput[i]);
  198.         }
  199.     }
  200.     return oOut;
  201. }
  202.  
  203. static vector<vector<short>> vector_remove_cells(vector<vector<short>> oInput, vector<short> iPositions)
  204. {
  205.     vector<vector<short>> oOut;
  206.     for (int i = 0; i < oInput.size(); i++)
  207.     {
  208.         if (vector_contains_short(iPositions, i) < 0)
  209.         {
  210.             oOut.push_back(oInput[i]);
  211.         }
  212.     }
  213.     return oOut;
  214. }
  215.  
  216. bool ReadData(vector<short> oCells[9][9])
  217. {
  218.     string sInput;
  219.     short iChar = 0;
  220.     if (try_read_file("Project4_input2.in", sInput))
  221.     {
  222.         //remove all non-digit chars
  223.         string sTmp = "";
  224.         for (int i = 0; i < sInput.length(); i++)
  225.         {
  226.             if(is_single_digit(sInput[i]))
  227.             {
  228.                 sTmp += sInput[i];
  229.             }
  230.         }
  231.         sInput = sTmp;
  232.  
  233.         //build cells
  234.         char * oChar = new char[1];
  235.         for (int i = 0; i < 9; i++) //for each row
  236.         {
  237.             for (int j = 0; j < 9; j++) //for each column
  238.             {
  239.                 oChar[0] = sInput[i * 9 + j]; //get corresponding char in string
  240.                 iChar = atoi(oChar); //convert char to int
  241.                 if (iChar > 0) //if cell content isn't zero, set new content
  242.                 {
  243.                     oCells[i][j].clear();
  244.                     oCells[i][j].push_back(iChar);
  245.                 }
  246.             }
  247.         }
  248.  
  249.         delete [] oChar;
  250.  
  251.         return true;
  252.     }
  253.     return false;
  254. }
  255.  
  256. void PrintData(vector<short> oCells[9][9])
  257. {
  258.     cout << cells_to_str(oCells).c_str();
  259. }
  260.  
  261. bool CheckColumn(vector<short> oCells[9][9], int iRow, int iCol)
  262. {
  263.     bool bRemovedPossible = false;
  264.     for (int i = 0; i < 9; i++) //for each row in cell's column
  265.     {
  266.         if (i != iRow && oCells[i][iCol].size() == 1 && vector_remove_short(oCells[iRow][iCol], oCells[i][iCol][0])) //if cell has 1 possible value and we removed it from input cell
  267.         {
  268.             bRemovedPossible = true; //mark flag for "removed possible value"
  269.         }
  270.     }
  271.     return bRemovedPossible;
  272. }
  273.  
  274. bool CheckRow(vector<short> oCells[9][9], int iRow, int iCol)
  275. {
  276.     bool bRemovedPossible = false;
  277.     for (int i = 0; i < 9; i++) //for each column in cell's row
  278.     {
  279.         if (i != iCol && oCells[iRow][i].size() == 1 && vector_remove_short(oCells[iRow][iCol], oCells[iRow][i][0])) //if cell has 1 possible value and we removed it from input cell
  280.         {
  281.             bRemovedPossible = true; //mark flag for "removed possible value"
  282.         }
  283.     }
  284.     return bRemovedPossible;
  285. }
  286.  
  287. bool CheckSubSquare(vector<short> oCells[9][9], int iRow, int iCol)
  288. {
  289.     int iSqrRow = floor((double)iRow / (double)3); //find corresponding square row
  290.     int iSqrCol = floor((double)iCol / (double)3); //find corresponding square column
  291.     bool bRemovedPossible = false;
  292.     for (int i = iSqrRow * 3; i < iSqrRow * 3 + 3; i++) //for each row in cell's square
  293.     {
  294.         for (int j = iSqrCol * 3; j < iSqrCol * 3 + 3; j++) //for each column in cell's square
  295.         {
  296.             if (i != iRow && j != iCol && oCells[i][j].size() == 1 && vector_remove_short(oCells[iRow][iCol], oCells[i][j][0])) //if cell has 1 possible value and we removed it from input cell
  297.             {
  298.                 bRemovedPossible = true; //mark flag for "removed possible value"
  299.             }
  300.         }
  301.     }
  302.     return bRemovedPossible;
  303. }
  304.  
  305. void SolvePuzzle(vector<short> oCells[9][9])
  306. {
  307.     vector<vector<short>> oToSolve; //vector of cells that need solving
  308.     vector<short> iToRemove; //reused vector of cell indeces, to remove from "oToSolve" later
  309.     vector<short> iToSolveX; //keep track of what column each cell in "oToSolve" is in
  310.     vector<short> iToSolveY; //keep track of what row each cell in "oToSolve" is in
  311.     int iPos = -1;
  312.     int i, j;
  313.  
  314.     //find all the cells that originally need to be solved
  315.     for (i = 0; i < 9; i++)
  316.     {
  317.         for (j = 0; j < 9; j++)
  318.         {
  319.             if (oCells[i][j].size() > 1)
  320.             {
  321.                 iToSolveY.push_back(i);
  322.                 iToSolveX.push_back(j);
  323.                 oToSolve.push_back(oCells[i][j]);
  324.             }
  325.         }
  326.     }
  327.  
  328.     //start the loop to solve cells
  329.     for (i = 0; i < 100; i++) //run through 100 times? could improve stopping condition later
  330.     {
  331.         if (oToSolve.size() == 0) //if oToSolve is empty, return; we are done
  332.         {
  333.             return;
  334.         }
  335.  
  336.         //check each cell's column for "possible values" to remove
  337.         iToRemove.clear();
  338.         for (j = 0; j < oToSolve.size(); j++)
  339.         {
  340.             if (CheckColumn(oCells, iToSolveY[j], iToSolveX[j]) && oCells[iToSolveY[j]][iToSolveX[j]].size() == 1) //if some value(s) were removed from cell and it now has only 1 possible value
  341.             {
  342.                 iToRemove.push_back(j); //cell no longer needs to be solved; add it's position to oToRemove, to later remove from oToSolve
  343.             }
  344.         }
  345.  
  346.         oToSolve = vector_remove_cells(oToSolve, iToRemove);
  347.         iToSolveY = vector_remove_shorts(iToSolveY, iToRemove);
  348.         iToSolveX = vector_remove_shorts(iToSolveX, iToRemove);
  349.  
  350.         //check each cell's row for "possible values" to remove
  351.         //same procedure as column check
  352.         iToRemove.clear();
  353.         for (j = 0; j < oToSolve.size(); j++)
  354.         {
  355.             if (CheckRow(oCells, iToSolveY[j], iToSolveX[j]) && oCells[iToSolveY[j]][iToSolveX[j]].size() == 1)
  356.             {
  357.                 iToRemove.push_back(j);
  358.             }
  359.         }
  360.  
  361.         oToSolve = vector_remove_cells(oToSolve, iToRemove);
  362.         iToSolveY = vector_remove_shorts(iToSolveY, iToRemove);
  363.         iToSolveX = vector_remove_shorts(iToSolveX, iToRemove);
  364.  
  365.         //check each cell's square for "possible values" to remove
  366.         //same procedure as column check
  367.         iToRemove.clear();
  368.         for (j = 0; j < oToSolve.size(); j++)
  369.         {
  370.             if (CheckSubSquare(oCells, iToSolveY[j], iToSolveX[j]) && oCells[iToSolveY[j]][iToSolveX[j]].size() == 1)
  371.             {
  372.                 iToRemove.push_back(j);
  373.             }
  374.         }
  375.  
  376.         oToSolve = vector_remove_cells(oToSolve, iToRemove);
  377.         iToSolveY = vector_remove_shorts(iToSolveY, iToRemove);
  378.         iToSolveX = vector_remove_shorts(iToSolveX, iToRemove);
  379.     }
  380. }
Add Comment
Please, Sign In to add comment