package com.interview.multiarray;
/**
* http://www.geeksforgeeks.org/divide-and-conquer-set-6-tiling-problem/
* Test cases
* Size of matrix is at least 2 and power of 2 always
* Missing point could be on edges
* Missing point could be in any of 4 quadrants
*/
class Position{
int x;
int y;
Position(int x, int y){
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Position other = (Position) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
public class TilingProblem {
char tileCount = 'a';
public char[][] fit(int size, Position missingPosition){
char matrix[][] = new char[size][size];
matrix[missingPosition.x][missingPosition.y] = 'X';
fit(matrix, new Position(0,0), matrix.length, missingPosition);
return matrix;
}
private void fit(char matrix[][], Position topLeft,
int size, Position missingPosition){
if(size == 2){
updateMatrix(matrix, topLeft, missingPosition);
return;
}
Position alreadyFilledQuadrantPosition = determineQuadrant(topLeft, size, missingPosition);
updateMatrix(matrix, new Position(topLeft.x + size/2-1, topLeft.y + size/2-1), alreadyFilledQuadrantPosition);
for(int i=0 ; i < 2; i++){
for(int j=0; j < 2; j++){
Position newMissingPosition = new Position(topLeft.x + size/2 -1+i, topLeft.y + size/2 -1 + j);
if(newMissingPosition.equals(alreadyFilledQuadrantPosition)){
fit(matrix, new Position(topLeft.x + i*size/2, topLeft.y + j*size/2) , size/2, missingPosition);
}else{
fit(matrix, new Position(topLeft.x + i*size/2, topLeft.y + j*size/2) , size/2, newMissingPosition);
}
}
}
}
private Position determineQuadrant(Position topLeft, int size, Position missingPosition){
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
if(missingPosition.x >= topLeft.x + i*size/2 && missingPosition.x <= topLeft.x + i*size/2 + size/2-1 &&
missingPosition.y >= topLeft.y + j*size/2 && missingPosition.y <= topLeft.y + j*size/2 + size/2 -1){
return new Position(topLeft.x+size/2 -1 +i, topLeft.y + size/2 - 1 + j);
}
}
}
throw new IllegalArgumentException("Something went wrong in determining quadrant");
}
private void updateMatrix(char matrix[][], Position topLeft, Position missingPosition){
for(int i=topLeft.x; i < topLeft.x + 2; i++){
for(int j=topLeft.y; j < topLeft.y + 2; j++){
if(i == missingPosition.x && j == missingPosition.y){
continue;
}
matrix[i][j] = tileCount;
}
}
tileCount++;
}
public static void main(String args[]){
TilingProblem tp = new TilingProblem();
Position p = new Position(5,6);
char matrix[][] = tp.fit(8, p);
for(int i=0; i < matrix.length; i++){
for(int j=0; j < matrix[0].length ; j++){
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
}