Iterate over m^n combinations with nested loops [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have an array y of dimension n, every dimension has m entries.
How do I iterate over all combinations of indices using nested for loops?
I'd like to get all possible combinations of sums like shown in this code:
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j) {
...
for (int k = 0; k < m; ++k) {
z = x[0] + y[i]*x[1] + y[j]*x[2] + ... + y[k]*x[n];
}
}
}
If this is not possible using for loops, how else can it be achieved?

Here's a solution to the problem, probably not the optimal one, but illustrates the idea. Since you need to index y with as many indices at a time as there are y's, you need an array. The array's indices will be incremented each iteration, starting at the 0th index. When the 0th index reaches m, we carry over a 1, just like normal addition. When the integer at that next index reaches m, we carry over a 1 to the next index. When all of the indices went from 0 through m - 1, we know we're done. Test it in the browser if you wish.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<int> y = { 1, 2, 3 };
std::vector<int> x = { 0, 1, 2, 3 };
std::vector<int> indices = { 0, 0, 0 };
int m = y.size();
int sum = 0;
int index_to_increment_next = 0;
while (index_to_increment_next < m)
{
// sum up at current indices
sum += x[0];
for (int i = 0; i < m; i++)
{
sum += x[i + 1] * y[indices[i]];
}
int j;
for (j = 0; j < m; j++)
{
if (indices[j] < m - 1)
{
// increment indices
indices[j]++;
break;
}
// when the index reaches m, reset it to 0
// and try to increment the next one
indices[j] = 0;
}
// on the last iteration, this will be equal to m
// and all of the indices will be reset back to 0
index_to_increment_next = j;
}
std::cout << sum;
}
Update
I need a separate sum for every possible combination z = x[0] + y[i]*x[1] + y[j]*x[2] + ... + y[k]*x[n] where i,j,...k are n counters and take on values from 0 to m.
Just save the individual sums on each iteration and store them in e.g. a vector. See the code.
// declare above the while
std::vector<int> sums;
// ...
int sum = x[0];
for (int i = 0; i < m; i++)
{
sum += x[i + 1] * y[indices[i]];
}
sums.push_back(sum);

If I understand your problem correctly, then as Daniyal Shaikh said above in a comment
You can use recursion instead. it can prove to be a better alternate
An easy implementation of n for-loops is:
(n_counter and z are globals)
int n_counter = 0; // which is the 1,2,3 of your y[i]*x[**1**]
int z = x[0]; // all possible combinations of sums at every iteration
void recursion(int n, int m){
n_counter++;
for(int i=0 ; i<m ; i++){
z += y[i]*x[n_counter];
}
if(n_counter<=n){ // go deeper n times, which is equal to n for-loops
recursion(n, m);
}
return;
}
Every time we get deeper in the recursion, n_counter will increase because we need the number that increases.
For example with number 2: ".. + y[j]*x[2] + ..".
Lastly, all you have to do is to print z.

Related

C++ sort ascending non-zero values

I'm a bit rusted with c++ and after one day of thinking I coulnd't come out with an efficient way of computing this problem.
Suppose I have an array of 5 float values
lints[5]={0, 0.5, 3, 0, 0.6};
I would like to introduce a new array:
ranks[5] that contains the ascending rank of the non-0 values of the array lints.
in this case the answer would read
ranks[1]=0;
ranks[2]=1;
ranks[3]=3;
ranks[4]=0;
ranks[5]=2;
In this example the 0 values returns rank 0 but they're not relevant since i only need the rank of positive values.
Thanks in advance
edit:
Thanks to everybody for help, this is what I found suiting my needs in case you have the same task :)
double lengths[5], ranks[5];
double temp;
int i,j;
lengths[0] = 2,lengths[1] = 0,lengths[2] = 1,lengths[3] = 0,lengths[4] = 4;
ranks[0] = 1, ranks[1] = 2, ranks[2] = 3, ranks[3] = 4, ranks[4] = 5;
for(i=0;i<4;i++){
for(j=0;j<4-i;j++){
if((lengths[j]>lengths[j+1] && lengths[j+1]) || lengths[j]==0){
// swap lenghts
temp=lengths[j];
lengths[j]=lengths[j+1];
lengths[j+1]=temp;
// swap ranks
temp=ranks[j];
ranks[j]=ranks[j+1];
ranks[j+1]=temp;
}
}
}
cheers.
You can use any sorting algorithm with a simple addition. When swapping 2 values you can swap index values too.
Create index values for initial indexes
ranks[5] = {1,2,3,4,5}; //or 0,1,2,3,4
for (int i = 0 ; i < 5 ; i++){
for(int j = 0 ; j < 5 ; j++){
//if array[i] < array[j]
//swap array[i] - array[j]
//swap ranks[i] - ranks[j]
}
}
As #cokceken said (I know answers shouldn't refer to other answers but I'm not a high enough Stack Overflow rank to comment on answers :/ ), use any simple sorting algorithm, and simply add in your own functionality for any special cases, such as values of 0 or negative values in your example.
For example, assuming you don't actually want to sort the original array and just create a new array that links indices in the array to their sorted rank,
array[arraySize] = // insert array here;
ranks[arraySize];
for (int i = 0; i < arraySize; i++){
int indexRank = 0;
for (int j = 0; j < arraySize; j++){
if (array[j] < array[i]){
indexRank++;
}
}
if (array[i] <= 0) {
ranks[i] = -1 // or whatever implementation you want here
} else {
ranks[i] = indexRank;
}
}
(note that arraySize must be a value and not a variable, since C++ does not let you statically define an array with a variable size)
I found this was easier if you keep separate values for the value, original position and the rank in a class:
#include <vector>
#include <iostream>
#include <algorithm>
struct Item {
float value;
int original_position;
int rank;
};
int main() {
float lints[5] = {0, 0.5, 3, 0, 0.6};
std::vector<Item> items{};
int index{};
for(auto i : lints)
items.push_back(Item{i,index++,0}); // assign index to original_position
std::sort(items.begin(), items.end(), [](auto& l, auto& r) {return l.value < r.value; }); // sort by float value
auto it = std::find_if(items.begin(), items.end(), [](auto& i) {return i.value > 0; }); // find first non-zero position (as iterator)
int new_rank_value{1}; // start numbering non-zero numbers from 1
std::for_each(it, items.end(), [&new_rank_value](auto& i) {i.rank = new_rank_value++; }); // assign non-zero numbers a rank value
std::sort(items.begin(), items.end(), [](auto& l, auto& r) {return l.original_position < r.original_position ; }); // sort by original position again
for(auto i : items)
std::cout << "ranks[" << i.original_position << "]=" << i.rank << ";\n";
}
Output:
ranks[0]=0;
ranks[1]=1;
ranks[2]=3;
ranks[3]=0;
ranks[4]=2;

Bubble Sort Using Slides instead of swaps

currently I'm being asked to design four sorting algorithms (insertion, shell, selection, and bubble) and I have 3 of the 4 working perfectly; the only one that isn't functioning correctly is the Bubble Sort. Now, I'm well aware of how the normal bubble sort works with using a temp var to swap the two indexes, but the tricky part about this is that it needs to use the array index[0] as a temp instead of a normal temp, which is used in swapping, and slide the lower array variables down to the front of the list and at the end of the pass assign the last index to the temp which is the greatest value.
I've been playing around with this for a while and even tried to look up references but sadly I cannot find anything. I'm hoping that someone else has done this prior and can offer some helpful tips. This is sort of a last resort as I've been modifying and running through the passes with pen and paper to try and find my fatal error. Anyways, my code is as follows...
void BubbleSort(int TheArray[], int size)
{
for (int i = 1; i < size + 1; i++)
{
TheArray[0] = TheArray[i];
for (int j = i + 1; j < size; j++)
{
if (TheArray[j] > TheArray[0])
TheArray[0] = TheArray[j];
else
{
TheArray[j - 1] = TheArray[j];
}
}
TheArray[size- 1] = TheArray[0];
}
}
Thanks for any feedback whatsoever; it's much appreciated.
If I understand the problem statement, I think you're looking for something along these lines :
void BubbleSort(int theArray[], int size)
{
for (int i = 1; i < size + 1; i++)
{
theArray[0] = theArray[1];
for (int j = 1; j <= size + 1 - i; j++)
{
if (theArray[j] > theArray[0])
{
theArray[j-1] = theArray[0];
theArray[0] = theArray[j];
}
else
{
theArray[j - 1] = theArray[j];
}
}
theArray[size-i+1] = theArray[0];
}
}
The piece that you're code was missing, I think, was that once you find a new maximum, you have to put it back in the array before placing the new maximum in theArray[0] storage location (see theArray[j-1] = theArray[0] after the compare). Additionally, the inner loop wants to run one less each time since the last element will be the current max value so you don't want to revisit those array elements. (See for(int j = 1 ; j <= size + 1 - i ; j++))
For completeness, here's the main driver I used to (lightly) test this :
int main()
{
int theArray[] = { 0, 5, 7, 3, 2, 8, 4, 6 };
int size = 7;
BubbleSort(theArray, size);
for (int i = 1; i < size + 1; i++)
cout << theArray[i] << endl;
return 0;
}

Count triplets which satisfy given condition [duplicate]

This question already has answers here:
Number of all increasing subsequences in given sequence?
(7 answers)
Closed 8 years ago.
Given an array A of size N I need to count such triplets (i,j,k) such that:
Condition 1 : i < j < k
Condition 2 : A[i] > A[j] > A[k]
I know a O(N^3) solution to do it. Can their be something like O(N) or O(NlogN) solution to do this problem as N can be up to 100000
Example : Let N=4 and array be [4,3,2,1] then answer is 4 as {4,3,2},{4,3,1},{4,2,1} and {3,2,1} are all possible answers
How to find this count for given N and array A?
My Approach :
int n;
cin>>n;
vector<int> A(n);
for(int i=0;i<n;i++){
cin>>A[i];
}
int count=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
for(int k=j+1;k<n;k++){
if(A[i]>A[j] && A[j]>A[k]){
count++;
}
}
}
}
cout<<count<<"\n";
First, sort the array, maintain the index of each element.
class Node{
int index, val;
}
For comparing two nodes, we first need to compare their values. If the values equals, we will compare their index, consider a node is greater if its index is smaller.
Now, process each node in sorted order, we try to add each node's index into a Fenwick tree. So, for each index i, we query the tree for the frequency of this index, which added previously in the tree. This is the number of index that has value greater than value of the current index.
Note for the case elements have equal value, by the sorting mechanism mentioned above, we will add those have greater index to the tree first, thus, doesn't affect the frequency value query from the tree.
Apply similar step to obtains those elements that smaller than i and has index j < i.
For example:
If we have an array
{0(1) ,1(2) , 2(2) ,3(4) , 4(4) ,5(4) ,6(1)} //index(value)
After sort -> {5(4), 4(4), 3(4), 2(2), 1(2), 6(1), 0(1) }
Pseudo code
Node[]data;
sort(data)
Fenwick tree;
int[]less;
int[]more;
for(int i = 0; i < data.length; i++){
less[data[i].index] = tree.query(data[i].index);
tree.add(data[i].index, 1);
}
tree.clear();
for(int i = data.length - 1; i >= 0; i--){
more[data[i].index] = tree.query(data.length) -tree.query(data[i].index);
tree.add(data[i].index, 1);
}
int result = 0;
for(int i = 0; i < data.length; i++)
result += more[i]*less[i];
Time complexity will be O(n logn).
Working Java code (FT is my Fenwick tree)
PrintWriter out;
Scanner in = new Scanner(System.in);
out = new PrintWriter(System.out);
int n = in.nextInt();
Node[] data = new Node[n];
for (int i = 0; i < n; i++) {
data[i] = new Node(i + 1, in.nextInt());
}
FT tree = new FT(n + 2);
Arrays.sort(data, new Comparator<Node>() {
#Override
public int compare(Node o1, Node o2) {
if (o1.val != o2.val) {
return o2.val - o1.val;
}
return o2.index - o1.index;
}
});
int[] less = new int[n];//Store all nodes with greater index and smaller value;
int[] greater = new int[n];//Store all nodes with smaller index and greater value
for (int i = 0; i < n; i++) {
greater[data[i].index - 1] = (int) tree.get(data[i].index);
tree.update(data[i].index, 1);
}
tree = new FT(n + 2);
for (int i = n - 1; i >= 0; i--) {
less[data[i].index - 1] = (int) (tree.get(n) - tree.get(data[i].index));
tree.update(data[i].index, 1);
}
long total = 0;
for (int i = 0; i < n; i++) {
total += less[i] * greater[i];
}
out.println(total);
out.close();
You can do this in O(n*n) pretty easily, you just need to keep track of how many smaller number each element had:
vector<int> smallerNumbers(A.size());
for (int i = A.size() - 2; i >= 0; --i){
for (int j = i + 1; j < A.size(); ++j){
if (A[i] > A[j]){
smallerNumbers[i]++;
count += smallerNumbers[j];
}
}
}
For an O(nklogn) solution see my answer here: https://stackoverflow.com/a/28379003/2642059
Note that is for an increasing sequence and you're asking for a decreasing sequence.
To accomplish that you will need to reverse the ranking created by mapIndex. So simply reverse temp before creating mapIndex by swapping the partial_sort_copy line with this one:
partial_sort_copy(values.cbegin(), values.cend(), temp.rbegin(), temp.rend());

c++ array can't get the right array

I have Array A[9]= {1,2,3,4,5,6,7,8,9} and I need to delete the numbers which are not dividing by 2. The code I tried to do:
int main()
{
int n;
ifstream fd(Cdf);
fd>>n; // read how many numbers are in the file.
int A[n];
for(int i = 0; i < n; i++)
{
fd >> A[i]; //read the numbers from file
}
for(int i = 0; i < n; i ++) // moving the numbers.
{
if(A[i] % 2 !=0)
{
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
}
}
fd.close();
return 0;
}
But I get numbers like 224466888. what I need to do to get 2,4,6,8?
I need to delete numbers in the same array.
First you should use std::vector for dynamic size arrays.
Second, for removing numbers that are even in a vector, you can do :
std::vector<int> inf = {12,0,5,6,8};
auto func = [](int i){return i % 2 != 0;};
inf.erase(std::remove_if(inf.begin(),inf.end(),func), inf.end());
EDIT :
Ok, so you can still do this without std::vectors, but it will be uglier :
#include <algorithm>
int res[] = {2,5,9,8,6,7};
int size = 6;
auto func = [](int i){return i % 2 != 0;};
int new_size = std::remove_if(res,res + size, func) - res;
All the data you want is in [0, new_size[ range, the other part of your array is now garbage.
Your removal loop is indexing with the wrong variable:
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
You're using i, which doesn't change in the loop.
Change it to j. You also need to subtract one from the upper limit, as you'd step outside of the array otherwise when accessing A[j + 1].
for(int j = i; j < n - 1; j++)
{
A[j] = A[j + 1];
}
An array can't be used for your purpose. It is allocated on stack and its size can't be changed dynamically (you can't change the size of an array in general, not only when it is allocated on stack).
You could allocate a second array and keep reallocating it with realloc everytime you add a new element but that's not the good way to do it. You are working with C++ so just use a std::vector<int> and your problems will be solved:
std::vector<int> evenArray;
evenArray.reserve(sizeof(A)/sizeof(A[0])/2);
if (number is even) {
evenArray.pushBack(number);
}
Mind that vector stores elements contiguously so this is legal:
int *evenA = &evenArray[0];
For your inner for loop you should be referencing j, not i.
for(int j = i; j < n - 1; j++)
{
A[j] = A[j+1];
}
Otherwise, what's the point of creating j?
Of course, this also means if you read the whole array back you will display all the characters that were shifted (which will just be equal to the last number). So, you should probably keep track of the new length of the array and just iterate to that instead of the end of the array.
EDIT:
In the inner for loop you need to loop to n - 1 otherwise when you have A[j + 1] it will go off the end of the array when you to change it, which may or may not give you a runtime error.

All possible combination. Faster way

I have a vector of numbers between 1 and 100(this is not important) which can take sizes between 3 and 1.000.000 values.
If anyone can help me getting 3 value unique* combinations from that vector.
*Unique
Example: I have in the array the following values: 1[0] 5[1] 7[2] 8[3] 7[4] (the [x] is the index)
In this case 1[0] 5[1] 7[2] and 1[3] 5[1] 7[4] are different, but 1[0] 5[1] 7[2] and 7[2] 1[0] 5[1] are the same(duplicate)
My algorithm is a little slow when i work with a lot of values(example 1.000.000). So what i want is a faster way to do it.
for(unsigned int x = 0;x<vect.size()-2;x++){
for(unsigned int y = x+1;y<vect.size()-1;y++){
for(unsigned int z = y+1;z<vect.size();z++)
{
// do thing with vect[x],vect[y],vect[z]
}
}
}
In fact it is very very important that your values are between 1 and 100! Because with a vector of size 1,000,000 you have a lot of numbers that are equal and you don't need to inspect all of them! What you can do is the following:
Note: the following code is just an outline! It may lack sufficient error checking and is just here to give you the idea, not for copy paste!
Note2: When I wrote the answer, I assumed the numbers to be in the range [0, 99]. Then I read that they are actually in [1, 100]. Obviously this is not a problem and you can either -1 all the numbers or even better, change all the 100s to 101s.
bool exists[100] = {0}; // exists[i] means whether i exists in your vector
for (unsigned int i = 0, size = vect.size(); i < size; ++i)
exists[vect[i]] = true;
Then, you do similar to what you did before:
for(unsigned int x = 0; x < 98; x++)
if (exists[x])
for(unsigned int y = x+1; y < 99; y++)
if (exists[y])
for(unsigned int z = y+1; z < 100; z++)
if (exists[z])
{
// {x, y, z} is an answer
}
Another thing you can do is spend more time in preparation to have less time generating the pairs. For example:
int nums[100]; // from 0 to count are the numbers you have
int count = 0;
for (unsigned int i = 0, size = vect.size(); i < size; ++i)
{
bool exists = false;
for (int j = 0; j < count; ++j)
if (vect[i] == nums[j])
{
exists = true;
break;
}
if (!exists)
nums[count++] = vect[i];
}
Then
for(unsigned int x = 0; x < count-2; x++)
for(unsigned int y = x+1; y < count-1; y++)
for(unsigned int z = y+1; z < count; z++)
{
// {nums[x], nums[y], nums[z]} is an answer
}
Let us consider 100 to be a variable, so let's call it k, and the actual numbers present in the array as m (which is smaller than or equal to k).
With the first method, you have O(n) preparation and O(m^2*k) operations to search for the value which is quite fast.
In the second method, you have O(nm) preparation and O(m^3) for generation of the values. Given your values for n and m, the preparation takes too long.
You could actually merge the two methods to get the best of both worlds, so something like this:
int nums[100]; // from 0 to count are the numbers you have
int count = 0;
bool exists[100] = {0}; // exists[i] means whether i exists in your vector
for (unsigned int i = 0, size = vect.size(); i < size; ++i)
{
if (!exists[vect[i]])
nums[count++] = vect[i];
exists[vect[i]] = true;
}
Then:
for(unsigned int x = 0; x < count-2; x++)
for(unsigned int y = x+1; y < count-1; y++)
for(unsigned int z = y+1; z < count; z++)
{
// {nums[x], nums[y], nums[z]} is an answer
}
This method has O(n) preparation and O(m^3) cost to find the unique triplets.
Edit: It turned out that for the OP, the same number in different locations are considered different values. If that is really the case, then I'm sorry, there is no faster solution. The reason is that all the possible combinations themselves are C(n, m) (That's a combination) that although you are generating each one of them in O(1), it is still too big for you.
There's really nothing that can be done to speed up the loop body you have there. Consider that with 1M vector size, you are making one trillion loop iterations.
Producing all combinations like that is an exponential problem, which means that you won't be able to practically solve it when the input size becomes large enough. Your only option would be to leverage specific knowledge of your application (what you need the results for, and how exactly they will be used) to "work around" the issue if possible.
Possibly you can sort your input, make it unique, and pick x[a], x[b] and x[c] when a < b < c. The sort will be O(n log n) and picking the combination will be O(n³). Still you will have less triplets to iterate over:
std::vector<int> x = original_vector;
std::sort(x.begin(), x.end());
std::erase(std::unique(x.begin(), x.end()), x.end());
for(a = 0; a < x.size() - 2; ++a)
for(b=a+1; b < x.size() - 1; ++b)
for(c=b+1; c< x.size(); ++c
issue triplet(x[a],x[b],x[c]);
Depending on your actual data, you may be able to speed it up significantly by first making a vector that has at most three entries with each value and iterate over that instead.
As r15habh pointed out, I think the fact that the values in the array are between 1-100 is in fact important.
Here's what you can do: make one pass through the array, reading values into a unique set. This by itself is O(n) time complexity. The set will have no more than 100 elements, which means O(1) space complexity.
Now since you need to generate all 3-item permutations, you'll still need 3 nested loops, but instead of operating on the potentially huge array, you'll be operating on a set that has at most 100 elements.
Overall time complexity depends on your original data set. For a small data set, time complexity will be O(n^3). For a large data set, it will approach O(n).
If understand your application correctly then you can use a tuple instead, and store in either a set or hash table depending on your requirements. If the normal of the tri matters, then make sure that you shift the tri so that lets say the largest element is first, if normal shouldn't matter, then just sort the tuple. A version using boost & integers:
#include <set>
#include <algorithm>
#include "boost/tuple/tuple.hpp"
#include "boost/tuple/tuple_comparison.hpp"
int main()
{
typedef boost::tuple< int, int, int > Tri;
typedef std::set< Tri > TriSet;
TriSet storage;
// 1 duplicate
int exampleData[4][3] = { { 1, 2, 3 }, { 2, 3, 6 }, { 5, 3, 2 }, { 2, 1, 3 } };
for( unsigned int i = 0; i < sizeof( exampleData ) / sizeof( exampleData[0] ); ++i )
{
std::sort( exampleData[i], exampleData[i] + ( sizeof( exampleData[i] ) / sizeof( exampleData[i][0] ) ) );
if( !storage.insert( boost::make_tuple( exampleData[i][0], exampleData[i][1], exampleData[i][2] ) ).second )
std::cout << "Duplicate!" << std::endl;
else
std::cout << "Not duplicate!" << std::endl;
}
}