After analyzing the source code of Muduo Network Library, we try to complete an efficient Sudoku and eight-digit problem solving server.
First of all, why choose these two questions? Sudoku has always been a favorite problem for aboutspeaker teachers, and has been mentioned several times in the Muduo network library for example. Eight digital problem is my favorite problem, so this comprehensive completion of solving Sudoku and eight digital problems of efficient service-side procedures.
The technical content of writing such a seemingly simple service program is much higher than the so-called control-piling development, although there are muduo network libraries that help us handle network events, we only need to focus on setconnectioncallback () and Setmessagecallback ( ) events, but both are CPU-intensive tasks that require efficient algorithms while using multicore acceleration (ThreadPool). We use the dancing links algorithm to solve the Sudoku problem, using a * algorithm + Cantor to solve eight digital problems and print the operation path. The algorithm is written by me and implemented by the online Judge test data (Hdu 1043, POJ 3074), the correctness of a certain guarantee.
About the algorithms involved in this is not mentioned here, please the weak algorithm base readers to view the following reference links:
Dancing Links algorithm: http://wenku.baidu.com/link?url=ENP5vkf6Ws54iuVhEFFvnkLrgWuv_ Ukhvnfbufszeifqjrzx-hxja-laccl6bkos-x1sdv3uyv0vxsf2j95lrw_p_fyqkdw2zk2lmzlcxq3
A * algorithm:http://www.cnblogs.com/luxiaoxun/archive/2012/08/05/2624115.html
Cantor expand : http://baike.baidu.com/link?url=kBFlr76wrl2UsxzU_pNNJpCtIvOa8LSjM5_ B6di6xbhekb00ax8fr7ybktqhbzt-dnk4v90vrlh1kujtqzazb_
(i) Sudoku
The input format is 81 numbers, followed by the checkerboard from left to right, from top to bottom, preceded by a ":" Delimited sequence number and flags, for example:
00000000000.....00000 or a:00000000000...00000, there is a solution to return the answer string, no solution returned "no solution"
The core code classes of the Sudoku algorithm are as follows:
struct Node;typedef Node column;struct node{node* left; node* right; node* up; Node* down; column* Col; int name; int size;}; const int kmaxnodes = 1 + 81*4 + 9*9*9*4;//const int kmaxcolumns = 400;const int krow = +, Kcol = $, Kbox = 300;exter n const char knosolution[] = "nosolution"; class sudokusolver{Public:sudokusolver (int board[kcells]): Inout_ (boa RD), Cur_node_ (0) {stack_.reserve (100); Root_ = New_column (); Root_->left = Root_->right = Root_; memset (columns_, 0, sizeof (columns_)); BOOL Rows[kcells][10] = {{false}}; BOOL Cols[kcells][10] = {{false}}; BOOL Boxes[kcells][10] = {{false}}; for (int i = 0; i < kcells; ++i) {int row = I/9; int col = i% 9; int box = row/3*3 + COL/3; int val = inout_[i]; Rows[row][val] = true; Cols[col][val] = true; Boxes[box][val] = true; } for(int i = 0; i < kcells; ++i) {if (inout_[i] = = 0) {append_column (i); }} for (int i = 0, i < 9; ++i) {for (int v = 1; v < ++v) {if (!rows[i ][V]) Append_column (Get_row_col (i, v)); if (!cols[i][v]) append_column (Get_col_col (i, v)); if (!boxes[i][v]) append_column (Get_box_col (i, v)); }} for (int i = 0; i < kcells; ++i) {if (inout_[i] = = 0) {int row = I/9; int col = i% 9; int box = row/3*3 + COL/3; int val = inout[i]; for (int v = 1; v < ++v) {if (!) ( ROWS[ROW][V] | | COLS[COL][V] | | Boxes[box][v]) {node* n0 = New_row (i); node* nr = New_row (Get_row_col (row, v)); node* NC = New_row (Get_col_col (col, v)); node* NB = New_row (get_box_col (box, v)); Put_left (N0, NR); Put_left (N0, NC); Put_left (N0, NB); }}}}} bool Solve () {if (Root_->left = = Root_) {for (s ize_t i = 0; I < stack_.size (); ++i) {node* n = stack_[i]; int cell =-1; int val =-1; while (cell = =-1 | | val = = 1) {if (N->name <) cell = n->name; else val = n->name% 10; n = n->right; }//assert (Cell! =-1 && val! =-1); Inout_[cell] = val; } return true; } column* Const COL = get_min_column (); Cover (COL); for (node* row = col->down; row! = col; row = Row->down){stack_.push_back (row); for (node* j = row->right; J! = row; j = j->right) {cover (j->col); } if (solve ()) {return true; } stack_.pop_back (); for (node* j = row->left; J! = row; j = j->left) {uncover (J->col); }} uncover (col); return false; } private:column* Root_; int* Inout_; column* columns_[400]; Std::vector<node*> Stack_; Node Nodes_[kmaxnodes]; int cur_node_; column* new_column (int n = 0) {assert (Cur_node_ < kmaxnodes); column* C = &nodes_[cur_node_++]; memset (c, 0, sizeof (Column)); C->left = C; C->right = C; C->up = C; C->down = C; C->col = C; C->name = n; return C; } void Append_column (int n) {assert (columns_[n] = = NULL); column* C = New_column (n); Put_left (Root_, C); Columns_[n] = c; } node* new_row (int col) {assert (Columns_[col]! = NULL); ASSERT (Cur_node_ < kmaxnodes); node* r = &nodes_[cur_node_++]; node* r = new Node; memset (r, 0, sizeof (Node)); R->left = R; R->right = R; R->up = R; R->down = R; R->name = col; R->col = Columns_[col]; Put_up (R->col, R); return R; } int Get_row_col (int row, int val) {return krow+row*10+val; } int Get_col_col (int col, int val) {return kcol+col*10+val; } int get_box_col (int box, int val) {return kbox+box*10+val; } column* Get_min_column () {column* c = root_->right; int min_size = c->size; if (Min_size > 1) {for (column* cc = c->right; cc! = root_; cc = cc->right) {if (min_ Size > Cc->size) {c = cc; Min_size = cc->size; if (min_size <= 1) break; }}} return C; } void Cover (column* c) {c->right->left = c->left; C->left->right = c->right; for (node* row = c->down; row! = c; row = Row->down) {for (node* j = row->right; J! = row; j = j-> right) {j->down->up = j->up; J->up->down = j->down; j->col->size--; }}} void Uncover (column* c) {for (node* row = c->up; row! = c; row = Row->up) { for (node* j = row->left; J! = row; j = j->left) {j->col->size++; J->down->up = j; J->up->down = j; }} c->right->left = C; C->left->right = C; } void Put_left (column* old, column* nnew) { Nnew->left = old->left; Nnew->right = old; Old->left->right = nnew; Old->left = nnew; } void Put_up (column* old, node* nnew) {nnew->up = old->up; Nnew->down = old; Old->up->down = nnew; Old->up = nnew; old->size++; Nnew->col = old; }};string Solvesudoku (const stringpiece& puzzle) {assert (puzzle.size () = = Kcells); string result = Knosolution; int Board[kcells] = {0}; bool valid = true; for (int i = 0; i < kcells; ++i) {board[i] = puzzle[i]-' 0 '; valid = valid && (0 <= board[i] && Board[i] <= 9); } if (valid) {SudokuSolver s (board); if (S.solve ()) {result.clear (); Result.resize (Kcells); for (int i = 0; i < kcells; ++i) {Result[i] = static_cast<char> (board[i] + ' 0 '); }}} return result;
(ii) eight digital
The input data is a 9-character string, and the current space is represented by X. There is a solution to return the Operation string L (left), R (right), U (UP), D (bottom), or the minimum number of steps to move the path, no solution returns "no solution".
To speak here, in addition to using a * algorithm for heuristic search, the re-use of Cantor deployment, can effectively save space and improve efficiency (only using the Int record State).
Eight Digital algorithm core code:
struct node{int maze[3][3]; int fun_h,fun_g; int pos_x,pos_y; int Hash; BOOL operator< (const Node NT) const{return fun_h+fun_g>nt.fun_h+nt.fun_g; } bool Check () {if (pos_x>=0 && pos_x<3 && pos_y>=0 && pos_y<3) return true; return false; }};const int maxnum=370000;int hash[9]={1,1,2,6,24,120,720,5040,40320};//0!~8!int dest=46233;int vis[MAXNUM];int Pre [Maxnum];int WAY[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//4 Waysclass eightsolver{public:eightsolver (string s) {memset (vis,-1,sizeof (VIS)); memset (pre,-1,sizeof (pre)); int k=0; for (int i=0;i<3;i++) for (int j=0;j<3;j++) {if (s[k]<= ' 9 ' &&A mp;s[k]>= ' 0 ') | | s[k]== ' x ') {if (s[k]== ' x ') {b egnode.maze[i][j]=0; Begnode.pos_x=i; Begnode.pos_y=j; } else begnode.maze[i][j]=s[k]-' 0 '; } k++; } begnode.hash=gethash (Begnode); begnode.fun_g=0; Begnode.fun_h=geth (Begnode); Vis[begnode.hash]=1; } string Getans () {string ans= ""; int nxt=dest; while (pre[nxt]!=-1) {switch (VIS[NXT]) {case 0:ans+= ' r '; ; Case 1:ans+= ' l '; Case 2:ans+= ' d '; Case 3:ans+= ' u '; } NXT=PRE[NXT]; } reverse (Ans.begin (), Ans.end ()); return ans; } bool IsOK () {std::vector<int> V; for (int i=0;i<3;i++) for (int j=0;j<3;j++) V.push_back (Begnode.maze[i][j]); int sum=0; for (int i=0;i<9;i++) for (int j=i+1;j<9;j++) if (v[j]&&v[i]&&v[i]> ; v[j]) sum++; Return! (sum&1); } void AStar () {if (begnode.hash==dest) return; std::p riority_queue<node> que; Que.push (Begnode); while (!que.empty ()) {Node u=que.top (); Que.pop (); for (int i=0;i<4;i++) {Node v=u; V.POS_X+=WAY[I][0]; V.POS_Y+=WAY[I][1]; if (V.check ()) {Std::swap (v.maze[v.pos_x][v.pos_y],v.maze[u.pos_x][u.pos_y]); V.hash=gethash (v); if (vis[v.hash]==-1) {vis[v.hAsh]=i; v.fun_g++; Pre[v.hash]=u.hash; V.fun_h=geth (v); Que.push (v); } if (v.hash==dest) return; }}}} Private:node Begnode; int Gethash (Node &tmp) {std::vector<int> v; for (int. i=0;i<3;i++) for (int j=0;j<3;j++) V.push_back (Tmp.maze[i][j]); int res=0; for (int i=0;i<9;i++) {int k=0; for (int j=i+1;j<9;j++) if (v[j]<v[i]) k++; Res+=hash[8-i]*k; } return res; } int Geth (Node &tmp) {int ans=0; for (int i=0;i<3;i++) for (int j=0;j<3;j++) if (Tmp.maze[i][j]) ans+=abs (i-(tmp.maze[i][j]-1)/3) +abs (J (tmp.maze[i][j]-1)%3); return ans; }};string solveeight (const stringpiece& puzzle) {string board= ""; String conststr= "No solution"; for (int i=0;i<puzzle.size (); i++) {board+=puzzle[i]; } eightsolver S (board); if (!s.isok ()) return conststr; else {S.astar (); return S.getans (); }}
Finally, the two services are fused, after the server is turned on and accessed using the Telnet command, the strings that meet the requirements are automatically categorized and parsed to return the results as follows (Linux):
Because it is based on the Muduo network library, it is easy to achieve efficient and reliable concurrent access ~.
all project source is hosted in Github (Https://github.com/Tachone/sukuEight), interested readers can continue to improve, but also strongly welcome the front-end students to do some web interface, so that the solution more humane ~
Using Muduo to complete Sudoku and eight-digit problem solving servers