YauhenMardan

Untitled

May 30th, 2019
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.14 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <memory>
  5. using namespace std;
  6.  
  7. const string LETTERS="ABCDEFGHIJKLMNOP";
  8. const int L_SZ=16;
  9. const int S_SZ=4;
  10.  
  11. class Possible {
  12. vector<bool> _b;
  13. public:
  14. Possible() : _b(L_SZ, true) {}
  15. bool is_on(int i) const { return _b[i-1]; }
  16. int count() const { return std::count(_b.begin(), _b.end(), true); }
  17. void eliminate(int i) { _b[i-1] = false; }
  18. int val() const {
  19. auto it = find(_b.begin(), _b.end(), true);
  20. return (it != _b.end() ? 1 + (it - _b.begin()) : -1);
  21. }
  22. string str(int wth) const;
  23. };
  24.  
  25. string Possible::str(int width) const {
  26. string s(width, ' ');
  27. int k = 0;
  28. for (int i = 1; i <= 9; i++) {
  29. if (is_on(i)) s[k++] = 'A' + i;
  30. }
  31. return s;
  32. }
  33.  
  34. class Sudoku {
  35. vector<Possible> _cells;
  36. static vector< vector<int> > _group, _neighbors, _groups_of;
  37.  
  38. bool eliminate(int k, int val);
  39. public:
  40. Sudoku(string s);
  41. static void init();
  42.  
  43. Possible possible(int k) const { return _cells[k]; }
  44. bool is_solved() const;
  45. bool assign(int k, int val);
  46. int least_count() const;
  47. void write(ostream& o) const;
  48. };
  49.  
  50. bool Sudoku::is_solved() const {
  51. for (int k = 0; k < _cells.size(); k++) {
  52. if (_cells[k].count() != 1) {
  53. return false;
  54. }
  55. }
  56. return true;
  57. }
  58.  
  59. void Sudoku::write(ostream& o) const {
  60. int width = 1;
  61. for (int k = 0; k < _cells.size(); k++) {
  62. width = max(width, 1 + _cells[k].count());
  63. }
  64. const string sep(3 * width, '-');
  65. for (int i = 0; i < 9; i++) {
  66. if (i == 3 || i == 6) {
  67. o << sep << "+-" << sep << "+" << sep << endl;
  68. }
  69. for (int j = 0; j < 9; j++) {
  70. if (j == 3 || j == 6) o << "| ";
  71. o << _cells[i*9 + j].str(width);
  72. }
  73. o << endl;
  74. }
  75. }
  76.  
  77. vector< vector<int> >
  78. Sudoku::_group(27), Sudoku::_neighbors(81), Sudoku::_groups_of(81);
  79.  
  80. void Sudoku::init() {
  81. for (int i = 0; i < 9; i++) {
  82. for (int j = 0; j < 9; j++) {
  83. const int k = i*9 + j;
  84. const int x[3] = {i, 9 + j, 18 + (i/3)*3 + j/3};
  85. for (int g = 0; g < 3; g++) {
  86. _group[x[g]].push_back(k);
  87. _groups_of[k].push_back(x[g]);
  88. }
  89. }
  90. }
  91. for (int k = 0; k < _neighbors.size(); k++) {
  92. for (int x = 0; x < _groups_of[k].size(); x++) {
  93. for (int j = 0; j < 9; j++) {
  94. int k2 = _group[_groups_of[k][x]][j];
  95. if (k2 != k) _neighbors[k].push_back(k2);
  96. }
  97. }
  98. }
  99. }
  100.  
  101. bool Sudoku::assign(int k, int val) {
  102. for (int i = 1; i <= 9; i++) {
  103. if (i != val) {
  104. if (!eliminate(k, i)) return false;
  105. }
  106. }
  107. return true;
  108. }
  109.  
  110. bool Sudoku::eliminate(int k, int val) {
  111. if (!_cells[k].is_on(val)) {
  112. return true;
  113. }
  114. _cells[k].eliminate(val);
  115. const int N = _cells[k].count();
  116. if (N == 0) {
  117. return false;
  118. } else if (N == 1) {
  119. const int v = _cells[k].val();
  120. for (int i = 0; i < _neighbors[k].size(); i++) {
  121. if (!eliminate(_neighbors[k][i], v)) return false;
  122. }
  123. }
  124. for (int i = 0; i < _groups_of[k].size(); i++) {
  125. const int x = _groups_of[k][i];
  126. int n = 0, ks;
  127. for (int j = 0; j < 9; j++) {
  128. const int p = _group[x][j];
  129. if (_cells[p].is_on(val)) {
  130. n++, ks = p;
  131. }
  132. }
  133. if (n == 0) {
  134. return false;
  135. } else if (n == 1) {
  136. if (!assign(ks, val)) {
  137. return false;
  138. }
  139. }
  140. }
  141. return true;
  142. }
  143.  
  144. int Sudoku::least_count() const {
  145. int k = -1, min;
  146. for (int i = 0; i < _cells.size(); i++) {
  147. const int m = _cells[i].count();
  148. if (m > 1 && (k == -1 || m < min)) {
  149. min = m, k = i;
  150. }
  151. }
  152. return k;
  153. }
  154.  
  155. Sudoku::Sudoku(string s)
  156. : _cells(81)
  157. {
  158. int k = 0;
  159. for (int i = 0; i < s.size(); i++) {
  160. if (s[i] >= '1' && s[i] <= '9') {
  161. if (!assign(k, s[i] - '0')) {
  162. cerr << "error" << endl;
  163. return;
  164. }
  165. k++;
  166. } else if (s[i] == '0' || s[i] == '.') {
  167. k++;
  168. }
  169. }
  170. }
  171.  
  172. unique_ptr<Sudoku> solve(unique_ptr<Sudoku> S) {
  173. if (S == nullptr || S->is_solved()) {
  174. return S;
  175. }
  176. int k = S->least_count();
  177. Possible p = S->possible(k);
  178. for (int i = 1; i <= 9; i++) {
  179. if (p.is_on(i)) {
  180. unique_ptr<Sudoku> S1(new Sudoku(*S));
  181. if (S1->assign(k, i)) {
  182. if (auto S2 = solve(std::move(S1))) {
  183. return S2;
  184. }
  185. }
  186. }
  187. }
  188. return {};
  189. }
  190.  
  191. int main() {
  192. Sudoku::init();
  193. string line;
  194. while (getline(cin, line)) {
  195. if (auto S = solve(unique_ptr<Sudoku>(new Sudoku(line)))) {
  196. S->write(cout);
  197. } else {
  198. cout << "No solution";
  199. }
  200. cout << endl;
  201. }
  202. }
Advertisement
Add Comment
Please, Sign In to add comment