2

I am trying to solve this tromino tiling problem for n x n board. Given Missing square co-ordinate(MS) x and y in n x n board, we have to fill the rest of the board with 'L' shaped tile.

I have managed to get the output for 2 x 2 board. But, I am stuck with the output for board sizes 4 x 4, 8 x 8...and so on.

Following is the function I wrote that recursively calls itself to print the board:

/* This program tiles with right trominoes an nxn
   board with one square missing, assuming that n
   is a power of 2.                                */

#include <stdio.h>
#include <stdlib.h>

// #define LR 0
// #define LL 1
// #define UR 3
// #define UL 2
// #define MS -1

const int Max = 256;

int board[Max][Max];

void tromino /* function to do tiling */
     ( int x_board,      /* x coordinate of board */
       int y_board,      /* y coordinate of board */
       int x_missing,    /* x coordinate of missing square */
       int y_missing,    /* y coordinate of missing square */
       int board_size);   /* size of board */

void show_Tromino(int size, int x_miss, int y_miss);

int main()
{
     int board_size,
         x_missing,  /* x coordinate of missing square */
         y_missing;  /* y coordinate of missing square */
     do {
          printf( "\n-------------------------------------" );
          printf( "\nEnter size of board (0 to quit): " );
          scanf( "%d", &board_size );
          if ( board_size ) {
               printf( "\nEnter coordinates of missing square: " );
               scanf( "%d%d", &x_missing, &y_missing );
               printf( "\n\nTiling\n" );
               // if(board[x_board][0] == x_missing && board[0][y_board] == y_missing)
               //  printf("MS\t");
               //board[x_missing][y_missing] = -1;
               tromino( 0, 0, x_missing, y_missing, board_size);
               show_Tromino(board_size, x_missing, y_missing);
          }
     } while ( board_size );

     return EXIT_SUCCESS;
}

void tromino( int x_board,     /* x coordinate of board */
              int y_board,     /* y coordinate of board */
              int x_missing,   /* x coordinate of missing square */
              int y_missing,   /* y coordinate of missing square */
              int board_size) /* size of board */

{
     int half_size = board_size/2, /* size of subboard */
         x_center,  /* x coordinate of center of board */
         y_center,  /* y coordinate of center of board */
         x_upper_left,  /* x coordinate of missing square in upper
                                                     left subboard */
         y_upper_left,  /* y coordinate of missing square in upper
                                                     left subboard */
         x_upper_right, /* x coordinate of missing square in upper
                                                    right subboard */
         y_upper_right, /* y coordinate of missing square in upper
                                                    right subboard */
         x_lower_right, /* x coordinate of missing square in lower
                                                    right subboard */
         y_lower_right, /* y coordinate of missing square in lower
                                                    right subboard */
         x_lower_left,  /* x coordinate of missing square in lower
                                                     left subboard */
         y_lower_left;  /* y coordinate of missing square in lower
                                                     left subboard */

     if ( board_size == 2 ) /* 2x2 board */
     {
       for(int i=board_size-1; i>=0; i--)
       {
         for(int j=0;j<board_size;j++)
         {
           if(i==x_missing && j==y_missing)
            //printf("MS\t");
          {  board[i][j] = -1;}
           //printf( "%d %d ", x_board + 1, y_board + 1 );
           /* find and print orientation of tromino */
         if(x_missing == x_board)
          {
            if(y_missing == y_board)
              // printf("UR\t");
              {board[i][j] = 2;}
            else
              // printf("LR\t");
              {board[i][j] = 0;}
          }

          else
          {
            if(y_missing == y_board)
              // printf("UL\t");
              {board[i][j] = 3;}
            else
              // printf("LL\t");
              {board[i][j] = 1;}
          }
       }
       printf("\n");
     }
     return;
    }

   // if(board_size>2)
   // {   /* compute x and y coordinates of center of board */
     x_center = x_board + half_size;
     y_center = y_board + half_size;


         if((x_missing < x_center) && (y_missing < y_center))
         {
           //printf("UR\t");
           x_upper_left = x_center - 1;
           y_upper_left = y_center;
           x_upper_right = x_center;
           y_upper_right = y_center;
           x_lower_left = x_missing;
           y_lower_left = y_missing;
           x_lower_right = x_center;
           y_lower_right = y_center - 1;

         }
         if((x_missing >= x_center) && (y_missing < y_center))
         {
           //printf("UL\t");
           x_upper_left = x_center - 1;
           y_upper_left = y_center;
           x_upper_right = x_center;
           y_upper_right = y_center;
           x_lower_left = x_center - 1;
           y_lower_left = y_center - 1;
           x_lower_right = x_missing;
           y_lower_right = y_missing;
         }
         if((x_missing >= x_center) && (y_missing >= y_center))
         {
           //printf("LL\t");
           x_upper_left = x_center - 1;
           y_upper_left = y_center;
           x_upper_right = x_missing;
           y_upper_right = y_missing;
           x_lower_left = x_center - 1;
           y_lower_left = y_center - 1;
           x_lower_right = x_center;
           y_lower_right = y_center - 1;
         }
         if((x_missing < x_center) && (y_missing >= y_center))
         {
           //printf("LR\t");
           x_upper_left = x_missing;
           y_upper_left = y_missing;
           x_upper_right = x_center;
           y_upper_right = y_center;
           x_lower_left = x_center - 1;
           y_lower_left = y_center - 1;
           x_lower_right = x_center;
           y_lower_right = y_center - 1;
         }
     /* tile the four subboards */
     tromino( x_board, y_board + half_size,
          x_upper_left, y_upper_left, half_size);
     tromino( x_board + half_size, y_board + half_size,
          x_upper_right, y_upper_right, half_size);
     tromino( x_board + half_size, y_board,
          x_lower_right, y_lower_right, half_size);
     tromino( x_board, y_board,
                    x_lower_left, y_lower_left, half_size);

}

void show_Tromino(int size, int x_miss, int y_miss)
{
  int bsize[Max][Max];
  for(int i=size-1; i>=0;i--)
  {
    for(int j=0; j<size;j++)
    {
      if(!(bsize[i][j] == -1 || (j==x_miss && i==y_miss)))
      {
        if(bsize[i][j] == 1)
        {
          printf("LL\t");
        }

        else if(bsize[i][j] == 2)
        {
          printf("UL\t");
        }

        else if(bsize[i][j] == 3)
        {
          printf("UR\t");
        }

        else if(bsize[i][j] == 0)
        {
          printf("LR\t");
        }
      }
      else if (bsize[i][j] == -1 || (j==x_miss && i==y_miss))
      {
        printf("MS\t");
      }
      bsize[i][j] += 1;
    }

    printf("\n");
  }
}

output1 : when board size 2 x 2(which is correct)

Enter size of board (0 to quit): 2

Enter coordinates of missing square: 0 1


Tiling
------
MS  LR  
LR  LR

output2 : when board size 4 x 4(which is incorrect). Though, I am getting the correct position of Missing Square(MS).

Enter size of board (0 to quit): 4

Enter coordinates of missing square: 0 1


Tiling
------
LR  LR  LR  LR  
LR  LR  LR  LR  
MS  LR  LR  LR  
LR  LR  LR  LR

output2 : when board size 4 x 4(which is expected)

Enter size of board (0 to quit): 4

Enter coordinates of missing square: 0 1

Tiling
------

UL UL UR UR
UL UR UR UR
MS LR UR LR 
LR LR LR LR

Note:

  • UL- Upper Left
  • UR- Upper Right
  • LL- Lower Left
  • LR- Lower Right
  • MS- Missing Square
  • Note that you are redefining both `x_board` and `y_board`. Also, I'd use some curly brackets in those nested `if`, to be sure that the actual logic is as expected. – Bob__ Mar 18 '20 at 09:11
  • @Bob__ I tried but it's not working –  Mar 18 '20 at 17:29
  • 1
    Perfect opportunity to step through the code in a debugger. Put a breakpoint before and after where you place a piece and see if it makes sense. – stark Mar 18 '20 at 18:29

2 Answers2

0

The problem is due to the base case. When solving for 2x2 you forgot to take the offset into consideration. Only [0,0],[0,1],[1,0],[1,1] are updated each time. The rest of the values (except the missing tile) are holding garbage values.

I believe your compiler sets all array values to zero by default. So the garbage values result in value LR.

Edit: Added the corrected code. Just map the outputs to the letters (I've printed the numbers)

/* This program tiles with right trominoes an nxn
   board with one square missing, assuming that n
   is a power of 2.                                */

#include <stdio.h>
#include <stdlib.h>

// #define LR 4
// #define LL 1
// #define UR 3
// #define UL 2
// #define MS -1

# define Max 256
int board[Max][Max];

void tromino /* function to do tiling */
     ( int x_board,      /* x coordinate of board */
       int y_board,      /* y coordinate of board */
       int x_missing,    /* x coordinate of missing square */
       int y_missing,    /* y coordinate of missing square */
       int board_size);   /* size of board */

void show_Tromino(int size, int x_miss, int y_miss);

int main()
{
     int board_size,
         x_missing,  /* x coordinate of missing square */
         y_missing;  /* y coordinate of missing square */
     do {
          printf( "\n-------------------------------------" );
          printf( "\nEnter size of board (0 to quit): " );
          scanf( "%d", &board_size );
          if ( board_size ) {
               printf( "\nEnter coordinates of missing square: " );
               scanf( "%d%d", &x_missing, &y_missing );
               printf( "\n\nTiling\n" );
               // if(board[x_board][0] == x_missing && board[0][y_board] == y_missing)
               //  printf("MS\t");
               //board[x_missing][y_missing] = -1;
               tromino( 0, 0, x_missing, y_missing, board_size);
               show_Tromino(board_size, x_missing, y_missing);
          }
     } while ( board_size );

     return EXIT_SUCCESS;
}

void tromino( int x_board,     /* x coordinate of board */
              int y_board,     /* y coordinate of board */
              int x_missing,   /* x coordinate of missing square */
              int y_missing,   /* y coordinate of missing square */
              int board_size) /* size of board */

{
     int half_size = board_size/2, /* size of subboard */
         x_center,  /* x coordinate of center of board */
         y_center,  /* y coordinate of center of board */
         x_upper_left,  /* x coordinate of missing square in upper
                                                     left subboard */
         y_upper_left,  /* y coordinate of missing square in upper
                                                     left subboard */
         x_upper_right, /* x coordinate of missing square in upper
                                                    right subboard */
         y_upper_right, /* y coordinate of missing square in upper
                                                    right subboard */
         x_lower_right, /* x coordinate of missing square in lower
                                                    right subboard */
         y_lower_right, /* y coordinate of missing square in lower
                                                    right subboard */
         x_lower_left,  /* x coordinate of missing square in lower
                                                     left subboard */
         y_lower_left;  /* y coordinate of missing square in lower
                                                     left subboard */

     if ( board_size == 2 ) /* 2x2 board */
     {
       //Theres too much of nesting for only 4 cases. Got rid of it
       if(x_board==x_missing && y_board==y_missing)
         board[x_board+1][y_board] = board[x_board][y_board+1]=board[x_board+1][y_board+1]=2;

       if(x_board+1==x_missing && y_board==y_missing)
         board[x_board][y_board]= board[x_board][y_board+1]=board[x_board+1][y_board+1]=3;

       if(x_board==x_missing && y_board+1==y_missing)
         board[x_board][y_board]= board[x_board+1][y_board] = board[x_board+1][y_board+1]=1;

       if(x_board+1==x_missing && y_board+1==y_missing)
         board[x_board][y_board]= board[x_board+1][y_board] = board[x_board][y_board+1]=0;
       return;
     }

   // if(board_size>2)
   // {   /* compute x and y coordinates of center of board */
     x_center = x_board + half_size;
     y_center = y_board + half_size;


         if((x_missing < x_center) && (y_missing < y_center))
         {
           //printf("UR\t");
           x_upper_left = x_center - 1;
           y_upper_left = y_center;
           x_upper_right = x_center;
           y_upper_right = y_center;
           x_lower_left = x_missing;
           y_lower_left = y_missing;
           x_lower_right = x_center;
           y_lower_right = y_center - 1;
           board[x_upper_left][y_upper_left]=2;     //CHANGE MADE. You forgot to tile the board
           board[x_upper_right][y_upper_right]=2;
           board[x_lower_right][y_lower_right]=2;

         }
         if((x_missing >= x_center) && (y_missing < y_center))
         {
           //printf("UL\t");
           x_upper_left = x_center - 1;
           y_upper_left = y_center;
           x_upper_right = x_center;
           y_upper_right = y_center;
           x_lower_left = x_center - 1;
           y_lower_left = y_center - 1;
           x_lower_right = x_missing;
           y_lower_right = y_missing;
           board[x_upper_left][y_upper_left]=3;     //CHANGE MADE. You forgot to tile the board
           board[x_upper_right][y_upper_right]=3;
           board[x_lower_left][y_lower_left]=3;
         }
         if((x_missing >= x_center) && (y_missing >= y_center))
         {
           //printf("LL\t");
           x_upper_left = x_center - 1;
           y_upper_left = y_center;
           x_upper_right = x_missing;
           y_upper_right = y_missing;
           x_lower_left = x_center - 1;
           y_lower_left = y_center - 1;
           x_lower_right = x_center;
           y_lower_right = y_center - 1;
           board[x_upper_left][y_upper_left]=1;     //CHANGE MADE. You forgot to tile the board
           board[x_lower_left][y_lower_left]=1;
           board[x_lower_right][y_lower_right]=1;
         }
         if((x_missing < x_center) && (y_missing >= y_center))
         {
           //printf("LR\t");
           x_upper_left = x_missing;
           y_upper_left = y_missing;
           x_upper_right = x_center;
           y_upper_right = y_center;
           x_lower_left = x_center - 1;
           y_lower_left = y_center - 1;
           x_lower_right = x_center;
           y_lower_right = y_center - 1;
           board[x_lower_left][y_lower_left]=0;  //CHANGE MADE. You forgot to tile the board
           board[x_upper_right][y_upper_right]=0;
           board[x_lower_right][y_lower_right]=0;
         }
     /* tile the four subboards */
     tromino( x_board, y_board + half_size,
          x_upper_left, y_upper_left, half_size);
     tromino( x_board + half_size, y_board + half_size,
          x_upper_right, y_upper_right, half_size);
     tromino( x_board + half_size, y_board,
          x_lower_right, y_lower_right, half_size);
     tromino( x_board, y_board,
                    x_lower_left, y_lower_left, half_size);

}

void show_Tromino(int size, int x_miss, int y_miss)
{
  for(int i=size-1;i>=0;i--)
  {
     for(int j=0; j<size;j++)
     {
       if(j==x_miss && i==y_miss)
        printf("-1");
       else
        printf("%d ",board[j][i]);
     }
    printf("\n");
  }
  //int bsize[Max][Max]; //CHANGE: WTH is bsize? All changes were made to board. Edited and changed them all

}
Abhay Aravinda
  • 878
  • 6
  • 17
  • Ah..the misery you have to undergo for a few reputations. Done. Updated the answer with the code – Abhay Aravinda Mar 18 '20 at 22:43
  • I'd like to mention that I haven't bothered to fully fix your code. It still crashes for board sizes not powers of 2. I've just got it working enough to show the right output for the right input – Abhay Aravinda Mar 18 '20 at 22:46
0

There is a dynamic recursion solution, and a similar dynamic iteration solution, which help to avoid stack overflow error due to deep recursive calls when input is very large.


Dynamic - recursion

Analysis:

* for a 2*2 cell, could simply fill it,
* for a 4*4 cell,
    * divide it into 4 2*2 smaller squares,
    * first fill the 2*2 square that already has 1 cell filled,
    * now the 2*2 square at the center of the original square has 3 empty cells, just fill it with a tile,
    * now all the 3 remain 2*2 squares divided in previous step, has 1 cell filled,
    * then for each of the 3 remain 2*2 squares, fill with a tile,
    * 
* for a 8*8 cell,
    * divide it into 4 4*4 smaller squares,
    * then fill the 4*4 square that already has 1 cell filled, in similar way as a 4*4 input,
    * now the 2*2 square at the center of the original square has 3 empty cells, just fill it with a tile,
    * now all the 3 remain 4*4 squares divided in previous step, has 1 cell filled,
    * then for each of the 3 remain 4*4 squares, fill it in similar way as a 4*4 input,
    * 
* for a n*n cell,
    repeat divide & conquer,
    steps:
    * if n = 2,
        this is base, simple fill a tile,
    * else
        * divide it into 4 (n/2 * n/2) squares,
        * work on the one already with has a tile, by a recursive call,
        * then put a tile at center of input cell, to fill the (2*2) square in center,
        * then for each of the 3 (n/2 * n/2) squares,
            * work on it, by a recursive call,
            * 
        * 
    * 
* 

Dynamic - iteration

Similar as Dynamic - recursion above, but it use loop to avoid deep recursive calls.

Thus it's preferred.

Analysis:

* if it's base case (2*2 square),
    it's the same as `Dynamic - recursion`,
* if it's not base case,
    * divide it into 4 (n/2 * n/2) squares, mark the one already has a cell filled as A,
    * then fill (2*2) square at the center of input square first, leave the cell belong to A empty,
        now all the 4 (n/2 * n/2) squares, has a single cell filled,
    * 
    * then loop the 4 (n/2 * n/2) squares, for each:
        * work on it, by a recursive call,
        * 
    * 
* 

Representation of Shapes

  • Cell

Need its x and y position.

Thus the structure may look like this, in c:

typedef struct {
    int x;
    int y;
} Cell;
  • L tile

There could be 4 direction, mark as: 1, 2, 3, 4;
And need the coordinate of the middle cell of L tile to locate it,

Thus the structure may look like this, in c:

typedef struct {
    char direction; // 1, 2, 3, 4;
    Cell mid; // position of middle cell of tile,
} Tile;
  • Square

Need left/top cell to decide its position.
And length of side to decide its size.

Thus the structure may look like this, in c:

typedef struct {
    Cell start; // top/left cell,
    int size; // length of side,
} Square;

Eric
  • 22,183
  • 20
  • 145
  • 196