pentominoes.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 00002 /* 00003 * Main authors: 00004 * Mikael Lagerkvist <lagerkvist@gecode.org> 00005 * 00006 * Contributing authors: 00007 * Guido Tack <tack@gecode.org> 00008 * 00009 * Copyright: 00010 * Mikael Lagerkvist, 2006 00011 * Guido Tack, 2006 00012 * 00013 * Last modified: 00014 * $Date: 2010-10-07 11:52:01 +0200 (Thu, 07 Oct 2010) $ by $Author: schulte $ 00015 * $Revision: 11473 $ 00016 * 00017 * This file is part of Gecode, the generic constraint 00018 * development environment: 00019 * http://www.gecode.org 00020 * 00021 * Permission is hereby granted, free of charge, to any person obtaining 00022 * a copy of this software and associated documentation files (the 00023 * "Software"), to deal in the Software without restriction, including 00024 * without limitation the rights to use, copy, modify, merge, publish, 00025 * distribute, sublicense, and/or sell copies of the Software, and to 00026 * permit persons to whom the Software is furnished to do so, subject to 00027 * the following conditions: 00028 * 00029 * The above copyright notice and this permission notice shall be 00030 * included in all copies or substantial portions of the Software. 00031 * 00032 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00033 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00034 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00035 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00036 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00037 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00038 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00039 * 00040 */ 00041 00042 #include <gecode/driver.hh> 00043 #include <gecode/int.hh> 00044 #include <gecode/minimodel.hh> 00045 00046 using namespace Gecode; 00047 00056 class TileSpec { 00057 public: 00058 int width; 00059 int height; 00060 int amount; 00061 const char *tile; 00062 }; 00063 00072 extern const TileSpec *examples[]; 00077 extern const int examples_size[]; 00082 extern const unsigned int n_examples; 00083 00084 namespace { 00097 int pos(int h, int w, int h1, int w1); 00099 typedef void (*tsymmfunc)(const char*, int, int, char*, int&, int&); 00101 typedef void (*bsymmfunc)(const IntVarArgs, int, int, IntVarArgs&, int&, int&); 00103 template<class CArray, class Array> 00104 void id(CArray t1, int w1, int h1, Array t2, int& w2, int&h2); 00106 template<class CArray, class Array> 00107 void rot90(CArray t1, int w1, int h1, Array t2, int& w2, int& h2); 00109 template<class CArray, class Array> 00110 void rot180(CArray t1, int w1, int h1, Array t2, int& w2, int& h2); 00112 template<class CArray, class Array> 00113 void rot270(CArray t1, int w1, int h1, Array t2, int& w2, int& h2); 00115 template<class CArray, class Array> 00116 void flipx(CArray t1, int w1, int h1, Array t2, int& w2, int& h2); 00118 template<class CArray, class Array> 00119 void flipy(CArray t1, int w1, int h1, Array t2, int& w2, int& h2); 00121 template<class CArray, class Array> 00122 void flipd1(CArray t1, int w1, int h1, Array t2, int& w2, int& h2); 00124 template<class CArray, class Array> 00125 void flipd2(CArray t1, int w1, int h1, Array t2, int& w2, int& h2); 00127 } 00128 00265 class Pentominoes : public Script { 00266 public: 00268 enum { 00269 PROPAGATION_INT, 00270 PROPAGATION_BOOLEAN, 00271 }; 00273 enum { 00274 SYMMETRY_NONE, 00275 SYMMETRY_FULL, 00276 }; 00277 private: 00279 const TileSpec *spec; 00281 int width, height; 00283 bool filled; 00285 int nspecs; 00287 int ntiles; 00288 00290 IntVarArray board; 00291 00293 int compute_number_of_tiles(const TileSpec* ts, int nspecs) { 00294 int res = 0; 00295 for (int i = nspecs; i--; ) { 00296 res += ts[i].amount; 00297 } 00298 return res; 00299 } 00300 00303 REG tile_reg(int twidth, int theight, const char* tile, 00304 REG mark, REG other, REG eol) { 00305 REG oe = other | eol; 00306 REG res = *oe; 00307 REG color[] = {other, mark}; 00308 for (int h = 0; h < theight; ++h) { 00309 for (int w = 0; w < twidth; ++w) { 00310 int which = tile[h*twidth + w] == 'X'; 00311 res += color[which]; 00312 } 00313 if (h < theight-1) { 00314 res += oe(width-twidth, width-twidth); 00315 } 00316 } 00317 res += *oe + oe; 00318 return res; 00319 } 00320 00323 REG get_constraint(int t, REG mark, REG other, REG eol) { 00324 // This should be done for all rotations 00325 REG res; 00326 char *t2 = new char[width*height]; 00327 int w2, h2; 00328 tsymmfunc syms[] = {id, flipx, flipy, flipd1, flipd2, rot90, rot180, rot270}; 00329 int symscnt = sizeof(syms)/sizeof(tsymmfunc); 00330 for (int i = 0; i < symscnt; ++i) { 00331 syms[i](spec[t].tile, spec[t].width, spec[t].height, t2, w2, h2); 00332 res = res | tile_reg(w2, h2, t2, mark, other, eol); 00333 } 00334 delete [] t2; 00335 00336 return res; 00337 } 00338 00339 00340 public: 00342 Pentominoes(const SizeOptions& opt) 00343 : spec(examples[opt.size()]), 00344 width(spec[0].width+1), // Add one for extra row at end. 00345 height(spec[0].height), 00346 filled(spec[0].amount), 00347 nspecs(examples_size[opt.size()]-1), 00348 ntiles(compute_number_of_tiles(spec+1, nspecs)), 00349 board(*this, width*height, filled,ntiles+1) { 00350 spec += 1; // No need for the specification-part any longer 00351 00352 // Set end-of-line markers 00353 for (int h = 0; h < height; ++h) { 00354 for (int w = 0; w < width-1; ++w) 00355 rel(*this, board[h*width + w], IRT_NQ, ntiles+1); 00356 rel(*this, board[h*width + width - 1], IRT_EQ, ntiles+1); 00357 } 00358 00359 // Post constraints 00360 if (opt.propagation() == PROPAGATION_INT) { 00361 int tile = 0; 00362 for (int i = 0; i < nspecs; ++i) { 00363 for (int j = 0; j < spec[i].amount; ++j) { 00364 // Color 00365 int col = tile+1; 00366 // Expression for color col 00367 REG mark(col); 00368 // Build expression for complement to color col 00369 REG other; 00370 bool first = true; 00371 for (int j = filled; j <= ntiles; ++j) { 00372 if (j == col) continue; 00373 if (first) { 00374 other = REG(j); 00375 first = false; 00376 } else { 00377 other |= REG(j); 00378 } 00379 } 00380 // End of line marker 00381 REG eol(ntiles+1); 00382 extensional(*this, board, get_constraint(i, mark, other, eol)); 00383 ++tile; 00384 } 00385 } 00386 } else { // opt.propagation() == PROPAGATION_BOOLEAN 00387 int ncolors = ntiles + 2; 00388 // Boolean variables for channeling 00389 BoolVarArgs p(*this,ncolors * board.size(),0,1); 00390 00391 // Post channel constraints 00392 for (int i=board.size(); i--; ) { 00393 BoolVarArgs c(ncolors); 00394 for (int j=ncolors; j--; ) 00395 c[j]=p[i*ncolors+j]; 00396 channel(*this, c, board[i]); 00397 } 00398 00399 // For placing tile i, we construct the expression over 00400 // 0/1-variables and apply it to the projection of 00401 // the board on the color for the tile. 00402 REG other(0), mark(1); 00403 int tile = 0; 00404 for (int i = 0; i < nspecs; ++i) { 00405 for (int j = 0; j < spec[i].amount; ++j) { 00406 int col = tile+1; 00407 // Projection for color col 00408 BoolVarArgs c(board.size()); 00409 00410 for (int k = board.size(); k--; ) { 00411 c[k] = p[k*ncolors+col]; 00412 } 00413 00414 extensional(*this, c, get_constraint(i, mark, other, other)); 00415 ++tile; 00416 } 00417 } 00418 } 00419 00420 if (opt.symmetry() == SYMMETRY_FULL) { 00421 // Remove symmetrical boards 00422 IntVarArgs orig(board.size()-height), symm(board.size()-height); 00423 int pos = 0; 00424 for (int i = 0; i < board.size(); ++i) { 00425 if ((i+1)%width==0) continue; 00426 orig[pos++] = board[i]; 00427 } 00428 00429 int w2, h2; 00430 bsymmfunc syms[] = {flipx, flipy, flipd1, flipd2, rot90, rot180, rot270}; 00431 int symscnt = sizeof(syms)/sizeof(bsymmfunc); 00432 for (int i = 0; i < symscnt; ++i) { 00433 syms[i](orig, width-1, height, symm, w2, h2); 00434 if (width-1 == w2 && height == h2) 00435 rel(*this, orig, IRT_LQ, symm); 00436 } 00437 } 00438 00439 // Install branching 00440 branch(*this, board, INT_VAR_NONE, INT_VAL_MIN); 00441 } 00442 00444 Pentominoes(bool share, Pentominoes& s) : 00445 Script(share,s), spec(s.spec), width(s.width), height(s.height), 00446 filled(s.filled), nspecs(s.nspecs) { 00447 board.update(*this, share, s.board); 00448 } 00449 00451 virtual Space* 00452 copy(bool share) { 00453 return new Pentominoes(share,*this); 00454 } 00455 00457 virtual void 00458 print(std::ostream& os) const { 00459 for (int h = 0; h < height; ++h) { 00460 os << "\t"; 00461 for (int w = 0; w < width-1; ++w) { 00462 int val = board[h*width + w].val(); 00463 char c = val < 10 ? '0'+val : 'A' + (val-10); 00464 os << c; 00465 } 00466 os << std::endl; 00467 } 00468 os << std::endl; 00469 } 00470 }; 00471 00472 00476 int 00477 main(int argc, char* argv[]) { 00478 SizeOptions opt("Pentominoes"); 00479 opt.size(1); 00480 opt.symmetry(Pentominoes::SYMMETRY_FULL); 00481 opt.symmetry(Pentominoes::SYMMETRY_NONE, 00482 "none", "do not remove symmetric solutions"); 00483 opt.symmetry(Pentominoes::SYMMETRY_FULL, 00484 "full", "remove symmetric solutions"); 00485 00486 opt.propagation(Pentominoes::PROPAGATION_BOOLEAN); 00487 opt.propagation(Pentominoes::PROPAGATION_INT, 00488 "int", "use integer propagators"); 00489 opt.propagation(Pentominoes::PROPAGATION_BOOLEAN, 00490 "bool", "use Boolean propagators"); 00491 00492 opt.parse(argc,argv); 00493 if (opt.size() >= n_examples) { 00494 std::cerr << "Error: size must be between 0 and " 00495 << n_examples-1 << std::endl; 00496 return 1; 00497 } 00498 Script::run<Pentominoes,DFS,SizeOptions>(opt); 00499 return 0; 00500 } 00501 00502 00508 00509 static const TileSpec puzzle0[] = 00510 { 00511 // Width and height of board 00512 {4, 4, true, ""}, 00513 {2, 3, 1, 00514 "XX" 00515 "X " 00516 "X "}, 00517 {2, 1, 1, 00518 "XX"}, 00519 {3, 3, 1, 00520 " XX" 00521 " X" 00522 "XXX"}, 00523 {1, 1, 1, 00524 "X"}, 00525 {3, 1, 1, 00526 "XXX"} 00527 }; 00529 static const TileSpec puzzle1[] = 00530 { 00531 // Width and height of board 00532 {8, 8, true, ""}, 00533 {3, 3, 1, 00534 "XXX" 00535 "XXX" 00536 "XX "}, 00537 {5, 3, 1, 00538 " XXX" 00539 " X " 00540 "XXX "}, 00541 {3, 4, 1, 00542 "XXX" 00543 "XXX" 00544 " X" 00545 " X"}, 00546 {3, 4, 1, 00547 "XXX" 00548 " X" 00549 " X" 00550 " X"}, 00551 {2, 5, 1, 00552 " X" 00553 " X" 00554 " X" 00555 "XX" 00556 "XX"}, 00557 {4, 2, 1, 00558 "XX " 00559 "XXXX"}, 00560 {3, 3, 1, 00561 "XXX" 00562 " X" 00563 " X"}, 00564 {2, 3, 1, 00565 "XX" 00566 "X " 00567 "X "}, 00568 {2, 4, 1, 00569 "XX" 00570 "XX" 00571 "XX" 00572 "XX"}, 00573 {3, 2, 1, 00574 "XX " 00575 "XXX"} 00576 }; 00577 00578 // Perfect square number 2 from examples/perfect-square.cc 00579 static const TileSpec square2[] = 00580 { 00581 // Width and height of board 00582 {10, 10, true, ""}, 00583 {6, 6, 1, 00584 "XXXXXX" 00585 "XXXXXX" 00586 "XXXXXX" 00587 "XXXXXX" 00588 "XXXXXX" 00589 "XXXXXX" 00590 }, 00591 {4, 4, 3, 00592 "XXXX" 00593 "XXXX" 00594 "XXXX" 00595 "XXXX"}, 00596 {2, 2, 4, 00597 "XX" 00598 "XX"} 00599 }; 00600 00601 // Perfect square number 3 from examples/perfect-square.cc 00602 static const TileSpec square3[] = 00603 { 00604 // Width and height of board 00605 {20, 20, true, ""}, 00606 {9, 9, 1, 00607 "XXXXXXXXX" 00608 "XXXXXXXXX" 00609 "XXXXXXXXX" 00610 "XXXXXXXXX" 00611 "XXXXXXXXX" 00612 "XXXXXXXXX" 00613 "XXXXXXXXX" 00614 "XXXXXXXXX" 00615 "XXXXXXXXX" 00616 }, 00617 {8, 8, 2, 00618 "XXXXXXXX" 00619 "XXXXXXXX" 00620 "XXXXXXXX" 00621 "XXXXXXXX" 00622 "XXXXXXXX" 00623 "XXXXXXXX" 00624 "XXXXXXXX" 00625 "XXXXXXXX" 00626 }, 00627 {7, 7, 1, 00628 "XXXXXXX" 00629 "XXXXXXX" 00630 "XXXXXXX" 00631 "XXXXXXX" 00632 "XXXXXXX" 00633 "XXXXXXX" 00634 "XXXXXXX" 00635 }, 00636 {5, 5, 1, 00637 "XXXXX" 00638 "XXXXX" 00639 "XXXXX" 00640 "XXXXX" 00641 "XXXXX" 00642 }, 00643 {4, 4, 5, 00644 "XXXX" 00645 "XXXX" 00646 "XXXX" 00647 "XXXX"}, 00648 {3, 3, 3, 00649 "XXX" 00650 "XXX" 00651 "XXX"}, 00652 {2, 2, 2, 00653 "XX" 00654 "XX"}, 00655 {1, 1, 2, 00656 "X"} 00657 }; 00658 00659 static const TileSpec pentomino6x10[] = 00660 { 00661 // Width and height of board 00662 {10, 6, true, ""}, 00663 {2, 4, 1, 00664 "X " 00665 "X " 00666 "X " 00667 "XX"}, 00668 {3,3, 1, 00669 "XX " 00670 " XX" 00671 " X "}, 00672 {3,3, 1, 00673 "XXX" 00674 " X " 00675 " X "}, 00676 {3,3, 1, 00677 " X" 00678 " XX" 00679 "XX "}, 00680 {2,4, 1, 00681 " X" 00682 "XX" 00683 " X" 00684 " X"}, 00685 {5,1, 1, 00686 "XXXXX"}, 00687 {3,3, 1, 00688 "X " 00689 "XXX" 00690 " X"}, 00691 {4,2, 1, 00692 " XXX" 00693 "XX "}, 00694 {2,3, 1, 00695 "XX" 00696 "XX" 00697 " X"}, 00698 {3,2, 1, 00699 "X X" 00700 "XXX"}, 00701 {3,3, 1, 00702 " X " 00703 "XXX" 00704 " X "}, 00705 {3,3, 1, 00706 " X" 00707 " X" 00708 "XXX"} 00709 }; 00710 00711 static const TileSpec pentomino5x12[] = 00712 { 00713 // Width and height of board 00714 {12, 5, true, ""}, 00715 {2, 4, 1, 00716 "X " 00717 "X " 00718 "X " 00719 "XX"}, 00720 {3,3, 1, 00721 "XX " 00722 " XX" 00723 " X "}, 00724 {3,3, 1, 00725 "XXX" 00726 " X " 00727 " X "}, 00728 {3,3, 1, 00729 " X" 00730 " XX" 00731 "XX "}, 00732 {2,4, 1, 00733 " X" 00734 "XX" 00735 " X" 00736 " X"}, 00737 {5,1, 1, 00738 "XXXXX"}, 00739 {3,3, 1, 00740 "X " 00741 "XXX" 00742 " X"}, 00743 {4,2, 1, 00744 " XXX" 00745 "XX "}, 00746 {2,3, 1, 00747 "XX" 00748 "XX" 00749 " X"}, 00750 {3,2, 1, 00751 "X X" 00752 "XXX"}, 00753 {3,3, 1, 00754 " X " 00755 "XXX" 00756 " X "}, 00757 {3,3, 1, 00758 " X" 00759 " X" 00760 "XXX"} 00761 }; 00762 00763 static const TileSpec pentomino4x15[] = 00764 { 00765 // Width and height of board 00766 {15, 4, true, ""}, 00767 {2, 4, 1, 00768 "X " 00769 "X " 00770 "X " 00771 "XX"}, 00772 {3,3, 1, 00773 "XX " 00774 " XX" 00775 " X "}, 00776 {3,3, 1, 00777 "XXX" 00778 " X " 00779 " X "}, 00780 {3,3, 1, 00781 " X" 00782 " XX" 00783 "XX "}, 00784 {2,4, 1, 00785 " X" 00786 "XX" 00787 " X" 00788 " X"}, 00789 {5,1, 1, 00790 "XXXXX"}, 00791 {3,3, 1, 00792 "X " 00793 "XXX" 00794 " X"}, 00795 {4,2, 1, 00796 " XXX" 00797 "XX "}, 00798 {2,3, 1, 00799 "XX" 00800 "XX" 00801 " X"}, 00802 {3,2, 1, 00803 "X X" 00804 "XXX"}, 00805 {3,3, 1, 00806 " X " 00807 "XXX" 00808 " X "}, 00809 {3,3, 1, 00810 " X" 00811 " X" 00812 "XXX"} 00813 }; 00814 00815 static const TileSpec pentomino3x20[] = 00816 { 00817 // Width and height of board 00818 {20, 3, true, ""}, 00819 {2, 4, 1, 00820 "X " 00821 "X " 00822 "X " 00823 "XX"}, 00824 {3,3, 1, 00825 "XX " 00826 " XX" 00827 " X "}, 00828 {3,3, 1, 00829 "XXX" 00830 " X " 00831 " X "}, 00832 {3,3, 1, 00833 " X" 00834 " XX" 00835 "XX "}, 00836 {2,4, 1, 00837 " X" 00838 "XX" 00839 " X" 00840 " X"}, 00841 {5,1, 1, 00842 "XXXXX"}, 00843 {3,3, 1, 00844 "X " 00845 "XXX" 00846 " X"}, 00847 {4,2, 1, 00848 " XXX" 00849 "XX "}, 00850 {2,3, 1, 00851 "XX" 00852 "XX" 00853 " X"}, 00854 {3,2, 1, 00855 "X X" 00856 "XXX"}, 00857 {3,3, 1, 00858 " X " 00859 "XXX" 00860 " X "}, 00861 {3,3, 1, 00862 " X" 00863 " X" 00864 "XXX"} 00865 }; 00866 00868 const TileSpec *examples[] = {puzzle0, puzzle1, square2, square3, 00869 pentomino6x10,pentomino5x12, 00870 pentomino4x15,pentomino3x20}; 00871 const int examples_size[] = {sizeof(puzzle0)/sizeof(TileSpec), 00872 sizeof(puzzle1)/sizeof(TileSpec), 00873 sizeof(square2)/sizeof(TileSpec), 00874 sizeof(square3)/sizeof(TileSpec), 00875 sizeof(pentomino6x10)/sizeof(TileSpec), 00876 sizeof(pentomino5x12)/sizeof(TileSpec), 00877 sizeof(pentomino4x15)/sizeof(TileSpec), 00878 sizeof(pentomino3x20)/sizeof(TileSpec)}; 00879 00881 const unsigned n_examples = sizeof(examples)/sizeof(TileSpec*); 00883 00884 // Symmetry functions 00885 namespace { 00886 int pos(int h, int w, int h1, int w1) { 00887 if (!(0 <= h && h < h1) || 00888 !(0 <= w && w < w1)) { 00889 std::cerr << "Cannot place (" << h << "," << w 00890 << ") on board of size " << h1 << "x" << w1 << std::endl; 00891 } 00892 return h * w1 + w; 00893 } 00894 template<class CArray, class Array> 00895 void id(CArray t1, int w1, int h1, Array t2, int& w2, int&h2) { 00896 w2 = w1; h2 = h1; 00897 for (int h = 0; h < h1; ++h) 00898 for (int w = 0; w < w1; ++w) 00899 t2[pos(h, w, h2, w2)] = t1[pos(h, w, h1, w1)]; 00900 } 00901 template<class CArray, class Array> 00902 void rot90(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) { 00903 w2 = h1; h2 = w1; 00904 for (int h = 0; h < h1; ++h) 00905 for (int w = 0; w < w1; ++w) 00906 t2[pos(w, w2-h-1, h2, w2)] = t1[pos(h, w, h1, w1)]; 00907 } 00908 template<class CArray, class Array> 00909 void rot180(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) { 00910 w2 = w1; h2 = h1; 00911 for (int h = 0; h < h1; ++h) 00912 for (int w = 0; w < w1; ++w) 00913 t2[pos(h2-h-1, w2-w-1, h2, w2)] = t1[pos(h, w, h1, w1)]; 00914 } 00915 template<class CArray, class Array> 00916 void rot270(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) { 00917 w2 = h1; h2 = w1; 00918 for (int h = 0; h < h1; ++h) 00919 for (int w = 0; w < w1; ++w) 00920 t2[pos(h2-w-1, h, h2, w2)] = t1[pos(h, w, h1, w1)]; 00921 } 00922 template<class CArray, class Array> 00923 void flipx(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) { 00924 w2 = w1; h2 = h1; 00925 for (int h = 0; h < h1; ++h) 00926 for (int w = 0; w < w1; ++w) 00927 t2[pos(h, w2-w-1, h2, w2)] = t1[pos(h, w, h1, w1)]; 00928 } 00929 template<class CArray, class Array> 00930 void flipy(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) { 00931 w2 = w1; h2 = h1; 00932 for (int h = 0; h < h1; ++h) 00933 for (int w = 0; w < w1; ++w) 00934 t2[pos(h2-h-1, w, h2, w2)] = t1[pos(h, w, h1, w1)]; 00935 } 00936 template<class CArray, class Array> 00937 void flipd1(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) { 00938 w2 = h1; h2 = w1; 00939 for (int h = 0; h < h1; ++h) 00940 for (int w = 0; w < w1; ++w) 00941 t2[pos(w, h, h2, w2)] = t1[pos(h, w, h1, w1)]; 00942 } 00943 template<class CArray, class Array> 00944 void flipd2(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) { 00945 w2 = h1; h2 = w1; 00946 for (int h = 0; h < h1; ++h) 00947 for (int w = 0; w < w1; ++w) 00948 t2[pos(h2-w-1, w2-h-1, h2, w2)] = t1[pos(h, w, h1, w1)]; 00949 } 00950 } 00951 00952 // STATISTICS: example-any