I have an array of arrays of things
typedef std::vector<thing> group;
std::vector<group> groups;
things could be compared like so
int comparison(thing a, thing b);
where the return value is 0, 1 or 2
0 means that the things are not alike
1 means that they are alike and a is more specific or equal to b
2 means that they are alike and b is more specific or equal to a
and I am looking for a function that would return me a group that contains all things that appear in every group.
std::getgroup(groups.begin(), groups.end(), myComparisonFunction);
the problem is I have no idea what this function may be called, if it does even exist, or what the closest thing to it would be.
Eventually, what you want is an intersection. Luckily, there is std::set_intersection which almost does what you need. Here's a simple example on std::vector<std::vector<int>>. You can easily change it to work with your thing:
#include <iostream>
#include <vector>
#include <algorithm>
std::vector<int> getGroup(const std::vector<std::vector<int>>& groups) {
std::vector<int> group;
std::vector<int> temp = groups[0];
std::sort(temp.begin(), temp.end());
for ( unsigned i = 1; i < groups.size(); ++i ) {
group = std::vector<int>();
std::vector<int> temp2 = groups[i];
std::sort(temp2.begin(), temp2.end());
std::set_intersection(temp2.begin(), temp2.end(),
temp.begin(), temp.end(),
std::back_inserter(group));
temp = group;
}
return group;
}
int main() {
std::vector<std::vector<int>> groups = { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{1, 2, 3, 5, 6, 7, 8, 10},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{1, 3, 4, 5, 6, 9, 10},
{1, 2, 6, 7, 8, 9, 10},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} };
for ( auto g : getGroup(groups) )
std::cout << g << "\n";
return 0;
}
This will print:
1
6
10
Related
So the aim is to take two arrays as shown below
int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int k[4] = {1, 2, 3, 4};
and add each element of k to each element of x in a loop as shown
1 2 3 4 5 6 7 8 9 10
+1 +2 +3 +4 +1 +2 +3 +4 +1 +2
This should give us a final array [2, 4, 6, 8, 6, 8, 10, 12, 10, 12].
Any suggestions as to how I could achieve this in C++
Loop through the indexes of the larger array, using the modulus (%) operator to wrap-around the indexes when accessing the smaller array.
int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int k[4] = {1, 2, 3, 4};
int res[10];
for (int i = 0; i < 10; ++i) {
res[i] = x[i] + k[i % 4];
}
Online Demo
With % you can have the wrap-around behavior and with std::size(from C++17 onwards) the size of the array.
#include <algorithm>
#include <iostream>
int main()
{
int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int k[4] = {1, 2, 3, 4};
for(int i = 0; i < std::size(x); ++i)
{
x[i] = x[i] + k[i%std::size(k)];
}
//lets confirm if x has the right elmennts
for(const int& element: x)
{
std::cout<< element<<std::endl;
}
}
Note that here i have not used a separate array to store the resulting array. Instead the elements are added into the original array x. Storing the result in a new array is trivial.
What is the right way to implement the function below to allow the caller to iterate over the range it returns?
#include <set>
#include <ranges>
std::set<int> set{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto find_range(int a)
{
//What type should I return?
return std::make_tuple(set.lower_bound(a - 3), set.upper_bound(a + 3));
}
int main()
{
for (int x : find_range(5)) {...}
}
The function returns a couple of iterators pointing to 2 and 9, so the loop should iterate over 2, 3, 4, 5, 6, 7, 8.
You can return a subrange like this
auto find_range(int a)
{
return std::ranges::subrange(set.lower_bound(a - 3),
set.upper_bound(a + 3));
}
Here's a demo.
This question already has answers here:
std::remove_if - lambda, not removing anything from the collection
(4 answers)
Closed 1 year ago.
I am trying to remove elements from a vector of ints using std::remove_if, but am not getting the required output.
Initial vector members: {0, 1, 2, 1, 3, 1, 4, 5, 1, 6, 1, 7, 1, 8, 1, 9}
Required Output: {0, 2, 3, 4, 5, 6, 7, 8, 9}
Actual Output: {0, 2, 3, 4, 5, 6, 7, 8, 9, 6, 1, 7, 1, 8, 1, 9}
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
class Equal
{
public:
Equal(int a): a_(a){}
bool operator()(int b)
{
return a_ == b;
}
private:
int a_;
};
int main()
{
std::vector<int> vi{0, 1, 2, 1, 3, 1, 4, 5, 1, 6, 1, 7, 1, 8, 1, 9};
std::cout << std::endl;
std::remove_if(vi.begin(), vi.end(), Equal(1));
for (const auto &i : vi) std::cout << i << " ";
return 0;
}
There are just as many elements in the vector before and after the call to
std::remove_if:
Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range.
... and std::remove_if returns an iterator to the start of the "removed" elements and you can use that iterator to actually erase the elements: See Erase–remove idiom
vi.erase(
std::remove_if(vi.begin(), vi.end(), Equal(1)), // returns iterator
vi.end() // erase to the end
);
Demo
Also note that std::vector got a new specialized function in C++20 that does both things, namely std::erase_if.
Example:
std::erase_if(vi, Equal(1));
I have the following code:
int *exceptions[7];
int a[] = {1, 4, 11, 13};
int b[] = {5, 6, 11, 12, 14, 15};
int c[] = {2, 12, 14, 15};
int d[] = {1, 4, 7, 9, 10, 15};
int e[] = {1, 3, 4, 5, 7, 9};
int f[] = {1, 2, 3, 7, 13};
int g[] = {0, 1, 7, 12};
exceptions[0] = a;
exceptions[1] = b;
exceptions[2] = c;
exceptions[3] = d;
exceptions[4] = e;
exceptions[5] = f;
exceptions[6] = g;
Size of exception[0] and exception[1] should be 4 and 6 respectively.
Here's my code:
short size = sizeof(exceptions[1]) / sizeof(exceptions[1][0]);
But I'm getting 2 for every row. How can I solve this problem?
short size = sizeof(exceptions[1]) / sizeof(exceptions[1][0]);
effectively does the same as
short size = sizeof(int*) / sizeof(int);
On a 64 bit platform, that yields most probably 2.
How can I solve this problem?
Use some c++ standard container like std::vector<std::vector<int>> instead:
std::vector<std::vector<int>> exceptions {
{1, 4, 11, 13},
{5, 6, 11, 12, 14, 15},
{2, 12, 14, 15},
{1, 4, 7, 9, 10, 15},
{1, 3, 4, 5, 7, 9},
{1, 2, 3, 7, 13},
{0, 1, 7, 12},
}
Your statement will become:
short size = exceptions[0].size();
size = exceptions[1].size();
(for whatever that's needed)
The best remedy would be to use vector provided in standard template library. They have a size() function which you can use and they are much more versatile than array.
How to initialize a 2 dimensional vector<int> in C++?
For instance I have 4 arrays each of length 8 ints, like the below
int a1[] = {1,2,3,4,5,6,7,8};
int a2[] = {1,2,3,4,9,10,11,12};
int a3[] = {1,2,5,6,9,10,13,14};
int a4[] = {1,3,5,7,9,11,13,15};
and I have this
vector< vector <int> > aa (4);
aa[i] (a1,a1+8);
But this gives error. I even tried supplying the array a1 to v1 and passed v1 to aa[i] , still it fails.
So what would be the proper way of initializing the elements of a 2 dimensional vector<int>
aa[i].assign(a1,a1+8);
int arr[4][8] =
{
{1, 2, 3, 4, 5, 6, 7, 8},
{1, 2, 3, 4, 9, 10, 11, 12},
{1, 2, 5, 6, 9, 10, 13, 14},
{1, 3, 5, 7, 9, 11, 13, 15},
};
std::vector<std::vector<int> > vec(4, std::vector<int>(8));
for (int i = 0; i < 4; ++i)
{
vec[i].assign(arr[i], arr[i] + 8);
}
The initialization of aa also initialized all four of the contained vector<int> objects, using the default constructor for vector<int>. So you'll need to add data to those empty vectors, not initialize them.
Try for example:
std::copy(a1, a1+8, std::back_inserter(aa[i]));