so true

          心懷未來,開創未來!
          隨筆 - 160, 文章 - 0, 評論 - 40, 引用 - 0
          數據加載中……

          sudoku

            1 #include <sys/time.h>
            2 #include <stdlib.h>
            3 #include <string.h>
            4 #include <iostream>
            5 #include <vector>
            6 #include <string>
            7 #include <set>
            8 
            9 class Sudoku {
           10 public:
           11     Sudoku(const std::string& question, bool does_try_all_answers = false): m_does_try_all_answers(does_try_all_answers), m_data(9) {
           12         for (int i = 0; i < 9; ++i) {
           13             m_data[i].resize(9);
           14             for (int j = 0; j < 9; ++j) {
           15                 m_data[i][j] = question[i * 9 + j];
           16             }
           17         }
           18     }
           19 
           20     bool Solve() {
           21         return Fill(0, 0);
           22     }
           23 
           24     const std::string GiveOneAnswer() const {
           25         return m_all_answers.empty() ? "" : *m_all_answers.begin();
           26     }
           27 
           28     const std::set<std::string> GiveAllAnswers() const {
           29         return m_all_answers;
           30     }
           31 
           32     static const std::string ProvideOneQuestionRandomly(int min_filled_num = 30) {
           33         std::vector<std::vector<char> > ques(9, std::vector<char>(9, '.'));
           34 
           35         struct timeval cur_tv;
           36         gettimeofday(&cur_tv, NULL);
           37         srand(cur_tv.tv_usec);
           38 
           39         int valid_digit_num = 0;
           40         for (int i = 0; i < 9; ++i) {
           41             for (int j = 0; j < 9; ++j) {
           42                 if (rand() % 81 <= min_filled_num + valid_digit_num / 6) {
           43                     char c = rand() % 9 + '1';
           44 
           45                     if (DoesConflict(ques, i, j, c)) {
           46                         int k = 0;
           47                         for (; k < 8; ++k) {
           48                             if (c == '9') {
           49                                 c = '1';
           50                             }
           51                             if (!DoesConflict(ques, i, j, ++c)) {
           52                                 break;
           53                             }
           54                         }
           55                         if (8 == k) {
           56                             c = '.';
           57                         }
           58                     }
           59 
           60                     valid_digit_num += ('.' != c);
           61                     ques[i][j] = c;
           62                 } else {
           63                     ques[i][j] = '.';
           64                 }
           65             }
           66         }
           67 
           68         char buf[82];
           69         buf[81] = '\0';
           70         for (int i = 0; i < 9; ++i) {
           71             for (int j = 0; j < 9; ++j) {
           72                 buf[i * 9 + j] = ques[i][j];
           73             }
           74         }
           75 
           76         Sudoku sudoku(buf);
           77         sudoku.Solve();
           78         if (81 == sudoku.GiveOneAnswer().size()) {
           79             return buf;
           80         } else {
           81             return ProvideOneQuestionRandomly(min_filled_num);
           82         }
           83 
           84         return buf;
           85     }
           86 
           87     static void PrintSudoku(const std::string& sudoku) {
           88         if (sudoku.size() < 81) {
           89             return;
           90         }
           91 
           92         for (int i = 0; i < 9; ++i) {
           93             for (int j = 0; j < 9; ++j) {
           94                 if (0 != j) {
           95                     std::cout << " ";
           96                 }
           97                 std::cout << sudoku[i * 9 + j];
           98             }
           99             std::cout << std::endl;
          100         }
          101     }
          102 
          103     static bool ValidateOneAnswer(const std::string& answer) {
          104         if (answer.size() != 81) {
          105             return false;
          106         }
          107 
          108         for (int i = 0; i < 9; ++i) {
          109             char hit_h[9] = { '\0' };
          110             char hit_v[9] = { '\0' };
          111             for (int j = 0; j < 9; ++j) {
          112                 if ('.' == answer[i * 9 + j] || ++hit_h[answer[i * 9 + j] - '1'] != 1) { //row check
          113                     return false;
          114                 } else if ('.' == answer[j * 9 + i] || ++hit_v[answer[j * 9 + i] - '1'] != 1) { //column check
          115                     return false;
          116                 }
          117                 if (0 == i % 3 && 0 == j % 3) { //3x3 square check
          118                     char hit_m[9] = { '\0' };
          119                     for (int i2 = i; i2 < i + 3; ++i2) {
          120                         for (int j2 = j; j2 < j + 3; ++j2) {
          121                             if ('.' == answer[i2 * 9 + j2] || ++hit_m[answer[i2 * 9 + j2] - '1'] != 1) {
          122                                 return false;
          123                             }
          124                         }
          125                     }
          126                 }
          127             }
          128         }
          129         return true;
          130     }
          131 
          132 private:
          133     void AddOneAnswer() {
          134         char buf[82];
          135         buf[81] = '\0';
          136 
          137         for (int i = 0; i < 9; ++i) {
          138             for (int j = 0; j < 9; ++j) {
          139                 buf[i * 9 + j] = m_data[i][j];
          140             }
          141         }
          142 
          143         m_all_answers.insert(buf);
          144     }
          145 
          146     static bool DoesConflict(const std::vector<std::vector<char> >& data, int i, int j, char digit) {
          147         for (int k = 0; k < 9; ++k) {
          148             if (digit == data[i][k]) {
          149                 return true;
          150             }
          151             if (digit == data[k][j]) {
          152                 return true;
          153             }
          154         }
          155 
          156         int i0 = i - i % 3;
          157         int j0 = j - j % 3;
          158         for (int i2 = i0; i2 < i0 + 3; ++i2) {
          159             for (int j2 = j0; j2 < j0 + 3; ++j2) {
          160                 if (digit == data[i2][j2]) {
          161                     return true;
          162                 }
          163             }
          164         }
          165 
          166         return false;
          167     }
          168 
          169     bool Fill(int i, int j) {
          170         for (; i < 9; ++i, j = 0) {
          171             for (; j < 9; ++j) {
          172                 if ('.' == m_data[i][j]) {
          173                     for (int k = '1'; k <= '9'; ++k) {
          174                         if (DoesConflict(m_data, i, j, k)) {
          175                             continue;
          176                         }
          177 
          178                         m_data[i][j] = k;
          179                         if (8 == j) {
          180                             if (Fill(i + 1, 0)) {
          181                                 AddOneAnswer();
          182                                 if (!m_does_try_all_answers) {
          183                                     return true;
          184                                 }
          185                             }
          186                         } else {
          187                             if (Fill(i, j + 1)) {
          188                                 AddOneAnswer();
          189                                 if (!m_does_try_all_answers) {
          190                                     return true;
          191                                 }
          192                             }
          193                         }
          194                     }
          195                     m_data[i][j] = '.';
          196                     return false;
          197                 }
          198             }
          199         }
          200 
          201         AddOneAnswer();
          202         return true;
          203     }
          204 
          205 private:
          206     bool m_does_try_all_answers;
          207     std::vector<std::vector<char> > m_data;
          208     std::set<std::string> m_all_answers;
          209 };
          210 
          211 int main(int argc, char* argv[]) {
          212     std::string question;
          213     //with many answers
          214     question = ".2..4836..5163887..63195..45.4.7.2.98..";
          215 
          216     //with just one answer: https://baike.baidu.com/item/%E4%B8%96%E7%95%8C%E6%9C%80%E9%9A%BE%E6%95%B0%E7%8B%AC/13848819
          217     question = "..53..82..7..1.5..4.531..76..328..6.5.9..4.397..";
          218 
          219     bool find_all_answers = false;
          220     if (argc > 1 && 81 == strlen(argv[1])) {
          221         question = argv[1];
          222     } else {
          223         if (argc > 1) {
          224             find_all_answers = true;
          225         }
          226         question = Sudoku::ProvideOneQuestionRandomly();
          227     }
          228 
          229     Sudoku::PrintSudoku(question);
          230 
          231     Sudoku sudoku(question, find_all_answers);
          232     sudoku.Solve();
          233 
          234     const std::set<std::string>& all_answers = sudoku.GiveAllAnswers();
          235     int idx = 0;
          236     for (typeof(all_answers.begin()) iter = all_answers.begin(); all_answers.end() != iter; ++iter) {
          237         std::cout << "answer " << ++idx << " for this sudoku is:" << std::endl;
          238         Sudoku::PrintSudoku(*iter);
          239         if (!Sudoku::ValidateOneAnswer(*iter)) {
          240             std::cout << "answer is not correct: " << *iter << std::endl;
          241         }
          242         std::cout << "[" << *iter << "]" << std::endl;
          243     }
          244     return 0;
          245 }
          246 

          posted on 2017-11-03 17:19 so true 閱讀(188) 評論(0)  編輯  收藏 所屬分類: C&C++Linux

          主站蜘蛛池模板: 曲松县| 东山县| 鲜城| 股票| 凌海市| 满洲里市| 固原市| 昭通市| 治县。| 汝南县| 汽车| 隆德县| 历史| 河间市| 阜城县| 呼图壁县| 静海县| 青海省| 锦屏县| 茌平县| 福安市| 永登县| 株洲县| 图片| 茂名市| 齐齐哈尔市| 固安县| 廉江市| 寻甸| 博罗县| 格尔木市| 佛山市| 孝义市| 紫金县| 黄平县| 高台县| 昌平区| 辽中县| 溧水县| 呼伦贝尔市| 黔西县|