array not being read properly - c

I have a 2D array. I am iterating all the 8 rows and 10 columns and reading the values using a for loop. Here is the our array and the output:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 1 1 1 0 0 0 0 0
0 0 0 1 2 1 2 2 1 2 1 2 1 0 0 0
0 0 0 1 2 1 2 2 1 2 1 2 1 0 0 0
0 0 0 1 2 1 2 2 1 2 1 2 1 0 0 0
0 0 0 1 2 1 2 2 1 2 1 2 1 0 0 0
0 0 0 1 2 1 2 2 1 2 1 2 1 0 0 0
0 0 0 1 2 1 2 2 1 2 1 2 1 0 0 0
0 0 0 1 2 1 2 2 1 2 1 2 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
empty row board[3][3] = 0 empty row board[3][4] = 1
empty row board[4][3] = 0 empty row board[4][4] = 2
empty row board[5][3] = 0 empty row board[5][4] = 1
empty row board[6][3] = 0 empty row board[6][4] = 2
empty row board[7][3] = 0 empty row board[7][4] = 2
empty row board[8][3] = 0 empty row board[8][4] = 1
empty row board[9][3] = 0 empty row board[9][4] = 2
empty row board[10][3] = 0 empty row board[10][4] = 1
empty row board[11][3] = 0 empty row board[11][4] = 2
empty row board[12][3] = 0 empty row board[12][4] = 1
The actual array is surrounded by buffer of zeros (atleast 3 on each side). When we try to read row =3, it doesn't read the elements but rather reads them as all zeros. We have printed below the array the elements of row 3 and elements of row+1, which is 4. It can read all elements from row 4 but nothing from row 3. WHY? Please Help!!!
#Mat
Posted Code:
We are trying to find if the row is empty or not.
int emptyRow(int row){
int i, counter;
counter = 0;
for(i=3; i<=num_col+2; i++) {
printf ("empty row board[%d][%d] = %d ", i, row, board[i][row]);
printf ("empty row board[%d][%d] = %d\n", i, row+1, board[i][row+1]);
if(board[i][row] == 1 || board[i][row] == 2 || board[i][row] == 3)
counter++;
}
return counter; /* Counter = 0 means its empty*/
}
The row being passed is 3, the counter counts the number of elements in the row, num_col is the number of columns.
The functions returns counter = 0 which means row 3 is empty.
We are reading the input from a file and printing it. This code is part of an AI we are working on, so cannot post all of the code since it is complicated. Print board is posted below:
Row 3 is our boundary condition, so we dont care whats above row 3 but we need to read in row 3 properly
void print_board(){
int i;
int j;
for(i=0;i< 16; i++){
for(j=0;j<16;j++){
printf("%d ", board[j][i]);
}
printf("\n");
}
}

Assuming the displayed output is from a call to print_board(), and the debugging output shown is from a call to emptyRow(3), then the only explanation that makes sense is that board was modified between those two calls. Check your software to make sure that the board contains the values you expect it to at each stage leading up to the call to emptyRow(3).

Use these lines,
printf ("empty row board[%d][%d] = %d ", i, row, board[row][i]);
printf ("empty row board[%d][%d] = %d\n", i, row+1, board[row+1][i]);
if(board[row][i] == 1 || board[row][i] == 2 || board[row][i] == 3)
This should work as expected. See previous answers re row/col mix up.
This assumes the board array is in fact 16 x 16 in size, and num_col+2 evaluates to 12.
I would use gdb to run the program and then you can use print board[3], print board[4], etc to see what the program sees.

Row and column interchanged up in the code of printing the first set of whole array as matrix
Use
void print_board(){
int i;
int j;
for(i=0;i< 16; i++){
for(j=0;j<16;j++){
printf("%d ", board[i][j]);
}
printf("\n");
}
}

Related

Find all possible knight move on chess board within the limit, with recursion, C language

So I tried to make a program that shows you all the possible knight moves within the limit, the possible move marked with the number '1'. but when I run the program with a movement limit more than 2, it's kind of messed up. what did I do wrong?
#include<stdio.h>
int xpos[8]={2,1,-1,-2,-2,-1,1,2};
int ypos[8]={1,2,2,1,-1,-2,-2,-1};
void whiteMove(int wx, int wy,int map[8][8],int limit);
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
int map[8][8]={{0}};
int limit; char k1[3];
scanf("%d",&limit);getchar();
scanf("%s",k1);getchar();
int wx=k1[0]-'A';
int wy='8'-k1[1];
printf("Case #%d: \n",i+1);
whiteMove(wx,wy,map,limit+1);
for(int j=0;j<8;j++){
for(int k=0;k<8;k++){
printf("%d ",map[j][k]);
}
puts("");
}
}
return 0;
}
void whiteMove(int wx, int wy,int map[8][8], int limit){
if(wx<0||wy<0||wx>7||wy>7||limit==0){
return;
}else if(map[wy][wx]!=1){
map[wy][wx]=1;
}else{
return;
}
for(int i=0;i<8;i++){
whiteMove(wx+xpos[i],wy+ypos[i],map,limit-1);
}
}
input example:
1 => the amount of test case
3 => movement limit
A1 =>starting coordinate
th result is
Case #1:
0 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0
1 0 1 0 1 0 0 0
1 1 1 0 0 1 0 0
1 0 1 1 1 0 0 0
*0 1 0 1 0 1 0 0 *map[5][0]
1 0 *1 1 1 0 0 0 *map[6][2]
1 1 1 0 *0 1 0 0 *map[7][4]
as you can see theres some place that should be '1' but for some reason is not, for example:
map[5][0] and map[7][4] should be '1' because map[6][2] is '1', i dunno whats the problem with my code but my asumption is maybe the coordinate is visited twice, but i already make limitation about the coordinate, so i dont know wheres the problem.
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0
1 1 0 0 1 0 0 0
0 0 1 1 0 0 0 0
1 0 1 0 1 0 0 0
this is the result when the movement limit is 2.
as you can see map[5][0] and map[7][4] is '1' as it should be.
any help will be apreciated, thank you
what did I do wrong?
Stopping, when recursion should go on.
else if (map[wy][wx] != 1) { and map[wy][wx] = 1 are problems.
The test map[wy][wx] != 1 is simple asking, have I been here before? But that is not enough.
The test should be have I been here before in less moves?
If during the tour, it is possible to get to a square in fewer moves, then the recursion from that point needs to go deeper, even though the square has been visited.
Two changes I made help see this, but do not solve it. Leave that for OP. (Note there are many ways to solve this.)
if (wx < 0 || wy < 0 || wx > 7 || wy > 7 || limit == 0) {
return;
// } else if (map[wy][wx] != 1) {
} else if (map[wy][wx] == 0) {
// map[wy][wx] = 1;
map[wy][wx] = limit;
} else {
return;
}
Case #1:
0 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0
1 0 1 0 1 0 0 0
2 1 2 0 0 1 0 0
1 0 1 2 1 0 0 0
0 3 0 1 0 1 0 0
1 0(1)2 1 0 0 0 From this square, recursion should go deeper ...
4 1 2 0(0)1 0 0 ... to get to this square.

Create a matrix blockwise attaching blocks like a stairway MATLAB

I want to build an Array containing of different blocks in the following way.
Given the block I want to repeat the block n-times so that it looks like this:
A =
1 0 0 -1 0 0 0 0 0 1 0 0
0 1 0 0 -1 0 0 0 0 0 1 0
0 0 1 0 0 -1 0 0 0 0 0 1
and I want the Array look like this, n times repeating the scheme:
newArray =
1 0 0 -1 0 0 0 0 0 1 0 0
0 1 0 0 -1 0 0 0 0 0 1 0
0 0 1 0 0 -1 0 0 0 0 0 1
1 0 0 -1 0 0 0 0 0 1 0 0
0 1 0 0 -1 0 0 0 0 0 1 0
0 0 1 0 0 -1 0 0 0 0 0 1
and so on...
With the free space being zeros, since the final array should be a sparse array either way.
How can I repeat and attach the block without using loops?
I'm assuming that the leftward offset of each block with respect to a pure block-diagonal matrix is the number of rows of A, as in your example.
You can build a matrix t that 2D-convolved with A gives the result, as follows:
A = [1 2 3 4; 5 6 7 8]; % data matrix
n = 3; % number of repetitions
[r, c] = size(A);
d = c-r;
t = zeros(r*(n-1)+1, d*(n-1)+1);
t(1:(r*(n-1)+1)*d+r:end) = 1;
result = conv2(t,A);
This gives
A =
1 2 3 4
5 6 7 8
result =
1 2 3 4 0 0 0 0
5 6 7 8 0 0 0 0
0 0 1 2 3 4 0 0
0 0 5 6 7 8 0 0
0 0 0 0 1 2 3 4
0 0 0 0 5 6 7 8
Here is a solution using kron:
n = 5; % number of repetitions
v = 3; % overlapping
s = size(A);
B = A(:,1:s(2)-v)
C = zeros(s(1),s(2)-v);
C(:,end-v+1:end) = A(:,end-v+1:end);
result = kron(eye(n) , B);
result(end,end+v)=0;
result(:,v+1:end) = result(:,v+1:end) + kron(eye(n) , C);
When the matrix size is large you can use sparse matrix:
n = 5;
v = 3;
s = size(A);
B = sparse(A(:,1:s(2)-v));
C = sparse(s(1),s(2)-v);
C(:,end-v+1:end) = A(:,end-v+1:end);
result = kron(eye(n) , B);
result(end,end+v) = 0;
result(:,v+1:end) = result(:,v+1:end) + kron(eye(n) , C);

finding minimum number of rectangular pieces in a rectangular chocolate bar, with a rule

I'm having trouble with my school homework. I have a chocolate bar that consists of either black, white or black & white (mixed) squares. I'm supposed to divide it in two groups, one that has only white or black&white pieces and the other that has only black or black&white pieces. Dividing the chocolate bar means cracking it either horizontally or vertically along the line that separates individual squares.
Given a layout of a chocolate bar, I am to find an optimal division which separates dark and white cubes and results in the smallest possible number of pieces, the chocolate bar being not bigger than 50x50 squares.
The chocolate bar is defined on the standard input like this:
first line consists of two integers M (number of rows in chocolate bar) and N (no. of columns), then there M columns each consisting of N characters symbolizing individual squares (0-black, 1-white, 2-mixed)
Some examples of an optimal division, their inputs respectively (correct outputs are 3 and 7):
3 3
1 1 2
1 2 0
2 0 0
4 4
0 1 1 1
1 0 1 0
1 0 1 0
2 0 0 0
My problem is that I managed to work out a solution, but the algorithm I'm using isn't fast enough, if the chocolate bar is big like this for example:
40 40
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 2 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 2 1 2 1 2 0 0 1 2 2 0 0 0 0 0 0 0 0 1 1 2 1 2 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 2 0 1 1 1 1 1 0 0 1 2 2 0 0 0 0 0 1 0 0 2 2 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 2 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1 1 2 2 0 0 0 1 2 2 1 2 1 0 0 0 0 0 1 2 1 2 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 2 2 1 2 0 0 0 0 0 2 1 2 2 0 0 0 0 0 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 2 2 2 1 1 0 0 0 0 0 2 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 0 0
0 2 1 2 1 0 2 2 2 2 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 2 0 2 2 1 0 0 0 0 0 0
0 2 2 1 2 0 1 2 2 1 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 1 0 0 0 0 0 0
0 2 2 1 2 0 0 0 0 2 1 2 1 2 1 1 2 0 2 0 0 0 0 0 0 0 1 2 2 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 2 2 2 2 1 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 2 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 2 0 0 0 0
0 0 0 0 0 0 0 2 1 2 0 0 2 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 2 0 0 0 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 1 2 2 1 0 0 0 0 2 0 1 1 1 2 1 2 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 2 1 2 2 2 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 1 2 1 1 2 2 0 0 0 0 0
0 0 0 0 0 0 1 2 1 2 2 1 0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0 0 2 1 2 0 0 0 0 0
0 0 0 0 0 0 1 2 2 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0
0 0 0 0 0 0 1 1 1 1 1 2 2 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0
0 0 0 0 0 0 1 2 2 2 1 1 1 0 0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0 0 0 2 2 2 1 0
0 0 0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0 1 1 1 2 2 0 0 0 0 0 0 0 0 0 1 2 1 1 0
0 0 0 2 1 1 2 2 0 1 2 1 1 0 0 0 0 0 2 2 1 2 2 1 2 2 0 0 0 0 0 0 0 0 0 1 2 2 2 0
0 0 0 2 2 2 1 1 0 0 1 2 2 2 0 0 0 0 2 2 2 1 1 2 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 1 2 2 1 1 0 2 1 2 1 2 1 2 1 1 2 1 1 1 1 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 2 2 2 2 1 0 1 1 1 1 1 1 2 1 1 2 2 1 0 1 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 0 0 2 1 1 1 2 1 2 0 0 1 2 1 2 1 2 2 0 0 0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 2 2 1 1 2 2 1 1 1 1 1 1 1 2 1 0 0 0 0 0 0 0 2 2 2 0 0 0
0 0 0 0 0 0 0 1 1 1 2 0 0 1 1 1 2 2 1 2 2 2 1 0 0 0 1 1 1 0 0 0 0 0 1 2 1 0 0 0
0 0 0 0 0 0 0 2 1 1 2 0 0 0 0 0 0 2 2 2 1 1 1 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 2 1 1 1 2 0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 0 0 0 1 1 2 0 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 1 2 1 0 0
0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 1 2 1 0 0
0 0 0 0 0 0 0 0 0 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
then it takes 10 seconds for my program to solve it (correct solution for that one is 126 and I should be able to solve it in under 2 seconds!)
My algorithm works roughly with some minor optimization like this: iterate through all possible lines where it's possible to cut and then recursively do the same for the 2 newly emerged rectangles, if they cannot be divided anymore, then return 1.
The function after it iterates trough all the possible cuts always returns the minimum, once the minimum is found then store it and if I'd happen to need to solve this rectangle again then just return the value.
I thought that maybe If I happen to have already solved a particular rectangle and now I need to solve one that is one row or column bigger or smaller, then I could somehow use the solution I already have for that one and use it for the new one. But I really don't know how would i implement such a feature.
Right now my algorithm treats it like a completely new unsolved rectangle.
My code so far:
#include <stdio.h>
#include <stdlib.h>
unsigned int M, N;
unsigned int ****pieces; ////already solved rectangles, the value of pieces[y0][x0][y1][x1] is the optimal number of pieces in which the particular rectangle(that has upperleft corner in [x0,y0] and bottomright corner in[x1,y1]) can be divided
int ****checked;
unsigned int inf;
unsigned int minbreaks(int mat[M][N], unsigned int starti, unsigned int startj, unsigned int maxi, unsigned int maxj) {
if (pieces[starti][startj][maxi][maxj] != 0) {
return pieces[starti][startj][maxi][maxj];
} else {
unsigned int vbreaks[maxj - 1];
unsigned int hbreaks[maxi - 1];
for (unsigned int i = 0; i < maxj - 1; i++) {
vbreaks[i] = inf;
}
for (unsigned int i = 0; i < maxi - 1; i++) {
hbreaks[i] = inf;
}
unsigned int currentmin = inf;
for (unsigned int i = starti; i < maxi; i++) {
for (unsigned int j = startj; j < maxj - 1; j++) {
if (mat[i][j] != 2) {
for (unsigned int k = startj + 1; k < maxj; k++) {
if (vbreaks[k - 1] == inf) {
for (unsigned int z = starti; z < maxi; z++) {
if (!checked[i][j][z][k]) {
if (mat[z][k] != 2 && mat[i][j] != mat[z][k]) {
vbreaks[k - 1] = minbreaks(mat, starti, startj, maxi, k) + minbreaks(mat, starti, k, maxi, maxj);
if (vbreaks[k - 1] < currentmin) {
currentmin = vbreaks[k - 1];
}
break;
}
checked[i][j][z][k] = 1;
}
}
}
}
}
}
}
for (unsigned int i = starti; i < maxi - 1; i++) {
for (unsigned int j = startj; j < maxj; j++) {
if (mat[i][j] != 2) {
for (unsigned int k = starti + 1; k < maxi; k++) {
if (hbreaks[k - 1] == inf) {
for (unsigned int z = startj; z < maxj; z++) {
if (!checked[i][j][k][z]) {
if (mat[k][z] != 2 && mat[i][j] != mat[k][z]) {
hbreaks[k - 1] = minbreaks(mat, starti, startj, k, maxj) + minbreaks(mat, k, startj, maxi, maxj);
if (hbreaks[k - 1] < currentmin) {
currentmin = hbreaks[k - 1];
}
break;
}
checked[i][j][k][z] = 1;
}
}
}
}
}
}
}
if (currentmin == inf) {
currentmin = 1;
}
pieces[starti][startj][maxi][maxj] = currentmin;
return currentmin;
}
}
int main(void) {
FILE *file = stdin;
fscanf(file, "%u %u", &M, &N);
int mat[M][N];
pieces = malloc(sizeof (unsigned int***)*M);
checked = malloc(sizeof (int***)*M);
for (unsigned int i = 0; i < M; i++) {//initialize the pieces,checked and mat arrays.
pieces[i] = malloc(sizeof (unsigned int**)*N);
checked[i] = malloc(sizeof (int**)*N);
for (unsigned int j = 0; j < N; j++) {
int x;
fscanf(file, "%d", &x);
mat[i][j] = x;
pieces[i][j] = malloc(sizeof (unsigned int*)*(M + 1));
checked[i][j] = malloc(sizeof (int*)*M);
for (unsigned int y = i; y < M + 1; y++) {
pieces[i][j][y] = malloc(sizeof (unsigned int)*(N + 1));
for (unsigned int x = j; x < N + 1; x++) {
pieces[i][j][y][x] = 0;
}
}
for (unsigned int y = 0; y < M; y++) {
checked[i][j][y] = malloc(sizeof (int)*N);
for (unsigned int x = 0; x < N; x++) {
checked[i][j][y][x] = 0;
}
}
}
}
inf = M * N + 1; //number one bigger than maximal theoretically possible number of divisions
unsigned int result = minbreaks(mat, 0, 0, M, N);
printf("%u\n", result);
return (EXIT_SUCCESS);
}
So anybody has any idea for improvements?
For any arbitrary rectangle, we can know if it contains either no white or no black pieces in O(1) time, with O(M * N) preprocessing of matrix prefix-sums for white and black separately (count 1 for each piece).
We can store potential horizontal and vertical split points separately in two k-d trees for O(log(|splitPoints|) + k) retrieval for an arbitrary rectangle, again preprocessing the entire input.
After that, a general recursive algorithm could look like:
f(tl, br):
if storedSolution(tl, br):
return storedSolution(tl, br)
else if isValid(tl, br):
return setStoredSolution(tl, br, 0)
best = Infinity
for p in vSplitPoints(tl, br):
best = min(
best,
1 +
f(tl, (p.x-1, br.y)) +
f((p.x, tl.y), br)
)
for p in hSplitPoints(tl, br):
best = min(
best,
1 +
f(tl, (br.x, p.y-1)) +
f((tl.x, p.y), br)
)
return setStoredSolution(tl, br, best)
There is a dynamic programming approach to this, but it won't be cheap either. You need to fill in a load of tables giving, for each size and position of rectangle within the main square, the minimum number of divisions necessary to divide up that smaller rectangle fully.
For a rectangle of size 1x1 then answer is 0.
For a rectangle of size AxB look and see if all of its cells are uniform enough that the answer is 0 for that rectangle. If so, fine. If not try all possible horizontal and vertical divisions. Each of these divisions gives you two smaller rectangles. If you work out the answers for all rectangles of size A-1xB and smaller and size AxB-1 and smaller before you try and work out the answers for rectangles of size AxB you all ready know the answers for the two smaller rectangles. So for each possible division, add up the answers for the two smaller rectangles and add one to get the cost for that division. Chose the division that gives you the smallest cost and that gives you the answer for your current AxB rectangle.
Working out the answers for all smaller rectangles before larger rectangles, the very last answer you work out gives you the optimum number of divisions for the full square. The easiest way to work out what the best division is is to keep a little extra information for each rectangle, recording what the best division found was.
For an NxN square there are O(N^4) rectangles - any two points in the square define a rectangle as opposite corners. A rectangle of size O(N)xO(N) has O(N) possible divisions so you have something like an O(N^5) algorithm, or O(N^2.5) if N is the input size since an NxN square has input data of size O(N^2).
(You could also do something very like this by taking your original code and storing the results from calls to minBreaks() so that if minBreaks() is called more than once with the same arguments it simply returns the stored answer instead of recalculating it with yet more recursive calls to minBreaks()).
Thanks to everybody who helped me, my mistake was that in those nested loops I tried to avoid some unnecessary breaks, like this for example
1 1 -> 1 | 1
1 1 1 | 1
1 1 1 | 1
thinking it would speed up the runtime but the correct approach was just simply breaking the chocolate bar always everywhere possible.
Anyway for anyone interested here is my working code:
#include <stdio.h>
#include <stdlib.h>
unsigned int M, N;
unsigned int ****pieces; ////already solved rectangles, the value of pieces[y0][x0][y1][x1] is the optimal number of pieces in which the particular rectangle(that has upperleft corner in [x0,y0] and bottomright corner in[x1,y1]) can be divided
unsigned int inf;
int isOneColor(int mat[M][N], unsigned int starti, unsigned int startj, unsigned int maxi, unsigned int maxj) {
int c = 2;
for (unsigned int i = starti; i < maxi; i++) {
for (unsigned int j = startj; j < maxj; j++) {
if (c == 2) {
if (mat[i][j] != 2) {
c = mat[i][j];
}
} else if (c != mat[i][j] && mat[i][j] != 2) {
return 0;
}
}
}
return 1;
}
unsigned int minbreaks(int mat[M][N], unsigned int starti, unsigned int startj, unsigned int maxi, unsigned int maxj) {
if (pieces[starti][startj][maxi][maxj] != 0) {
return pieces[starti][startj][maxi][maxj];
} else if (isOneColor(mat, starti, startj, maxi, maxj)) {
return pieces[starti][startj][maxi][maxj] = 1;
} else {
unsigned int currentmin = inf;
for (unsigned int j = startj; j < maxj - 1; j++) {
unsigned int c = minbreaks(mat, starti, startj, maxi, j + 1) + minbreaks(mat, starti, j + 1, maxi, maxj);
if (c < currentmin) {
currentmin = c;
}
}
for (unsigned int i = starti; i < maxi - 1; i++) {
unsigned int c = minbreaks(mat, starti, startj, i + 1, maxj) + minbreaks(mat, i + 1, startj, maxi, maxj);
if (c < currentmin) {
currentmin = c;
}
}
pieces[starti][startj][maxi][maxj] = currentmin;
return currentmin;
}
}
int main(void) {
FILE *file = stdin;
//FILE *file = fopen("inputfile", "r");
fscanf(file, "%u %u", &M, &N);
int mat[M][N];
pieces = malloc(sizeof (unsigned int***)*M);
for (unsigned int i = 0; i < M; i++) {
pieces[i] = malloc(sizeof (unsigned int**)*N);
for (unsigned int j = 0; j < N; j++) {
int x;
fscanf(file, "%d", &x);
mat[i][j] = x;
pieces[i][j] = malloc(sizeof (unsigned int*)*(M + 1));
for (unsigned int y = i; y < M + 1; y++) {
pieces[i][j][y] = malloc(sizeof (unsigned int)*(N + 1));
for (unsigned int x = j; x < N + 1; x++) {
pieces[i][j][y][x] = 0;
}
}
}
}
inf = M * N + 1; //number that is bigger by one than maximal theoretically possible number of divisions
unsigned int result = minbreaks(mat, 0, 0, M, N);
printf("%u\n", result);
return (EXIT_SUCCESS);
}

Check all diags in square matrix for true

I am trying to check if in a square matrix there is more than one true value in all possible diagonals and anti-diagonals, and return true, otherwise false.
So far I have tried as following but is not covering all possible diagonals:
n=8; %matrix dimension 8 x 8
diag= sum(A(1:n+1:end));
d1=diag>=2;
antiDiag=sum(A(n:n-1:end));
d2=antiDiag>=2;
if ~any(d1(:)) || ~any(d2(:))
res= true;
else
res=false;
end
this is a false:
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
this is a true:
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Since these are my first steps in using Matlab, is there a specific function or a better way to achieve the result I am looking for?
To detect if there are more than one nonzero value in any diagonal or anti-diagonal (not just the main diagonal and antidiagonal): get the row and column indices of nonzero values, ii and jj; and then check if any value of ii-jj (diagonals) or ii+jj (anti-diagonals) is repeated:
[ii, jj] = find(A);
res = (numel(unique(ii-jj)) < numel(ii)) || (numel(unique(ii+jj)) < numel(ii));
One approach:
n=8; %// size of square matrix
A = logical(randi(2,n)-1); %// Create a logical matrix of 0s and 1s
d1 = sum(A(1:n+1:end)); %// sum all the values of Main diagonal
d2 = sum(A(n:n-1:end-1)); %// sum all the values of Main anti-diag
result = d1>=2 | d2>=2 %// result is true when any one of them is > than or = to 2
Sample run:
Inputs:
>> A
A =
0 1 1 1 1 0 1 0
0 1 1 1 1 1 0 0
0 1 0 1 1 0 0 1
0 1 1 0 1 1 0 0
0 1 0 1 1 0 0 1
1 0 0 0 1 1 0 1
1 1 1 1 1 1 0 0
1 1 1 1 0 0 0 1
Output:
result =
1
Note: This approach considers only the Main diag and Main Anti-Diag (considering the example you provided). If you want for all possible diags, the other answer from Luis Mendo is the way to go
Using #Santhan Salai's generating technique, we can use the diag function (to pull out the main diagonal of the matrix), the fliplr to flip over the center column and any to reduced to a single value.
n=8; %// size of square matrix
A = logical(randi(2,n)-1); %// Create a logical matrix of 0s and 1s
any([diag(A) ; diag(fliplr(A))])

Array of points algorithm

I'm having trouble designing an algorithm that will pretty much make a line move like in a snake game using an array that holds all the points on the line. I would do something like...
for (int x = 0; i < array.length; i++) {
array[i] = array[i+1]
}
array[array.length] = (the new point)
but this will happen many times a second and it is very slow. I thought of doing something similar but instead of moving each number every time, they stay in the same position in the array but an int is saved to keep track of which one will be removed next and which will contain the new nummber.
If you have any idea what I just said, please help me. Thanks
Use a circular buffer. This can be implemented using an array and two indices (one for head, one for tail). If the snake always has the same length, you can get away with using a single index.
With such a structure, the entire operation that you require can be done in constant time (i.e. independent of the size of the array).
You're correct to think that moving all of the blocks each time is slow.
There is a more efficient way to do it.
Only the first at last positions change with each move.
So, if you have your snake array[i] and a "head" marker head then you can simply march head through your array and overwrite the next location with where the head moved that turn.
The place you just overwrote? That was where the tail was, and you don't need it anymore.
It gets a little trickier if the snake grows, but not too much more so.
(The data structure, as NPE points out, is a circular buffer.)
int front, back, length; // 0<=front,back<length
increaseLength()
{
back--;
if(back<0)
back=length-1;
}
goForward()
{
front++;
back++;
if (front==length)
front=0;
if (back==length)
back=0;
}
checkFull() // check every time you increase length
{
if (back==front)
return true;
return false;
}
NPE is correct that a circular buffer is the best solution. This is a simple example of a circular buffer using C++. Notice the modulus operators instead of if tests.
#include <iostream>
int main(int argc, char **argv)
{
int front = 4;
int back = 0;
int length = 10;
int snake[10] = { 1,1,1,1,1,0,0,0,0,0 };
for (int i = 0; i < length * 3; i++)
{
for (int j = 0; j < length; j++)
std::cout << snake[j] << " ";
std::cout << std::endl;
snake[back] = 0;
front = (front + 1) % length;
back = (back + 1) % length;
snake[front] = 1;
}
}
Output:
1 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 1
1 0 0 0 0 0 1 1 1 1
1 1 0 0 0 0 0 1 1 1
1 1 1 0 0 0 0 0 1 1
1 1 1 1 0 0 0 0 0 1
1 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 1
1 0 0 0 0 0 1 1 1 1
1 1 0 0 0 0 0 1 1 1
1 1 1 0 0 0 0 0 1 1
1 1 1 1 0 0 0 0 0 1
1 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 1
1 0 0 0 0 0 1 1 1 1
1 1 0 0 0 0 0 1 1 1
1 1 1 0 0 0 0 0 1 1
1 1 1 1 0 0 0 0 0 1
Notice how the output nicely demonstrates the snake "moving" through the buffer.

Resources