![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright 2005-2010 Intel Corporation. All Rights Reserved. 00003 00004 This file is part of Threading Building Blocks. 00005 00006 Threading Building Blocks is free software; you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License 00008 version 2 as published by the Free Software Foundation. 00009 00010 Threading Building Blocks is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00012 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Threading Building Blocks; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 As a special exception, you may use this file as part of a free software 00020 library without restriction. Specifically, if other files instantiate 00021 templates or use macros or inline functions from this file, or you compile 00022 this file and link it with other files to produce an executable, this 00023 file does not by itself cause the resulting executable to be covered by 00024 the GNU General Public License. This exception does not however 00025 invalidate any other reasons why the executable file might be covered by 00026 the GNU General Public License. 00027 */ 00028 00029 #include <cstdio> 00030 #include <cstdlib> 00031 #include "tbb/atomic.h" 00032 #include "tbb/tick_count.h" 00033 #include "tbb/task_scheduler_init.h" 00034 #include "tbb/task_group.h" 00035 00036 #pragma warning(disable: 4996) 00037 00038 #define __TBB_LAMBDAS_PRESENT ( _MSC_VER >= 1600 && !__INTEL_COMPILER || __INTEL_COMPILER > 1100 && _TBB_CPP0X ) 00039 00040 const unsigned BOARD_SIZE=81; 00041 const unsigned BOARD_DIM=9; 00042 00043 using namespace tbb; 00044 using namespace std; 00045 00046 atomic<unsigned> nSols; 00047 unsigned NThreads, NSolutions; 00048 bool Verbose=false; 00049 unsigned short init_values[BOARD_SIZE]; 00050 task_group *g; 00051 00052 typedef struct { 00053 unsigned short solved_element; 00054 unsigned potential_set; 00055 } board_element; 00056 00057 void read_board(char *filename) { 00058 FILE *fp; 00059 int input; 00060 fp = fopen(filename, "r"); 00061 for (unsigned i=0; i<BOARD_SIZE; ++i) { 00062 if (fscanf(fp, "%d", &input)) 00063 init_values[i] = input; 00064 else { 00065 fprintf(stderr, "sudoku: Error in input file at entry %d, assuming 0.\n", i); 00066 init_values[i] = 0; 00067 } 00068 } 00069 fclose(fp); 00070 } 00071 00072 void print_board(board_element *b) { 00073 for (unsigned row=0; row<BOARD_DIM; ++row) { 00074 for (unsigned col=0; col<BOARD_DIM; ++col) { 00075 printf(" %d", b[row*BOARD_DIM+col].solved_element); 00076 if (col==2 || col==5) printf(" |"); 00077 } 00078 printf("\n"); 00079 if (row==2 || row==5) printf(" ---------------------\n"); 00080 } 00081 } 00082 00083 void print_potential_board(board_element *b) { 00084 for (unsigned row=0; row<BOARD_DIM; ++row) { 00085 for (unsigned col=0; col<BOARD_DIM; ++col) { 00086 if (b[row*BOARD_DIM+col].solved_element) 00087 printf(" %4d ", b[row*BOARD_DIM+col].solved_element); 00088 else 00089 printf(" [%4d]", b[row*BOARD_DIM+col].potential_set); 00090 if (col==2 || col==5) printf(" |"); 00091 } 00092 printf("\n"); 00093 if (row==2 || row==5) 00094 printf(" ------------------------------------------------------------------\n"); 00095 } 00096 } 00097 00098 void init_board(board_element *b) { 00099 for (unsigned i=0; i<BOARD_SIZE; ++i) 00100 b[i].solved_element = b[i].potential_set = 0; 00101 } 00102 00103 void init_board(board_element *b, unsigned short arr[81]) { 00104 for (unsigned i=0; i<BOARD_SIZE; ++i) { 00105 b[i].solved_element = arr[i]; 00106 b[i].potential_set = 0; 00107 } 00108 } 00109 00110 void init_potentials(board_element *b) { 00111 for (unsigned i=0; i<BOARD_SIZE; ++i) 00112 b[i].potential_set = 0; 00113 } 00114 00115 void copy_board(board_element *src, board_element *dst) { 00116 for (unsigned i=0; i<BOARD_SIZE; ++i) 00117 dst[i].solved_element = src[i].solved_element; 00118 } 00119 00120 bool fixed_board(board_element *b) { 00121 for (int i=BOARD_SIZE-1; i>=0; --i) 00122 if (b[i].solved_element==0) return false; 00123 return true; 00124 } 00125 00126 bool in_row(board_element *b, unsigned row, unsigned col, unsigned short p) { 00127 for (unsigned c=0; c<BOARD_DIM; ++c) 00128 if (c!=col && b[row*BOARD_DIM+c].solved_element==p) return true; 00129 return false; 00130 } 00131 00132 bool in_col(board_element *b, unsigned row, unsigned col, unsigned short p) { 00133 for (unsigned r=0; r<BOARD_DIM; ++r) 00134 if (r!=row && b[r*BOARD_DIM+col].solved_element==p) return true; 00135 return false; 00136 } 00137 00138 bool in_block(board_element *b, unsigned row, unsigned col, unsigned short p) { 00139 unsigned b_row = row/3 * 3, b_col = col/3 * 3; 00140 for (unsigned i=b_row; i<b_row+3; ++i) 00141 for (unsigned j=b_col; j<b_col+3; ++j) 00142 if (!(i==row && j==col) && b[i*BOARD_DIM+j].solved_element==p) return true; 00143 return false; 00144 } 00145 00146 void calculate_potentials(board_element *b) { 00147 for (unsigned i=0; i<BOARD_SIZE; ++i) { 00148 b[i].potential_set = 0; 00149 if (!b[i].solved_element) { // element is not yet fixed 00150 unsigned row = i/BOARD_DIM, col = i%BOARD_DIM; 00151 for (unsigned potential=1; potential<=BOARD_DIM; ++potential) { 00152 if (!in_row(b, row, col, potential) && !in_col(b, row, col, potential) 00153 && !in_block(b, row, col, potential)) 00154 b[i].potential_set |= 1<<(potential-1); 00155 } 00156 } 00157 } 00158 } 00159 00160 bool valid_board(board_element *b) { 00161 bool success=true; 00162 for (unsigned i=0; i<BOARD_SIZE; ++i) { 00163 if (success && b[i].solved_element) { // element is fixed 00164 unsigned row = i/BOARD_DIM, col = i%BOARD_DIM; 00165 if (in_row(b, row, col, b[i].solved_element) || in_col(b, row, col, b[i].solved_element) || in_block(b, row, col, b[i].solved_element)) 00166 success = false; 00167 } 00168 } 00169 return success; 00170 } 00171 00172 bool examine_potentials(board_element *b, bool *progress) { 00173 bool singletons = false; 00174 for (unsigned i=0; i<BOARD_SIZE; ++i) { 00175 if (b[i].solved_element==0 && b[i].potential_set==0) // empty set 00176 return false; 00177 switch (b[i].potential_set) { 00178 case 1: { b[i].solved_element = 1; singletons=true; break; } 00179 case 2: { b[i].solved_element = 2; singletons=true; break; } 00180 case 4: { b[i].solved_element = 3; singletons=true; break; } 00181 case 8: { b[i].solved_element = 4; singletons=true; break; } 00182 case 16: { b[i].solved_element = 5; singletons=true; break; } 00183 case 32: { b[i].solved_element = 6; singletons=true; break; } 00184 case 64: { b[i].solved_element = 7; singletons=true; break; } 00185 case 128: { b[i].solved_element = 8; singletons=true; break; } 00186 case 256: { b[i].solved_element = 9; singletons=true; break; } 00187 } 00188 } 00189 *progress = singletons; 00190 return valid_board(b); 00191 } 00192 00193 #if !__TBB_LAMBDAS_PRESENT 00194 void partial_solve(board_element *b, unsigned first_potential_set); 00195 00196 class PartialSolveBoard { 00197 board_element *b; 00198 unsigned first_potential_set; 00199 public: 00200 PartialSolveBoard(board_element *_b, unsigned fps) : 00201 b(_b), first_potential_set(fps) {} 00202 void operator() () const { 00203 partial_solve(b, first_potential_set); 00204 } 00205 }; 00206 #endif 00207 00208 void partial_solve(board_element *b, unsigned first_potential_set) { 00209 if (fixed_board(b)) { 00210 if (NSolutions == 1) 00211 g->cancel(); 00212 if (++nSols==1 && Verbose) { 00213 print_board(b); 00214 } 00215 free(b); 00216 return; 00217 } 00218 calculate_potentials(b); 00219 bool progress=true; 00220 bool success = examine_potentials(b, &progress); 00221 if (success && progress) { 00222 partial_solve(b, first_potential_set); 00223 } else if (success && !progress) { 00224 board_element *new_board; 00225 while (b[first_potential_set].solved_element!=0) ++first_potential_set; 00226 for (unsigned short potential=1; potential<=BOARD_DIM; ++potential) { 00227 if (1<<(potential-1) & b[first_potential_set].potential_set) { 00228 new_board = (board_element *)malloc(BOARD_SIZE*sizeof(board_element)); 00229 copy_board(b, new_board); 00230 new_board[first_potential_set].solved_element = potential; 00231 #if __TBB_LAMBDAS_PRESENT 00232 g->run( [=]{ partial_solve(new_board, first_potential_set); } ); 00233 #else 00234 g->run(PartialSolveBoard(new_board, first_potential_set)); 00235 #endif 00236 } 00237 } 00238 free(b); 00239 } 00240 else { 00241 free(b); 00242 } 00243 } 00244 00245 void ParseCommandLine(int argc, char *argv[]) { 00246 if (argc < 4) { 00247 fprintf(stderr, 00248 "Usage: sudoku <inputfilename> <nthreads> <nSolutions> [-p]\n" 00249 " nSolutions=1 stops after finding first solution\n" 00250 " and any other value finds all solutions; \n" 00251 " -p prints the first solution.\n"); 00252 exit(1); 00253 } 00254 else { 00255 sscanf(argv[2], "%d", &NThreads); 00256 sscanf(argv[3], "%d", &NSolutions); 00257 } 00258 if (argc==5) Verbose = true; 00259 } 00260 00261 int main(int argc, char *argv[]) { 00262 board_element *start_board; 00263 start_board = (board_element *)malloc(BOARD_SIZE*sizeof(board_element)); 00264 NThreads = 1; 00265 nSols = 0; 00266 ParseCommandLine(argc, argv); 00267 read_board(argv[1]); 00268 init_board(start_board, init_values); 00269 task_scheduler_init init(NThreads); 00270 g = new task_group; 00271 tick_count t0 = tick_count::now(); 00272 partial_solve(start_board, 0); 00273 g->wait(); 00274 tick_count t1 = tick_count::now(); 00275 delete g; 00276 00277 if (NSolutions == 1) { 00278 printf("Sudoku: Time to find first solution on %d threads: %6.6f seconds.\n", NThreads, (t1 - t0).seconds()); 00279 } 00280 else { 00281 printf("Sudoku: Time to find all %d solutions on %d threads: %6.6f seconds.\n", (int)nSols, NThreads, (t1 - t0).seconds()); 00282 } 00283 }; 00284
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.