Advertisement
Guest User

dgh

a guest
Jan 23rd, 2020
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.29 KB | None | 0 0
  1. /*
  2. Suduko Solver
  3. by someone
  4.  
  5. examples of sudoku available at http://magictour.free.fr/top1465
  6. */
  7.  
  8. #include <iostream>
  9. #include <string>
  10. //#include <array>
  11. #include <algorithm>
  12. #include <exception>
  13. #include <cctype>
  14. #include <vector>
  15. #include <memory>
  16.  
  17. class InitNbrSudokuError : public std::runtime_error
  18. {
  19. public :
  20.  
  21.     InitNbrSudokuError(std::string str) : std::runtime_error(str) {}
  22.  
  23.     enum TypeErr
  24.     {
  25.         err_alloc
  26.     };
  27.    
  28.     TypeErr getErrType()
  29.     {
  30.         return err_alloc;
  31.     }
  32. };
  33.  
  34. class NbrSudoku
  35. {
  36. public :
  37.    
  38.     NbrSudoku();
  39.     void init(int val);
  40.    
  41.     NbrSudoku(const NbrSudoku& val);
  42.    
  43.     int getNbr() const;
  44.     std::vector<int>& getVec() const;
  45.    
  46.     bool isValid() const;
  47.    
  48.     void addLittleNbr(int val);
  49.    
  50.     void putOffLitteNbr(int val);
  51.    
  52.     void set(int val);
  53.    
  54.     void setIfOnlyOne();
  55.    
  56. private :
  57.  
  58.     int nbr;
  59.    
  60.     std::unique_ptr<std::vector<int>> listInt;
  61. };
  62.  
  63. std::ostream& operator<<(std::ostream& outuput, NbrSudoku a);
  64. //external overloading lul
  65.  
  66. NbrSudoku::NbrSudoku()
  67. {
  68.     listInt = nullptr;
  69. }
  70.  
  71. NbrSudoku::NbrSudoku(const NbrSudoku& val)
  72. {
  73.     nbr = val.nbr;
  74.    
  75.     try
  76.     {
  77.         listInt = std::unique_ptr<std::vector<int>>(new std::vector<int> {val.getVec()});
  78.     }
  79.     catch (const InitNbrSudokuError& e)
  80.     {
  81.         listInt = std::unique_ptr<std::vector<int>>(new std::vector<int> {});
  82.     }
  83. }
  84.  
  85. void NbrSudoku::addLittleNbr(int val)
  86. {
  87.     listInt->push_back(val);
  88. }
  89.  
  90. int NbrSudoku::getNbr() const
  91. {
  92.     return nbr;
  93. }
  94.  
  95. bool NbrSudoku::isValid() const
  96. {
  97.     if(nbr == 0)
  98.     {
  99.         return false; //the vector is used
  100.     }
  101.     else
  102.     {
  103.         return true;
  104.     }
  105. }
  106.  
  107. std::vector<int>& NbrSudoku::getVec() const
  108. {
  109.     if(listInt != nullptr)
  110.     {
  111.         return *listInt;
  112.     }
  113.     else
  114.     {
  115.         throw InitNbrSudokuError("There aren't any vector to give here, sorry");
  116.     }
  117. }
  118.  
  119. void NbrSudoku::init(int val)
  120. {
  121.     nbr = val;
  122.        
  123.     if(nbr == 0) //if the case is empty
  124.     {
  125.         listInt = std::unique_ptr<std::vector<int>>(new std::vector<int> {}) ;
  126.     }
  127. }
  128.  
  129. std::ostream& operator<<(std::ostream& outuput, NbrSudoku a)
  130. {
  131.     if(a.isValid())
  132.     {
  133.         outuput << a.getNbr();
  134.     }
  135.     else
  136.     {
  137.         for(unsigned int i = 0; i < a.getVec().size() ; i++)
  138.         {
  139.             outuput << a.getVec()[i] << " ";
  140.         }
  141.     }
  142.    
  143.     return outuput;
  144. }
  145.  
  146. void NbrSudoku::putOffLitteNbr(int val)
  147. {
  148.     std::vector<int>::iterator listVirer {std::find_if(listInt->begin(), listInt->end(), [val](int val_) -> bool {return val == val_;})};
  149.    
  150.     if(listVirer != listInt->end())
  151.     {
  152.         listInt->erase(listVirer);
  153.     }
  154. }
  155.  
  156. void NbrSudoku::set(int val)
  157. {
  158.     if(val >= 0 && val <= 10)
  159.     {
  160.         nbr = val;
  161.     }
  162. }
  163.  
  164. class Sudoku
  165. {
  166. public :
  167.  
  168.     Sudoku(std::string sentence);
  169.    
  170.     std::string toString();
  171.    
  172.     bool isValid();
  173.    
  174.     void addLittleNbrEveywhere();
  175.     void addLittleNbrForOne(int x, int y);
  176.    
  177.     void addBigNbr(int x, int y, int val);
  178.    
  179.     std::ostream& coutLittleNbr(std::ostream& prut);
  180.     std::ostream& coutLittleNbrInGrid(std::ostream& prut);
  181.     std::ostream& coutOneLittleNbrInGrid(std::ostream& prut, int nbr);
  182.    
  183.     void solve(); //c'est si symple que ça
  184.    
  185.     bool setIfOnlyOne();
  186.     bool setIfOnlyOneOnThisBloc();
  187.     bool setIfOnlyOneLineRowCase();
  188.    
  189. private :
  190.  
  191.     std::vector<std::vector<NbrSudoku>> listNbr;
  192.     //Wide spaces are saved into 0
  193. };
  194.  
  195. Sudoku::Sudoku(std::string sentence)
  196. {
  197.     listNbr  = std::vector<std::vector<NbrSudoku>>
  198.                 {9, std::vector<NbrSudoku>
  199.                     {9, NbrSudoku {/* default constructor */}   }  };
  200.  
  201.     if(sentence.size() != 81 ||
  202.         !std::any_of(sentence.begin(), sentence.end(), [](char a) -> bool
  203.             {
  204.                 if(!isdigit(a) || a != '.')
  205.                 {
  206.                     return true;
  207.                 }
  208.                
  209.                 return false;
  210.             }) )
  211.     {
  212.         throw std::runtime_error("This isn't a valid input");
  213.     }
  214.    
  215.     for(unsigned int i = 0; i < listNbr.size() ; i++)
  216.     {
  217.         for(unsigned int j = 0; j < listNbr[i].size() ; j++)
  218.         {
  219.             char nbr = sentence[i * 9 + j];
  220.            
  221.             if(isdigit(nbr))
  222.             {
  223.                 listNbr[i][j].init(nbr - '0');
  224.             }
  225.             else if(nbr == '.')
  226.             {
  227.                 listNbr[i][j].init(0);
  228.             }
  229.             else
  230.             {
  231.                 throw std::runtime_error("Something went wrong");
  232.             }
  233.         }
  234.     }
  235. }
  236.  
  237. std::string Sudoku::toString()
  238. {
  239.     std::string output;
  240.    
  241.     for(unsigned int i = 0; i < listNbr.size() ; i++)
  242.     {
  243.         if(i % 3 == 0)
  244.         {
  245.             output += "+ - - - + - - - + - - - +\n";
  246.         }
  247.        
  248.         for(unsigned int j = 0 ; j < listNbr.size() ; j++)
  249.         {
  250.             if(j % 3 == 0)
  251.             {
  252.                 output += "| ";
  253.             }
  254.            
  255.             if(listNbr[i][j].getNbr() == 0)
  256.             {
  257.                 output += ".";
  258.             }
  259.             else
  260.             {
  261.                 output += std::to_string(listNbr[i][j].getNbr());
  262.             }
  263.            
  264.             output += " ";
  265.         }
  266.         output += "|\n";
  267.     }
  268.    
  269.     output += "+ - - - + - - - + - - - +\n";
  270.    
  271.     return output;
  272. }
  273.  
  274. bool Sudoku::isValid()
  275. {
  276.    
  277.    
  278.     //try for each ligne
  279.     for(unsigned int i = 0 ; i < listNbr.size() ; i++)
  280.     {
  281.         std::vector<int> listFind;
  282.        
  283.         for(unsigned int j = 0 ; j < listNbr[i].size() ; j++)
  284.         {
  285.             int val = listNbr[i][j].getNbr();
  286.            
  287.             listFind.push_back(val);
  288.            
  289.             if(any_of(listFind.begin(), listFind.end(),
  290.                 [val](int nbrTest) -> bool
  291.                 {
  292.                     return nbrTest == val;
  293.                 }))
  294.             {
  295.                 //the "pitu" come back
  296.                 std::cout << "pitu" << std::endl;
  297.                
  298.                 return false;
  299.             }
  300.         }
  301.        
  302.         if(listFind.size() != 9)
  303.         {
  304.             return false;
  305.         }
  306.     }
  307.    
  308.     //try for each row
  309.     for(unsigned int i = 0 ; i < listNbr[0].size() ; i++)
  310.     {
  311.         std::vector<int> listFind;
  312.        
  313.         for(unsigned int j = 0 ; j < listNbr.size() ; j++)
  314.         {
  315.             int val {listNbr[j][i].getNbr()};
  316.            
  317.             listFind.push_back(val);
  318.            
  319.             if(std::any_of(listFind.begin(), listFind.end(),
  320.                 [val](int nbrTest) -> bool
  321.                 {
  322.                     return nbrTest == val;
  323.                 }))
  324.             {
  325.                 std::cout << "pruti" << std::endl;
  326.                 return false; //salut ca va
  327.             }
  328.         }
  329.        
  330.         if(listFind.size() != 9)
  331.         {
  332.             return false;
  333.         }
  334.     }
  335.    
  336.     //the hard part : the cases
  337.     for(unsigned int nbrCase = 0; nbrCase < 9 ; nbrCase++)
  338.     {
  339.         std::vector<int> listFind;
  340.         for(unsigned int i = nbrCase % 3 * 3; i < (nbrCase) % 3 * 3 + 3; i++)
  341.         {
  342.             std::vector<int> listFind;
  343.            
  344.             for(unsigned int j = nbrCase / 3 * 3; j < (nbrCase) / 3 * 3 + 3; j++)
  345.             {
  346.                 int val {listNbr[j][i].getNbr()};
  347.                
  348.                 listFind.push_back(val);
  349.            
  350.                 if(std::any_of(listFind.begin(), listFind.end(),
  351.                     [val](int nbrTest) -> bool
  352.                     {
  353.                         return nbrTest == val;
  354.                     }))
  355.                 {
  356.                     std::cout << "pruti" << std::endl;
  357.                     return false; //salut ca va
  358.                 }
  359.             }
  360.         }
  361.     }
  362.    
  363.     return true;
  364. }
  365.  
  366. bool ifIsNotInVect(int valTest, std::vector<int> v)
  367. {
  368.     return !isInVect(valTest, v);
  369. }
  370.  
  371. bool isInVect(int valTest, std::vector<int> v)
  372. {
  373.     return std::find(v.begin(), v.end(), valTest) != v.end();
  374. }
  375.  
  376. void Sudoku::addLittleNbrForOne(int x, int y)
  377. {
  378.     std::vector<int> nbrFind;
  379.    
  380.     for(unsigned int i = 0; i < listNbr.size() ; i++)
  381.     {
  382.         if(listNbr[i][y].getNbr() != 0 && ifIsNotInVect(listNbr[i][y].getNbr(), nbrFind) )
  383.         {
  384.             nbrFind.push_back(listNbr[i][y].getNbr());
  385.         }
  386.     }
  387.    
  388.     //for each line
  389.     for(unsigned int j = 0; j < listNbr[x].size() ; j++)
  390.     {
  391.         if(listNbr[x][j].getNbr() != 0 && ifIsNotInVect(listNbr[x][j].getNbr(), nbrFind))
  392.         {
  393.             nbrFind.push_back(listNbr[x][j].getNbr());
  394.         }
  395.     }
  396.    
  397.     //for each case
  398.     int nbrCase = (x / 3) * 3 + (y / 3);
  399.    
  400.     std::cout << nbrCase << " " << x << " " << y <<  " " << listNbr[x][y].getNbr() << std::endl;
  401.    
  402.     for(unsigned int i = nbrCase % 3 * 3; i < (nbrCase) % 3 * 3 + 3; i++)
  403.     {
  404.         std::vector<int> listFind;
  405.            
  406.         for(unsigned int j = nbrCase / 3 * 3; j < (nbrCase) / 3 * 3 + 3; j++)
  407.         {
  408.             if(listNbr[j][i].getNbr() != 0 && ifIsNotInVect(listNbr[j][i].getNbr(), nbrFind))
  409.             {
  410.                 nbrFind.push_back(listNbr[j][i].getNbr());
  411.             }
  412.            
  413.             //std::cout << listNbr[j][i].getNbr() << " ";
  414.         }
  415.     }
  416.    
  417.     std::cout << std::endl;
  418.    
  419.     for(int i = 1; i <= 9; i++)
  420.     {
  421.         if(std::count(nbrFind.begin(), nbrFind.end(), i) == 0)
  422.         {
  423.             listNbr[x][y].addLittleNbr(i);
  424.         }
  425.     }
  426. }
  427.  
  428. void Sudoku::addLittleNbrEveywhere()
  429. {
  430.     for(unsigned int i = 0; i < listNbr.size() ; i++)
  431.     {
  432.         for(unsigned int j = 0; j < listNbr[i].size() ; j++)
  433.         {
  434.             if(listNbr[i][j].getNbr() == 0)
  435.             {
  436.                 addLittleNbrForOne(i, j);
  437.             }
  438.         }
  439.     }
  440. }
  441.  
  442. void Sudoku::addBigNbr(int x, int y, int val)
  443. {
  444.     listNbr[x][y].set(val);
  445.    
  446.     for(int i = 0; i < listNbr.size() ; i++)
  447.     {
  448.         listNbr[i][y].putOffLitteNbr(val);
  449.     }
  450.    
  451.     for(int j = 0; j < listNbr[x].size(); j++)
  452.     {
  453.         listNbr[x][j].putOffLitteNbr(val);
  454.     }
  455.    
  456.     int nbrCase = (x / 3) * 3 + (y / 3);
  457.    
  458.     for(int i = nbrCase % 3 * 3; i < (nbrCase) % 3 * 3 + 3; i++)
  459.     {
  460.         for(int j = (nbrCase) / 3 * 3; j < (nbrCase) / 3 * 3 + 3; j++)
  461.         {
  462.             listNbr[j][i].putOffLitteNbr(val);
  463.         }
  464.     }
  465. }
  466.  
  467. std::ostream& Sudoku::coutLittleNbr(std::ostream& prut)
  468. {
  469.     for(unsigned int i = 0 ; i < listNbr.size() ; i++)
  470.     {
  471.         for(unsigned int j = 0 ; j < listNbr[i].size() ; j++)
  472.         {
  473.             prut << listNbr[i][j] << std::endl;
  474.         }
  475.         prut << std::endl;
  476.     }
  477.     return prut;
  478. }
  479.  
  480. void Sudoku::solve()
  481. {
  482.     bool haveAChange {true};
  483.    
  484.     while(haveAChange)
  485.     {
  486.         haveAChange = false;
  487.        
  488.         haveAChange = setIfOnlyOne();
  489.        
  490.         haveAChange = setIfOnlyOneLineRowCase()
  491.     }
  492. }
  493.  
  494. bool Sudoku::setIfOnlyOne()
  495. {
  496.     bool haveAChange {false};
  497.    
  498.     for(int i = 0; i < listNbr.size(); i++)
  499.     {
  500.         for(int j = 0 ; j < listNbr[i].size(); j++)
  501.         {
  502.             if(listNbr[i][j].isValid() && listNbr[i][j].getVec().size() == 1)
  503.             {
  504.                 addBigNbr(i, j, listNbr[i][j].getVec().front());
  505.                 haveAChange = true;
  506.             }
  507.         }
  508.     }
  509.    
  510.     return haveAChange;
  511. }
  512.  
  513. bool Sudoku::setIfOnlyOneLineRowCase()
  514. {
  515.     bool haveAChange {false};
  516.    
  517.     for(int nbrTest = 1; nbrTest <= 9; nbrTest++)
  518.     {
  519.         for(int i = 0; i < listNbr.size(); i++)
  520.         {
  521.             int find = 0;
  522.            
  523.             for(int j = 0; j < listNbr[i].size(); j++)
  524.             {
  525.                 if(isInVect(nbrTest, listNbr[i][j].getVec()) )
  526.                 {
  527.                     find++;
  528.                 }
  529.             }
  530.            
  531.             if(find == 1)
  532.             {
  533.                 for(int j = 0; j < listNbr[i].size(); j++)
  534.                 {
  535.                     if(isInVect(nbrTest, listNbr[i][j].getVec()) )
  536.                     {
  537.                         addBigNbr(i, j, nbrTest);
  538.                     }
  539.                 }
  540.             }
  541.         }
  542.     }
  543. }
  544.  
  545. bool Sudoku::setIfOnlyOneOnThisBloc()
  546. {
  547.     int nbreLittleCase = 0;
  548.    
  549.     for(int nbrCase = 0; nbrCase < 9; nbrCase++)
  550.     {
  551.         std::vector<int> listPossibility {9, 0};
  552.        
  553.         nbreLittleCase++;
  554.        
  555.         for(int i = nbrCase % 3 * 3; i < (nbrCase) % 3 * 3 + 3; i++)
  556.         {
  557.             for(int j = (nbrCase) / 3 * 3; j < (nbrCase) / 3 * 3 + 3; j++)
  558.             {
  559.                 if(listNbr[j][i].isValid())
  560.                 {
  561.                     listPossibility[listNbr[j][i].getNbr()]++;
  562.                 }
  563.                 else
  564.                 {
  565.                     for(int k = 0; k < listNbr[j][i].getVec().size(); k++)
  566.                     {
  567.                         listPossibility[listNbr[j][i].getVec()[k]]++;
  568.                     }
  569.                 }
  570.             }
  571.         }
  572.        
  573.        
  574.     }
  575. }
  576.  
  577.  
  578. std::ostream& Sudoku::coutLittleNbrInGrid(std::ostream& prut)
  579. {
  580.     for(int i = 1; i <= 9; i++)
  581.     {
  582.         coutOneLittleNbrInGrid(prut, i);
  583.         prut << std::endl << std::endl;
  584.     }
  585. }
  586.  
  587. std::ostream& Sudoku::coutOneLittleNbrInGrid(std::ostream& output, int nbr)
  588. {
  589.     for(unsigned int i = 0; i < listNbr.size() ; i++)
  590.     {
  591.         if(i % 3 == 0)
  592.         {
  593.             output << "+ - - - + - - - + - - - +" << std::endl;
  594.         }
  595.        
  596.         for(unsigned int j = 0 ; j < listNbr.size() ; j++)
  597.         {
  598.             if(j % 3 == 0)
  599.             {
  600.                 if(j != 0)
  601.                 {
  602.                     output << " ";
  603.                 }
  604.                
  605.                 output << "|";
  606.             }
  607.            
  608.             if(listNbr[i][j].isValid() && listNbr[i][j].getNbr() == nbr)
  609.             {
  610.                 output << "*" << listNbr[i][j].getNbr();
  611.             }
  612.             else if(std::count(listNbr[i][j].getVec().begin(), listNbr[i][j].getVec().end(), nbr))
  613.             {
  614.                 output << " " << nbr;
  615.             }
  616.             else
  617.             {
  618.                 output << " .";
  619.             }
  620.         }
  621.         output << " |" << std::endl;
  622.     }
  623.    
  624.     output << "+ - - - + - - - + - - - +" << std::endl;
  625.    
  626.     return output;
  627. }
  628.  
  629. std::ostream& operator<<(std::ostream& output, Sudoku s)
  630. {
  631.     output << s.toString();
  632.     return output;
  633. }
  634.  
  635. int main()
  636. {
  637.     try
  638.     {
  639.         Sudoku a("4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........");
  640.         std::cout << a << std::endl;
  641.         std::cout << a.isValid() << std::endl << std::endl;
  642.        
  643.         a.coutLittleNbrInGrid(std::cout);
  644.        
  645.         a.addLittleNbrEveywhere();
  646.        
  647.         std::cout << std::endl << std::endl;
  648.        
  649.         //a.coutLittleNbr(std::cout);
  650.         //std::cout << std::endl;
  651.         // ui c la flemme de surcharger l'operateur << une deusième fois
  652.        
  653.         std::cout << a << std::endl;
  654.        
  655.         //a.solve();
  656.        
  657.         //std::cout << a << std::endl;
  658.        
  659.         a.coutLittleNbrInGrid(std::cout);
  660.     }
  661.     catch (const std::exception& e)
  662.     {
  663.         std::cout << "error : " << e.what() << std::endl;
  664.     }
  665.  
  666.     return 0;
  667. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement