I was solving just for kicks this very famous brain teaser:
Count the number of set bits in a number.
and this is what came out:
//edit: I have to find a proper way of formatting code here before posting...
martedì 2 marzo 2010
giovedì 18 febbraio 2010
Find the Largest Square Submatrix in a NxM Matrix
Some time ago a bright intern we had came up with a really interesting brain teaser he was asked during one of the interview he made to get an internship.
The problem is this:
having as input a random generated matrix N x M whose elements are integers with values {1,2,....,9}, you are asked to find the biggest square made of he same digits.
In the case there are multiple equally big squares, just pick up the first one.
Since it is and interesting brain teaser and I'm currently experimenting a bit with Dynamic Programming I came up with this solution:
Let's define T(i,j) as the side's length of the biggest square which is possible to build having those characteristic and having the cell (i,j) as bottom right element, then:
if
so basically if the matrix is:
5,5,6
5,5,5
5,5,5
the respective T(i,j) values when considering the cell (3,3) would be
1,1,1
1,2,1
1,1,X
being X what we want to find out.
So our if else will in turn compare the element (i,j) marked in green with the elements marked in red stopping when one of the checks fails or, if they all pass, updating the value to T(i-1,j-1) +1:
5,5,6
5,5,5
5,5,5
5,5,6
5,5,5
5,5,5
5,5,6
5,5,5
5,5,5
which in this case will fail at the second test causing: X = 1.
If the matrix would have been made of all of 5 then: X = T(i-1,j-1) + 1 = 2 + 1 = 3
Here comes the code:
This algorithm can be still be improved:
The problem is this:
having as input a random generated matrix N x M whose elements are integers with values {1,2,....,9}, you are asked to find the biggest square made of he same digits.
In the case there are multiple equally big squares, just pick up the first one.
Since it is and interesting brain teaser and I'm currently experimenting a bit with Dynamic Programming I came up with this solution:
Let's define T(i,j) as the side's length of the biggest square which is possible to build having those characteristic and having the cell (i,j) as bottom right element, then:
if
- (i,j) == (i-1,j-1) and
- the previous T(i-1,j-1) elements in the same column have the same value as (i,j) and
- the previous T(i-1,j-1) elements in the same row have the same value as (i,j)
- T(i,j) = T(i-1,j-1) +1
- T(i,j) = 1 since we can't expand the previous square and we have to start building another one instead
so basically if the matrix is:
5,5,6
5,5,5
5,5,5
the respective T(i,j) values when considering the cell (3,3) would be
1,1,1
1,2,1
1,1,X
being X what we want to find out.
So our if else will in turn compare the element (i,j) marked in green with the elements marked in red stopping when one of the checks fails or, if they all pass, updating the value to T(i-1,j-1) +1:
5,5,6
5,5,5
5,5,5
5,5,6
5,5,5
5,5,5
5,5,6
5,5,5
5,5,5
which in this case will fail at the second test causing: X = 1.
If the matrix would have been made of all of 5 then: X = T(i-1,j-1) + 1 = 2 + 1 = 3
Here comes the code:
void findMaxSquare(const unsigned int* aMatrix,
const unsigned int aNumRows, const unsigned int aNumColumns) {
unsigned int *result = (unsigned int*) malloc(sizeof(unsigned int) * aNumColumns * aNumRows);
int i,j;
// set the first row to 1 (it's the biggest square those cells can build)
for(i = 0; i < aNumColumns; ++i) {
result[i] = 1;
}
// set the first column to 1 (it's the biggest square those cells can build)
for(i = 1; i < aNumRows; ++i) {
*(result + i*aNumColumns) = 1;
}
unsigned int maxSquareSide = 1; // store the side of the biggest square we can build
unsigned int maxXIndex = 0; // and its row
unsigned int maxYIndex = 0; // and its column
for(i = 1; i < aNumRows; ++i) {
for(j = 1; j < aNumColumns; ++j) {
// check whether the current item is the same as the previous one
// if so, the previous element aMatrix[i-1][j-1] build a square of side result[i-1][j-1]
// so check whether the same value aMatrix[i][j] is repeated in column j result[i-1][j-1] times.
// if so, check whether the same value aMatrix[i][j] is repeated in row i result[i-1][j-1] times.
if( (aMatrix + i*aNumColumns)[j] == (aMatrix + (i-1)*aNumColumns)[j-1] &&
isColumnTheSame(aMatrix, aNumColumns, i, j, (result + (i-1)*aNumColumns)[j-1]) &&
isRowTheSame(aMatrix, aNumColumns, i, j, (result + (i-1)*aNumColumns)[j-1])) {
// if we get here, this item enlarges of 1 cell
// the square having as bottom right aMatrix[i-1][j-1]
(result + i*aNumColumns)[j] = (result + (i-1)*aNumColumns)[j-1] + 1;
//store the value and relative indexes if it's the biggest square found found so far
if(maxSquareSide < (result + i*aNumColumns)[j]) {
maxSquareSide = (result + i*aNumColumns)[j];
maxXIndex = i;
maxYIndex = j;
}
continue;
}
// this is the begininning of a new square
(result + i*aNumColumns)[j] = 1;
}
}
printf("the maximum square is made of '%d', is %3d digits wide and has top left ( %3d , %3d )\n",
(aMatrix+(maxXIndex-(maxSquareSide - 1))*aNumColumns)[maxYIndex - (maxSquareSide - 1)],
maxSquareSide,
maxXIndex - (maxSquareSide - 1) + 1,
maxYIndex - (maxSquareSide - 1) + 1);
free(result);
}
This algorithm can be still be improved:
- if the input matrix is not a squared but n >>m or m>>n the first for loop instead of iterating through all the rows should iterate through max{n,m}
- once found a square made of the same integers we should check whether is possible to build a bigger one, if not stop the procedure
domenica 14 febbraio 2010
God Bless Peripheral Vision
Just saved my macbook pro from falling from the armrest of my sofa (yeah, I shouldn't have put it there in the first place, I know).
While I was reading a book something was bothering me, at the last (milli)second I realised it was my macbook that was slowly sliding out of the armrest.
Saved it when it had just begun the free fall.
God bless peripheral vision...that and my feline reaction time.
While I was reading a book something was bothering me, at the last (milli)second I realised it was my macbook that was slowly sliding out of the armrest.
Saved it when it had just begun the free fall.
God bless peripheral vision...that and my feline reaction time.
Iscriviti a:
Post (Atom)