Cパズルプログラミング-再帰編 > ペントミノ > 対称性を除去して2339通り、でも遅い > pentomino17.c


[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

pentomino17.c 応援する 

/************************************************************************/
/*      ペントミノ   その17                                    */
/*                                                                      */
/*      盤面の対称移動                                                 */
/*                                                                      */
/*      usage: pentomino                                                */
/************************************************************************/
#include        <stdio.h>

#define TRUE    1
#define FALSE   0

#define CN      5               /* セル数  */
#define PN      12              /* ピース数 */

#define WIDTH  10               /* 盤面の幅 */
#define HEIGHT 6                /* 盤面の高さ        */

#define BLANK   '.'             /* ブランク */

int     answercount;            /* 解の数  */
char    board[WIDTH][HEIGHT];   /* 盤面           */
int     used[PN];               /* 使用済み状態       */
int     usedcount;              /* 使用済みピース数     */

typedef struct {
        int     x;
        int     y;
} Pos;

typedef struct {
        char            name;           /* 名称   */
        Pos             form[CN];       /* 配置   */
} PieceForm;

PieceForm AllPieces[] = {
        { 'F', {{ 0, 0},{ 0, 1},{ 1, 1},{ 1, 2},{ 2, 1}} },
        { 'F', {{ 0, 0},{ 1, 0},{ 1, 1},{ 1, 2},{ 2, 1}} },
        { 'F', {{ 0, 0},{ 1, 0},{ 1, 1},{ 2,-1},{ 2, 0}} },
        { 'F', {{ 0, 0},{ 1,-1},{ 1, 0},{ 1, 1},{ 2,-1}} },
        { 'F', {{ 0, 0},{ 0, 1},{ 1,-1},{ 1, 0},{ 2, 0}} },
        { 'F', {{ 0, 0},{ 1,-2},{ 1,-1},{ 1, 0},{ 2,-1}} },
        { 'F', {{ 0, 0},{ 1,-1},{ 1, 0},{ 2, 0},{ 2, 1}} },
        { 'F', {{ 0, 0},{ 1,-1},{ 1, 0},{ 1, 1},{ 2, 1}} },
        { 'I', {{ 0, 0},{ 0, 1},{ 0, 2},{ 0, 3},{ 0, 4}} },
        { 'I', {{ 0, 0},{ 1, 0},{ 2, 0},{ 3, 0},{ 4, 0}} },
        { 'L', {{ 0, 0},{ 0, 1},{ 0, 2},{ 0, 3},{ 1, 0}} },
        { 'L', {{ 0, 0},{ 0, 1},{ 1, 0},{ 2, 0},{ 3, 0}} },
        { 'L', {{ 0, 0},{ 1, 0},{ 1, 1},{ 1, 2},{ 1, 3}} },
        { 'L', {{ 0, 0},{ 1, 0},{ 2, 0},{ 3, 0},{ 3, 1}} },
        { 'L', {{ 0, 0},{ 0, 1},{ 0, 2},{ 0, 3},{ 1, 3}} },
        { 'L', {{ 0, 0},{ 0, 1},{ 1, 1},{ 2, 1},{ 3, 1}} },
        { 'L', {{ 0, 0},{ 1,-3},{ 1,-2},{ 1,-1},{ 1, 0}} },
        { 'L', {{ 0, 0},{ 1, 0},{ 2, 0},{ 3,-1},{ 3, 0}} },
        { 'N', {{ 0, 0},{ 0, 1},{ 1, 1},{ 1, 2},{ 1, 3}} },
        { 'N', {{ 0, 0},{ 1, 0},{ 1, 1},{ 2, 1},{ 3, 1}} },
        { 'N', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1,-1},{ 1, 0}} },
        { 'N', {{ 0, 0},{ 1, 0},{ 2,-1},{ 2, 0},{ 3,-1}} },
        { 'N', {{ 0, 0},{ 0, 1},{ 1,-2},{ 1,-1},{ 1, 0}} },
        { 'N', {{ 0, 0},{ 1,-1},{ 1, 0},{ 2,-1},{ 3,-1}} },
        { 'N', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1, 2},{ 1, 3}} },
        { 'N', {{ 0, 0},{ 1, 0},{ 2, 0},{ 2, 1},{ 3, 1}} },
        { 'P', {{ 0, 0},{ 0, 1},{ 1, 0},{ 1, 1},{ 2, 0}} },
        { 'P', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1, 0},{ 1, 1}} },
        { 'P', {{ 0, 0},{ 1, 0},{ 1, 1},{ 2, 0},{ 2, 1}} },
        { 'P', {{ 0, 0},{ 0, 1},{ 1, 0},{ 1, 1},{ 1, 2}} },
        { 'P', {{ 0, 0},{ 0, 1},{ 1, 0},{ 1, 1},{ 2, 1}} },
        { 'P', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1, 1},{ 1, 2}} },
        { 'P', {{ 0, 0},{ 1,-1},{ 1, 0},{ 2,-1},{ 2, 0}} },
        { 'P', {{ 0, 0},{ 0, 1},{ 1,-1},{ 1, 0},{ 1, 1}} },
        { 'T', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1, 1},{ 2, 1}} },
        { 'T', {{ 0, 0},{ 1, 0},{ 1, 1},{ 1, 2},{ 2, 0}} },
        { 'T', {{ 0, 0},{ 1, 0},{ 2,-1},{ 2, 0},{ 2, 1}} },
        { 'T', {{ 0, 0},{ 1,-2},{ 1,-1},{ 1, 0},{ 2, 0}} },
        { 'U', {{ 0, 0},{ 0, 2},{ 1, 0},{ 1, 1},{ 1, 2}} },
        { 'U', {{ 0, 0},{ 0, 1},{ 1, 1},{ 2, 0},{ 2, 1}} },
        { 'U', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1, 0},{ 1, 2}} },
        { 'U', {{ 0, 0},{ 0, 1},{ 1, 0},{ 2, 0},{ 2, 1}} },
        { 'V', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1, 0},{ 2, 0}} },
        { 'V', {{ 0, 0},{ 1, 0},{ 2, 0},{ 2, 1},{ 2, 2}} },
        { 'V', {{ 0, 0},{ 0, 1},{ 0, 2},{ 1, 2},{ 2, 2}} },
        { 'V', {{ 0, 0},{ 1, 0},{ 2,-2},{ 2,-1},{ 2, 0}} },
        { 'W', {{ 0, 0},{ 0, 1},{ 1, 1},{ 1, 2},{ 2, 2}} },
        { 'W', {{ 0, 0},{ 1, 0},{ 1, 1},{ 2, 1},{ 2, 2}} },
        { 'W', {{ 0, 0},{ 1,-1},{ 1, 0},{ 2,-2},{ 2,-1}} },
        { 'W', {{ 0, 0},{ 0, 1},{ 1,-1},{ 1, 0},{ 2,-1}} },
        { 'X', {{ 0, 0},{ 1,-1},{ 1, 0},{ 1, 1},{ 2, 0}} },
        { 'Y', {{ 0, 0},{ 0, 1},{ 0, 2},{ 0, 3},{ 1, 1}} },
        { 'Y', {{ 0, 0},{ 1, 0},{ 1, 1},{ 2, 0},{ 3, 0}} },
        { 'Y', {{ 0, 0},{ 1,-1},{ 1, 0},{ 1, 1},{ 1, 2}} },
        { 'Y', {{ 0, 0},{ 1, 0},{ 2, 0},{ 2, 1},{ 3, 0}} },
        { 'Y', {{ 0, 0},{ 0, 1},{ 0, 2},{ 0, 3},{ 1, 2}} },
        { 'Y', {{ 0, 0},{ 1,-1},{ 1, 0},{ 2, 0},{ 3, 0}} },
        { 'Y', {{ 0, 0},{ 1,-2},{ 1,-1},{ 1, 0},{ 1, 1}} },
        { 'Y', {{ 0, 0},{ 1, 0},{ 2,-1},{ 2, 0},{ 3, 0}} },
        { 'Z', {{ 0, 0},{ 0, 1},{ 1, 1},{ 2, 1},{ 2, 2}} },
        { 'Z', {{ 0, 0},{ 1, 0},{ 1, 1},{ 1, 2},{ 2, 2}} },
        { 'Z', {{ 0, 0},{ 0, 1},{ 1, 0},{ 2,-1},{ 2, 0}} },
        { 'Z', {{ 0, 0},{ 1,-2},{ 1,-1},{ 1, 0},{ 2,-2}} },
        { '\0', }       /* ←番犬 */
};

                         /*  F  I  L  N  P  T  U  V  W  X  Y  Z  */
const   int     base[PN] = { 0, 8,10,18,26,34,38,42,46,50,51,59 };

Pos     nextblank( int x, int y );
int     ison( int x, int y );
int     ispieceok( int x, int y, PieceForm *pf );
void    pieceset( int x, int y, PieceForm *pf );
void    pieceunset( int x, int y, PieceForm *pf );
void    initboard( void );
void    copyboard( char dest[WIDTH][HEIGHT], char src[WIDTH][HEIGHT] );
void    udmirror( char dest[WIDTH][HEIGHT], char src[WIDTH][HEIGHT] );
void    lrmirror( char dest[WIDTH][HEIGHT], char src[WIDTH][HEIGHT] );
int     isunique( void );
void    printboard( char bd[WIDTH][HEIGHT] );
void    foundanswer( void );
void    trypiece( int x, int y );
void    initialize( void );
int     main(int argc, char **argv);

/*----------------------------------------------------------------------*/
/*      次の空き位置を見付ける                                             */
/*----------------------------------------------------------------------*/
Pos     nextblank( int x, int y )
{
        Pos     q;
        
        for(;;) {
                if( board[x][y] == BLANK ) {
                        q.x = x;
                        q.y = y;
                        return  q;
                }
                if( ++y >= HEIGHT ) {
                        ++x;
                        y = 0;
                }
        }
}

/*----------------------------------------------------------------------*/
/*      指定位置(x,y)が盤上かどうかの判定                             */
/*----------------------------------------------------------------------*/
int     ison( int x, int y )
{
        if( x<0 || x>=WIDTH )
                return  FALSE;
        if( y<0 || y>=HEIGHT )
                return  FALSE;
        return  TRUE;
}

/*----------------------------------------------------------------------*/
/*      指定位置(x,y)を基準に指定向きのピースを置けるかの判定           */
/*----------------------------------------------------------------------*/
int     ispieceok( int x, int y, PieceForm *pf )
{
        int     i;
        int     u, v;

        for( i=0; i<CN; ++i ) {
                u = x + pf->form[i].x;
                v = y + pf->form[i].y;
                if( ! ison(u,v) )
                        return  FALSE;
                if( board[u][v] != BLANK )
                        return  FALSE;
        }
        return  TRUE;
}

/*----------------------------------------------------------------------*/
/*      指定位置(x,y)の指定のピース(含む方向)をセットする            */
/*----------------------------------------------------------------------*/
void    pieceset( int x, int y, PieceForm *pf )
{
        int     i;
        int     u, v;

        for( i=0; i<CN; ++i ) {
                u = x + pf->form[i].x;
                v = y + pf->form[i].y;
                board[u][v] = pf->name;
        }
}

/*----------------------------------------------------------------------*/
/*      指定位置(x,y)の指定のピース(含む方向)を取り除く                     */
/*----------------------------------------------------------------------*/
void    pieceunset( int x, int y, PieceForm *pf )
{
        int     i;
        int     u, v;

        for( i=0; i<CN; ++i ) {
                u = x + pf->form[i].x;
                v = y + pf->form[i].y;
                board[u][v] = BLANK;
        }
}

/*----------------------------------------------------------------------*/
/*      盤面の初期化                                                  */
/*----------------------------------------------------------------------*/
void    initboard( void )
{
        int     x, y;

        for( x=0; x<WIDTH; ++x ) {
                for( y=0; y<HEIGHT; ++y ) {
                        board[x][y] = BLANK;
                }
        }
}
                                                                        

/*----------------------------------------------------------------------*/
/*      盤面のコピー                                                  */
/*----------------------------------------------------------------------*/
void    copyboard( char dest[WIDTH][HEIGHT], char src[WIDTH][HEIGHT] )
{
        int     x, y;

        for( x=0; x<WIDTH; ++x )
                for( y=0; y<HEIGHT; ++y )
                        dest[x][y] = src[x][y];
}

/*----------------------------------------------------------------------*/
/*      盤面の上下を反転する                                              */
/*----------------------------------------------------------------------*/
void    udmirror( char dest[WIDTH][HEIGHT], char src[WIDTH][HEIGHT] )
{
        int     x, y;
        char    work[WIDTH][HEIGHT];

        copyboard( work, src );

        for( x=0; x<WIDTH; ++x )
                for( y=0; y<HEIGHT; ++y )
                        dest[x][HEIGHT-1-y] = work[x][y];
}

/*----------------------------------------------------------------------*/
/*      盤面の上下を反転する                                              */
/*----------------------------------------------------------------------*/
void    lrmirror( char dest[WIDTH][HEIGHT], char src[WIDTH][HEIGHT] )
{
        int     x, y;
        char    work[WIDTH][HEIGHT];

        copyboard( work, src );

        for( x=0; x<WIDTH; ++x )
                for( y=0; y<HEIGHT; ++y )
                        dest[WIDTH-1-x][y] = work[x][y];
}

/*----------------------------------------------------------------------*/
/*      回転・反転などによるユニーク性のチェック                    */
/*----------------------------------------------------------------------*/
int     isunique( void )
{
        char    work[WIDTH][HEIGHT];            /* 作業用盤面        */

        printboard( board );                            /*  候補  */

        copyboard( work, board );

        udmirror( work, work ); printboard( work );     /* 上下反転 */
        lrmirror( work, work ); printboard( work );     /* 左右反転 */
        udmirror( work, work ); printboard( work );     /* 上下反転 */
}

/*----------------------------------------------------------------------*/
/*      盤面の初期化                                                  */
/*----------------------------------------------------------------------*/
void    printboard( char bd[WIDTH][HEIGHT] )
{
        int     x, y;

        for( y=0; y<HEIGHT; ++y ) {
                for( x=0; x<WIDTH; ++x ) {
                        printf( " %c", bd[x][y] );
                }
                printf( "\n" );
        }
        printf( "\n" );
}

/*----------------------------------------------------------------------*/
/*      解を見付けた                                                  */
/*----------------------------------------------------------------------*/
void    foundanswer( void )
{
        printf( "-->foundanswer\n" );
        isunique();             /* ユニークかどうかの検査を行う予定     */

        ++answercount;
        printf( "Answer No. %d\n", answercount );
        printboard( board );
}

/*----------------------------------------------------------------------*/
/*      試す                                                              */
/*----------------------------------------------------------------------*/
void    trypiece( int x, int y )
{
        int     i;
        Pos     bp;
        PieceForm       *p;
        char    name;

        if( usedcount == PN ) {
                foundanswer();
                return;
        }

        bp = nextblank( x, y );
        x = bp.x;
        y = bp.y;

        for( i=0; i<PN; ++i ) {
                if( used[i] )           /* 使用済チェック      */
                        continue;
                p = &AllPieces[base[i]];
                name = p->name;
                for( ; p->name == name; ++p ) {
                        if( !ispieceok( x, y, p ) )
                                continue;
                        pieceset( x, y, p );
                        used[i] = TRUE;
                        ++usedcount;

                        trypiece( x, y );       /* 再帰   */

                        pieceunset( x, y, p );
                        used[i] = FALSE;
                        --usedcount;
                }
        }
}

/*----------------------------------------------------------------------*/
/*      初期化                                                             */
/*----------------------------------------------------------------------*/
void    initialize( void )
{
        int     i;

        initboard();
        for( i=0; i<PN; ++i )
                used[i] = FALSE;
        usedcount = 0;
        answercount = 0;
}

/*----------------------------------------------------------------------*/
/*      main                                                            */
/*----------------------------------------------------------------------*/
int     main(int argc, char **argv)
{
        initialize();

        trypiece(0,0);
}

/************************************************************************/
/*                              End of Pentomino                        */
/************************************************************************/

[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

このサイトについて|ヘルプ|Q&A|個人情報保護|プライバシーポリシー|利用規約|コメント・トラックバック規約|削除規程|広告掲載
Copyright (c) 2005-2007 Time Intermedia Corporation