1 /* 2 Redistribution and use in source and binary forms, with or without 3 modification, are permitted provided that the following conditions are met: 4 5 * Redistributions of source code must retain the above copyright 6 notice, this list of conditions and the following disclaimer. 7 8 * Redistributions in binary form must reproduce the above copyright 9 notice, this list of conditions and the following disclaimer in the 10 documentation and/or other materials provided with the distribution. 11 12 * Neither the name of "The Computer Language Benchmarks Game" nor the 13 name of "The Computer Language Shootout Benchmarks" nor the names of 14 its contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* The Computer Language Benchmarks Game 31 * http://shootout.alioth.debian.org/ 32 * 33 * contributed by Christian Vosteen 34 */ 35 36 #include <stdlib.h> 37 #include <stdio.h> 38 #define TRUE 1 39 #define FALSE 0 40 41 /* The board is a 50 cell hexagonal pattern. For . . . . . 42 * maximum speed the board will be implemented as . . . . . 43 * 50 bits, which will fit into a 64 bit long long . . . . . 44 * int. . . . . . 45 * . . . . . 46 * I will represent 0's as empty cells and 1's . . . . . 47 * as full cells. . . . . . 48 * . . . . . 49 * . . . . . 50 * . . . . . 51 */ 52 53 unsigned long long board = 0xFFFC000000000000ULL; 54 55 /* The puzzle pieces must be specified by the path followed 56 * from one end to the other along 12 hexagonal directions. 57 * 58 * Piece 0 Piece 1 Piece 2 Piece 3 Piece 4 59 * 60 * O O O O O O O O O O O O O O O 61 * O O O O O O O 62 * O O O 63 * 64 * Piece 5 Piece 6 Piece 7 Piece 8 Piece 9 65 * 66 * O O O O O O O O O O O O O 67 * O O O O O O O O O 68 * O O O 69 * 70 * I had to make it 12 directions because I wanted all of the 71 * piece definitions to fit into the same size arrays. It is 72 * not possible to define piece 4 in terms of the 6 cardinal 73 * directions in 4 moves. 74 */ 75 76 #define E 0 77 #define ESE 1 78 #define SE 2 79 #define S 3 80 #define SW 4 81 #define WSW 5 82 #define W 6 83 #define WNW 7 84 #define NW 8 85 #define N 9 86 #define NE 10 87 #define ENE 11 88 #define PIVOT 12 89 90 char piece_def[10][4] = { 91 { E, E, E, SE}, 92 { SE, E, NE, E}, 93 { E, E, SE, SW}, 94 { E, E, SW, SE}, 95 { SE, E, NE, S}, 96 { E, E, SW, E}, 97 { E, SE, SE, NE}, 98 { E, SE, SE, W}, 99 { E, SE, E, E}, 100 { E, E, E, SW} 101 }; 102 103 104 /* To minimize the amount of work done in the recursive solve function below, 105 * I'm going to allocate enough space for all legal rotations of each piece 106 * at each position on the board. That's 10 pieces x 50 board positions x 107 * 12 rotations. However, not all 12 rotations will fit on every cell, so 108 * I'll have to keep count of the actual number that do. 109 * The pieces are going to be unsigned long long ints just like the board so 110 * they can be bitwise-anded with the board to determine if they fit. 111 * I'm also going to record the next possible open cell for each piece and 112 * location to reduce the burden on the solve function. 113 */ 114 unsigned long long pieces[10][50][12]; 115 int piece_counts[10][50]; 116 char next_cell[10][50][12]; 117 118 /* Returns the direction rotated 60 degrees clockwise */ 119 char rotate(char dir) { 120 return (dir + 2) % PIVOT; 121 } 122 123 /* Returns the direction flipped on the horizontal axis */ 124 char flip(char dir) { 125 return (PIVOT - dir) % PIVOT; 126 } 127 128 129 /* Returns the new cell index from the specified cell in the 130 * specified direction. The index is only valid if the 131 * starting cell and direction have been checked by the 132 * out_of_bounds function first. 133 */ 134 char shift(char cell, char dir) { 135 switch(dir) { 136 case E: 137 return cell + 1; 138 case ESE: 139 if((cell / 5) % 2) 140 return cell + 7; 141 else 142 return cell + 6; 143 case SE: 144 if((cell / 5) % 2) 145 return cell + 6; 146 else 147 return cell + 5; 148 case S: 149 return cell + 10; 150 case SW: 151 if((cell / 5) % 2) 152 return cell + 5; 153 else 154 return cell + 4; 155 case WSW: 156 if((cell / 5) % 2) 157 return cell + 4; 158 else 159 return cell + 3; 160 case W: 161 return cell - 1; 162 case WNW: 163 if((cell / 5) % 2) 164 return cell - 6; 165 else 166 return cell - 7; 167 case NW: 168 if((cell / 5) % 2) 169 return cell - 5; 170 else 171 return cell - 6; 172 case N: 173 return cell - 10; 174 case NE: 175 if((cell / 5) % 2) 176 return cell - 4; 177 else 178 return cell - 5; 179 case ENE: 180 if((cell / 5) % 2) 181 return cell - 3; 182 else 183 return cell - 4; 184 default: 185 return cell; 186 } 187 } 188 189 /* Returns wether the specified cell and direction will land outside 190 * of the board. Used to determine if a piece is at a legal board 191 * location or not. 192 */ 193 char out_of_bounds(char cell, char dir) { 194 char i; 195 switch(dir) { 196 case E: 197 return cell % 5 == 4; 198 case ESE: 199 i = cell % 10; 200 return i == 4 || i == 8 || i == 9 || cell >= 45; 201 case SE: 202 return cell % 10 == 9 || cell >= 45; 203 case S: 204 return cell >= 40; 205 case SW: 206 return cell % 10 == 0 || cell >= 45; 207 case WSW: 208 i = cell % 10; 209 return i == 0 || i == 1 || i == 5 || cell >= 45; 210 case W: 211 return cell % 5 == 0; 212 case WNW: 213 i = cell % 10; 214 return i == 0 || i == 1 || i == 5 || cell < 5; 215 case NW: 216 return cell % 10 == 0 || cell < 5; 217 case N: 218 return cell < 10; 219 case NE: 220 return cell % 10 == 9 || cell < 5; 221 case ENE: 222 i = cell % 10; 223 return i == 4 || i == 8 || i == 9 || cell < 5; 224 default: 225 return FALSE; 226 } 227 } 228 229 /* Rotate a piece 60 degrees clockwise */ 230 void rotate_piece(int piece) { 231 int i; 232 for(i = 0; i < 4; i++) 233 piece_def[piece][i] = rotate(piece_def[piece][i]); 234 } 235 236 /* Flip a piece along the horizontal axis */ 237 void flip_piece(int piece) { 238 int i; 239 for(i = 0; i < 4; i++) 240 piece_def[piece][i] = flip(piece_def[piece][i]); 241 } 242 243 /* Convenience function to quickly calculate all of the indices for a piece */ 244 void calc_cell_indices(char *cell, int piece, char index) { 245 cell[0] = index; 246 cell[1] = shift(cell[0], piece_def[piece][0]); 247 cell[2] = shift(cell[1], piece_def[piece][1]); 248 cell[3] = shift(cell[2], piece_def[piece][2]); 249 cell[4] = shift(cell[3], piece_def[piece][3]); 250 } 251 252 /* Convenience function to quickly calculate if a piece fits on the board */ 253 int cells_fit_on_board(char *cell, int piece) { 254 return (!out_of_bounds(cell[0], piece_def[piece][0]) && 255 !out_of_bounds(cell[1], piece_def[piece][1]) && 256 !out_of_bounds(cell[2], piece_def[piece][2]) && 257 !out_of_bounds(cell[3], piece_def[piece][3])); 258 } 259 260 /* Returns the lowest index of the cells of a piece. 261 * I use the lowest index that a piece occupies as the index for looking up 262 * the piece in the solve function. 263 */ 264 char minimum_of_cells(char *cell) { 265 char minimum = cell[0]; 266 minimum = cell[1] < minimum ? cell[1] : minimum; 267 minimum = cell[2] < minimum ? cell[2] : minimum; 268 minimum = cell[3] < minimum ? cell[3] : minimum; 269 minimum = cell[4] < minimum ? cell[4] : minimum; 270 return minimum; 271 } 272 273 /* Calculate the lowest possible open cell if the piece is placed on the board. 274 * Used to later reduce the amount of time searching for open cells in the 275 * solve function. 276 */ 277 char first_empty_cell(char *cell, char minimum) { 278 char first_empty = minimum; 279 while(first_empty == cell[0] || first_empty == cell[1] || 280 first_empty == cell[2] || first_empty == cell[3] || 281 first_empty == cell[4]) 282 first_empty++; 283 return first_empty; 284 } 285 286 /* Generate the unsigned long long int that will later be anded with the 287 * board to determine if it fits. 288 */ 289 unsigned long long bitmask_from_cells(char *cell) { 290 unsigned long long piece_mask = 0ULL; 291 int i; 292 for(i = 0; i < 5; i++) 293 piece_mask |= 1ULL << cell[i]; 294 return piece_mask; 295 } 296 297 /* Record the piece and other important information in arrays that will 298 * later be used by the solve function. 299 */ 300 void record_piece(int piece, int minimum, char first_empty, 301 unsigned long long piece_mask) { 302 pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask; 303 next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty; 304 piece_counts[piece][minimum]++; 305 } 306 307 308 /* Fill the entire board going cell by cell. If any cells are "trapped" 309 * they will be left alone. 310 */ 311 void fill_contiguous_space(char *board, int index) { 312 if(board[index] == 1) 313 return; 314 board[index] = 1; 315 if(!out_of_bounds(index, E)) 316 fill_contiguous_space(board, shift(index, E)); 317 if(!out_of_bounds(index, SE)) 318 fill_contiguous_space(board, shift(index, SE)); 319 if(!out_of_bounds(index, SW)) 320 fill_contiguous_space(board, shift(index, SW)); 321 if(!out_of_bounds(index, W)) 322 fill_contiguous_space(board, shift(index, W)); 323 if(!out_of_bounds(index, NW)) 324 fill_contiguous_space(board, shift(index, NW)); 325 if(!out_of_bounds(index, NE)) 326 fill_contiguous_space(board, shift(index, NE)); 327 } 328 329 330 /* To thin the number of pieces, I calculate if any of them trap any empty 331 * cells at the edges. There are only a handful of exceptions where the 332 * the board can be solved with the trapped cells. For example: piece 8 can 333 * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0 334 * can split the board in half where both halves are viable. 335 */ 336 int has_island(char *cell, int piece) { 337 char temp_board[50]; 338 char c; 339 int i; 340 for(i = 0; i < 50; i++) 341 temp_board[i] = 0; 342 for(i = 0; i < 5; i++) 343 temp_board[((int)cell[i])] = 1; 344 i = 49; 345 while(temp_board[i] == 1) 346 i--; 347 fill_contiguous_space(temp_board, i); 348 c = 0; 349 for(i = 0; i < 50; i++) 350 if(temp_board[i] == 0) 351 c++; 352 if(c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) || 353 (c % 5 == 0 && piece == 0)) 354 return FALSE; 355 else 356 return TRUE; 357 } 358 359 360 /* Calculate all six rotations of the specified piece at the specified index. 361 * We calculate only half of piece 3's rotations. This is because any solution 362 * found has an identical solution rotated 180 degrees. Thus we can reduce the 363 * number of attempted pieces in the solve algorithm by not including the 180- 364 * degree-rotated pieces of ONE of the pieces. I chose piece 3 because it gave 365 * me the best time ;) 366 */ 367 void calc_six_rotations(char piece, char index) { 368 char rotation, cell[5]; 369 char minimum, first_empty; 370 unsigned long long piece_mask; 371 372 for(rotation = 0; rotation < 6; rotation++) { 373 if(piece != 3 || rotation < 3) { 374 calc_cell_indices(cell, piece, index); 375 if(cells_fit_on_board(cell, piece) && !has_island(cell, piece)) { 376 minimum = minimum_of_cells(cell); 377 first_empty = first_empty_cell(cell, minimum); 378 piece_mask = bitmask_from_cells(cell); 379 record_piece(piece, minimum, first_empty, piece_mask); 380 } 381 } 382 rotate_piece(piece); 383 } 384 } 385 386 /* Calculate every legal rotation for each piece at each board location. */ 387 void calc_pieces(void) { 388 char piece, index; 389 390 for(piece = 0; piece < 10; piece++) { 391 for(index = 0; index < 50; index++) { 392 calc_six_rotations(piece, index); 393 flip_piece(piece); 394 calc_six_rotations(piece, index); 395 } 396 } 397 } 398 399 400 401 /* Calculate all 32 possible states for a 5-bit row and all rows that will 402 * create islands that follow any of the 32 possible rows. These pre- 403 * calculated 5-bit rows will be used to find islands in a partially solved 404 * board in the solve function. 405 */ 406 #define ROW_MASK 0x1F 407 #define TRIPLE_MASK 0x7FFF 408 char all_rows[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 409 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; 410 int bad_even_rows[32][32]; 411 int bad_odd_rows[32][32]; 412 int bad_even_triple[32768]; 413 int bad_odd_triple[32768]; 414 415 int rows_bad(char row1, char row2, int even) { 416 /* even is referring to row1 */ 417 int i, in_zeroes, group_okay; 418 char block, row2_shift; 419 /* Test for blockages at same index and shifted index */ 420 if(even) 421 row2_shift = ((row2 << 1) & ROW_MASK) | 0x01; 422 else 423 row2_shift = (row2 >> 1) | 0x10; 424 block = ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift); 425 /* Test for groups of 0's */ 426 in_zeroes = FALSE; 427 group_okay = FALSE; 428 for(i = 0; i < 5; i++) { 429 if(row1 & (1 << i)) { 430 if(in_zeroes) { 431 if(!group_okay) 432 return TRUE; 433 in_zeroes = FALSE; 434 group_okay = FALSE; 435 } 436 } else { 437 if(!in_zeroes) 438 in_zeroes = TRUE; 439 if(!(block & (1 << i))) 440 group_okay = TRUE; 441 } 442 } 443 if(in_zeroes) 444 return !group_okay; 445 else 446 return FALSE; 447 } 448 449 /* Check for cases where three rows checked sequentially cause a false 450 * positive. One scenario is when 5 cells may be surrounded where piece 5 451 * or 7 can fit. The other scenario is when piece 2 creates a hook shape. 452 */ 453 int triple_is_okay(char row1, char row2, char row3, int even) { 454 if(even) { 455 /* There are four cases: 456 * row1: 00011 00001 11001 10101 457 * row2: 01011 00101 10001 10001 458 * row3: 011?? 00110 ????? ????? 459 */ 460 return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) || 461 ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) || 462 ((row1 == 0x19) && (row2 == 0x11)) || 463 ((row1 == 0x15) && (row2 == 0x11)); 464 } else { 465 /* There are two cases: 466 * row1: 10011 10101 467 * row2: 10001 10001 468 * row3: ????? ????? 469 */ 470 return ((row1 == 0x13) && (row2 == 0x11)) || 471 ((row1 == 0x15) && (row2 == 0x11)); 472 } 473 } 474 475 476 void calc_rows(void) { 477 int row1, row2, row3; 478 int result1, result2; 479 for(row1 = 0; row1 < 32; row1++) { 480 for(row2 = 0; row2 < 32; row2++) { 481 bad_even_rows[row1][row2] = rows_bad(row1, row2, TRUE); 482 bad_odd_rows[row1][row2] = rows_bad(row1, row2, FALSE); 483 } 484 } 485 for(row1 = 0; row1 < 32; row1++) { 486 for(row2 = 0; row2 < 32; row2++) { 487 for(row3 = 0; row3 < 32; row3++) { 488 result1 = bad_even_rows[row1][row2]; 489 result2 = bad_odd_rows[row2][row3]; 490 if(result1 == FALSE && result2 == TRUE 491 && triple_is_okay(row1, row2, row3, TRUE)) 492 bad_even_triple[row1+(row2*32)+(row3*1024)] = FALSE; 493 else 494 bad_even_triple[row1+(row2*32)+(row3*1024)] = result1 || result2; 495 496 result1 = bad_odd_rows[row1][row2]; 497 result2 = bad_even_rows[row2][row3]; 498 if(result1 == FALSE && result2 == TRUE 499 && triple_is_okay(row1, row2, row3, FALSE)) 500 bad_odd_triple[row1+(row2*32)+(row3*1024)] = FALSE; 501 else 502 bad_odd_triple[row1+(row2*32)+(row3*1024)] = result1 || result2; 503 } 504 } 505 } 506 } 507 508 509 510 /* Calculate islands while solving the board. 511 */ 512 int boardHasIslands(char cell) { 513 /* Too low on board, don't bother checking */ 514 if(cell >= 40) 515 return FALSE; 516 int current_triple = (board >> ((cell / 5) * 5)) & TRIPLE_MASK; 517 if((cell / 5) % 2) 518 return bad_odd_triple[current_triple]; 519 else 520 return bad_even_triple[current_triple]; 521 } 522 523 524 /* The recursive solve algorithm. Try to place each permutation in the upper- 525 * leftmost empty cell. Mark off available pieces as it goes along. 526 * Because the board is a bit mask, the piece number and bit mask must be saved 527 * at each successful piece placement. This data is used to create a 50 char 528 * array if a solution is found. 529 */ 530 short avail = 0x03FF; 531 char sol_nums[10]; 532 unsigned long long sol_masks[10]; 533 signed char solutions[2100][50]; 534 int solution_count = 0; 535 int max_solutions = 2100; 536 537 void record_solution(void) { 538 int sol_no, index; 539 unsigned long long sol_mask; 540 for(sol_no = 0; sol_no < 10; sol_no++) { 541 sol_mask = sol_masks[sol_no]; 542 for(index = 0; index < 50; index++) { 543 if(sol_mask & 1ULL) { 544 solutions[solution_count][index] = sol_nums[sol_no]; 545 /* Board rotated 180 degrees is a solution too! */ 546 solutions[solution_count+1][49-index] = sol_nums[sol_no]; 547 } 548 sol_mask = sol_mask >> 1; 549 } 550 } 551 solution_count += 2; 552 } 553 554 void solve(int depth, int cell) { 555 int piece, rotation, max_rots; 556 unsigned long long *piece_mask; 557 short piece_no_mask; 558 559 if(solution_count >= max_solutions) 560 return; 561 562 while(board & (1ULL << cell)) 563 cell++; 564 565 for(piece = 0; piece < 10; piece++) { 566 piece_no_mask = 1 << piece; 567 if(!(avail & piece_no_mask)) 568 continue; 569 avail ^= piece_no_mask; 570 max_rots = piece_counts[piece][cell]; 571 piece_mask = pieces[piece][cell]; 572 for(rotation = 0; rotation < max_rots; rotation++) { 573 if(!(board & *(piece_mask + rotation))) { 574 sol_nums[depth] = piece; 575 sol_masks[depth] = *(piece_mask + rotation); 576 if(depth == 9) { 577 /* Solution found!!!!!11!!ONE! */ 578 record_solution(); 579 avail ^= piece_no_mask; 580 return; 581 } 582 board |= *(piece_mask + rotation); 583 if(!boardHasIslands(next_cell[piece][cell][rotation])) 584 solve(depth + 1, next_cell[piece][cell][rotation]); 585 board ^= *(piece_mask + rotation); 586 } 587 } 588 avail ^= piece_no_mask; 589 } 590 } 591 592 593 /* qsort comparator - used to find first and last solutions */ 594 int solution_sort(const void *elem1, const void *elem2) { 595 signed char *char1 = (signed char *) elem1; 596 signed char *char2 = (signed char *) elem2; 597 int i = 0; 598 while(i < 50 && char1[i] == char2[i]) 599 i++; 600 return char1[i] - char2[i]; 601 } 602 603 604 /* pretty print a board in the specified hexagonal format */ 605 void pretty(signed char *b) { 606 int i; 607 for(i = 0; i < 50; i += 10) { 608 printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0', 609 b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0', 610 b[i+7]+'0', b[i+8]+'0', b[i+9]+'0'); 611 } 612 printf("\n"); 613 } 614 615 int main(int argc, char **argv) { 616 if(argc > 1) 617 max_solutions = atoi(argv[1]); 618 calc_pieces(); 619 calc_rows(); 620 solve(0, 0); 621 printf("%d solutions found\n\n", solution_count); 622 qsort(solutions, solution_count, 50 * sizeof(signed char), solution_sort); 623 pretty(solutions[0]); 624 pretty(solutions[solution_count-1]); 625 return 0; 626 } 627