How to read matrix recursively c++ - c++

Can anyone help me with understanding recursion? I want to read a matrix recursively, and I don't really know how.
I made up a plan of transforming iterative agorithms to recursive ones in the following steps:
Repetitive structure-> if followed by recall of function somewhere in the body
Going from "top" to 0 and the going back to be alike the iterative way (i'm new to the concept, the idea may be dumb)
My function to read a matrix recursively (not working) is as follows:
void read_m(int n,int m)
{
if(n)
{
if(m)
{
read_m(n,m-1);
}
f>>v[n][m];
read_m(n-1,m);
}
}
I know what the mistake is, what I do not know is how should I solve this.
Thanks in advance.
P.S. n and m are width and height

Using recursion is probably not the greatest way to do this here but assuming you want it and you want the 'f' to execute for all the elements, it isn't going to work when n is 0 as it is inside the if(n) block.

first you should move f>>v[n][m];out if (n) block or it will not fill entire row with index 0.
second assuming that you keep data row by row you should read data before going to recursion, also to prevent double read you should only decrease rows when full column is read.
void read_m(int n,int m)
{
f>>v[width-1-n][height-1-m]; //suppose that width and height defined elsewhere
if(m)
{
read_m(n,m-1);
}
else if(n)
{
read_m(n-1,m);
}
}
if it is column by column you should change m and n in your code.

#include<fstream>
using namespace std;
ifstream f("recurs.in");
ofstream g("recurs.out");
int a[20][20],n,m;
void read(int i, int j)
{
if(j>1)
read(i,j-1);
else if(i>1)
read(i-1,j);
f>>a[i][j];
}
int main()
{
int i,j;
f>>n>>m;
read(n,m);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
g<<a[i][j]<<' ';
g<<endl;
}
}
Working

Related

How can I apply memoization to this recursive function?

I was solving the Subset Sum problem: "Given a set of numbers, check whether it can be partitioned into two subsets such that the sum of elements in both subsets is same or not." For this problem I created a recursive function which works correctly but I am not able to correctly memoize it.
The code is:
bool func(int a[], int i, int n, long sum) // i is 0, n is the array size, sum is required sum
{
if(sum<0||i>=n)
return 0;
if(sum==0)
return 1;
if(func(a,i+1,n,sum-a[i]))
return 1;
if(func(a,i+1,n,sum))
return 1;
return 0;
}
Please help in memoizing this code. Also can you tell that which is better for these type of problems recursive code with memoization or tabulation.
Memoization just means storing already-computed results so you don't have to recompute them later. So, whenever func calls itself and gets an answer, add an entry to a dictionary that maps func's inputs to its output. Then, before calling func, see if there's already an entry in the dictionary for the inputs you're about to use and, if so, don't call func again; instead, use the output you cached in the dictionary.
Tabulation is much easier.
bool ss(int a[],int n,int s){
bool r[n+1][s+1];
for(int i=0;i<=n;++i)
r[i][0]=true;
for(int i=1;i<=s;++i)
r[0][s]=false;
for(int i=1;i<=n;++i)
for(int j=1;j<=s;++j)
if(j>=a[i])
r[i][j]=r[i-1][j] || r[i-1][j-a[i]];
else r[i][j]=r[i-1][j];
return r[n][s];
}

Understanding the dp on tree

I was recently solving a problem from Codeforces. After giving it a lot of tries I was not able to get how in tree dp the matrix calculation works in the editorial solution. The following is the code where I have added comments to the parts I don't understand in it.
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int f[2][10010][110];//0 max 1 min
char s[10010];
int tr[10010][2],size,n,fa[10010],p,m,minn,pre;
void dfs(int x)
{
//cout<<x<<" "<<f[0][x][0]<<endl;
if (!tr[x][0]) return;
int l=tr[x][0],r=tr[x][1];
dfs(l),dfs(r);
/*The part which gets complicated need help why and how this calculation works*/
for (int i=0;i<=minn;i++)
for (int j=0;i+j<=minn;j++)
{
f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
f[0][x][i+j+(p>=m)]=max(f[0][x][i+j+(p>=m)],f[0][l][i]-f[1][r][j]);
f[1][x][i+j+(p<m)]=min(f[1][x][i+j+(p<m)],f[1][l][i]+f[1][r][j]);
f[1][x][i+j+(p>=m)]=min(f[1][x][i+j+(p>=m)],f[1][l][i]-f[0][r][j]);
}
}
int main()
{
scanf("%s",s+1);
scanf("%d%d",&p,&m);
memset(f[0],-63,sizeof(f[0]));
memset(f[1],63,sizeof(f[1]));
/* Why we have used min of the two and how does it handle both condition */
minn=min(p,m);
n=strlen(s+1);
size=1;pre=size;
for (int i=1;i<=n;i++)
{
if (s[i]=='('||s[i]=='?')
{
tr[pre][tr[pre][0]?1:0]=++size;
fa[size]=pre;
pre=size;
}
else if (s[i]==')') pre=fa[pre];
else f[0][size][0]=f[1][size][0]=s[i]-'0',pre=fa[pre];
}
dfs(1);
printf("%d",f[0][1][minn]);
}
The part where I get lost is this
f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
f[0][x][i+j+(p>=m)]=max(f[0][x][i+j+(p>=m)],f[0][l][i]-f[1][r][j]);
f[1][x][i+j+(p<m)]=min(f[1][x][i+j+(p<m)],f[1][l][i]+f[1][r][j]);
f[1][x][i+j+(p>=m)]=min(f[1][x][i+j+(p>=m)],f[1][l][i]-f[0][r][j]);
I always struggle with such types of problems. Can someone give the link to approach such problems.
Which part of the lines don't you understood? I take one line
f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
and rewrite it
const int index_max = 0;
int y = i+j + (p<m? 1: 0); // in your code p<m is cast to int, true=1, false=0
int old_max = f[index_max][x][y];
int next_value = f[index_max][l][i] + f[index_max][r][j]:
f[index_max][x][y] = max(old_max, next_value);
You are looking for the maximum of the next_values of your double-loop. As l, r are fixed the next_values are sums of values in two rows.
Similar for the other 3 lines.

Program to find greatest common divisor

Here's a c++ program i tried to write for the above question.Our teacher told us to use a for loop.
void main()
int A[30],B[30],m,n,i,j,x,z;
cout<< "enter two numbers";
cin>>m>>n;
for(i=1,j=0;i<=m,j<30;i++,j++)
{
if(m%i==0)
{ A[j]=i;
z=j;
}
}
for(i=1,j=0;i<=n,j<30;i++,j++)
{
if(n%i==0)
{ B[j]=i;
x=j;
}
}
for(i=z;i>=0;--i)
{
for(j=x;j>=0;--j)
{
if(A[i]==B[j])
{ cout<<"gcd="<<A[i];
}
}
}
}
The output displays " Enter two numbers:" and when i entered 15 and 3, the result i got was a blinking cursor. Working through the program, I realised that the divisors for each number when stored in the arrays of A and B were not stored continuously or had gaps in between. If there isn't anything in the memory for say A[11], what happens when you check it against another variable with a number? Can somebody please modify this to make it work and tell me what's wrong? I am new to programming, so excuse my program if it is clumsy.
Andreas has pointed out that there are other ways to achieve the goal of finding the gcd, but the point of the exercise is to get a better handle on some basic programming constructs. So lets go with your approach.
Your idea is to compute the two lists of divisors and then compare them. As you say, having a list with gaps in makes this harder.
So adapt your loop, only increment the storage index when you've stored something
for(i=1,j=0;i<=m && j<30;i++) // need the && here; a comma means something different
{
if(m%i==0)
{ A[j++]=i;
z=j;
}
}
Second, you have a typo you're not storing in B, so fix that
for(i=1,j=0;i<=n && j<30;i++)
{
if(n%i==0)
{ B[j++]=i; //B here not A
x=j;
}
}
That should help.
Try this:
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
As taken from here: https://codereview.stackexchange.com/questions/66711/greatest-common-divisor

Wrong Answer on SPOJ

I was trying a problem on SPOJ,in which we have to simply find the Length of Longest Increasing Sub-sequence of the given Array A.
I had solved this problem using a dynamic programming O(n^2)algorithm and the solution got accepted..Here is the code,that got Accepted:
void LIS(int *A,int A_Length)
{
int Seq[MAX];
for(int i=0;i<A_Length;++i)
{
int maxima=0;
for(int j=0;j<i;++j)
{
if(A[i]>A[j])
{
maxima=max(Seq[j],maxima);
}
}
Seq[i]=maxima+1;
//cout<<Seq[i]<<endl;
}
cout<<*max_element(Seq,Seq+A_Length)<<endl;
}
But When i tried to solve it using the Second Method (LINK),which is ::
A simple way of finding the longest increasing subsequence is
to use the Longest Common Subsequence (Dynamic Programming) algorithm.
[1]Make a sorted copy of the sequence A, denoted as B. O(nlog(n)) time.
[2]Use Longest Common Subsequence on with A and B. O(n2) time.
,I got Wrong Answer .
This is my c++ code
//Global Variable
int A[100],B[100];
int DP[100][100];
//This function Finds the Longest common subsequce of Array A[1,2,3...,N] and B[1,2,3...,N]
void LIS(int N)
{
sort((B+1),(B+1)+N);//STL SORT sort from index 1 to N of Array B.
int i,j;
//Base Cases
for(i=0;i<=N;++i)
DP[i][0]=0;
for(j=0;j<=N;++j)
DP[0][j]=0;
for(i=1;i<=N;++i)
{
for(j=1;j<=N;++j)
{
if(A[i]==B[j])
DP[i][j]=DP[i-1][j-1]+1;
else
DP[i][j]=max(DP[i-1][j],DP[i][j-1]);
}
}
printf("%d\n",DP[N][N]);
}
int main()
{
int N,i;
scanf("%d",&N);
for(i=1;i<=N;++i)
{
scanf("%d",&A[i]);
B[i]=A[i];
}
LIS(N);
return 0;
}
I don't know why i am getting the Wrong Answer.Can You please Help me in Finding the Bug. Or the LIS by LCS Algorithm given in the site is incorrect??
The Second Method is correct, but can't be applied to this problem directly. That's because the numbers in the sequence are not guaranteed to be unique in this SPOJ problem, and the target is to find a strict increasing subsequence, while Your Second Method's output is non-decreasing subsequence here. Demonstrating on a simple test case [1,2,2,3] will help you find the difference.
This solution is also simple: just remove the duplicated elements after sorting.

C++ program to compute lcm of numbers between 1 to 20 (project euler )

as the title explains this is a program to find lcm of numbers between 1 to 20. i found an algorithm to do this, here's the link
http://www.cut-the-knot.org/Curriculum/Arithmetic/LCM.shtml
there is a java applet on the webpage that might explain the algorithm better
Problem: i wrote the code compiler shows no error but when i run the code the program goes berserk, i guess may be some infinite loopig but i can't figure it out for the life of me. i use turbo c++ 4.5 so basically if anyone can look at the code and help me out it would be great . thanks in advance
Algorithm:
say we need to find lcm of 2,6,8
first we find the least of the series and add to it the number above it, i.e the series become
4,6,8
now we find the least value again and add to it the intitial value in the column i.e 2
6,6,8
so the next iteration becomes
8,6,8
8,12,8
10,12,8
10,12,16
12,12,16
14,12,16
14,18,16
16,18,16
18,18,16
18,18,24
20,18,24
20,24,24
22,24,24
24,24,24
as you can see at one point all numbers become equal which is our lcm
#include<iostream.h>
/*function to check if all the elements of an array are equal*/
int equl(int a[20], int n)
{
int i=0;
while(n==1&&i<20)
{
if (a[i]==a[i+1])
n=1;
else
n=0;
i++;
}
return n;
}
/*function to calculate lcm and return that value to main function*/
int lcm()
{
int i,k,j,check=1,a[20],b[20];
/*loading both arrays with numbers from 1 to 20*/
for(i=0;i<20;i++)
{
a[i]=i+1;
b[i]=i+1;
}
check= equl(a,1);
/*actual implementation of the algorith*/
while(check==0)
{
k=a[0]; /*looks for the least value in the array*/
for(i=0;i<20;i++)
{
if(a[i+1]<k)
{
k=a[i+1]; /*find the least value*/
j=i+1; /*mark the position in array */
}
else
continue;
}
a[j]=k+b[j]; /*adding the least value with its corresponding number*/
check= equl(a,1);
}
return (a[0]);
/*at this point all numbers in the array must be same thus any value gives us the lcm*/
}
void main()
{
int l;
l=lcm();
cout<<l;
}
In this line:
a[j]=k+b[j];
You use j but it is unitialized so it's some huge value and you are outside of the array bounds and thus you get a segmentation fault.
You also have some weird things going on in your code. void main() and you use cout without either saying std::cout or using namespace std; or something similar. An odd practice.
Also don't you think you should pass the arrays as arguments if you're going to make lcm() a function? That is int lcm(int a[], int b[]);.
You might look into using a debugger also and improving your coding practices. I found this error within 30 seconds of pasting your code into the compiler with the help of the debugger.
Your loop condition is:
while(n==1&&i<20)
So your equl function will never return 1 because if n happens to be 1 then the loop will just keep going and never return a 1.
However, your program still does not appear to return the correct result. You can split the piece of your code that finds the minimum element and replace it with this for cleanliness:
int least(int a[], int size){
int minPos = 0;
for(int i=0; i<size ;i++){
if (a[i] < a[minPos] ){
minPos = i;
}
}
return minPos;
}
Then you can call it by saying j = least(a, 20);. I will leave further work on your program to you. Consider calling your variables something meaningful instead of i,j,k,a,b.
Your equl function is using array indices from 0-20, but the arrays only have 1-19
j in lcm() is uninitialized if the first element is the smallest. It should be set to 0 at the top of the while loop
In the following code, when i=19, you are accessing a[20], which is out of the bounds of the array. Should be for(i=0;i<19;i++)
for(i=0;i<20;i++) {
if(a[i+1]<k)
You are not actually using the std namespace for the cout. this should be std::cout<<l
Your are including iostream.h. The standard is iostream without the .h, this may not work on such an old compiler tho
instead of hard-coding 20 everywhere, you should use a #define. This is not an error, just a style thing.
The following code does nothing. This is the default behavior
else
continue;