1
+ // Usage: g++ -Ofast solution-1.cpp -o solution && .\solution
2
+
3
+ #include < array>
4
+ #include < bitset>
5
+ #include < iostream>
6
+ #include < memory>
7
+ #include < numeric>
8
+ #include < vector>
9
+ #include < stack>
10
+
11
+ enum BoardStatus {
12
+ NOT_FINISHED,
13
+ FINISHED,
14
+ ILLEGAL
15
+ };
16
+
17
+ class Board {
18
+ private:
19
+ std::array<uint8_t , 81 > cells;
20
+
21
+ public:
22
+ Board (std::array<uint8_t , 81 > cells): cells{cells} {}
23
+
24
+ void set_cell (uint8_t cell, uint8_t val) {
25
+ cells[cell] = val;
26
+ }
27
+
28
+ bool is_cell_empty (uint8_t cell) {
29
+ return !cells[cell];
30
+ }
31
+
32
+ BoardStatus check_board () const {
33
+ auto status = FINISHED;
34
+
35
+ std::bitset<81 >
36
+ lateral_set,
37
+ vertical_set,
38
+ sub_set;
39
+
40
+ for (uint8_t index = 0 ; index < 81 ; index ++) {
41
+ uint8_t
42
+ x = index % 9 ,
43
+ y = index / 9 ,
44
+ val = cells[index ] - 1 ; // 0 is empty, 0 - 1 = 255 (unsigned)
45
+
46
+ if (val > 9 ) {
47
+ status = NOT_FINISHED;
48
+ continue ;
49
+ }
50
+
51
+ uint8_t
52
+ lateral_set_index = y * 9 + val,
53
+ vertical_set_index = val * 9 + x,
54
+ sub_set_index = ((y / 3 * 3 ) + val / 3 ) * 9 + ((x / 3 * 3 ) + val % 3 );
55
+
56
+ if (
57
+ lateral_set.test (lateral_set_index) ||
58
+ vertical_set.test (vertical_set_index) ||
59
+ sub_set.test (sub_set_index)
60
+ ) return ILLEGAL;
61
+
62
+ lateral_set.set (lateral_set_index);
63
+ vertical_set.set (vertical_set_index);
64
+ sub_set.set (sub_set_index);
65
+ }
66
+
67
+ return status;
68
+ }
69
+
70
+ void print () const {
71
+ for (uint8_t index = 0 ; index < 81 ; index ++) {
72
+ int val = static_cast <int >(cells[index ]);
73
+ std::cout << " " << (val ? val : ' ' ) << " " ;
74
+ if (index % 9 == 8 ) std::cout << " \n " ;
75
+ }
76
+ }
77
+ };
78
+
79
+ class BoardStack {
80
+ private:
81
+ std::shared_ptr<Board> board;
82
+ std::stack<std::pair<uint8_t , uint8_t >> move_stack; // std::pair<first: cell, second: val>
83
+
84
+ public:
85
+ BoardStack (std::shared_ptr<Board> board): board{board} {}
86
+
87
+ void make_move (uint8_t cell, uint8_t val) {
88
+ board->set_cell (cell, val);
89
+ move_stack.push ({cell, val});
90
+ }
91
+
92
+ std::pair<uint8_t , uint8_t > undo_move () {
93
+ auto prev_move = move_stack.top ();
94
+ board->set_cell (prev_move.first , 0 );
95
+ move_stack.pop ();
96
+ return prev_move;
97
+ }
98
+
99
+ bool is_empty () const {
100
+ return move_stack.empty ();
101
+ }
102
+ };
103
+
104
+ class SudokuSolver {
105
+ private:
106
+ std::shared_ptr<Board> board;
107
+ BoardStack board_stack;
108
+ std::vector<uint8_t > empty_cells;
109
+
110
+ public:
111
+ SudokuSolver (std::shared_ptr<Board> board):
112
+ board{board},
113
+ board_stack{BoardStack (board)} {
114
+ init_empty_cells ();
115
+ }
116
+
117
+ BoardStatus solve () {
118
+ BoardStatus status;
119
+
120
+ uint8_t current_empty_cell = 0 , last_value = 0 ;
121
+ while ((status = board->check_board ()) != FINISHED) {
122
+ if (status == ILLEGAL || last_value == 9 ) {
123
+ if (board_stack.is_empty ()) break ;
124
+
125
+ auto last_move = board_stack.undo_move ();
126
+ last_value = last_move.second ;
127
+ current_empty_cell--;
128
+ continue ;
129
+ }
130
+
131
+ board_stack.make_move (empty_cells[current_empty_cell++], last_value + 1 );
132
+ last_value = 0 ;
133
+ }
134
+
135
+ return status;
136
+ }
137
+
138
+ private:
139
+ void init_empty_cells () {
140
+ for (uint8_t index = 0 ; index < 81 ; index ++) {
141
+ if (board->is_cell_empty (index )) empty_cells.push_back (index );
142
+ }
143
+ }
144
+ };
145
+
146
+ std::array<uint8_t , 81 > parse () {
147
+ std::array<uint8_t , 81 > cells;
148
+
149
+ for (uint8_t index = 0 ; index < 81 ;) {
150
+ char ch;
151
+ std::cin >> ch;
152
+
153
+ if (!isdigit (ch)) continue ;
154
+
155
+ cells[index ++] = ch - ' 0' ;
156
+ }
157
+
158
+ return cells;
159
+ }
160
+
161
+ void solve () {
162
+ auto cells = parse ();
163
+ auto board = std::make_shared<Board>(Board (cells));
164
+
165
+ if (board->check_board () == ILLEGAL) {
166
+ std::cout << " Initial board is in an illagel state!\n " ;
167
+ return ;
168
+ }
169
+
170
+ SudokuSolver (board).solve ();
171
+ if (board->check_board () == NOT_FINISHED) {
172
+ std::cout << " The board is not solveable!\n " ;
173
+ return ;
174
+ }
175
+
176
+ board->print ();
177
+ }
178
+
179
+ int main (void ) {
180
+ solve ();
181
+ }
0 commit comments