Generated on Thu Mar 22 10:39:31 2012 for Gecode by doxygen 1.6.3

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