Power set of large set - c++
I have to calculate power set of set which may have more elements upto 10^5. I tried an algo and the code below but it failed (I think cause large value of pow(2, size)).
void printPowerSet(int *set, int set_size)
{
unsigned int pow_set_size = pow(2, set_size);
int counter, j,sum=0;
for(counter = 0; counter < pow_set_size; counter++)
{
for(j = 0; j < set_size; j++)
{
if(counter & (1<<j))
std::cout<<set[i]<<" ";
}
std::cout<<sum;
sum=0;
printf("\n");
}
}
Is there any other algorithm or how can I fix this one (if it is possible)??
OR
Can you suggest me how to do it i.e. finding subset of large set.
As pointed out in an answer it seems I'm stuck in
X-Y problem. Basically, I need sum of all subsets of any set. Now if you can suggest me any other approach to solve the problem.
Thank you.
Here is an algorithm which will print out the power set of any set that will fit in your computer's memory.
Given enough time, it will print the power set of a set of length 10^5.
However, "enough time" will be something like several trillion billion gazillion years.
c++14
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#include <iostream>
void printPowerset (const vector<int>& original_set)
{
auto print_set = [&original_set](auto first, auto last) -> ostream&
{
cout << '(';
auto sep = "";
for ( ; first != last ; ++first, sep = ",")
{
cout << sep << original_set[(*first) - 1];
}
return cout << ')';
};
const int n = original_set.size();
std::vector<int> index_stack(n + 1, 0);
int k = 0;
while(1){
if (index_stack[k]<n){
index_stack[k+1] = index_stack[k] + 1;
k++;
}
else{
index_stack[k-1]++;
k--;
}
if (k==0)
break;
print_set(begin(index_stack) + 1, begin(index_stack) + 1 + k);
}
print_set(begin(index_stack), begin(index_stack)) << endl;
}
int main(){
auto nums = vector<int> { 2, 4, 6, 8 };
printPowerset(nums);
nums = vector<int> { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
printPowerset(nums);
return 0;
}
expected results:
first power set (4 items):
(2)(2,4)(2,4,6)(2,4,6,8)(2,4,8)(2,6)(2,6,8)(2,8)(4)(4,6)(4,6,8)(4,8)(6)(6,8)(8)()
second power set (10 items)
(2)(2,4)(2,4,6)(2,4,6,8)(2,4,6,8,10)(2,4,6,8,10,12)(2,4,6,8,10,12,14)(2,4,6,8,10,12,14,16)(2,4,6,8,10,12,14,16,18)(2,4,6,8,10,12,14,16,18,20)(2,4,6,8,10,12,14,16,20)(2,4,6,8,10,12,14,18)(2,4,6,8,10,12,14,18,20)(2,4,6,8,10,12,14,20)(2,4,6,8,10,12,16)(2,4,6,8,10,12,16,18)(2,4,6,8,10,12,16,18,20)(2,4,6,8,10,12,16,20)(2,4,6,8,10,12,18)(2,4,6,8,10,12,18,20)(2,4,6,8,10,12,20)(2,4,6,8,10,14)(2,4,6,8,10,14,16)(2,4,6,8,10,14,16,18)(2,4,6,8,10,14,16,18,20)(2,4,6,8,10,14,16,20)(2,4,6,8,10,14,18)(2,4,6,8,10,14,18,20)(2,4,6,8,10,14,20)(2,4,6,8,10,16)(2,4,6,8,10,16,18)(2,4,6,8,10,16,18,20)(2,4,6,8,10,16,20)(2,4,6,8,10,18)(2,4,6,8,10,18,20)(2,4,6,8,10,20)(2,4,6,8,12)(2,4,6,8,12,14)(2,4,6,8,12,14,16)(2,4,6,8,12,14,16,18)(2,4,6,8,12,14,16,18,20)(2,4,6,8,12,14,16,20)(2,4,6,8,12,14,18)(2,4,6,8,12,14,18,20)(2,4,6,8,12,14,20)(2,4,6,8,12,16)(2,4,6,8,12,16,18)(2,4,6,8,12,16,18,20)(2,4,6,8,12,16,20)(2,4,6,8,12,18)(2,4,6,8,12,18,20)(2,4,6,8,12,20)(2,4,6,8,14)(2,4,6,8,14,16)(2,4,6,8,14,16,18)(2,4,6,8,14,16,18,20)(2,4,6,8,14,16,20)(2,4,6,8,14,18)(2,4,6,8,14,18,20)(2,4,6,8,14,20)(2,4,6,8,16)(2,4,6,8,16,18)(2,4,6,8,16,18,20)(2,4,6,8,16,20)(2,4,6,8,18)(2,4,6,8,18,20)(2,4,6,8,20)(2,4,6,10)(2,4,6,10,12)(2,4,6,10,12,14)(2,4,6,10,12,14,16)(2,4,6,10,12,14,16,18)(2,4,6,10,12,14,16,18,20)(2,4,6,10,12,14,16,20)(2,4,6,10,12,14,18)(2,4,6,10,12,14,18,20)(2,4,6,10,12,14,20)(2,4,6,10,12,16)(2,4,6,10,12,16,18)(2,4,6,10,12,16,18,20)(2,4,6,10,12,16,20)(2,4,6,10,12,18)(2,4,6,10,12,18,20)(2,4,6,10,12,20)(2,4,6,10,14)(2,4,6,10,14,16)(2,4,6,10,14,16,18)(2,4,6,10,14,16,18,20)(2,4,6,10,14,16,20)(2,4,6,10,14,18)(2,4,6,10,14,18,20)(2,4,6,10,14,20)(2,4,6,10,16)(2,4,6,10,16,18)(2,4,6,10,16,18,20)(2,4,6,10,16,20)(2,4,6,10,18)(2,4,6,10,18,20)(2,4,6,10,20)(2,4,6,12)(2,4,6,12,14)(2,4,6,12,14,16)(2,4,6,12,14,16,18)(2,4,6,12,14,16,18,20)(2,4,6,12,14,16,20)(2,4,6,12,14,18)(2,4,6,12,14,18,20)(2,4,6,12,14,20)(2,4,6,12,16)(2,4,6,12,16,18)(2,4,6,12,16,18,20)(2,4,6,12,16,20)(2,4,6,12,18)(2,4,6,12,18,20)(2,4,6,12,20)(2,4,6,14)(2,4,6,14,16)(2,4,6,14,16,18)(2,4,6,14,16,18,20)(2,4,6,14,16,20)(2,4,6,14,18)(2,4,6,14,18,20)(2,4,6,14,20)(2,4,6,16)(2,4,6,16,18)(2,4,6,16,18,20)(2,4,6,16,20)(2,4,6,18)(2,4,6,18,20)(2,4,6,20)(2,4,8)(2,4,8,10)(2,4,8,10,12)(2,4,8,10,12,14)(2,4,8,10,12,14,16)(2,4,8,10,12,14,16,18)(2,4,8,10,12,14,16,18,20)(2,4,8,10,12,14,16,20)(2,4,8,10,12,14,18)(2,4,8,10,12,14,18,20)(2,4,8,10,12,14,20)(2,4,8,10,12,16)(2,4,8,10,12,16,18)(2,4,8,10,12,16,18,20)(2,4,8,10,12,16,20)(2,4,8,10,12,18)(2,4,8,10,12,18,20)(2,4,8,10,12,20)(2,4,8,10,14)(2,4,8,10,14,16)(2,4,8,10,14,16,18)(2,4,8,10,14,16,18,20)(2,4,8,10,14,16,20)(2,4,8,10,14,18)(2,4,8,10,14,18,20)(2,4,8,10,14,20)(2,4,8,10,16)(2,4,8,10,16,18)(2,4,8,10,16,18,20)(2,4,8,10,16,20)(2,4,8,10,18)(2,4,8,10,18,20)(2,4,8,10,20)(2,4,8,12)(2,4,8,12,14)(2,4,8,12,14,16)(2,4,8,12,14,16,18)(2,4,8,12,14,16,18,20)(2,4,8,12,14,16,20)(2,4,8,12,14,18)(2,4,8,12,14,18,20)(2,4,8,12,14,20)(2,4,8,12,16)(2,4,8,12,16,18)(2,4,8,12,16,18,20)(2,4,8,12,16,20)(2,4,8,12,18)(2,4,8,12,18,20)(2,4,8,12,20)(2,4,8,14)(2,4,8,14,16)(2,4,8,14,16,18)(2,4,8,14,16,18,20)(2,4,8,14,16,20)(2,4,8,14,18)(2,4,8,14,18,20)(2,4,8,14,20)(2,4,8,16)(2,4,8,16,18)(2,4,8,16,18,20)(2,4,8,16,20)(2,4,8,18)(2,4,8,18,20)(2,4,8,20)(2,4,10)(2,4,10,12)(2,4,10,12,14)(2,4,10,12,14,16)(2,4,10,12,14,16,18)(2,4,10,12,14,16,18,20)(2,4,10,12,14,16,20)(2,4,10,12,14,18)(2,4,10,12,14,18,20)(2,4,10,12,14,20)(2,4,10,12,16)(2,4,10,12,16,18)(2,4,10,12,16,18,20)(2,4,10,12,16,20)(2,4,10,12,18)(2,4,10,12,18,20)(2,4,10,12,20)(2,4,10,14)(2,4,10,14,16)(2,4,10,14,16,18)(2,4,10,14,16,18,20)(2,4,10,14,16,20)(2,4,10,14,18)(2,4,10,14,18,20)(2,4,10,14,20)(2,4,10,16)(2,4,10,16,18)(2,4,10,16,18,20)(2,4,10,16,20)(2,4,10,18)(2,4,10,18,20)(2,4,10,20)(2,4,12)(2,4,12,14)(2,4,12,14,16)(2,4,12,14,16,18)(2,4,12,14,16,18,20)(2,4,12,14,16,20)(2,4,12,14,18)(2,4,12,14,18,20)(2,4,12,14,20)(2,4,12,16)(2,4,12,16,18)(2,4,12,16,18,20)(2,4,12,16,20)(2,4,12,18)(2,4,12,18,20)(2,4,12,20)(2,4,14)(2,4,14,16)(2,4,14,16,18)(2,4,14,16,18,20)(2,4,14,16,20)(2,4,14,18)(2,4,14,18,20)(2,4,14,20)(2,4,16)(2,4,16,18)(2,4,16,18,20)(2,4,16,20)(2,4,18)(2,4,18,20)(2,4,20)(2,6)(2,6,8)(2,6,8,10)(2,6,8,10,12)(2,6,8,10,12,14)(2,6,8,10,12,14,16)(2,6,8,10,12,14,16,18)(2,6,8,10,12,14,16,18,20)(2,6,8,10,12,14,16,20)(2,6,8,10,12,14,18)(2,6,8,10,12,14,18,20)(2,6,8,10,12,14,20)(2,6,8,10,12,16)(2,6,8,10,12,16,18)(2,6,8,10,12,16,18,20)(2,6,8,10,12,16,20)(2,6,8,10,12,18)(2,6,8,10,12,18,20)(2,6,8,10,12,20)(2,6,8,10,14)(2,6,8,10,14,16)(2,6,8,10,14,16,18)(2,6,8,10,14,16,18,20)(2,6,8,10,14,16,20)(2,6,8,10,14,18)(2,6,8,10,14,18,20)(2,6,8,10,14,20)(2,6,8,10,16)(2,6,8,10,16,18)(2,6,8,10,16,18,20)(2,6,8,10,16,20)(2,6,8,10,18)(2,6,8,10,18,20)(2,6,8,10,20)(2,6,8,12)(2,6,8,12,14)(2,6,8,12,14,16)(2,6,8,12,14,16,18)(2,6,8,12,14,16,18,20)(2,6,8,12,14,16,20)(2,6,8,12,14,18)(2,6,8,12,14,18,20)(2,6,8,12,14,20)(2,6,8,12,16)(2,6,8,12,16,18)(2,6,8,12,16,18,20)(2,6,8,12,16,20)(2,6,8,12,18)(2,6,8,12,18,20)(2,6,8,12,20)(2,6,8,14)(2,6,8,14,16)(2,6,8,14,16,18)(2,6,8,14,16,18,20)(2,6,8,14,16,20)(2,6,8,14,18)(2,6,8,14,18,20)(2,6,8,14,20)(2,6,8,16)(2,6,8,16,18)(2,6,8,16,18,20)(2,6,8,16,20)(2,6,8,18)(2,6,8,18,20)(2,6,8,20)(2,6,10)(2,6,10,12)(2,6,10,12,14)(2,6,10,12,14,16)(2,6,10,12,14,16,18)(2,6,10,12,14,16,18,20)(2,6,10,12,14,16,20)(2,6,10,12,14,18)(2,6,10,12,14,18,20)(2,6,10,12,14,20)(2,6,10,12,16)(2,6,10,12,16,18)(2,6,10,12,16,18,20)(2,6,10,12,16,20)(2,6,10,12,18)(2,6,10,12,18,20)(2,6,10,12,20)(2,6,10,14)(2,6,10,14,16)(2,6,10,14,16,18)(2,6,10,14,16,18,20)(2,6,10,14,16,20)(2,6,10,14,18)(2,6,10,14,18,20)(2,6,10,14,20)(2,6,10,16)(2,6,10,16,18)(2,6,10,16,18,20)(2,6,10,16,20)(2,6,10,18)(2,6,10,18,20)(2,6,10,20)(2,6,12)(2,6,12,14)(2,6,12,14,16)(2,6,12,14,16,18)(2,6,12,14,16,18,20)(2,6,12,14,16,20)(2,6,12,14,18)(2,6,12,14,18,20)(2,6,12,14,20)(2,6,12,16)(2,6,12,16,18)(2,6,12,16,18,20)(2,6,12,16,20)(2,6,12,18)(2,6,12,18,20)(2,6,12,20)(2,6,14)(2,6,14,16)(2,6,14,16,18)(2,6,14,16,18,20)(2,6,14,16,20)(2,6,14,18)(2,6,14,18,20)(2,6,14,20)(2,6,16)(2,6,16,18)(2,6,16,18,20)(2,6,16,20)(2,6,18)(2,6,18,20)(2,6,20)(2,8)(2,8,10)(2,8,10,12)(2,8,10,12,14)(2,8,10,12,14,16)(2,8,10,12,14,16,18)(2,8,10,12,14,16,18,20)(2,8,10,12,14,16,20)(2,8,10,12,14,18)(2,8,10,12,14,18,20)(2,8,10,12,14,20)(2,8,10,12,16)(2,8,10,12,16,18)(2,8,10,12,16,18,20)(2,8,10,12,16,20)(2,8,10,12,18)(2,8,10,12,18,20)(2,8,10,12,20)(2,8,10,14)(2,8,10,14,16)(2,8,10,14,16,18)(2,8,10,14,16,18,20)(2,8,10,14,16,20)(2,8,10,14,18)(2,8,10,14,18,20)(2,8,10,14,20)(2,8,10,16)(2,8,10,16,18)(2,8,10,16,18,20)(2,8,10,16,20)(2,8,10,18)(2,8,10,18,20)(2,8,10,20)(2,8,12)(2,8,12,14)(2,8,12,14,16)(2,8,12,14,16,18)(2,8,12,14,16,18,20)(2,8,12,14,16,20)(2,8,12,14,18)(2,8,12,14,18,20)(2,8,12,14,20)(2,8,12,16)(2,8,12,16,18)(2,8,12,16,18,20)(2,8,12,16,20)(2,8,12,18)(2,8,12,18,20)(2,8,12,20)(2,8,14)(2,8,14,16)(2,8,14,16,18)(2,8,14,16,18,20)(2,8,14,16,20)(2,8,14,18)(2,8,14,18,20)(2,8,14,20)(2,8,16)(2,8,16,18)(2,8,16,18,20)(2,8,16,20)(2,8,18)(2,8,18,20)(2,8,20)(2,10)(2,10,12)(2,10,12,14)(2,10,12,14,16)(2,10,12,14,16,18)(2,10,12,14,16,18,20)(2,10,12,14,16,20)(2,10,12,14,18)(2,10,12,14,18,20)(2,10,12,14,20)(2,10,12,16)(2,10,12,16,18)(2,10,12,16,18,20)(2,10,12,16,20)(2,10,12,18)(2,10,12,18,20)(2,10,12,20)(2,10,14)(2,10,14,16)(2,10,14,16,18)(2,10,14,16,18,20)(2,10,14,16,20)(2,10,14,18)(2,10,14,18,20)(2,10,14,20)(2,10,16)(2,10,16,18)(2,10,16,18,20)(2,10,16,20)(2,10,18)(2,10,18,20)(2,10,20)(2,12)(2,12,14)(2,12,14,16)(2,12,14,16,18)(2,12,14,16,18,20)(2,12,14,16,20)(2,12,14,18)(2,12,14,18,20)(2,12,14,20)(2,12,16)(2,12,16,18)(2,12,16,18,20)(2,12,16,20)(2,12,18)(2,12,18,20)(2,12,20)(2,14)(2,14,16)(2,14,16,18)(2,14,16,18,20)(2,14,16,20)(2,14,18)(2,14,18,20)(2,14,20)(2,16)(2,16,18)(2,16,18,20)(2,16,20)(2,18)(2,18,20)(2,20)(4)(4,6)(4,6,8)(4,6,8,10)(4,6,8,10,12)(4,6,8,10,12,14)(4,6,8,10,12,14,16)(4,6,8,10,12,14,16,18)(4,6,8,10,12,14,16,18,20)(4,6,8,10,12,14,16,20)(4,6,8,10,12,14,18)(4,6,8,10,12,14,18,20)(4,6,8,10,12,14,20)(4,6,8,10,12,16)(4,6,8,10,12,16,18)(4,6,8,10,12,16,18,20)(4,6,8,10,12,16,20)(4,6,8,10,12,18)(4,6,8,10,12,18,20)(4,6,8,10,12,20)(4,6,8,10,14)(4,6,8,10,14,16)(4,6,8,10,14,16,18)(4,6,8,10,14,16,18,20)(4,6,8,10,14,16,20)(4,6,8,10,14,18)(4,6,8,10,14,18,20)(4,6,8,10,14,20)(4,6,8,10,16)(4,6,8,10,16,18)(4,6,8,10,16,18,20)(4,6,8,10,16,20)(4,6,8,10,18)(4,6,8,10,18,20)(4,6,8,10,20)(4,6,8,12)(4,6,8,12,14)(4,6,8,12,14,16)(4,6,8,12,14,16,18)(4,6,8,12,14,16,18,20)(4,6,8,12,14,16,20)(4,6,8,12,14,18)(4,6,8,12,14,18,20)(4,6,8,12,14,20)(4,6,8,12,16)(4,6,8,12,16,18)(4,6,8,12,16,18,20)(4,6,8,12,16,20)(4,6,8,12,18)(4,6,8,12,18,20)(4,6,8,12,20)(4,6,8,14)(4,6,8,14,16)(4,6,8,14,16,18)(4,6,8,14,16,18,20)(4,6,8,14,16,20)(4,6,8,14,18)(4,6,8,14,18,20)(4,6,8,14,20)(4,6,8,16)(4,6,8,16,18)(4,6,8,16,18,20)(4,6,8,16,20)(4,6,8,18)(4,6,8,18,20)(4,6,8,20)(4,6,10)(4,6,10,12)(4,6,10,12,14)(4,6,10,12,14,16)(4,6,10,12,14,16,18)(4,6,10,12,14,16,18,20)(4,6,10,12,14,16,20)(4,6,10,12,14,18)(4,6,10,12,14,18,20)(4,6,10,12,14,20)(4,6,10,12,16)(4,6,10,12,16,18)(4,6,10,12,16,18,20)(4,6,10,12,16,20)(4,6,10,12,18)(4,6,10,12,18,20)(4,6,10,12,20)(4,6,10,14)(4,6,10,14,16)(4,6,10,14,16,18)(4,6,10,14,16,18,20)(4,6,10,14,16,20)(4,6,10,14,18)(4,6,10,14,18,20)(4,6,10,14,20)(4,6,10,16)(4,6,10,16,18)(4,6,10,16,18,20)(4,6,10,16,20)(4,6,10,18)(4,6,10,18,20)(4,6,10,20)(4,6,12)(4,6,12,14)(4,6,12,14,16)(4,6,12,14,16,18)(4,6,12,14,16,18,20)(4,6,12,14,16,20)(4,6,12,14,18)(4,6,12,14,18,20)(4,6,12,14,20)(4,6,12,16)(4,6,12,16,18)(4,6,12,16,18,20)(4,6,12,16,20)(4,6,12,18)(4,6,12,18,20)(4,6,12,20)(4,6,14)(4,6,14,16)(4,6,14,16,18)(4,6,14,16,18,20)(4,6,14,16,20)(4,6,14,18)(4,6,14,18,20)(4,6,14,20)(4,6,16)(4,6,16,18)(4,6,16,18,20)(4,6,16,20)(4,6,18)(4,6,18,20)(4,6,20)(4,8)(4,8,10)(4,8,10,12)(4,8,10,12,14)(4,8,10,12,14,16)(4,8,10,12,14,16,18)(4,8,10,12,14,16,18,20)(4,8,10,12,14,16,20)(4,8,10,12,14,18)(4,8,10,12,14,18,20)(4,8,10,12,14,20)(4,8,10,12,16)(4,8,10,12,16,18)(4,8,10,12,16,18,20)(4,8,10,12,16,20)(4,8,10,12,18)(4,8,10,12,18,20)(4,8,10,12,20)(4,8,10,14)(4,8,10,14,16)(4,8,10,14,16,18)(4,8,10,14,16,18,20)(4,8,10,14,16,20)(4,8,10,14,18)(4,8,10,14,18,20)(4,8,10,14,20)(4,8,10,16)(4,8,10,16,18)(4,8,10,16,18,20)(4,8,10,16,20)(4,8,10,18)(4,8,10,18,20)(4,8,10,20)(4,8,12)(4,8,12,14)(4,8,12,14,16)(4,8,12,14,16,18)(4,8,12,14,16,18,20)(4,8,12,14,16,20)(4,8,12,14,18)(4,8,12,14,18,20)(4,8,12,14,20)(4,8,12,16)(4,8,12,16,18)(4,8,12,16,18,20)(4,8,12,16,20)(4,8,12,18)(4,8,12,18,20)(4,8,12,20)(4,8,14)(4,8,14,16)(4,8,14,16,18)(4,8,14,16,18,20)(4,8,14,16,20)(4,8,14,18)(4,8,14,18,20)(4,8,14,20)(4,8,16)(4,8,16,18)(4,8,16,18,20)(4,8,16,20)(4,8,18)(4,8,18,20)(4,8,20)(4,10)(4,10,12)(4,10,12,14)(4,10,12,14,16)(4,10,12,14,16,18)(4,10,12,14,16,18,20)(4,10,12,14,16,20)(4,10,12,14,18)(4,10,12,14,18,20)(4,10,12,14,20)(4,10,12,16)(4,10,12,16,18)(4,10,12,16,18,20)(4,10,12,16,20)(4,10,12,18)(4,10,12,18,20)(4,10,12,20)(4,10,14)(4,10,14,16)(4,10,14,16,18)(4,10,14,16,18,20)(4,10,14,16,20)(4,10,14,18)(4,10,14,18,20)(4,10,14,20)(4,10,16)(4,10,16,18)(4,10,16,18,20)(4,10,16,20)(4,10,18)(4,10,18,20)(4,10,20)(4,12)(4,12,14)(4,12,14,16)(4,12,14,16,18)(4,12,14,16,18,20)(4,12,14,16,20)(4,12,14,18)(4,12,14,18,20)(4,12,14,20)(4,12,16)(4,12,16,18)(4,12,16,18,20)(4,12,16,20)(4,12,18)(4,12,18,20)(4,12,20)(4,14)(4,14,16)(4,14,16,18)(4,14,16,18,20)(4,14,16,20)(4,14,18)(4,14,18,20)(4,14,20)(4,16)(4,16,18)(4,16,18,20)(4,16,20)(4,18)(4,18,20)(4,20)(6)(6,8)(6,8,10)(6,8,10,12)(6,8,10,12,14)(6,8,10,12,14,16)(6,8,10,12,14,16,18)(6,8,10,12,14,16,18,20)(6,8,10,12,14,16,20)(6,8,10,12,14,18)(6,8,10,12,14,18,20)(6,8,10,12,14,20)(6,8,10,12,16)(6,8,10,12,16,18)(6,8,10,12,16,18,20)(6,8,10,12,16,20)(6,8,10,12,18)(6,8,10,12,18,20)(6,8,10,12,20)(6,8,10,14)(6,8,10,14,16)(6,8,10,14,16,18)(6,8,10,14,16,18,20)(6,8,10,14,16,20)(6,8,10,14,18)(6,8,10,14,18,20)(6,8,10,14,20)(6,8,10,16)(6,8,10,16,18)(6,8,10,16,18,20)(6,8,10,16,20)(6,8,10,18)(6,8,10,18,20)(6,8,10,20)(6,8,12)(6,8,12,14)(6,8,12,14,16)(6,8,12,14,16,18)(6,8,12,14,16,18,20)(6,8,12,14,16,20)(6,8,12,14,18)(6,8,12,14,18,20)(6,8,12,14,20)(6,8,12,16)(6,8,12,16,18)(6,8,12,16,18,20)(6,8,12,16,20)(6,8,12,18)(6,8,12,18,20)(6,8,12,20)(6,8,14)(6,8,14,16)(6,8,14,16,18)(6,8,14,16,18,20)(6,8,14,16,20)(6,8,14,18)(6,8,14,18,20)(6,8,14,20)(6,8,16)(6,8,16,18)(6,8,16,18,20)(6,8,16,20)(6,8,18)(6,8,18,20)(6,8,20)(6,10)(6,10,12)(6,10,12,14)(6,10,12,14,16)(6,10,12,14,16,18)(6,10,12,14,16,18,20)(6,10,12,14,16,20)(6,10,12,14,18)(6,10,12,14,18,20)(6,10,12,14,20)(6,10,12,16)(6,10,12,16,18)(6,10,12,16,18,20)(6,10,12,16,20)(6,10,12,18)(6,10,12,18,20)(6,10,12,20)(6,10,14)(6,10,14,16)(6,10,14,16,18)(6,10,14,16,18,20)(6,10,14,16,20)(6,10,14,18)(6,10,14,18,20)(6,10,14,20)(6,10,16)(6,10,16,18)(6,10,16,18,20)(6,10,16,20)(6,10,18)(6,10,18,20)(6,10,20)(6,12)(6,12,14)(6,12,14,16)(6,12,14,16,18)(6,12,14,16,18,20)(6,12,14,16,20)(6,12,14,18)(6,12,14,18,20)(6,12,14,20)(6,12,16)(6,12,16,18)(6,12,16,18,20)(6,12,16,20)(6,12,18)(6,12,18,20)(6,12,20)(6,14)(6,14,16)(6,14,16,18)(6,14,16,18,20)(6,14,16,20)(6,14,18)(6,14,18,20)(6,14,20)(6,16)(6,16,18)(6,16,18,20)(6,16,20)(6,18)(6,18,20)(6,20)(8)(8,10)(8,10,12)(8,10,12,14)(8,10,12,14,16)(8,10,12,14,16,18)(8,10,12,14,16,18,20)(8,10,12,14,16,20)(8,10,12,14,18)(8,10,12,14,18,20)(8,10,12,14,20)(8,10,12,16)(8,10,12,16,18)(8,10,12,16,18,20)(8,10,12,16,20)(8,10,12,18)(8,10,12,18,20)(8,10,12,20)(8,10,14)(8,10,14,16)(8,10,14,16,18)(8,10,14,16,18,20)(8,10,14,16,20)(8,10,14,18)(8,10,14,18,20)(8,10,14,20)(8,10,16)(8,10,16,18)(8,10,16,18,20)(8,10,16,20)(8,10,18)(8,10,18,20)(8,10,20)(8,12)(8,12,14)(8,12,14,16)(8,12,14,16,18)(8,12,14,16,18,20)(8,12,14,16,20)(8,12,14,18)(8,12,14,18,20)(8,12,14,20)(8,12,16)(8,12,16,18)(8,12,16,18,20)(8,12,16,20)(8,12,18)(8,12,18,20)(8,12,20)(8,14)(8,14,16)(8,14,16,18)(8,14,16,18,20)(8,14,16,20)(8,14,18)(8,14,18,20)(8,14,20)(8,16)(8,16,18)(8,16,18,20)(8,16,20)(8,18)(8,18,20)(8,20)(10)(10,12)(10,12,14)(10,12,14,16)(10,12,14,16,18)(10,12,14,16,18,20)(10,12,14,16,20)(10,12,14,18)(10,12,14,18,20)(10,12,14,20)(10,12,16)(10,12,16,18)(10,12,16,18,20)(10,12,16,20)(10,12,18)(10,12,18,20)(10,12,20)(10,14)(10,14,16)(10,14,16,18)(10,14,16,18,20)(10,14,16,20)(10,14,18)(10,14,18,20)(10,14,20)(10,16)(10,16,18)(10,16,18,20)(10,16,20)(10,18)(10,18,20)(10,20)(12)(12,14)(12,14,16)(12,14,16,18)(12,14,16,18,20)(12,14,16,20)(12,14,18)(12,14,18,20)(12,14,20)(12,16)(12,16,18)(12,16,18,20)(12,16,20)(12,18)(12,18,20)(12,20)(14)(14,16)(14,16,18)(14,16,18,20)(14,16,20)(14,18)(14,18,20)(14,20)(16)(16,18)(16,18,20)(16,20)(18)(18,20)(20)()
Since number of elements in the set can go upto 10^5 and hence the size of the set will go upto 2^(10^5) which is huge. You can just either print it or if you want to store it , store it in a file.
It is not possible, as you pointed out yourself power set contains pow(2, size) no of elements. You need to print the entire set that can only be done by generating the set using backtracking, there is nothing better.
To find sum of all subsets of a given set is however a simpler problem.
If the no of elements is n, then each element in the array occurs 2^(n-1) times in the power set.
Pseudo code :
int sum = 0;
for(int i = 0;i < n;i++){
sum += ( set[i] * ( 1 << (n-1) ) ); //pow(2, n-1) == 1 << (n-1)
}
cout << sum << endl;
You would need a Big Integer Library for larger values of n.
Related
Minimum difference between the highest and the smallest value of mines distributed
Given Question: Given n companies and m oil mines with values, design an algorithm to distribute the sites among the companies in a fair manner, where the company getting the highest total value of its assigned sites and the one getting the lowest total value is minimal. Your algorithm should output this minimum difference. Note that oil mines sites assigned to each company should be adjacent to each other, and that the number of mines m is always bigger than or equal to the number of companies n Sample Input: Input : n = 3, site values = [6, 10, 13, 2] Output : 9 → for the assignment of [6] to company #1, [10] to company #2, and [13, 2] to company #3, making the minimum difference (13+2) - 6 = 9 My attempt at solving: Add all previous elements in array, so the new array becomes [6, 16, 29, 31]. Then, I form all possible solution arrays which are: note: 31 stays constant because it is the largest and I need to subtract the largest from the smallest 31, 29, 16 31, 29, 6 31, 16, 6 Then, I subtract all previous elements in array, so the new arrays become 2, 13, 16 2, 23, 6 15, 10, 6 Then I subtract the highest number from the lowest number in each array which would be: 16 - 2 = 14 23 - 2 = 21 15 - 6 = 9 // **answer** I would pick the smallest difference which is 9 My question: (1) Is there an easier way to solve this? As this seems like it a bit too complex and I'm just overthinking things. (2) How would I go about implementing generating all the possible combinations to the array? Should I use permutations? Recursion? This is the part that I'm stuck on the most, generating all possible solutions where 31 (in the example stays the same) and I select only 2 out of the 3 other elements in the array. void Func (int n, int m, int prosValues[], int solArray[], bool summed) { if (!summed) { for (int i = 1; i < m; i++) { prosValues[i] = prosValues[i] + prosValues[i-1]; } solArray[0] = prosValues[m-1]; summed = true; } // generate all possible combinations as shown in example }
Interesting problem! I chose a different approach to solve this. I don't know, if it is more elegant, but I spend some time thinking about it and wanted to share my solution at least. I make the following convention for the site assignment: The indices in the site array describe the start index for site values, from which the site values are assigned to that site. Let's make it clearer using two examples. values = {2,6,3,8,2,1} sites1 = {0,1,2} sites2 = {0,2,5} The two site distributions site1 and site2 will assign the site values as follows: distribution for site1: 0: 2 1: 6 2: 3, 8, 2, 1 distribution for site2: 0: 2, 6 1: 3, 8 2: 2, 1 This way we can iterate through all combinations by shifting the indices in sites up. In the example for 6 site values, we would get: {0,1,2} {0,1,3} {0,1,4} {0,1,5} {0,2,3} {0,2,4} {0,2,5} {0,3,4} {0,3,5} {0,4,5} {1,2,3} {1,3,4} {1,3,5} . . . {3,4,5} For all these site distributions we sum up the site values for each site, calculate the maximum difference and pick the distribution with the smallest difference. Putting it all together, here is the code I came up with: #include <iostream> #include <algorithm> int calc_diff(int m, int n, int* values, int* sites) { // stores the sum of values for each site int *result = new int[n] {0}; // iterate through all site values for (int j = 0; j < m; j++) { // find the correct site index to which the value is assigned int index = 0; for (int i = n-1; i >= 0; i--) { if (j >= sites[i]) { index = i; break; } } // sum up the site vaues result[index] += values[j]; // debug print // std::cout << index << ":\t" << result[index] << std::endl; } // print the site results std::cout << "result:\t"; for (int i = 0; i < n; i++) std::cout << result[i] << "\t"; // get the highest difference auto min = std::min_element(result, result+n); auto max = std::max_element(result, result+n); int diff = *max - *min; delete[] result; return diff; } int main() { int n = 3; int m = 6; auto values = new int[m] {2,6,3,8,2,1}; auto sites = new int[n] {0,1,2}; // start index of the first site int start_index = 0; // current best difference (some really high number) int max = 100000000; // the current best solution auto best = new int[n]; bool end = false; while(!end) { std::cout << "sites:\t"; for (int i = 0; i < n; i++) std::cout << sites[i] << "\t"; std::cout << std::endl; // calculate the maximal difference of the current site distribution auto diff = calc_diff(m, n, values, sites); std::cout << "\nmax diff:\t" << diff << std::endl << std::endl; // if we find a better solution than the current best, we store it as new best solution if (diff < max) { max = diff; memcpy(best, sites, n*sizeof(int)); } // calculate new site distribution int index = 0; for (int i = n-1; i >= 0; i--) { // get the current index index = sites[i]; // can we still move the index one position up? // the index of the last site should not exceed m-1 // the index of all other sites should be less than the index of the next site if ((i == n-1 && index < m-1) || (i < n-1 && i > 0 && index < sites[i+1]-1)) { // increase the index of the current site sites[i]++; break; } // all site index have moved to maximum position? // (we iterated through all indices (so i=0) and moved none of them) if (i == 0) { // increase the start index of the first site start_index++; // reset the indices by starting from the current start_index for (int j = 1; j < n; j++) { sites[j] = start_index + j; // if we exceed the numbers of site values, we can stop the loop if (sites[j] >= m) end = true; } } } } // print best soluition std::cout << "Best distribution: "; for (int i = 0; i < n; i++) std::cout << best[i] << " "; delete[] sites; delete[] values; delete[] best; }
How to find all possible combinations of adding two variables, each attached to a multiplier, summing up to a given number (cin)?
In my situation, a lorry has a capacity of 30, while a van has a capacity of 10. I need to find the number of vans/lorries needed to transport a given amount of cargo, say 100. I need to find all possible combinations of lorries + vans that will add up to 100. The basic math calculation would be: (30*lorrycount) + (10*vancount) = n, where n is number of cargo. Output Example Cargo to be transported: 100 Number of Lorry: 0 3 2 1 Number of Van: 10 1 4 7 For example, the 2nd combination is 3 lorries, 1 van. Considering that lorries have capacity = 30 and van capacity = 10, (30*3)+(10*1) = 100 = n. For now, we only have this code, which finds literally all combinations of numbers that add up to given number n, without considering the formula given above. #include <iostream> #include <vector> using namespace std; void findCombinationsUtil(int arr[], int index, int num, int reducedNum) { int lorry_capacity = 30; int van_capacity = 10; // Base condition if (reducedNum < 0) return; // If combination is found, print it if (reducedNum == 0) { for (int i = 0; i < index; i++) cout << arr[i] << " "; cout << endl; return; } // Find the previous number stored in arr[] // It helps in maintaining increasing order int prev = (index == 0) ? 1 : arr[index - 1]; // note loop starts from previous number // i.e. at array location index - 1 for (int k = prev; k <= num; k++) { // next element of array is k arr[index] = k; // call recursively with reduced number findCombinationsUtil(arr, index + 1, num, reducedNum - k); } } void findCombinations(int n) { // array to store the combinations // It can contain max n elements std::vector<int> arr(n); // allocate n elements //find all combinations findCombinationsUtil(&*arr.begin(), 0, n, n); } int main() { int n; cout << "Enter the amount of cargo you want to transport: "; cin >> n; cout << endl; //const int n = 10; findCombinations(n); return 0; } Do let me know if you have any solution to this, thank you.
An iterative way of finding all possible combinations #include <iostream> #include <vector> int main() { int cw = 100; int lw = 30, vw = 10; int maxl = cw/lw; // maximum no. of lorries that can be there std::vector<std::pair<int,int>> solutions; // for the inclusive range of 0 to maxl, find the corresponding no. of vans for each variant of no of lorries for(int l = 0; l<= maxl; ++l){ bool is_integer = (cw - l*lw)%vw == 0; // only if this is true, then there is an integer which satisfies for given l if(is_integer){ int v = (cw-l*lw)/vw; // no of vans solutions.push_back(std::make_pair(l,v)); } } for( auto& solution : solutions){ std::cout<<solution.first<<" lorries and "<< solution.second<<" vans" <<std::endl; } return 0; }
We will create a recursive function that walks a global capacities array left to right and tries to load cargo into the various vehicle types. We keep track of how much we still have to load and pass that on to any recursive call. If we reach the end of the array, we produce a solution only if the remaining cargo is zero. std::vector<int> capacities = { 30, 10 }; using Solution = std::vector<int>; using Solutions = std::vector<Solution>; void tryLoad(int remaining_cargo, int vehicle_index, Solution so_far, std::back_insert_iterator<Solutions>& solutions) { if (vehicle_index == capacities.size()) { if (remaining_cargo == 0) // we have a solution *solutions++ = so_far; return; } int capacity = capacities[vehicle_index]; for (int vehicles = 0; vehicles <= remaining_cargo / capacity; vehicles++) { Solution new_solution = so_far; new_solution.push_back(vehicles); tryLoad(remaining_cargo - vehicles * capacity, vehicle_index + 1, new_solution, solutions); } } Calling this as follows should produce the desired output in all_solutions: Solutions all_solutions; auto inserter = std::back_inserter(all_solutions) tryLoad(100, 0, Solution{}, inserter);
Divide elements of a sorted array into least number of groups such that difference between the elements of the new array is less than or equal to 1
How to divide elements in an array into a minimum number of arrays such that the difference between the values of elements of each of the formed arrays does not differ by more than 1? Let's say that we have an array: [4, 6, 8, 9, 10, 11, 14, 16, 17]. The array elements are sorted. I want to divide the elements of the array into a minimum number of array(s) such that each of the elements in the resulting arrays do not differ by more than 1. In this case, the groupings would be: [4], [6], [8, 9, 10, 11], [14], [16, 17]. So there would be a total of 5 groups. How can I write a program for the same? Or you can suggest algorithms as well. I tried the naive approach: Obtain the difference between consecutive elements of the array and if the difference is less than (or equal to) 1, I add those elements to a new vector. However this method is very unoptimized and straight up fails to show any results for a large number of inputs. Actual code implementation: #include<cstdio> #include<iostream> #include<vector> using namespace std; int main() { int num = 0, buff = 0, min_groups = 1; // min_groups should start from 1 to take into account the grouping of the starting array element(s) cout << "Enter the number of elements in the array: " << endl; cin >> num; vector<int> ungrouped; cout << "Please enter the elements of the array: " << endl; for (int i = 0; i < num; i++) { cin >> buff; ungrouped.push_back(buff); } for (int i = 1; i < ungrouped.size(); i++) { if ((ungrouped[i] - ungrouped[i - 1]) > 1) { min_groups++; } } cout << "The elements of entered vector can be split into " << min_groups << " groups." << endl; return 0; }
Inspired by Faruk's answer, if the values are constrained to be distinct integers, there is a possibly sublinear method. Indeed, if the difference between two values equals the difference between their indexes, they are guaranteed to belong to the same group and there is no need to look at the intermediate values. You have to organize a recursive traversal of the array, in preorder. Before subdividing a subarray, you compare the difference of indexes of the first and last element to the difference of values, and only subdivide in case of a mismatch. As you work in preorder, this will allow you to emit pieces of the groups in consecutive order, as well as detect to the gaps. Some care has to be taken to merge the pieces of the groups. The worst case will remain linear, because the recursive traversal can degenerate to a linear traversal (but not worse than that). The best case can be better. In particular, if the array holds a single group, it will be found in time O(1). If I am right, for every group of length between 2^n and 2^(n+1), you will spare at least 2^(n-1) tests. (In fact, it should be possible to estimate an output-sensitive complexity, equal to the array length minus a fraction of the lengths of all groups, or similar.) Alternatively, you can work in a non-recursive way, by means of exponential search: from the beginning of a group, you start with a unit step and double the step every time, until you detect a gap (difference in values too large); then you restart with a unit step. Here again, for large groups you will skip a significant number of elements. Anyway, the best case can only be O(Log(N)).
I would suggest encoding subsets into an offset array defined as follows: Elements for set #i are defined for indices j such that offset[i] <= j < offset[i+1] The number of subsets is offset.size() - 1 This only requires one memory allocation. Here is a complete implementation: #include <cassert> #include <iostream> #include <vector> std::vector<std::size_t> split(const std::vector<int>& to_split, const int max_dist = 1) { const std::size_t to_split_size = to_split.size(); std::vector<std::size_t> offset(to_split_size + 1); offset[0] = 0; size_t offset_idx = 1; for (std::size_t i = 1; i < to_split_size; i++) { const int dist = to_split[i] - to_split[i - 1]; assert(dist >= 0); // we assumed sorted input if (dist > max_dist) { offset[offset_idx] = i; ++offset_idx; } } offset[offset_idx] = to_split_size; offset.resize(offset_idx + 1); return offset; } void print_partition(const std::vector<int>& to_split, const std::vector<std::size_t>& offset) { const std::size_t offset_size = offset.size(); std::cout << "\nwe found " << offset_size-1 << " sets"; for (std::size_t i = 0; i + 1 < offset_size; i++) { std::cout << "\n"; for (std::size_t j = offset[i]; j < offset[i + 1]; j++) { std::cout << to_split[j] << " "; } } } int main() { std::vector<int> to_split{4, 6, 8, 9, 10, 11, 14, 16, 17}; std::vector<std::size_t> offset = split(to_split); print_partition(to_split, offset); } which prints: we found 5 sets 4 6 8 9 10 11 14 16 17
Iterate through the array. Whenever the difference between 2 consecutive element is greater than 1, add 1 to your answer variable. ` int getPartitionNumber(int arr[]) { //let n be the size of the array; int result = 1; for(int i=1; i<n; i++) { if(arr[i]-arr[i-1] > 1) result++; } return result; } `
And because it is always nice to see more ideas and select the one that suites you best, here the straight forward 6 line solution. Yes, it is also O(n). But I am not sure, if the overhead for other methods makes it faster. Please see: #include <iostream> #include <string> #include <algorithm> #include <vector> #include <iterator> using Data = std::vector<int>; using Partition = std::vector<Data>; Data testData{ 4, 6, 8, 9, 10, 11, 14, 16, 17 }; int main(void) { // This is the resulting vector of vectors with the partitions std::vector<std::vector<int>> partition{}; // Iterating over source values for (Data::iterator i = testData.begin(); i != testData.end(); ++i) { // Check,if we need to add a new partition // Either, at the beginning or if diff > 1 // No underflow, becuase of boolean shortcut evaluation if ((i == testData.begin()) || ((*i) - (*(i-1)) > 1)) { // Create a new partition partition.emplace_back(Data()); } // And, store the value in the current partition partition.back().push_back(*i); } // Debug output: Copy all data to std::cout std::for_each(partition.begin(), partition.end(), [](const Data& d) {std::copy(d.begin(), d.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n'; }); return 0; } Maybe this could be a solution . . .
How do you say your approach is not optimized? If your is correct, then according to your approach, it takes O(n) time complexity. But you can use binary-search here which can optimize in average case. But in worst case this binary search can take more than O(n) time complexity. Here's a tips, As the array sorted so you will pick such a position whose difference is at most 1. Binary search can do this in simple way. int arr[] = [4, 6, 8, 9, 10, 11, 14, 16, 17]; int st = 0, ed = n-1; // n = size of the array. int partitions = 0; while(st <= ed) { int low = st, high = n-1; int pos = low; while(low <= high) { int mid = (low + high)/2; if((arr[mid] - arr[st]) <= 1) { pos = mid; low = mid + 1; } else { high = mid - 1; } } partitions++; st = pos + 1; } cout<< partitions <<endl; In average case, it is better than O(n). But in worst case (where the answer would be equal to n) it takes O(nlog(n)) time.
How to get the equilibrium index of an array in O(n)?
I have done a test in C++ asking for a function that returns one of the indices that splits the input vector in 2 parts having the same sum of the elements, for eg: for the vec = {1, 2, 3, 5, 4, -1, 1, 1, 2, -1}, it may return 3, because 1+2+3 = 6 = 4-1+1+1+2-1. So I have done the function that returns the correct answer: int func(const std::vector< int >& vecIn) { for (std::size_t p = 0; p < vecin.size(); p++) { if (std::accumulator(vecIn.begin(), vecIn.begin() + p, 0) == std::accumulator(vecIn.begin() + p + 1, vecIn.end(), 0)) return p; } return -1; } My problem was when the input was a very long vector containing just 1 (or -1), the return of the function was slow. So I have thought of starting the search for the wanted index from middle, and then go left and right. But the best approach I suppose is the one where the index is in the merge-sort algorithm order, that means: n/2, n/4, 3n/4, n/8, 3n/8, 5n/8, 7n/8... where n is the size of the vector. Is there a way to write this order in a formula, so I can apply it in my function? Thanks EDIT After some comments I have to mention that I had done the test a few days ago, so I have forgot to put and mention the part of no solution: it should return -1... I have updated also the question title.
Specifically for this problem, I would use the following algorithm: Compute the total sum of the vector. This gives two sums (empty vector, and full vector) for each element in order, move one element from full to empty, which means adding the value of next element from sum(full) to sum(empty). When the two sums are equal, you have found your index. This give a o(n) algorithm instead of o(n2)
You can solve the problem much faster without calling std::accumulator at each step: int func(const std::vector< int >& vecIn) { int s1 = 0; int s2 = std::accumulator(vecIn.begin(), vecIn.end(), 0); for (std::size_t p = 0; p < vecin.size(); p++) { if (s1 == s2) return p; s1 += vecIn[p]; s2 -= vecIn[p]; } } This is O(n). At each step, s1 will contain the sum of the first p elements, and s2 the sum of the rest. You can update both of them with an addition and a subtraction when moving to the next element. Since std::accumulator needs to iterate over the range you give it, your algorithm was O(n^2), which is why it was so slow for many elements.
To answer the actual question: Your sequence n/2, n/4, 3n/5, n/8, 3n/8 can be rewritten as 1*n/2 1*n/4 3*n/4 1*n/8 3*n/8 5*n/8 7*n/8 ... that is to say, the denominator runs from i=2 up in powers of 2, and the nominator runs from j=1 to i-1 in steps of 2. However, this is not what you need for your actual problem, because the example you give has n=10. Clearly you don't want n/4 there - your indices have to be integer. The best solution here is to recurse. Given a range [b,e], pick a value middle (b+e/2) and set the new ranges to [b, (b+e/2)-1] and [(b+e/2)=1, e]. Of course, specialize ranges with length 1 or 2.
Considering MSalters comments, I'm afraid another solution would be better. If you want to use less memory, maybe the selected answer is good enough, but to find the possibly multiple solutions you could use the following code: static const int arr[] = {5,-10,10,-10,10,1,1,1,1,1}; std::vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) ); // compute cumulative sum std::vector<int> cumulative_sum( vec.size() ); cumulative_sum[0] = vec[0]; for ( size_t i = 1; i < vec.size(); i++ ) { cumulative_sum[i] = cumulative_sum[i-1] + vec[i]; } const int complete_sum = cumulative_sum.back(); // find multiple solutions, if there are any const int complete_sum_half = complete_sum / 2; // suggesting this is valid... std::vector<int>::iterator it = cumulative_sum.begin(); std::vector<int> mid_indices; do { it = std::find( it, cumulative_sum.end(), complete_sum_half ); if ( it != cumulative_sum.end() ) { mid_indices.push_back( it - cumulative_sum.begin() ); ++it; } } while( it != cumulative_sum.end() ); for ( size_t i = 0; i < mid_indices.size(); i++ ) { std::cout << mid_indices[i] << std::endl; } std::cout << "Split behind these indices to obtain two equal halfs." << std::endl; This way, you get all the possible solutions. If there is no solution to split the vector in two equal halfs, mid_indices will be left empty. Again, you have to sum up each value only once. My proposal is this: static const int arr[] = {1,2,3,5,4,-1,1,1,2,-1}; std::vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) ); int idx1(0), idx2(vec.size()-1); int sum1(0), sum2(0); int idxMid = -1; do { // fast access without using the index each time. const int& val1 = vec[idx1]; const int& val2 = vec[idx2]; // Precompute the next (possible) sum values. const int nSum1 = sum1 + val1; const int nSum2 = sum2 + val2; // move the index considering the balanace between the // left and right sum. if ( sum1 - nSum2 < sum2 - nSum1 ) { sum1 = nSum1; idx1++; } else { sum2 = nSum2; idx2--; } if ( idx1 >= idx2 ){ idxMid = idx2; } } while( idxMid < 0 && idx2 >= 0 && idx1 < vec.size() ); std::cout << idxMid << std::endl; It does add every value only once no matter how many values. Such that it's complexity is only O(n) and not O(n^2). The code simply runs from left and right simultanuously and moves the indices further if it's side is lower than the other.
You want nth term of the series you mentioned. Then it would be: numerator: (n - 2^((int)(log2 n)) ) *2 + 1 denominator: 2^((int)(log2 n) + 1)
I came across the same question in Codility tests. There is a similar looking answer above (didn't pass some of the unit tests), but below code segment was successful in tests. #include <vector> #include <numeric> #include <iostream> using namespace std; // Returns -1 if equilibrium point is not found // use long long to support bigger ranges int FindEquilibriumPoint(vector<long> &values) { long long lower = 0; long long upper = std::accumulate(values.begin(), values.end(), 0); for (std::size_t i = 0; i < values.size(); i++) { upper -= values[i]; if (lower == upper) { return i; } lower += values[i]; } return -1; } int main() { vector<long> v = {-1, 3, -4, 5, 1, -6, 2, 1}; cout << "Equilibrium Point:" << FindEquilibriumPoint(v) << endl; return 0; } Output Equilibrium Point:1
Here it is the algorithm in Javascript: function equi(arr){ var N = arr.length; if (N == 0){ return -1}; var suma = 0; for (var i=0; i<N; i++){ suma += arr[i]; } var suma_iz = 0; for(i=0; i<N; i++){ var suma_de = suma - suma_iz - arr[i]; if (suma_iz == suma_de){ return i}; suma_iz += arr[i]; } return -1; } As you see this code satisfy the condition of O(n)
How to produce random numbers so that their sum is equal to given number?
I want to produce X random numbers, each from the interval <0; Y> (given Y as a maximum of each number), but there is restriction that the sum of these numbers must be equal to Z. Example: 5 Randoms numbers, each max 6 and the sum must be equal to 14, e.g: 0, 2, 6, 4, 2 Is there already a C/C++ function that could do something like that? Personally I couldn't come up with more than some ugly if-else-constucts.
Since you don't need the generated sequence to be uniform, this could be one of the possible solutions: #include <iostream> #include <vector> #include <cstdlib> int irand(int min, int max) { return ((double)rand() / ((double)RAND_MAX + 1.0)) * (max - min + 1) + min; } int main() { int COUNT = 5, // X MAX_VAL = 6, // Y MAX_SUM = 14; // Z std::vector<int> buckets(COUNT, 0); srand(time(0)); int remaining = MAX_SUM; while (remaining > 0) { int rndBucketIdx = irand(0, COUNT-1); if (buckets[rndBucketIdx] == MAX_VAL) continue; // this bucket is already full buckets[rndBucketIdx]++; remaining--; } std::cout << "Printing sequence: "; for (size_t i = 0; i < COUNT; ++i) std::cout << buckets[i] << ' '; } which just simply divides the total sum to bunch of buckets until it's gone :) Example of output: Printing sequence: 4 4 1 0 5
NOTE: this solution was written when the question specified a "MAX SUM" parameter, implying a sum of less than that amount was equally acceptable. The question's now been edited based on the OP's comment that they meant the cumulative sum must actually hit that target. I'm not going to update this answer, but clearly it could trivially discard lesser totals at the last level of recursion. This solution does a one-time population of a vector<vector<int>> with all the possible combinations of numbers solving the input criterion, then each time a new solution is wanted it picks one of those at random and shuffles the numbers into a random order (thereby picking a permutation of the combination). It's a bit heavy weight - perhaps not suitable for the actual use that you mentioned after I'd started writing it ;-P - but it produces an even-weighted distribution, and you can easily do things like guarantee a combination won't be returned again until all other combinations have been returned (with a supporting shuffled vector of indices into the combinations). #include <iostream> #include <vector> #include <algorithm> using std::min; using std::max; using std::vector; // print solutions... void p(const vector<vector<int>>& vvi) { for (int i = 0; i < vvi.size(); ++i) { for (int j = 0; j < vvi[i].size(); ++j) std::cout << vvi[i][j] << ' '; std::cout << '\n'; } } // populate results with solutions... void f(vector<vector<int>>& results, int n, int max_each, int max_total) { if (n == 0) return; if (results.size() == 0) { for (int i = 0; i <= min(max_each, max_total); ++i) results.push_back(vector<int>(2, i)); f(results, n - 1, max_each, max_total); return; } vector<vector<int>> new_results; for (int r = 0; r < results.size(); ++r) { int previous = *(results[r].rbegin() + 1); int current_total = results[r].back(); int remaining = max_total - current_total; for (int i = 0; i <= min(previous,min(max_each, remaining)); ++i) { vector<int> v = results[r]; v.back() = i; v.push_back(current_total + i); new_results.push_back(v); } } results = new_results; f(results, n - 1, max_each, max_total); } const vector<int>& once(vector<vector<int>>& solutions) { int which = std::rand() % solutions.size(); vector<int>& v = solutions[which]; std::random_shuffle(v.begin(), v.end() - 1); return v; } int main() { vector<vector<int>> solutions; f(solutions, 5, 6, 14); std::cout << "All solution combinations...\n"; p(solutions); std::cout << "------------------\n"; std::cout << "A few sample permutations...\n"; for (int n = 1; n <= 100; ++n) { const vector<int>& o = once(solutions); for (int i = 0; i < o.size() - 1; ++i) std::cout << o[i] << ' '; std::cout << '\n'; } }
#include<iostream> #include <cstdlib> //rand () using namespace std; void main() { int random ,x=5; int max , totalMax=0 , sum=0; cout<<"Enter the total maximum number : "; cin>>totalMax; cout<<"Enter the maximum number: "; cin>>max; srand(0); for( int i=0; i<x ; i++) { random=rand()%max+1; //range from 0 to max sum+=random; if(sum>=totalMax) { sum-=random; i--; } else cout<<random<<' '; } cout<<endl<<"Reached total maximum number "<<totalMax<<endl; } I wrote this simple code I tested it using totalMax=14 and max=3 and it worked with me hope it's what you asked for
LiHo's answer looks pretty similar to my second suggestion, so I'll leave that, but here's an example of the first. It could probably be improved, but it shouldn't have any tragic bugs. Here's a live sample. #include <algorithm> #include <array> #include <random> std::random_device rd; std::mt19937 gen(rd()); constexpr int MAX = 14; constexpr int LINES = 5; int sum{}; int maxNum = 6; int minNum{}; std::array<int, LINES> nums; for (int i = 0; i < LINES; ++i) { maxNum = std::min(maxNum, MAX - sum); // e.g., after 0 0, min is 2 because only 12/14 can be filled after int maxAfterThis = maxNum * (LINES - i - 1); minNum = std::min(maxNum, std::max(minNum, MAX - sum - maxAfterThis)); std::uniform_int_distribution<> dist(minNum, maxNum); int num = dist(gen); nums[i] = num; sum += num; } std::shuffle(std::begin(nums), std::end(nums), gen); Creating that ditribution every time could potentially slow it down (I don't know), but the range has to go in the constructor, and I'm not one to say how well distributed these numbers are. However, the logic is pretty simple. Aside from that, it uses the nice, shiny C++11 <random> header. We just make sure no remaining number goes over MAX (14) and that MAX is reached by the end. minNum is the odd part, and that's due to how it progresses. It starts at zero and works its way up as needed (the second part to std::max is figuring out what would be needed if we got 6s for the rest), but we can't let it surpass maxNum. I'm open to a simpler method of calculating minNum if it exists.
Since you know how many numbers you need, generate them from the given distribution but without further conditions, store them, compute the actual sum, and scale them all up/down to get the desired sum.