Generated on Mon Aug 25 11:35:33 2008 for Gecode by doxygen 1.5.6

pentominoes.cc

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: 2008-01-13 14:21:22 +0100 (Sun, 13 Jan 2008) $ by $Author: zayenz $
00015  *     $Revision: 5861 $
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 "examples/support.hh"
00043 #include "gecode/minimodel.hh"
00044 
00053 struct TileSpec {
00054   int width, height;
00055   int amount;
00056   const char *tile;
00057 };
00058 
00067 extern const TileSpec *examples[];
00072 extern const int examples_size[];
00077 extern const unsigned int n_examples;
00078 
00079 namespace {
00092   int pos(int h, int w, int h1, int w1);
00094   typedef void (*tsymmfunc)(const char*, int, int, char*, int&, int&);
00096   typedef void (*bsymmfunc)(const IntVarArgs, int, int, IntVarArgs&, int&, int&);
00098   template <class CArray, class Array>
00099   void id(CArray t1, int w1, int h1, Array t2, int& w2, int&h2);
00101   template <class CArray, class Array>
00102   void rot90(CArray t1, int w1, int h1, Array t2, int& w2, int& h2);
00104   template <class CArray, class Array>
00105   void rot180(CArray t1, int w1, int h1, Array t2, int& w2, int& h2);
00107   template <class CArray, class Array>
00108   void rot270(CArray t1, int w1, int h1, Array t2, int& w2, int& h2);
00110   template <class CArray, class Array>
00111   void flipx(CArray t1, int w1, int h1, Array t2, int& w2, int& h2);
00113   template <class CArray, class Array>
00114   void flipy(CArray t1, int w1, int h1, Array t2, int& w2, int& h2);
00116   template <class CArray, class Array>
00117   void flipd1(CArray t1, int w1, int h1, Array t2, int& w2, int& h2);
00119   template <class CArray, class Array>
00120   void flipd2(CArray t1, int w1, int h1, Array t2, int& w2, int& h2);
00122 }
00123 
00260 class Pentominoes : public Example {
00261 public:
00263   enum {
00264     PROPAGATION_INT,       
00265     PROPAGATION_BOOLEAN,   
00266   };
00268   enum {
00269     MODEL_NONE, 
00270     MODEL_SYMMETRY, 
00271   };
00272 private:
00274   const TileSpec *spec;
00276   int width, height;
00278   bool filled;
00280   int nspecs;
00282   int ntiles;
00283 
00285   IntVarArray board;
00286 
00288   int compute_number_of_tiles(const TileSpec* ts, int nspecs) {
00289     int res = 0;
00290     for (int i = nspecs; i--; ) {
00291       res += ts[i].amount;
00292     }
00293     return res;
00294   }
00295 
00298   REG tile_reg(int twidth, int theight, const char* tile, 
00299                REG mark, REG other, REG eol) {
00300     REG oe = other | eol;
00301     REG res = *oe;
00302     REG color[] = {other, mark};
00303     for (int h = 0; h < theight; ++h) {
00304       for (int w = 0; w < twidth; ++w) {
00305         int which = tile[h*twidth + w] == 'X';
00306         res += color[which];
00307       }
00308       if (h < theight-1) {
00309         res += oe(width-twidth, width-twidth);
00310       }
00311     }
00312     res += *oe + oe;
00313     return res;
00314   } 
00315 
00318   REG get_constraint(int t, REG mark, REG other, REG eol) {
00319     // This should be done for all rotations
00320     REG res;
00321     char *t2 = new char[width*height];
00322     int w2, h2;
00323     tsymmfunc syms[] = {id, flipx, flipy, flipd1, flipd2, rot90, rot180, rot270};
00324     int symscnt = sizeof(syms)/sizeof(tsymmfunc);
00325     for (int i = 0; i < symscnt; ++i) {
00326       syms[i](spec[t].tile, spec[t].width, spec[t].height, t2, w2, h2);
00327       res = res | tile_reg(w2, h2, t2, mark, other, eol);
00328     }
00329     delete [] t2;
00330 
00331     return res;
00332   }
00333 
00334 
00335 public:
00337   Pentominoes(const SizeOptions& opt)
00338     : spec(examples[opt.size()]), 
00339       width(spec[0].width+1), // Add one for extra row at end.
00340       height(spec[0].height),
00341       filled(spec[0].amount),
00342       nspecs(examples_size[opt.size()]-1), 
00343       ntiles(compute_number_of_tiles(spec+1, nspecs)), 
00344       board(this, width*height, filled,ntiles+1) {
00345     spec += 1; // No need for the specification-part any longer
00346     
00347     // Set end-of-line markers
00348     for (int h = 0; h < height; ++h) {
00349       for (int w = 0; w < width-1; ++w)
00350         rel(this, board[h*width + w], IRT_NQ, ntiles+1);
00351       rel(this, board[h*width + width - 1], IRT_EQ, ntiles+1);
00352     }
00353 
00354     // Post constraints
00355     if (opt.propagation() == PROPAGATION_INT) {
00356       int tile = 0;
00357       for (int i = 0; i < nspecs; ++i) {
00358         for (int j = 0; j < spec[i].amount; ++j) {
00359           // Color
00360           int col = tile+1;
00361           // Expression for color col
00362           REG mark(col);
00363           // Build expression for complement to color col
00364           REG other; 
00365           bool first = true;
00366           for (int j = filled; j <= ntiles; ++j) {
00367             if (j == col) continue;
00368             if (first) {
00369               other = REG(j);
00370               first = false;
00371             } else {
00372               other |= REG(j);
00373             }
00374           }
00375           // End of line marker
00376           REG eol(ntiles+1);
00377           extensional(this, board, get_constraint(i, mark, other, eol));
00378           ++tile;
00379         }
00380       }
00381     } else { // opt.propagation() == PROPAGATION_BOOLEAN
00382       int ncolors = ntiles + 2;
00383       // Boolean variables for channeling
00384       BoolVarArgs p(ncolors * board.size());
00385       for (int i=p.size(); i--; )
00386         p[i].init(this,0,1);
00387       
00388       // Post channel constraints
00389       for (int i=board.size(); i--; ) {
00390         BoolVarArgs c(ncolors);
00391         for (int j=ncolors; j--; ) 
00392           c[j]=p[i*ncolors+j];
00393         channel(this, c, board[i]);
00394       }
00395       
00396       // For placing tile i, we construct the expression over
00397       // 0/1-variables and apply it to the projection of
00398       // the board on the color for the tile.
00399       REG other(0), mark(1);
00400       int tile = 0;
00401       for (int i = 0; i < nspecs; ++i) {
00402         for (int j = 0; j < spec[i].amount; ++j) {
00403           int col = tile+1;
00404           // Projection for color col
00405           BoolVarArgs c(board.size());
00406           
00407           for (int k = board.size(); k--; ) {
00408             c[k] = p[k*ncolors+col];
00409           }
00410         
00411           extensional(this, c, get_constraint(i, mark, other, other));
00412           ++tile;
00413         }
00414       }
00415     }
00416     
00417     if (opt.model() == MODEL_SYMMETRY) {
00418       // Remove symmetrical boards
00419       IntVarArgs orig(board.size()-height), symm(board.size()-height);
00420       int pos = 0;
00421       for (int i = 0; i < board.size(); ++i) {
00422         if ((i+1)%width==0) continue;
00423         orig[pos++] = board[i];
00424       }
00425       
00426       int w2, h2;
00427       bsymmfunc syms[] = {flipx, flipy, flipd1, flipd2, rot90, rot180, rot270};
00428       int symscnt = sizeof(syms)/sizeof(bsymmfunc);
00429       for (int i = 0; i < symscnt; ++i) {
00430         syms[i](orig, width-1, height, symm, w2, h2);
00431         if (width-1 == w2 && height == h2)
00432           rel(this, orig, IRT_LQ, symm);
00433       }
00434     }
00435       
00436     // Install branching
00437     branch(this, board, INT_VAR_NONE, INT_VAL_MIN);
00438   }
00439   
00441   Pentominoes(bool share, Pentominoes& s) :
00442     Example(share,s), spec(s.spec), width(s.width), height(s.height),
00443     filled(s.filled), nspecs(s.nspecs) {
00444     board.update(this, share, s.board);
00445   }
00446   
00448   virtual Space*
00449   copy(bool share) {
00450     return new Pentominoes(share,*this);
00451   }
00452   
00454   virtual void
00455   print(std::ostream& os) {
00456     for (int h = 0; h < height; ++h) {
00457       os << "\t";
00458       for (int w = 0; w < width-1; ++w) {
00459         int val =  board[h*width + w].val();
00460         char c = val < 10 ? '0'+val : 'A' + (val-10);
00461         os << c;
00462       }
00463       os << std::endl;
00464     }
00465     os << std::endl;
00466   }
00467 };
00468 
00469 
00473 int
00474 main(int argc, char* argv[]) {
00475   SizeOptions opt("Pentominoes");
00476   opt.size(1);
00477   opt.model(Pentominoes::MODEL_SYMMETRY);
00478   opt.model(Pentominoes::MODEL_NONE,
00479             "none", "do not remove symmetric solutions");
00480   opt.model(Pentominoes::MODEL_SYMMETRY,
00481             "sym", "remove symmetric solutions");
00482 
00483   opt.propagation(Pentominoes::PROPAGATION_BOOLEAN);
00484   opt.propagation(Pentominoes::PROPAGATION_INT, 
00485                   "int", "use integer propagators");
00486   opt.propagation(Pentominoes::PROPAGATION_BOOLEAN, 
00487                   "bool", "use Boolean propagators");  
00488 
00489   opt.parse(argc,argv);
00490   if (opt.size() >= n_examples) {
00491     std::cerr << "Error: size must be between 0 and "
00492               << n_examples-1 << std::endl;
00493     return 1;
00494   }
00495   Example::run<Pentominoes,DFS,SizeOptions>(opt);
00496   return 0;
00497 }
00498 
00499 
00505 
00506 static const TileSpec puzzle0[] = 
00507   {
00508     // Width and height of board
00509     {4, 4, true, ""},
00510     {2, 3, 1, 
00511      "XX"
00512      "X "
00513      "X "},
00514     {2, 1, 1,
00515      "XX"},
00516     {3, 3, 1,
00517      " XX"
00518      "  X"
00519      "XXX"},
00520     {1, 1, 1,
00521      "X"},
00522     {3, 1, 1,
00523      "XXX"}
00524   };
00526 static const TileSpec puzzle1[] =
00527   {
00528     // Width and height of board
00529     {8, 8, true, ""},
00530     {3, 3, 1,
00531      "XXX"
00532      "XXX"
00533      "XX "},
00534     {5, 3, 1,
00535      "  XXX"
00536      "  X  "
00537      "XXX  "},
00538     {3, 4, 1,
00539      "XXX"
00540      "XXX"
00541      "  X"
00542      "  X"},
00543     {3, 4, 1,
00544      "XXX"
00545      "  X"
00546      "  X"
00547      "  X"},
00548     {2, 5, 1,
00549      " X"
00550      " X"
00551      " X"
00552      "XX"
00553      "XX"},
00554     {4, 2, 1,
00555      "XX  "
00556      "XXXX"},
00557     {3, 3, 1,
00558      "XXX"
00559      "  X"
00560      "  X"},
00561     {2, 3, 1,
00562      "XX"
00563      "X "
00564      "X "},
00565     {2, 4, 1,
00566      "XX"
00567      "XX"
00568      "XX"
00569      "XX"},
00570     {3, 2, 1,
00571      "XX "
00572      "XXX"}
00573   };
00574 
00575 // Perfect square number 2 from examples/perfect-square.cc
00576 static const TileSpec square2[] =
00577   {
00578     // Width and height of board
00579     {10, 10, true, ""},
00580     {6, 6, 1,
00581      "XXXXXX"
00582      "XXXXXX"
00583      "XXXXXX"
00584      "XXXXXX"
00585      "XXXXXX"
00586      "XXXXXX"
00587     },
00588     {4, 4, 3,
00589      "XXXX"
00590      "XXXX"
00591      "XXXX"
00592      "XXXX"},
00593     {2, 2, 4,
00594      "XX"
00595      "XX"}
00596   };
00597 
00598 // Perfect square number 3 from examples/perfect-square.cc
00599 static const TileSpec square3[] =
00600   {
00601     // Width and height of board
00602     {20, 20, true, ""},
00603     {9, 9, 1,
00604      "XXXXXXXXX"
00605      "XXXXXXXXX"
00606      "XXXXXXXXX"
00607      "XXXXXXXXX"
00608      "XXXXXXXXX"
00609      "XXXXXXXXX"
00610      "XXXXXXXXX"
00611      "XXXXXXXXX"
00612      "XXXXXXXXX"
00613     },
00614     {8, 8, 2,
00615      "XXXXXXXX"
00616      "XXXXXXXX"
00617      "XXXXXXXX"
00618      "XXXXXXXX"
00619      "XXXXXXXX"
00620      "XXXXXXXX"
00621      "XXXXXXXX"
00622      "XXXXXXXX"
00623     },
00624     {7, 7, 1,
00625      "XXXXXXX"
00626      "XXXXXXX"
00627      "XXXXXXX"
00628      "XXXXXXX"
00629      "XXXXXXX"
00630      "XXXXXXX"
00631      "XXXXXXX"
00632     },
00633     {5, 5, 1,
00634      "XXXXX"
00635      "XXXXX"
00636      "XXXXX"
00637      "XXXXX"
00638      "XXXXX"
00639     },
00640     {4, 4, 5,
00641      "XXXX"
00642      "XXXX"
00643      "XXXX"
00644      "XXXX"},
00645     {3, 3, 3,
00646      "XXX"
00647      "XXX"
00648      "XXX"},
00649     {2, 2, 2,
00650      "XX"
00651      "XX"},
00652     {1, 1, 2,
00653      "X"}
00654   };
00655 
00656 static const TileSpec pentomino6x10[] =
00657   {
00658     // Width and height of board
00659     {10, 6, true, ""},
00660     {2, 4, 1,
00661      "X "
00662      "X "
00663      "X "
00664      "XX"},
00665     {3,3, 1,
00666      "XX "
00667      " XX"
00668      " X "},
00669     {3,3, 1,
00670      "XXX"
00671      " X "
00672      " X "},
00673     {3,3, 1,
00674      "  X"
00675      " XX"
00676      "XX "},
00677     {2,4, 1,
00678      " X"
00679      "XX"
00680      " X"
00681      " X"},
00682     {5,1, 1,
00683      "XXXXX"},
00684     {3,3, 1,
00685      "X  "
00686      "XXX"
00687      "  X"},
00688     {4,2, 1,
00689      " XXX"
00690      "XX  "},
00691     {2,3, 1,
00692      "XX"
00693      "XX"
00694      " X"},
00695     {3,2, 1,
00696      "X X"
00697      "XXX"},
00698     {3,3, 1,
00699      " X "
00700      "XXX"
00701      " X "},
00702     {3,3, 1,
00703      "  X"
00704      "  X"
00705      "XXX"}
00706   };
00707 
00708 static const TileSpec pentomino5x12[] =
00709   {
00710     // Width and height of board
00711     {12, 5, true, ""},
00712     {2, 4, 1,
00713      "X "
00714      "X "
00715      "X "
00716      "XX"},
00717     {3,3, 1,
00718      "XX "
00719      " XX"
00720      " X "},
00721     {3,3, 1,
00722      "XXX"
00723      " X "
00724      " X "},
00725     {3,3, 1,
00726      "  X"
00727      " XX"
00728      "XX "},
00729     {2,4, 1,
00730      " X"
00731      "XX"
00732      " X"
00733      " X"},
00734     {5,1, 1,
00735      "XXXXX"},
00736     {3,3, 1,
00737      "X  "
00738      "XXX"
00739      "  X"},
00740     {4,2, 1,
00741      " XXX"
00742      "XX  "},
00743     {2,3, 1,
00744      "XX"
00745      "XX"
00746      " X"},
00747     {3,2, 1,
00748      "X X"
00749      "XXX"},
00750     {3,3, 1,
00751      " X "
00752      "XXX"
00753      " X "},
00754     {3,3, 1,
00755      "  X"
00756      "  X"
00757      "XXX"}
00758   };
00759 
00760 static const TileSpec pentomino4x15[] =
00761   {
00762     // Width and height of board
00763     {15, 4, true, ""},
00764     {2, 4, 1,
00765      "X "
00766      "X "
00767      "X "
00768      "XX"},
00769     {3,3, 1,
00770      "XX "
00771      " XX"
00772      " X "},
00773     {3,3, 1,
00774      "XXX"
00775      " X "
00776      " X "},
00777     {3,3, 1,
00778      "  X"
00779      " XX"
00780      "XX "},
00781     {2,4, 1,
00782      " X"
00783      "XX"
00784      " X"
00785      " X"},
00786     {5,1, 1,
00787      "XXXXX"},
00788     {3,3, 1,
00789      "X  "
00790      "XXX"
00791      "  X"},
00792     {4,2, 1,
00793      " XXX"
00794      "XX  "},
00795     {2,3, 1,
00796      "XX"
00797      "XX"
00798      " X"},
00799     {3,2, 1,
00800      "X X"
00801      "XXX"},
00802     {3,3, 1,
00803      " X "
00804      "XXX"
00805      " X "},
00806     {3,3, 1,
00807      "  X"
00808      "  X"
00809      "XXX"}
00810   };
00811 
00812 static const TileSpec pentomino3x20[] =
00813   {
00814     // Width and height of board
00815     {20, 3, true, ""},
00816     {2, 4, 1,
00817      "X "
00818      "X "
00819      "X "
00820      "XX"},
00821     {3,3, 1,
00822      "XX "
00823      " XX"
00824      " X "},
00825     {3,3, 1,
00826      "XXX"
00827      " X "
00828      " X "},
00829     {3,3, 1,
00830      "  X"
00831      " XX"
00832      "XX "},
00833     {2,4, 1,
00834      " X"
00835      "XX"
00836      " X"
00837      " X"},
00838     {5,1, 1,
00839      "XXXXX"},
00840     {3,3, 1,
00841      "X  "
00842      "XXX"
00843      "  X"},
00844     {4,2, 1,
00845      " XXX"
00846      "XX  "},
00847     {2,3, 1,
00848      "XX"
00849      "XX"
00850      " X"},
00851     {3,2, 1,
00852      "X X"
00853      "XXX"},
00854     {3,3, 1,
00855      " X "
00856      "XXX"
00857      " X "},
00858     {3,3, 1,
00859      "  X"
00860      "  X"
00861      "XXX"}
00862   };
00863 
00865 const TileSpec *examples[] = {puzzle0, puzzle1, square2, square3,
00866                            pentomino6x10,pentomino5x12,
00867                            pentomino4x15,pentomino3x20};
00868 const int examples_size[] = {sizeof(puzzle0)/sizeof(TileSpec),
00869                              sizeof(puzzle1)/sizeof(TileSpec),
00870                              sizeof(square2)/sizeof(TileSpec),
00871                              sizeof(square3)/sizeof(TileSpec),
00872                              sizeof(pentomino6x10)/sizeof(TileSpec),
00873                              sizeof(pentomino5x12)/sizeof(TileSpec),
00874                              sizeof(pentomino4x15)/sizeof(TileSpec),
00875                              sizeof(pentomino3x20)/sizeof(TileSpec)};
00876 
00878 const unsigned n_examples = sizeof(examples)/sizeof(TileSpec*);
00880 
00881 // Symmetry functions
00882 namespace {
00883   int pos(int h, int w, int h1, int w1) {
00884     if (!(0 <= h && h < h1) ||
00885         !(0 <= w && w < w1)) {
00886       std::cerr << "Cannot place (" << h << "," << w 
00887                 << ") on board of size " << h1 << "x" << w1 << std::endl;
00888     }
00889     return h * w1 + w;
00890   }
00891   template <class CArray, class Array>
00892   void id(CArray t1, int w1, int h1, Array t2, int& w2, int&h2) {
00893     w2 = w1; h2 = h1;
00894     for (int h = 0; h < h1; ++h)
00895       for (int w = 0; w < w1; ++w)
00896         t2[pos(h, w, h2, w2)] = t1[pos(h, w, h1, w1)];
00897   }
00898   template <class CArray, class Array>
00899   void rot90(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) {
00900     w2 = h1; h2 = w1;
00901     for (int h = 0; h < h1; ++h)
00902       for (int w = 0; w < w1; ++w)
00903         t2[pos(w, w2-h-1, h2, w2)] = t1[pos(h, w, h1, w1)];
00904   }
00905   template <class CArray, class Array>
00906   void rot180(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) {
00907     w2 = w1; h2 = h1;
00908     for (int h = 0; h < h1; ++h)
00909       for (int w = 0; w < w1; ++w)
00910         t2[pos(h2-h-1, w2-w-1, h2, w2)] = t1[pos(h, w, h1, w1)];
00911   }
00912   template <class CArray, class Array>
00913   void rot270(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) {
00914     w2 = h1; h2 = w1;
00915     for (int h = 0; h < h1; ++h)
00916       for (int w = 0; w < w1; ++w)
00917         t2[pos(h2-w-1, h, h2, w2)] = t1[pos(h, w, h1, w1)];
00918   }
00919   template <class CArray, class Array>
00920   void flipx(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) {
00921     w2 = w1; h2 = h1;
00922     for (int h = 0; h < h1; ++h)
00923       for (int w = 0; w < w1; ++w)
00924         t2[pos(h, w2-w-1, h2, w2)] = t1[pos(h, w, h1, w1)];
00925   }
00926   template <class CArray, class Array>
00927   void flipy(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) {
00928     w2 = w1; h2 = h1;
00929     for (int h = 0; h < h1; ++h)
00930       for (int w = 0; w < w1; ++w)
00931         t2[pos(h2-h-1, w, h2, w2)] = t1[pos(h, w, h1, w1)];
00932   }
00933   template <class CArray, class Array>
00934   void flipd1(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) {
00935     w2 = h1; h2 = w1;
00936     for (int h = 0; h < h1; ++h)
00937       for (int w = 0; w < w1; ++w)
00938         t2[pos(w, h, h2, w2)] = t1[pos(h, w, h1, w1)];
00939   }
00940   template <class CArray, class Array>
00941   void flipd2(CArray t1, int w1, int h1, Array t2, int& w2, int& h2) {
00942     w2 = h1; h2 = w1;
00943     for (int h = 0; h < h1; ++h)
00944       for (int w = 0; w < w1; ++w)
00945         t2[pos(h2-w-1, w2-h-1, h2, w2)] = t1[pos(h, w, h1, w1)];
00946   }
00947 }
00948 
00949 // STATISTICS: example-any