Could someone explain me how this matrix exponentiation function works? - c++

#include <bits/stdc++.h>
using namespace std;
//Program to find the nth fib number using matrix exponentation
void multi_mat(int A[3][3], int B[3][3])
{
int res_mat[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
res_mat[i][j] = 0;
for (int k = 0; k < 3; k++)
{
res_mat[i][j] += A[i][k] * B[k][j];
}
}
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
A[i][j] = res_mat[i][j];
}
}
}
int power(int F[3][3], int n)
{
int M[3][3] = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}};
if (n == 1)
return F[0][0] + F[0][1];
power(F, n / 2);
multi_mat(F, F);
if (n % 2 != 0)
multi_mat(F, M);
return F[0][0] + F[0][1];
}
int findfib(int n)
{
int F[3][3] = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}};
if (n == 0)
return 0;
if (n == 1 || n == 2)
return 1;
return power(F, n - 2);
}
int main()
{
int n = 0;
cin >> n;
cout << "The fib of the " << n << "th number is : " << findfib(n) << '\n';
return 0;
}
This is the code for matrix exponentiation. I'm having trouble understanding where does the data get stored when the multi_mat function is invoked. Also when I call the multi_mat function does the matrix res_mat hold the values when it was previously invoked or does it initialize it with some junk value?

where does the data get stored when the multi_mat function is invoked
Initially, it's stored in res_mat:
res_mat[i][j] += A[i][k] * B[k][j];
but some lines later, it's copied to A:
A[i][j] = res_mat[i][j];
So at the end of the execution, the place where the result is stored is the first argument A, which outside the function is called F, as the function was invoked like:
multi_mat(F, F);
does the matrix res_mat hold the values when it was previously invoked or does it initialize it with some junk value?
Yes, it has "junk" values at this point:
int res_mat[3][3];
but, it's later initialized to zeroes when this line executes for each element of the matrix:
res_mat[i][j] = 0;

Related

Merge sort same output C++

I wrote the below code for merge sort but it's not working, And I am unable to find out problem!
Every time the output becomes same as input, I think that problem may occur due to vector reference.
I think mergeSort is not creating a new vector for sub array. But I am still confused.
input vector: 5, 4, 3, 2, 1
output: 5, 4, 3, 2, 1
Req output: 1, 2, 3, 4, 5
#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int> &la, vector<int> &ra, vector<int> &A) {
int i = 0, j = 0, k = 0;
// overwriting A using its solved sub arrays i.e la, ra
while (i < la.size() && j < ra.size()) {
if (la[i] <= ra[j]) {
A[k] = la[i];
i++;
k++;
} else {
A[k] = ra[j];
j++;
k++;
}
}
// if any subarray left then
while (i < la.size()) {
A[k] = la[i];
k++;
i++;
}
while (j < ra.size()) {
A[k] = ra[j];
k++;
j++;
}
}
mergeSort function:
void mergeSort(vector<int> &A) {
if (A.size() < 2)
return;
int len = A.size();
vector<int> la, ra;
for (int i = 0; i < len / 2; i++)
la.push_back(A[i]);
for (int i = len / 2; i < len; i++)
ra.push_back(A[i]);
// dividing the proble into subproblem
mergeSort(la);
mergeSort(ra);
// merging the solved subproblem
merge(la, ra, A);
}
Driver function:
int main(void) {
int arr[] = { 5, 4, 3, 2, 1 };
vector<int> A(arr, arr + 5);
for (int i = 0; i < A.size(); i++)
cout << A[i] << " ";
cout << endl;
mergeSort(A);
for (int i = 0; i < A.size(); i++)
cout << A[i] << " ";
return 0;
}
The code posted does not seem to have a problem.
Executing it produces the expected output: 1 2 3 4 5, so there is something else going on that could cause your observations: you might be running an executable produced by a previous or at least different version of the code.

having trouble making a function to find the determinant of a matrix

Probably a simple fix, but I keep getting 0 as the determinate when I should be getting 22, I have to use dynamic memory allocation as well. Might be some problem with using floats as I am not completely familiar with how they work with pointers. Honestly don't know what could be causing the function to output a zero.
cpp.sh link to test: http://cpp.sh/5bu2v
#include <iostream>
#include <math.h>
using namespace std;
float determinant(float *mat1, int &rows1)
{
float s = 1, D = 0;
float *temp = new float[rows1 * rows1];
int i, j, m, n, c;
if (rows1 == 1)
{
return (*(mat1 + 0 * rows1 + 0));
}
else
{
D = 0;
for (c = 0; c < rows1; c++)
{
m = 0;
n = 0;
for (i = 0; i < rows1; i++)
{
for (j = 0; j < rows1; j++)
{
*(temp + i * rows1 + j) = 0;
if (i != 0 && j != c)
{
*(temp + m * rows1 + n) = *(mat1 + i * rows1 + j);
if (n < (rows1 - 2))
n++;
else
{
n = 0;
m++;
}
}
}
}
int V1 = rows1 - 1;
D = D + s * (*(mat1 + 0 * rows1 + c) * determinant(temp, V1));
s = -1 * s;
}
}
return (D);
}
int main()
{
int i, j;
int n = 3;
int matrix[10][10] = {{1, 2, 3},
{0, 4, 5},
{1, 0, 6}};
float *mat1 = new float[n * n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
*(mat1 + i * n + j) = matrix[i][j];
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cout << matrix[i][j] << " ";
cout << endl;
}
cout << "Determinant of the matrix is " << determinant(mat1, n);
return 0;
}
Your first call into determinant, mat is a 3x3 matrix stored in a 1 dimensional array. Visualize it like this:
A B C
D E F
G H I
You create another 3x3 matrix, temp.
You series of loops to fill the temp matrix exclude the first row and column c, so it ends up looking like this the first time thru:
D E 0
G H 0
0 0 0
This gets passed to determinant, which is expecting a 2x2 matrix. Since you've passed it something else, what the recursive call sees is
D E
0 G
When you construct temp you need to do it with the smaller matrix size, not the source size.

Segmentation fault in matrix multiplication C++

I'm trying to make a function that receives as parameter two matrixes and returns the multiplication of both. But when I try to test it, it returns a segmentation fault, can anyone tell me why? And help me to fix it?
This is my function code:
#include <iostream>
#include <math.h>
#include <fstream>
#include <vector>
using namespace std;
vector<vector<double> > MMultiplication(vector<vector<double> > a, vector<vector<double> > b) {
int a_columns = a[0].size();
int a_rows = a.size();
int b_columns = b[0].size();
int b_rows = b.size();
< vector<vector<double> > result;
result.resize(a_columns);
for (int i = 0; i < m; ++i)
{
//Grow Columns by b_rows
result[i].resize(b_rows);
}
for (int p = 0; p < a_rows; p++) {
for (int q = 0; q < b_columns; q++) {
result[p][q] = 0;
}
}
if (a_columns != b_rows) {
cout << "Error: The number of columns of the first matrix needs to be equal to the number of rows of the second matrix" << endl;
return result;
}
for (int i = 0; i < a_rows; i++) { //i iterate a rows
for (int j = 0; j = b_columns; j++) //j iterates b columns
{
for (int k = 0; k < a_columns; k++) { //k goes back to a and iterates its columns
result[i][j] += a[i][k] * b[k][j]; //sums all multiplications into result[i][j]
}
}
}
return result;
}
And this is the main i'm using to test my function:
int main ()
{
vector < vector < double >>a;
int m = 4, n = 2;
//Grow rows by m
a.resize (m);
for (int i = 0; i < m; ++i)
{
//Grow Columns by n
a[i].resize (n);
}
a[0] =
{
1, 0};
a[1] =
{
1, 1};
a[2] =
{
1, 2};
a[3] =
{
1, 3};
cout << a.size () << endl;
cout << a[0].size () << endl;
vector < vector < double >>b;
int o = 2, p = 4;
b.resize (o);
for (int i = 0; i < o; i++)
{
b[i].resize (p);
}
b[0] =
{
1, 2, 3, 4};
b[1] =
{
1, 3, 5, 7};
vector < vector < double >>result = MMultiplication (a, b);
cout << result.size () << endl;
cout << result[0].size () << endl;
/* for(int k = 0; k < result.size(); k++) {
for(int q = 0; q < result[0].size(); q++)
cout << result[k][q] << endl;
} */
}
Also, it's important to point out that the function, so far, is returning a matrix of zeros if it's impossible to multiply a and b.
Thank you.

Recursion of for's

I'm tried to figure out how to do it for quite of time and its not working as intended; I'm writing a code where there is 1 to k numbers, I need to find all possible combination without repeats. e.g. for 3: 1, 2, 3, 12, 13.
Example for counting 4-digits numbers with 1, 2, 3, 4, 5.
int k = 5;
for (int p = 0; p < k; p++)
{
for (int i = p+1; i < k; i++)
{
for (int j = i + 1; j < k; j++)
{
for (int h = j + 1; h < k; h++)
{
cout << p + 1 << i + 1 << j + 1 << h + 1 << endl;
}
}
}
}
And there is example for 3-digits number with 1, 2, 3.
int k = 4
for (int p = 0; p < k; p++)
{
for (int i = p+1; i < k; i++)
{
for (int j = i + 1; j < k; j++)
{
cout << p + 1 << i + 1 << j + 1 << endl;
}
}
}
I think that to count n-digits possible position without repeat i need n for's.
And i don't know how to do it without recursion which don't work when i do it.
My goal to get recursion which will count and print possible positions for n-digits.
I did recursion to count possibility myself, but love you guys for all your help.
My recursion is
void col(int ilosc)
{
static int st;
for (int i = st++; i < k; i++)
{
if (ilosc > 1)
col(ilosc - 1);
else
sposob++;
}
}
where ilosc is digits number and sposob is count of possible positions numbers.
NOTE: sposob and k is global variables.
I am not sure whether recursion is the best choice here, but you could do it like this:
typedef std::vector<int> IV;
IV getFirst(int k){
IV res;
for (int i=0;i<k-1;i++){res.push_back(i+1);}
return res;
}
bool getNext(IV& numbers,int i){
if (i==-1){return false;} // end of recursion
if (numbers[i]>i+1){return getNext(numbers,i-1);}
numbers[i]++;
return true;
}
bool getNext(IV& numbers){ // start of recursion
return getNext(numbers,numbers.size()-1);
}
int main() {
IV numbers = getFirst(5);
for (int i=0;i<numbers.size();i++){std::cout << numbers[i];}
std::cout << std::endl;
while(getNext(numbers)){
for (int i=0;i<numbers.size();i++){std::cout << numbers[i];}
std::cout << std::endl;
}
}
I think this will get you pretty close. I have an occasional repeat here, but this should set you on the right path.
const int max_depth = 5; // How long your string is
const int max_digit = 3; // Max digit you are counting to
int *nums = new int [max_depth];
void recurse_count(int depth)
{
if (depth < max_depth)
{
for(int i = depth; i <= depth+1; i++)
{
nums[depth] = i;
recurse_count(i+1);
}
}
else
{
for (int j = 0; j < max_depth; j++)
cout<<nums[j]+1;
cout<<endl;
}
}
int main()
{
recurse_count(0);
return 0;
}
My approach (still too early in the evening probably, I had problems with it)
namespace detail
{
void recurse_hlp(int min, int max, std::vector<int> vals, std::function<void(const std::vector<int>&)> f, std::size_t ptr)
{
if (ptr == vals.size())
f(vals);
else
{
for (int i = min; i <= max; ++i)
{
vals[ptr] = i;
recurse_hlp(min, max, vals, f, ptr + 1);
}
}
}
}
void recurse(int min, int max, int count, std::function<void(const std::vector<int>&)> f)
{
std::vector<int> vals(count);
detail::recurse_hlp(min, max, vals, f, 0);
}
void print(const std::vector<int>& vals)
{
for (int v : vals)
std::cout << v << " ";
std::cout << std::endl;
}
int main()
{
recurse(0, 5, 3, &print);
}
recurse gets a function accepting std::vector<int>, which contains all numbers from min to max up to count places.

memory issue in using partially initialized array(in 0/1 knapsack)

Given n items with size Ai and value Vi, and a backpack with size m. What's the maximum value can you put into the backpack?
Have you met this question in a real interview? Yes
Example
Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 9.
Note
You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m.
int knapsack(int m, vector<int> A, vector<int> V) {
int dp[m + 1], tmp[m + 1];
for (int n = 1; n <= m; n++) {
//******the problem would disappear if i change n to start with 0
dp[n] = (n < A[0]) ? 0 : V[0] ;
tmp[n] = dp[n];
}
for (int i = 1; i < A.size(); i++) {
for (int n = 1; n <= m; n++) {
tmp[n] = dp[n];
}
for (int j = 1; j <= m; j++) {
if (j >= A[i]) {
dp[j] = max(tmp[j], (V[i] + tmp[j - A[i]]));
}
}
}
return dp[m];
}
I am failing the specific testcase and all other are fine(even larger m values)
m = 10, A = [2,3,5,7], V = [1,5,2,4]
Output: 563858905 (actually random every time) Expected: 9
I know this question is some what trivial but I'm really curious about the memory allocation process in this scenario
I'm guessing that it would be dangerous to use any array that is not initialized at the first memory location, can someone confirm with me?
I tried following code, a simpler version of yours;
#include <iostream>
using namespace std;
int knapsack(int m, int A[], int V[], int size) {
int dp[m+1], tmp[m+1];
for (int n = 1; n <= m; n++) { //*1*
dp[n] = (n < A[0]) ? 0 : V[0] ;
tmp[n] = dp[n];
}
for (int i = 1; i < 4; i++) { //*2*
for (int n = 1; n <= m; n++) { //*3*
tmp[n] = dp[n];
}
for (int j = 1; j <= m; j++) { //*4*
if (j >= A[i]) {
dp[j] = (tmp[j]> (V[i] + tmp[j - A[i]])? //*5*
tmp[j] :
(V[i] + tmp[j - A[i]])
);
}
}
}
cout << "answer:" << dp[m] << endl;
return dp[m];
}
int main(){
int a[] = {2,3,5,7};
int b[] = {1,5,2,4};
knapsack(10, a, b, 4);
return 0;
}
and got 8 as the answer, rather than a random number.
I'm not sure that my code is the correct version of yours, but I luckily noticed that the expression of V[i] + tmp[j-A[i]] at the line marked by "\\*5" accesses tmp[0] when j=2 and i=1, since A[1] == 2 and 2 >= A[1]. Thus it would not be safe without initialization of tmp[0] in this logic.
So, I guess you are right; the uninitialized value of tmp[0] may change the result value, (and in some cases the flow of the logic as well, at the conditional statement of line //*5.)