I made a similar post on here but didn't get any feedback. The problem came from here.
I am trying to simply print out the entries of the longest increasing matrix. I thought I had it figure out when I tried the following matrix:
2 2 1
1 2 1
2 2 1
I got an output of:
1
2
Then when I increased n , m = 4. I got this matrix:
2 2 1 1
2 1 2 2
1 2 2 3
1 2 1 3
And this output for the paths entries:
1
1
2
When it should be just:
1
2
3
Here is my code:
#include <algorithm>
#include <cmath>
#include <list>
#include <vector>
#include <stdio.h>
#include <random>
#include <utility>
#include <iostream>
void printPath(std::vector<int> &numPaths) {
std::sort(numPaths.begin(), numPaths.end());
for(int i = 0; i < numPaths.size(); i++) {
std::cout << numPaths[i] << std::endl;
}
}
int DFS(int i, int j, const std::vector<std::vector<int> > &matrix, std::vector<std::vector<int> > &length) {
std::vector<std::pair<int,int> > dics{{-1,0},{1,0},{0,-1},{0,1}}; // used to check the directions left, right, up, down
std::vector<int> path;
if(length[i][j] == -1) {
int len = 0;
for(auto p: dics) {
int x = i + p.first, y = j + p.second;
if(x < 0 || x >= matrix.size() || y < 0 || y >= matrix[0].size()) continue; // Check to make sure index is not out of boundary
if(matrix[x][y] > matrix[i][j]) { // compare number
len = std::max(len, DFS(x,y,matrix,length));
}
}
length[i][j] = len + 1;
}
return length[i][j];
}
int longestPath(std::vector<std::vector<int> > matrix) {
int n = matrix[0].size();
if (n == 0) {
return 0;
}
int m = matrix.size();
if (m == 0) {
return 0;
}
std::vector<std::vector<int> > length(m, std::vector<int>(n,-1));
std::vector<int> numPaths;
int len = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int newLen = DFS(i,j,matrix,length);
if(newLen > len) {
numPaths.push_back(matrix[i][j]);
}
len = std::max(len, DFS(i, j, matrix, length));
}
}
printPath(numPaths);
return len;
}
int main() {
// Specify the number of rows and columns of the matrix
int n = 4;
int m = 4;
// Declare random number generator
std::mt19937 gen(10);
std::uniform_int_distribution<> dis(1, 3);
// Fill matrix
std::vector<std::vector<int> > matrix;
for(int i = 0; i < m; i++) {
std::vector<int> row;
for(int j = 0; j < n; j++) {
row.push_back(0);
}
matrix.push_back(row);
}
// Apply random number generator to create matrix
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
matrix[i][j] = dis(gen);
}
}
// Print matrix to see contents
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
std::cout << matrix[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
//std::vector<std::vector<int> > mat = {{1,2,3}};
int result = longestPath(matrix);
std::cout << "The longest path is " << result << std::endl;
}
I would really appreciate if someone can tell me where I am going wrong.
#include <algorithm>
#include <cmath>
#include <vector>
#include <stdio.h>
#include <random>
#include <utility>
#include <iostream>
#define MATRIX_SIZE 1000
void printPath(std::vector<int> &numPaths) {
std::sort(numPaths.begin(), numPaths.end());
for(int i = 0; i < numPaths.size(); i++) {
std::cout << numPaths[i] << std::endl;
}
}
int DFS(int i, int j, const std::vector<std::vector<int> > &matrix, std::vector<std::vector<int> > &length) {
std::vector<std::pair<int,int> > dics{{-1,0},{1,0},{0,-1},{0,1}}; // used to check the directions left, right, up, down
std::vector<int> path;
if(length[i][j] == -1) {
int len = 0;
for(auto p: dics) {
int x = i + p.first, y = j + p.second;
if(x < 0 || x >= matrix.size() || y < 0 || y >= matrix[0].size()) continue; // Check to make sure index is not out of boundary
if(matrix[x][y] > matrix[i][j]) { // compare number
len = std::max(len, DFS(x,y,matrix,length));
}
}
length[i][j] = len + 1;
}
return length[i][j];
}
void printMatrix(std::vector<std::vector<int>> &matrix) {
for (int i =0; i < matrix.size(); i++) {
for (int j =0; j < matrix[0].size(); j++) {
std::cout << matrix[i][j] << " ";
}
std::cout << std::endl;
}
}
std::vector<int> generatePath(int i, int j, const std::vector<std::vector<int>> &matrix, const std::vector<std::vector<int>> &length) {
int max_length = length[i][j];
std::vector<int> path(max_length, 0);
for (int current_length = max_length; current_length >= 1; current_length--) {
std::vector<std::pair<int,int> > dics{{-1,0},{1,0},{0,-1},{0,1}}; // used to check the directions left, right, up, down
int index = max_length - current_length;
for (auto p: dics) {
path[index] = matrix[i][j];
int x = i + p.first, y = j + p.second;
if(x < 0 || x >= matrix.size() || y < 0 || y >= matrix[0].size()) continue;
if (current_length - length[x][y] == 1) {
i = x;
j = y;
break;
}
}
}
printPath(path);
return path;
}
int longestPath(std::vector<std::vector<int> > matrix) {
int n = matrix[0].size();
if (n == 0) {
return 0;
}
int m = matrix.size();
if (m == 0) {
return 0;
}
std::vector<std::vector<int> > length(m, std::vector<int>(n,-1));
std::vector<int> numPaths;
int len = 0;
int maxRow = 0;
int maxCol = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int currentLength = DFS(i, j, matrix, length);
if (currentLength > len) {
len = currentLength;
maxRow = i;
maxCol = j;
}
}
}
generatePath(maxRow, maxCol, matrix,length);
return len;
}
int main(int argc, char *argv[]) {
std::mt19937 gen(10);
std::uniform_int_distribution<> dis(1, 1000000);
// Fill matrix
std::vector<std::vector<int> > matrix;
for(int i = 0; i < MATRIX_SIZE; i++) {
std::vector<int> row;
for(int j = 0; j < MATRIX_SIZE; j++) {
row.push_back(0);
}
matrix.push_back(row);
}
// Apply random number generator to create matrix
for(int i = 0; i < MATRIX_SIZE; i++) {
for(int j = 0; j < MATRIX_SIZE; j++) {
matrix[i][j] = dis(gen);
}
}
// Print matrix
//printMatrix(matrix);
timespec start, end;
clock_gettime(CLOCK_REALTIME, &start);
printf("the longest path is %d\n", longestPath(matrix));
clock_gettime(CLOCK_REALTIME, &end);
printf("found in %ld micros\n", (end.tv_sec * 1000000 + end.tv_nsec / 1000) - (start.tv_sec * 1000000 + start.tv_nsec / 1000));
return 0;
}
# Print the Longest Increasing Path in a Matrix #
class Solution:
# Possible directions allowed from the given question.
DIRECTIONS = [[1, 0], [-1, 0], [0, 1], [0, -1]]
def longestIncreasingPath(self, matrix):
# From the given question:
# ----- m = rows ----- i
# ----- n = cols ----- j
m = len(matrix)
if m == 0:
return 0
n = len(matrix[0])
if n == 0:
return 0
cache = [[0] * n for _ in range(m)]
longestPath = 0
maximum = 1
for i in range(m):
for j in range(n):
longestPath = self.depthFirstSearch(matrix, i, j, m, n, cache)
maximum = max(maximum, longestPath)
return (cache, maximum)
def depthFirstSearch(self, matrix, i, j, m, n, cache):
if cache[i][j] != 0:
return cache[i][j]
maxPath = 1
for direction in self.DIRECTIONS:
x = direction[0] + i
y = direction[1] + j
if x < 0 or y < 0 or x >= m or y >= n or matrix[x][y] <= matrix[i][j]:
continue
length = 1 + self.depthFirstSearch(matrix, x, y, m, n, cache)
maxPath = max(maxPath, length)
cache[i][j] = maxPath # Save the value at i, j for future usage.
return maxPath
def printPath(self, matrix):
# Check if longestPath is 0.
if not self.longestIncreasingPath(matrix):
return None
length = self.longestIncreasingPath(matrix)[1]
cache = self.longestIncreasingPath(matrix)[0]
# From the given question:
# ----- m = rows ----- i
# ----- n = cols ----- j
m = len(cache)
n = len(cache[0])
location = []
# Traverse the cache to obtain the location of the starting point of the longest increasing path in the matrix.
# Time complexity, T(n) = O(n*m) ----- if not a square matrix.
for i in range(m):
for j in range(n):
if cache[i][j] == length:
location.extend([i, j])
i, j = location[0], location[1]
result = [matrix[i][j]] # The result container is initialised with the element of the matrix at the obtained position
# Time complexity, T(n) = O(4n) ----- where n = length of longest increasing path in the given matrix and the 4 being the length of the DIRECTIONS matrix.
for _ in range(length):
for direction in self.DIRECTIONS:
x = direction[0] + i
y = direction[1] + j
if x < 0 or y < 0 or x >= m or y >= n or cache[i][j] - 1 != cache[x][y]:
continue
result.append(matrix[x][y])
i = x
j = y
return result
Related
I've read many posts but I can't figure out where is my error so I go with it.
My program throws the segfault at the cout<<endl. When I erase it, the program doesn't even print anything. It just prints the segfault. Aparently the program never reach to sort the vector.
#include <iostream>
#include <vector>
using namesapce std
void inserctionSort(std::vector<double> &v, int i, int j)
{
double temp;
for(i; i < v.size(); i++)
{
temp = v[i];
j = i - 1;
while((v[j] > temp) && (j >= 0))
{
v[j+1] = v[j];
j--;
}
v[j+1] = temp;
}
}
void merge_(std::vector<double> &v, int i, int k, int j)
{
std::vector<double> w(v.size());
int n = j - i + 1;
int p = i;
int q = k + 1;
for(int l = 0; l < n; l++)
{
if(p <= k && (q > j || v[p] <= v[q]))
{
w[l] = v[p];
p++;
}else
{
w[l] = v[q];
q++;
}
}
for(int l = 0; l < n; l++)
v[i - 1 + l] = w[l];
}
void mergeSort(std::vector<double> &v, int i, int j)
{
int n = j - i + 1, n0 = 3;
int k;
if(n <= n0)
{
inserctionSort(v,i,j);
}else
{
k = i - 1 + n / 2;
mergeSort(v, i, k);
mergeSort(v, k + 1, j);
merge_(v, i, k, j);
}
}
int main()
{
vector<double> v1 = {3.2,4.1,55.42,2.24,5.424,667.32,35.54};
cout<<"Vector desordenado: ";
for(int i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
cout<<"hola";
cout<<endl;
cout<<"hola";
mergeSort(v1, 0, v1.size()-1); //--> Core generado
//quickSort(v1, 0, v1.size()-1);
cout<<"Vector ordenado: ";
for(int i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
return 0;
}
You have problems in your code with vector indices assuming value -1 inside a couple of loops.
I have corrected these mistakes below, a working version of your code:
#include <iostream>
#include <vector>
using namespace std;
void inserctionSort(vector<double> &v, int i, int j)
{
int v_size = v.size();
double temp;
for (; i < v_size; i++) {
temp = v[i];
j = i - 1;
while ( (j >= 0) && (v[j] > temp) ) { // swapped conditions, as when j=-1, v[j]>temp is undefined
v[j+1] = v[j];
j--;
}
v[j+1] = temp;
}
}
void merge_(vector<double> &v, int i, int k, int j)
{
vector<double> w( v.size() );
int n = j - i + 1;
int p = i;
int q = k + 1;
for (int l = 0; l < n; l++) {
if ( p <= k && (q > j || v[p] <= v[q]) ) {
w[l] = v[p];
p++;
} else {
w[l] = v[q];
q++;
}
}
for(int l = 0; l < n; l++)
v[i + l] = w[l]; // deleted -1 from v[i - 1 + l], as it leads to v[-1] for i,l = 0
}
void mergeSort(vector<double> &v, int i, int j)
{
int n = j - i + 1, n0 = 3; // n = v.size()
int k;
if (n <= n0) {
inserctionSort(v,i,j);
} else {
k = i - 1 + n / 2;
mergeSort(v, i, k);
mergeSort(v, k + 1, j);
merge_(v, i, k, j);
}
}
int main()
{
vector<double> v1 = {3.2,4.1,55.42,2.24,5.424,667.32,35.54};
cout<<"Vector desordenado: ";
for (unsigned i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
cout << "hola";
cout << endl;
cout << "hola";
mergeSort(v1, 0, v1.size()-1); //--> Core generado
//quickSort(v1, 0, v1.size()-1);
cout<<"Vector ordenado: ";
for (unsigned i = 0; i < v1.size(); i++)
cout << v1[i] << ", ";
return 0;
}
#include <stdio.h>
#include <bitset>
using namespace std;
short smallprimes[549]; // about 1100 bytes
char in[19531]; // almost 20k
int isprime(int j) {
if (j < 3)
return j == 2;
for (int i = 0; i < 549; i++) {
int p = smallprimes[i];
if (p * p > j)
break;
if (!(j % p))
return 0;
}
return 1;
}
void init() {
bitset<4000> siv;
for (int i = 2; i < 64; i++)
if (!siv[i])
for (int j = i + i; j < 4000; j += i)
siv[j] = 1;
int k = 0;
for (int i = 3; i < 4000; i += 2)
if (!siv[i]) {
smallprimes[k++] = i;
}
for (int a0 = 0; a0 < 10000000; a0 += 512) {
in[a0 / 512] = !a0;
for (int j = a0 + 1; j < a0 + 512; j += 2)
in[a0 / 512] += isprime(j);
}
}
int whichprime(int k) {
if (k == 2)
return 1;
int a = k / 512;
int ans = 1 + !a;
for (int i = 0; i < a; i++)
ans += in[i];
for (int i = a * 512 + 1; i < k; i += 2)
ans += isprime(i);
return ans;
}
int main() {
int k;
init();
while (1 == scanf("%i", &k))
printf("%i\n", whichprime(k));
}
This is my code. It shows the index value of the prime number in an array.
I want small code which can get index value of prime numbers store in an array. Or I enter a prime number and then program calculates prime number at that particular index and shows its index position.
Input: 2
Output: 1 (index in an array)
It's quite complicated. Looking for an alternate solution.
Here's my less complicated (fewer magic numbers) generic C approach to this problem. Like the OP's original code, it produces bad results if passed non-primes to index:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
typedef unsigned long PRIME;
bool *primes;
size_t calloc_size = 3;
void sieve(PRIME end) {
if (end >= calloc_size) {
primes = realloc(primes, end + 1);
memset(primes + calloc_size, true, end - calloc_size + 1);
calloc_size = end + 1;
}
// This might be optimized to not resieve old territory ...
for (size_t i = 0; i <= end; i++) {
if (primes[i]) {
for (size_t j = i * 2; j <= end; j += i) {
primes[j] = false;
}
}
}
}
// whichprime() returns 1-based index of target prime in primes array.
// Current and future results are indeterminate if argument isn't prime.
size_t whichprime(PRIME prime) {
if (prime < calloc_size) {
for (size_t i = 0, idx = 0; i < calloc_size; i++) {
if (primes[i]) {
idx++;
if (i == prime) {
return idx; // Target prime already in primes array
}
}
}
assert(false); // should never be reached
}
sieve(prime);
return whichprime(prime); // recurse as we now know it's in primes
}
int main() {
PRIME k;
// This could be optimized to not store even numbers ..
primes = calloc(calloc_size, sizeof(bool));
primes[calloc_size - 1] = true;
while (1 == scanf("%lu", &k)) {
printf("%lu\n", whichprime(k));
}
free(primes);
return 0;
}
The boolean primes array is a sieve that gets extended as needed.
USAGE
> ./a.out
2999
430
859433
68301
13
6
7919
1000
>
I want to make a function that, depending on the depth of nested loop, does this:
if depth = 1:
for(i = 0; i < max; i++){
pot[a++] = wyb[i];
}
if depth = 2:
for(i = 0; i < max; i++){
for( j = i+1; j < max; j++){
pot[a++] = wyb[i] + wyb[j];
}
}
if depth = 3:
for(i = 0; i < max; i++){
for( j = i+1; j < max; j++){
for( k = j+1; k < max; k++){
pot[a++] = wyb[i] + wyb[j] + wyb[k];
}
}
}
and so on.
So the result would be:
depth = 1
pot[0] = wyb[0]
pot[1] = wyb[1]
...
pot[max-1] = wyb[max-1]
depth = 2, max = 4
pot[0] = wyb[0] + wyb[1]
pot[1] = wyb[0] + wyb[2]
pot[2] = wyb[0] + wyb[3]
pot[3] = wyb[1] + wyb[2]
pot[4] = wyb[1] + wyb[3]
pot[5] = wyb[2] + wyb[3]
I think you get the idea. I can't think of a way to do this neatly.
Could someone present an easy way of using recursion (or maybe not?) to achieve this, keeping in mind that I'm still a beginner in c++, to point me in the right direction?
Thank you for your time.
You may use the std::next_permutation to manage the combinaison:
std::vector<int> compute(const std::vector<int>& v, std::size_t depth)
{
if (depth == 0 || v.size() < depth) {
throw "depth is out of range";
}
std::vector<int> res;
std::vector<int> coeffs(depth, 1);
coeffs.resize(v.size(), 0); // flags is now {1, .., 1, 0, .., 0}
do {
int sum = 0;
for (std::size_t i = 0; i != v.size(); ++i) {
sum += v[i] * coeffs[i];
}
res.push_back(sum);
} while (std::next_permutation(coeffs.rbegin(), coeffs.rend()));
return res;
}
Live example
Simplified recursive version:
int *sums_recursive(int *pot, int *wyb, int max, int depth) {
if (depth == 1) {
while (max--)
*pot++ = *wyb++;
return pot;
}
for (size_t i = 1; i <= max - depth + 1; ++i) {
int *pot2 = sums_recursive(pot, wyb + i, max - i, depth - 1);
for (int *p = pot ; p < pot2; ++p) *p += wyb[i - 1];
pot = pot2;
}
return pot;
}
Iterative version:
void sums(int *pot, int *wyb, int max, int depth) {
int maxi = 1;
int o = 0;
for (int d = 0; d < depth; ++d) { maxi *= max; }
for (int i = 0; i < maxi; ++i) {
int i_div = i;
int idx = -1;
pot[o] = 0;
int d;
for (d = 0; d < depth; ++d) {
int new_idx = i_div % max;
if (new_idx <= idx) break;
pot[o] += wyb[new_idx];
idx = new_idx;
i_div /= max;
}
if (d == depth) o++;
}
}
I have written a solution for the above problem but can someone please suggest an optimized way.
I have traversed through the array for count(2 to n) where count is finding subarrays of size count*count.
int n = 5; //Size of array, you may take a dynamic array as well
int a[5][5] = {{1,2,3,4,5},{2,4,7,-2,1},{4,3,9,9,1},{5,2,6,8,0},{5,4,3,2,1}};
int max = 0;
int **tempStore, size;
for(int count = 2; count < n; count++)
{
for(int i = 0; i <= (n-count); i++)
{
for(int j = 0; j <= (n-count); j++)
{
int **temp = new int*[count];
for(int i = 0; i < count; ++i) {
temp[i] = new int[count];
}
for(int k = 0; k < count; k++)
{
for(int l = 0; l <count; l++)
{
temp[k][l] = a[i+k][j+l];
}
}
//printing fetched array
int sum = 0;
for(int k = 0; k < count; k++)
{
for(int l = 0; l <count; l++)
{
sum += temp[k][l];
cout<<temp[k][l]<<" ";
}cout<<endl;
}cout<<"Sum = "<<sum<<endl;
if(sum > max)
{
max = sum;
size = count;
tempStore = new int*[count];
for(int i = 0; i < count; ++i) {
tempStore[i] = new int[count];
}
//Locking the max sum array
for(int k = 0; k < count; k++)
{
for(int l = 0; l <count; l++)
{
tempStore[k][l] = temp[k][l];
}
}
}
//printing finished
cout<<"------------------\n";
//Clear temp memory
for(int i = 0; i < size; ++i) {
delete[] temp[i];
}
delete[] temp;
}
}
}
cout<<"Max sum is = "<<max<<endl;
for(int k = 0; k < size; k++)
{
for(int l = 0; l <size; l++)
{
cout<<tempStore[k][l]<<" ";
}cout<<endl;
}cout<<"-------------------------";
//Clear tempStore memory
for(int i = 0; i < size; ++i) {
delete[] tempStore[i];
}
delete[] tempStore;
Example:
1 2 3 4 5
2 4 7 -2 1
4 3 9 9 1
5 2 6 8 0
5 4 3 2 1
Output:
Max sum is = 71
2 4 7 -2
4 3 9 9
5 2 6 8
5 4 3 2
This is a problem best solved using Dynamic Programming (DP) or memoization.
Assuming n is significantly large, you will find that recalculating the sum of every possible combination of matrix will take too long, therefore if you could reuse previous calculations that would make everything much faster.
The idea is to start with the smaller matrices and calculate sum of the larger one reusing the precalculated value of the smaller ones.
long long *sub_solutions = new long long[n*n*m];
#define at(r,c,i) sub_solutions[((i)*n + (r))*n + (c)]
// Winner:
unsigned int w_row = 0, w_col = 0, w_size = 0;
// Fill first layer:
for ( int row = 0; row < n; row++) {
for (int col = 0; col < n; col++) {
at(r, c, 0) = data[r][c];
if (data[r][c] > data[w_row][w_col]) {
w_row = r;
w_col = c;
}
}
}
// Fill remaining layers.
for ( int size = 1; size < m; size++) {
for ( int row = 0; row < n-size; row++) {
for (int col = 0; col < n-size; col++) {
long long sum = data[row+size][col+size];
for (int i = 0; i < size; i++) {
sum += data[row+size][col+i];
sum += data[row+i][col+size];
}
sum += at(row, col, size-1); // Reuse previous solution.
at(row, col, size) = sum;
if (sum > at(w_row, w_col, w_size)) { // Could optimize this part if you only need the sum.
w_row = row;
w_col = col;
w_size = size;
}
}
}
}
// The largest sum is of the sub_matrix starting a w_row, w_col, and has dimensions w_size+1.
long long largest = at(w_row, w_col, w_size);
delete [] sub_solutions;
This algorithm has complexity: O(n*n*m*m) or more precisely: 0.5*n*(n-1)*m*(m-1). (Now I haven't tested this so please let me know if there are any bugs.)
Try this one (using naive approach, will be easier to get the idea):
#include <iostream>
#include<vector>
using namespace std;
int main( )
{
int n = 5; //Size of array, you may take a dynamic array as well
int a[5][5] =
{{2,1,8,9,0},{2,4,7,-2,1},{5,4,3,2,1},{3,4,9,9,2},{5,2,6,8,0}};
int sum, partsum;
int i, j, k, m;
sum = -999999; // presume minimum part sum
for (i = 0; i < n; i++) {
partsum = 0;
m = sizeof(a[i])/sizeof(int);
for (j = 0; j < m; j++) {
partsum += a[i][j];
}
if (partsum > sum) {
k = i;
sum = partsum;
}
}
// print subarray having largest sum
m = sizeof(a[k])/sizeof(int); // m needs to be recomputed
for (j = 0; j < m - 1; j++) {
cout << a[k][j] << ", ";
}
cout << a[k][m - 1] <<"\nmax part sum = " << sum << endl;
return 0;
}
With a cumulative sum, you may compute partial sum in constant time
std::vector<std::vector<int>>
compute_cumulative(const std::vector<std::vector<int>>& m)
{
std::vector<std::vector<int>> res(m.size() + 1, std::vector<int>(m.size() + 1));
for (std::size_t i = 0; i != m.size(); ++i) {
for (std::size_t j = 0; j != m.size(); ++j) {
res[i + 1][j + 1] = m[i][j] - res[i][j]
+ res[i + 1][j] + res[i][j + 1];
}
}
return res;
}
int compute_partial_sum(const std::vector<std::vector<int>>& cumulative, std::size_t i, std::size_t j, std::size_t size)
{
return cumulative[i][j] + cumulative[i + size][j + size]
- cumulative[i][j + size] - cumulative[i + size][j];
}
live example
The problem is to print all subsets that sum up to a value. I wrote code to check if there is a possible subset. Can some one gimme an idea to print the numbers that form the sum. Below is my code. Assume the array contains only +ve nos for simplicity.
void subsetsum(int A[], int target) {
int N = sizeof(A)/sizeof(int), sum = 0;
for(int i = 0; i < N; i++) sum += A[i];
vector<bool> V(sum + 1, 0);
V[0] = 1;
for(int i = 0; i < N; i++)
for(int j = sum; j >= 0; j--) {
if(j + A[i] <= sum && V[j]) V[A[i] + j] = 1;
}
if(V[target]) cout << "Sumbset sum exists" << endl;
else cout << "Sumbset sum doesnt exist" << endl;
}
First you need to generate all the subsets
If [a,b,c,d] is given array, think about generating subsets taking each element from array one at a time.
subsets(X) including y = foreach x in X append y to x
Taking a, we get subsets(a) = { [], [a] }
Take b, we get subsets(a,b) = subsets(a) + (subsets(a) including b)
= { [], [a] } + { [b], [a,b] } = { [], [a], [b], [a,b] }
Take c, subsets(a,b,c) = subsets(a,b) + (subsets(a,b) including c)
= {[], [a],[b],[a,b]} + {[c], [a,c], [b,c], [a,b,c]}
Once you get all subsets, print those whose sums equals target. You can modify the above algo further if you don't need any subsets.
Here's an answer in javascript:
function subsetsum(A, target) {
//int N = sizeof(A)/sizeof(int), sum = 0;
var N = A.length, sum = 0;
//for(int i = 0; i < N; i++) sum += A[i];
for(var i = 0; i < N; i++) sum += A[i];
// vector<bool> V(sum + 1, 0);
var V = [];
V[0] = [];
for(var i = 0; i < N; i++) {
for(var j = sum; j >= 0; j--) {
if(j + A[i] <= sum && V[j]) {
//Join the subset of the memoized result to this result.
V[A[i] + j] = [A[i]].concat(V[j]);
}
}
}
console.log(V);
//evaluates to true if V[target] exists
return !!V[target];
}
function to find power set of a vector<int>
vector<vector<int>> power_set(const vector<int>& nums) {
if (nums.empty()) { return { {} }; }
auto set = power_set(vector<int>(begin(nums) +1, end(nums)));
auto tmp = set;
for (auto& p : tmp) {
p.push_back(nums[0]);
}
set.insert(end(set), begin(tmp), end(tmp));
return set;
}
function that return all sets in the power set that sum to target
vector<vector<int>> test_sum(const vector<vector<int>>& ps, int target) {
vector<vector<int>> v;
for (auto& p : ps) {
int sum = accumulate(begin(p), end(p), 0);
if (sum == target) {
v.push_back(p);
}
}
return v;
}
I modified your code to print the numbers.
void subsetsum(int A[], int target) {
int N = sizeof(A) / sizeof(int), sum = 0;
for (int i = 0; i < N; i++) sum += A[i];
vector<bool> V(sum + 1, 0);
V[0] = 1;
for (int i = 0; i < N; i++)
for (int j = sum; j >= 0; j--) {
if (j + A[i] <= sum && V[j]) V[A[i] + j] = 1;
}
if (V[target]) cout << "Sumbset sum exists" << endl;
else cout << "Sumbset sum doesnt exist" << endl;
if (V[target])
{
for (int i = N - 1; i >= 0; i--)
{
if (V[target - A[i]] == 1) printf("%d, ", A[i]), target -= A[i];
}
printf("\n");
}
}
or Here's my version with vector
bool subsetsum_dp(vector<int>& v, int sum)
{
int n = v.size();
const int MAX_ELEMENT = 100;
const int MAX_ELEMENT_VALUE = 1000;
static int dp[MAX_ELEMENT*MAX_ELEMENT_VALUE + 1]; memset(dp, 0, sizeof(dp));
dp[0] = 1;
for (int i = 0; i < n; i++)
{
for (int j = MAX_ELEMENT*MAX_ELEMENT_VALUE; j >= 0; j--)
{
if (j - v[i] < 0) continue;
if (dp[j - v[i]]) dp[j] = 1;
}
}
if (dp[sum])
{
for (int i = n - 1; i >= 0; i--)
{
if (dp[sum - v[i]] == 1) printf("%d, ", v[i]), sum -= v[i];
}
printf("\n");
}
return dp[sum] ? true : false;
}