How to fill in a matrix recursively in c++? - c++

So I have to fill in a square matrix recursively. For size N=5, it should be:
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
but my program shows:
1 1 1 1 1
1 2 2 2 1
1 2 3 3 1
1 2 2 2 1
1 1 1 1 1
void llenar5 (int** mat, int n, int f=0, int c=0,int k=2)
{
if (f<n)
{
if (c<n)
{
if (f==0 ||c==0||f==n-1||c==n-1)
{
*(*(mat+f)+c)=1;
llenar5(mat,n,f,c+1,k); //move to the right
}
else if (f==k-1 ||c==k-1||f==n-k||c==n-k)
{
*(*(mat+f)+c)=k;
llenar5(mat,n,f,c+1,k++);
}
}
llenar5(mat,n,f+1,c,k);
}
}
I am creating a matrix in dynamic memory, and I tried calling the function llenar5(mat,n,f+1,c+1,k+1) to jump a column and row while incrementing the values.

void llenar5 (int** mat, int n, int f=0, int c=0,int k=1)
{
if (f<n)
{
if (c<n)
{
if (f==k-1 ||c==k-1||f==n-k||c==n-k)
{
*(*(mat+f)+c)=k;
llenar5(mat,n,f,c+1,k+1);
}
llenar5(mat,n,f,c+1,k);
}
llenar5(mat,n,f+1,c,k);
}
}

I think it will help if you, temporarily, consider a matrix with 0-based numbers. For example, your initial matrix would look instead something like this:
0 0 0 0 0
0 1 1 1 0
0 1 2 1 0
0 1 1 1 0
0 0 0 0 0
If you inspect this matrix, you should quickly observe a fundamental property of this matrix. The value of each cell is the minimum distance from the cell to its closest horizontal or vertical edge.
So, for cell at coordinates (x,y), with the matrix of size w (width) and h (height), the value of each cell is:
min(x, y, (w-1-x), (h-1-y))
Where the min() function is a classical minimum function, that computes the minimum value of its arguments.
Then, it should be obvious that going from a 0-based matrix to a 1-based matrix you should simply add 1 to the result.
So, in conclusion your code should be trivially simple:
Loop over all the x and y coordinates.
Set the value of the corresponding cell based on the above formula.
Your code seems to be unnecessarily complicated. All that recursion is completely unneeded. This can be done using a single pass over their entire matrix, top to bottom, left to right. You don't need to know the values of adjacent cells, to compute the value in the next cell.

Related

Is there a way to insert row/column in matrix (Eigen C++)?

I am using the Eigen library in C++.
I need to insert a row and column to an existing matrix at specific index.
For example, say I need to insert a 0 row and 0 column at the 2nd index...
ORIGINAL MATRIX (A)
1 2 3
1 2 3
1 2 3
NEW MATRIX (B)
1 2 0 3
1 2 0 3
0 0 0 0
1 2 0 3
Thanks for the help in advance!
The new matrix B can be constructed from the original matrix A by using the block operations .topRows() and .bottomRows():
MatrixXd B = MatrixXd::Zero(4, 3);
B.topRows(2) = A.topRows(2);
B.bottomRows(1) = A.bottomRows(1);
This will insert a row of zeros between the second and third row. Analogous operations with .rightCols() and .leftCols() can be used to insert a column of zeros.

How do I generate all vectors of size n where each element may contain 1 of m different values?

Sorry if this is a duplicate, but I did not find any answers which match mine.
Consider that I have a vector which contains 3 values. I want to construct another vector of a specified length from this vector. For example, let's say that the length n=3 and the vector contains the following values 0 1 2. The output that I expect is as follows:
0 0 0
0 0 1
0 0 2
0 1 0
0 1 1
0 1 2
0 2 0
0 2 1
0 2 2
1 0 0
1 0 1
1 0 2
1 1 0
1 1 1
1 1 2
1 2 0
1 2 1
1 2 2
2 0 0
2 0 1
2 0 2
2 1 0
2 1 1
2 1 2
2 2 0
2 2 1
2 2 2
My current implementation simply constructs for loops based on nand generates the expected output. I want to be able to construct output vectors of different lengths and with different values in the input vector.
I have looked at possible implementations using next_permutation, but unfortunately passing a length value does not seem to work.
Are there time and complexity algorithms that one can use for this case? Again, I might have compute this for up to n=17and sizeof vector around 6.
Below is my implementation for n=3. Here, encis the vector which contains the input.
vector<vector<int> > combo_3(vector<double>enc,int bw){
vector<vector<int> > possibles;
for (unsigned int inner=0;inner<enc.size();inner++){
for (unsigned int inner1=0;inner1<enc.size();inner1++){
for (unsigned int inner2=0;inner2<enc.size();inner2++){
cout<<inner<<" "<<inner1<<" "<<inner2<<endl;
unsigned int arr[]={inner,inner1,inner2};
vector<int>current(arr,arr+sizeof(arr)/sizeof(arr[0]));
possibles.push_back(current);
current.clear();
}
}
}
return possibles;
}
What you are doing is simple counting. Think of your output vector as a list of a list of digits (a vector of a vector). Each digit may have one of m different values where m is the size of your input vector.
This is not permutation generation. Generating every permutation means generating every possible ordering of an input vector, which is not what you're looking for at all.
If you think of this as a counting problem the answer may become clearer to you. For example, how would you generate all base 10 numbers with 5 digits? In that case, your input vector has size 10, and each vector in your output list has length 5.

How to fix a bug in my homework solution in C++?

I need to write a program which reads the statistics of n League A football teams and prints the teams name which fall in League B.
A team falls in League B, if it has less than k points after having played m weeks where m is between 1 and 150. Each team gets three points for a win, one point for draw and zero points when lost.
Input Specification: In the first line, you will be given the number of teams 0 < n ≤ 500 and the points 0 < k ≤ 300 needed to stay in league A. Then in the following n lines, there will be the team name and its results. Semicolon indicates the end of input series.
Number 2 represents win, number one represents draw and number zero represents loss.
Output specification:
Sample Input I
4 19
Team_A 1 1 1 1 1 1 1 1 1 0 1 1 1 0 2 1 0 ;
Team_B 0 1 0 2 2 1 1 0 1 1 0 2 0 1 0 0 2 ;
Team_C 0 0 1 0 2 2 2 1 1 1 1 1 0 0 2 1 2 ;
Team_D 0 1 0 1 2 1 2 1 0 0 0 2 2 2 0 0 0 ;
Sample Output I
Team_A 16
Team_B 18
This is the code I came up with, but the output is wrong and I don't know why,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n,points,sum=0,i,value;
char name[15];
char p;
scanf("%d %d",&n,&points);
for(i=1;i<=n;i++)
{
scanf("%s",&name);
do
{
scanf("%c ",&p);
if(p!=';')
{
value=p-48;
sum=sum+value;
}
}while(p!=';');
if(sum<=points)
printf("%s %d",name,sum);
}
return 0;
}
You might look for problems by stuffing the program with output statements.
If you add after scanf("%c ",&p); an output statement to show the value of p, you will find that the first value for p is a space character, which spoils your calculation.
In the same way, if you trace the value of value, you will find that you forgot to initialize this variable to zero for each team.

CUSP sparse library giving strange results

I'm trying to do the following in CUSP:
A=[
1,1,0,0;
2,2,2,0;
0,3,3,3;
0,0,4,4];
B=[1,1,1,1]';
disp(mldivide(A,B));
which is
X=[0.9167,0.0833,-0.5000,0.7500]
On the other hand I get a strange answer from CUSP
#include <cusp/dia_matrix.h>
#include <cusp/krylov/cg.h>
#include <cusp/print.h>
int main()
{
cusp::dia_matrix<int,float,cusp::host_memory> A(4,4,10,3);
A.diagonal_offsets[0] = -1;
A.diagonal_offsets[1] = 0;
A.diagonal_offsets[2] = 1;
for (int i = 0;i <3;i++)
{
for (int q = 0 ;q < A.num_cols;q++)
{
A.values(q,i)=q+1;
}
}
//copy
cusp::dia_matrix<int,float,cusp::device_memory> AA = A;
cusp::array1d<float,cusp::device_memory> BB(A.num_rows,1);
cusp::array1d<float,cusp::device_memory> XX(A.num_rows,0);
cusp::print(AA);
cusp::print(XX);
cusp::print(BB);
cusp::krylov::cg(AA,XX,BB);\
cusp::print(XX);
return 0;
}
The result looks like
sparse matrix <4, 4> with 10 entries
0 0 1
0 1 1
1 0 2
1 1 2
1 2 2
2 1 3
2 2 3
2 3 3
3 2 4
3 3 4
array1d <4>
0
0
0
0
array1d <4>
1
1
1
1
array1d <4>
-39.9938
-53.436
87.9025
-30.1429
The last one doesn't look quite right. Anybody know what I'm doing wrong? Am I using the code wrong or are we supposed to have a really good guessed solution + use a preconditioner?
The conjugate gradient method is only valid for use in symmetric positive definite matrices. Your matrix isn't symmetric. That is why it isn't (and cannot) producing a valid solution. Either use an appropriate, well conditioned SPD matrix, or use a different numerical method.

Is there a function like next_permutation but for permutations with repetition?

What I want to do is to find every permutation of a 1-d array with repetitions of its contents.
e.g.
int array[]={1,2,3};
for(i=0;i<3;i++){
next_permutation(array,array+3)
for(int j=0;j<=3;j++){
printf("%d ",array[j]);
}
printf("\n");
}
will return:
1 2 3
1 3 2
2 1 3
etc...
what I want the function to return:
1 1 1
1 1 2
1 2 1
2 1 1
1 2 2
2 2 1
2 1 2
1 1 3
1 3 1
3 1 1
etc...
Is there a function that can do that?
Thanks in advance,
Erik
You are not doing permutation but just counting.
Ex. if your enumerating set {0, 1} over 3 digits, you'll get:
000
001
010
011
100
101
110
111
See, that's just binary counting.
So map your element set into n-digits, then do n-based count will give you the right awnser
I had this written in Java.
Non optimized code, but you get the point:
String [] data = {"1","2","3"};
public void perm(int maxLength, StringBuffer crtComb){
if (crtComb.length() == maxLength){
System.out.println(crtComb.toString());
return;
}
for (int i=0; i<data.length; i++){
crtComb.append(data[i]);
perm(maxLength, crtComb);
crtComb.setLength(crtComb.length()-1);
}
}
In general when computing permutations of integers from 1 to k (with repetition):
Initially set first permutation as 1 1 1 .... (k times).
Find the rightmost index (say j) such that the element at that index is less than k.
Increment the value of the element at index j by one, and from position j + 1 to k reset all elements to 1.
Repeat steps 2 and 3.
Applying this logic, we now get:
1st permutation -> 1 1 1.
Then at position 2 (0 index counting), we have 1 < 3, so increment it and reset all elements after this to 1. 2nd permutation -> 1 1 2.
Then at position 1 (0 index counting), we have 1 < 3, so increment it and reset all elements after this to 1. 3rd permutation -> 1 2 1
And so on.