Unique pairs in list with duplicates & position - c++

In preparation of tech interviews a friend of mine came across an interesting problem: given a list of n integers find all identical pairs and return their positions.
Example input: [3,6,6,6,1,3,1]
Expected output: (0,5), (1,2), (1,3), (2,3), (4,6)
Stack Overflow has tons of answers regarding existence checks of unique pairs or special cases like no-duplicates, but I did not find a general, fast solution. Time complexity of my approach below is O(n) best case but degrades to O(n^2) worst case (where input values are all identical).
Is there a way to bring this down to O(n*logN) worst case?
// output is a vector of pairs
using TVecPairs= vector<pair<size_t,size_t>>;
TVecPairs findPairs2( const vector<uint32_t> &input )
{
// map keyvalue -> vector of indices
unordered_map<uint32_t, vector<size_t>> mapBuckets;
// stick into groups of same value
for (size_t idx= 0; idx<input.size(); ++idx) {
// append index for given key value
mapBuckets[input[idx]].emplace_back( idx );
}
// list of index pairs
TVecPairs out;
// foreach group of same value
for (const auto &kvp : mapBuckets) {
const vector<size_t> &group= kvp.second;
for (auto itor= cbegin(group); itor!=cend(group); ++itor) {
for (auto other= itor+1; other!=cend(group); ++other) {
out.emplace_back( make_pair(*itor,*other) );
}
}
}
return out;
}

As the others have said it's a O(n^2) in case you want the output in the way that you mentioned. If you can print it a different way you can do it in O(n * (complexity of insertion/read from a hashmap) = O(n*log(n)) in C++. Some python code describing the above follows:
def dupes(arrlist):
mydict=dict()
count = 0
for x in arrlist:
if mydict.has_key(x):
mydict[x] = mydict[x] + [count]
else:
mydict[x] = [count]
count = count + 1
print mydict
return
And for the above example:
>>> dupes([3, 6, 6, 6, 1, 3, 1])
{1: [4, 6], 3: [0, 5], 6: [1, 2, 3]}

Related

Get the number of duplicated elements in a set

So a set doesn't allow duplicates, but is there a way, or another data structure, that can allow me to get the number of repeated elements even though they have been removed?. Let me explain myself better anyways.
Lets say I'm giveng this input:
[1, 2, 2, 3, 2, 5, 3]
If I put it in a set, it will end up like this:
[1, 2, 3, 5]
Which is what I want, but how can I know that there were three 2s before they were removed? Isn't this related to those data structure with "buckets" or something?
Basically I'd like the output to be something like this:
[1, 2, 3, 5]
| | | |
[1, 3, 2, 1]
With the bottom array being the number of duplicates of each element on the top array.
You can use a std::map to count the frequency of the items.
For example:
int arr[] = {1, 2, 2, 3, 2, 5, 3};
std::map<int, int> count;
for (int i = 0; i < 7; i++) {
count[arr[i]]++;
}
for (auto& [element, frequency] : count) {
std::cout << element << " : " << frequency << endl;
}
The output would be something like this:
1 : 1
2 : 3
3 : 2
5 : 1
You gave the answer yourself: if suffices to keep counts in correspondence to the unique elements. Hence a compact data structure is the list of the unique elements paired with the list of counts in the same order.
Now how this is obtained depends on how you plan to remove the duplicates and the kind of access desired. One way is to sort the initial list, purge the duplicates at the same time that you count them and fill the list of counts. Another way is to use a map with the list elements as keys and associate them with a count. Whether you keep the map or fill new lists is your choice.
The number of duplicate elements in a set in C++ can be determined by using the size() function and subtracting the number of unique elements in the set, which can be found by using the unique() function.
#include <iostream>
#include <set>
#include <algorithm>
int main()
{
std::set<int> mySet;
mySet.insert(1);
mySet.insert(2);
mySet.insert(2);
mySet.insert(3);
mySet.insert(3);
mySet.insert(3);
int numDuplicates = 0;
int lastElement = -1;
for (int element : mySet) {
if (element == lastElement) {
numDuplicates++;
}
lastElement = element;
}
std::cout << numDuplicates << std::endl;
return 0;
}

Sorting pairs of elements from vectors to maximize a function

I am working on a vector sorting algorithm for my personal particle physics studies but I am very new to coding.
Going through individual scenarios (specific vector sizes and combinations) by brute force becomes extremely chaotic for greater numbers of net vector elements, especially since this whole code will be looped up to 1e5 times.
Take four vectors of 'flavors' A and B: A+, A-, B+, and B-. I need to find two total pairs of elements such that some value k(V+, V-) is maximized with the restriction that different flavors cannot be combined! (V is just a flavor placeholder)
For example:
A+ = {a1+}
A- = {a1-}
B+ = {b1+, b2+}
B- = {b1-}
Since A+ and A- only have one element each, the value k(A+, A-) -> k(a1+, a1-). But for flavor B, there are two possible combinations.
k(b1+, b1-) OR k(b2+, b1-)
I would like to ensure that the combination of elements with the greater value of k is retained. As I said previously, this specific example is not TOO bad by brute force, but say B+ and B- had two elements each? The possible values would be:
k(b1+, b1-) or k(b2+,b2-) or k(b1+, b2-) or k(b2+, b1-)
where only one of these is correct. Furthermore, say two of those four B+B- combinations had greater k than that of A+A-. This would also be valid!
Any help would be appreciated!!! I can clarify if anything above is overly confusing!
I tried something like this,
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
static bool sortbypair(const pair<double, double> &a, const pair<double, double> &b)
{
return (k(a.first, a.second) > k(b.first, b.second)) && k(a.first, b.second) < k(a.second, b.first);
}
But I can't flesh it out.
If I understand your question correctly,
you have a function k which maps two doubles (or a std::pair<double, double>) to a single double. I am assuming double, it wasn't clear from the question. It also isn't strictly at the core of your problem.
you have four std::vector<double>s: aplus, aminus, bplus and bminus.
Your domain are all std::pair<double, double>s that you can form by combining the elements in aplus and aminus as well as all combinations from bplus and bminus respectively.
you want to either
find the pair in your domain that maximizes k
get a collection of all pairs in your domain, sorted by the value of k
Did I get this right? You state in your question
I need to find two total pairs of elements such that some value k(V+, V-) is maximized [...]
which confuses me a bit.
My suggestion is to break down your problem into three subtasks:
Create a range of all combinations of elements in the vectors Vplus and Vminus. This is often denoted as a cartesian product Vplus x Vminus.
Concatenate the ranges created in step 1 for aplus x aminus and bplus x bminus to get a range of all viable pairs in your domain.
Maximize/sort the range from step 2.
Implementation using range-v3
The range-v3 library provides some very convenient tools for this kind of task. Let's assume your k function looks like this:
double k(double x, double y) { return x*x + y*y; }
and your vectors look like this:
std::vector<double> ap{0., 4., 2., 3., 1.};
std::vector<double> am{2., -1.};
std::vector<double> bp{1., 0.5};
std::vector<double> bm{-1., 2.};
Let's define a range representing our domain:
using namespace ranges;
auto pairs_view = view::concat(
view::cartesian_product(ap, am),
view::cartesian_product(bp, bm)
);
The pairs_view instance doesn't actually create the pairs anywhere in memory. It is just an adaptor object that let's you iterate over all pairs that you can construct in the specified way. The pairs are created "lazily" on the fly as you - or an algorithm - iterates over it.
Let's print all pairs from our domain:
auto print = [](auto const& p){
auto first = std::get<0>(p);
auto second = std::get<1>(p);
std::cout << "[" << first << ", " << second << "] k = " << k(first, second) << std::endl;
};
for_each(pairs_view, print);
Output:
[0, 2] k = 4
[0, -1] k = 1
[4, 2] k = 20
[4, -1] k = 17
[2, 2] k = 8
[2, -1] k = 5
[3, 2] k = 13
[3, -1] k = 10
[1, 2] k = 5
[1, -1] k = 2
[1, -1] k = 2
[1, 2] k = 5
[0.5, -1] k = 1.25
[0.5, 2] k = 4.25
Finding the maximum element
Let's start by defining a convenience function (here, in the form of a lambda expression) that evaluates k for a tuple of doubles:
auto k_proj = [](auto const& p){
return k(std::get<0>(p), std::get<1>(p));
};
You can find an iterator to the pair in your domain that maximizes k with just the single line:
auto it = max_element(pairs_view, less{}, k_proj);
print(*it);
Output:
[4, 2] k = 20
The function max_element gets two additional arguments. The first is a comparison function that returns true, if two elements are in order. We provide the default less functor. The second argument is an optional projection that is to be applied on each element before the comparison. We pass k_proj.
Read the above line of code as "Find the element in pairs_view of which the projection onto its k value is maximal, where we want to compare the projected values with the standard less function."
Getting a sorted range of your domain
If you want to have all sorted range of all pairs in your domain, we must create an std::vector<std::pair<double, double>> for your domain first and then sort it. You cannot sort views created with the range-v3 library, because they are just a view into existing objects, they cannot be mutated. In addition, we have to map the special pair types created by the range-v3 library in the cartesian_product functions to actual std::pair<double, double to copy the values into our new container:
auto to_std_pair = [](auto const& p){
return std::pair<double, double>{std::get<0>(p), std::get<1>(p)};
};
auto pairs_vec = pairs_view | view::transform(to_std_pair) | to_vector;
Note that the "pipe" operator | is short-hand notation for the function composition to_vector(view::transform(pairs_view, to_std_pair)).
The invokation of the sorting algorithm looks very similar to the invokation of the max_element algorithm:
sort(pairs_vec, less{}, k_proj);
Let's print the result:
for_each(pairs_vec, print);
Output:
[0, -1] k = 1
[0.5, -1] k = 1.25
[1, -1] k = 2
[1, -1] k = 2
[0, 2] k = 4
[0.5, 2] k = 4.25
[2, -1] k = 5
[1, 2] k = 5
[1, 2] k = 5
[2, 2] k = 8
[3, -1] k = 10
[3, 2] k = 13
[4, -1] k = 17
[4, 2] k = 20
Here is a complete live code example: https://godbolt.org/z/6zo8oj3ah
If you don't want to use the range-v3 library you have two options:
You can wait. Large parts of the range-v3 library have been added to the standard library in C++20. The relevant functions concat, cartesian_product and to_vector will presumably be added in the upcoming standard C++23.
The standard library has max_element and sort. So you could just implement the concatenation and cartesian product on your own: https://godbolt.org/z/7Y5dG16WK
Thank you to everyone who commented!!! I really appreciate your effort. The solution ended up being much simpler than I was making it out to be.
Essentially, from the physics program I'm using, the particles are given in a listed form (ie. 533 e-, 534
p+, 535 e+, etc.). I couldn't figure out how to get range-v3 working (or any external libraries for that matter but thank you for the suggestion) so I figured out to make a tuple out of the indices of combined particles and their associated k value.
#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
using namespace std;
static bool weirdsort(const tuple<int, int, double> &a, const tuple<int, int, double> &b)
{
return get<2>(a) > get<2>(b);
}
int main()
{
vector<tuple<int, int, double>> net;
// Sample ptcl list
//
// A+ A- B+ B-
// 0 a1+
// 1 a1-
// 2 b1-
// 3 b1+
// 4 a2+
// 5 a2-
for(int i = 0; i < A+.size(); i++)
{
for (int j = 0; j < A-.size(); j++)
{
net.push_back(A+[i], A-[j], k(A+[i], A-[j]));
}
}
sort(net.begin(), net.end(), weirdsort);
//Now another for loop that erases a tuple (with a lower k value) if it has a repeated ptcl index.
for (int i = 0; i < net.size(); i++)
{
if (get<0>(net[i]) == get<0>(net[i + 1]) || get<1>(net[i]) == get<1>(net[i + 1]))
{
net.erase(net.begin() + i + 1);
}
}
//Now can plot third tuple element of net[0] and net[1]
return 0;
}
It's not quite perfect but since I'm only looking for the first two highest k values it works out just fine. Thanks again!

Find the first element that is n times larger than current element in a list

It is easy to come up with an O(n) algorithm to solve this very famous question:
For every element in the list, find the first element that is larger than it. This can be done using a stack. But, what if I want to find the first element that is larger than n*current element?
More specifically:
Given an array [2, 5, 4, 7, 3, 8, 9, 6] and n = 2.
I want [5, -1, 9, -1, 8, -1, -1, -1]
For 2, 5 is the next element larger than n * 2, for 4, 9 is the next element larger than n * 4. For 5, there is no element larger than n * 5 so return -1 at that position.
Can we do better than O(n^2)?
I agree with OP that, the simple predicate of the O(N) algo might not work on the stack-based solution when looking for the first element > 2x in the remaining array.
I found a O(NlogN) solution for this btw.
It uses a Min-heap to maintain the frontier elements we are interested in.
Pseudo-code:
def get_2x_elements(input_list, multipler = 2):
H = [] #min-heap with node-values as tuples (index, value)
R = [-1 for _ in range(len(input_list))] # results-list
for index, value in enumerate(input_list):
while multiplier*H[0][1] < value:
minval = extractMinFromHeap(H)
R[minval[0]] = value
insertToMinHeap(H, (index, value))
return R
Complexity-analysis:
1. Insertion/Extraction from min-heap = O(logN)
2. Number of such operations = N
Total-complexity = O(NlogN)
PS: This assumes we need the first >2x element from the remaining part of the list.
Re:
I made a Java verion implementation of your idea. Thanks #Serial Lazer
private static class ValueAndIndexPair implements Comparable<ValueAndIndexPair>{
public final double value;
public final int index;
public ValueAndIndexPair(double value, int index) {
this.value = value;
this.index = index;
}
#Override
public int compareTo(ValueAndIndexPair other) {
return Double.compare(value, other.value);
}
}
public static double[] returnNextNTimeLargerElementIndex(final List<Double> valueList, double multiplier) {
double[] result = new double[valueList.size()];
PriorityQueue<ValueAndIndexPair> minHeap = new PriorityQueue<>();
// Initialize O(n)
for (int i = 0; i < valueList.size(); i++) {
result[i] = -1.0;
}
if (valueList.size() <= 1) return result;
minHeap.add(new ValueAndIndexPair(valueList.get(0) * multiplier, 0));
for (int i = 1; i <valueList.size(); i++) {
double currentElement = valueList.get(i);
while (!minHeap.isEmpty() && minHeap.peek().value < currentElement) {
result[minHeap.poll().index] = currentElement;
}
minHeap.add(new ValueAndIndexPair(currentElement * multiplier, i));
}
return result;
}
Sure, easily.
We just need a sorted version of the array (sorted elements plus their original index) and then we can do an efficient search (a modified binary search) that points us to the start of the elements that are larger than the current number (or a multiple of it, it doesn't matter). Those elements we can then search sequentially for the one with the smallest index (that is greater than the one of the current number, if so required).
Edit: It was pointed out that the algorithm may not be better than O(n²) because of the sequential search of the elements that satisfy the condition of being greater. This may be so, I'm not sure.
But note that we may build a more complex search structure that involves the index already, somehow. This is left as homework. :)
The stack-based solution offered at geeksforgeeks does not seem to maintain the order of the elements in the result even in its output:
input: int arr[] = { 11, 13, 21, 3 };
output:
11 -- 13
13 -- 21
3 -- -1
21 -- -1
After minor modification to find the first element which is greater N times than a current, this algorithm fails to detect 9 for the element 4 from the given example.
Online demo
input: int arr[] = { 2, 5, 4, 7, 3, 8, 9, 6 }; // as in this question
output:
2 * 2 --> 5
2 * 3 --> 8
6 -- -1
9 -- -1
8 -- -1
7 -- -1
4 -- -1
5 -- -1
Thus, initial assumption about existing solution with complexity O(N) is not quite applicable to the expected result.

c++ Algorithm to Compare various length vectors and isolate "unique", sort of

I have a complex problem and have been trying to identify what needs to be a very, very efficient algorithm. I'm hoping i can get some ideas from you helpful folks. Here is the situation.
I have a vector of vectors. These nested vectors are of various length, all storing integers in a random order, such as (pseudocode):
vector_list = {
{ 1, 4, 2, 3 },
{ 5, 9, 2, 1, 3, 3 },
{ 2, 4, 2 },
...,
100 more,
{ 8, 2, 2, 4 }
}
and so on, up to over 100 different vectors at a time inside vector_list. Note that the same integer can appear in each vector more than once. I need to remove from this vector_list any vectors that are duplicates of another vector. A vector is a duplicate of another vector if:
It has the same integers as the other vector (regardless of order). So if we have
vec1 = { 1, 2, 3 }
vec2 = { 2, 3, 1 }
These are duplicates and I need to remove one of them, it doesnt matter which one.
A vector contains all of the other integers of the other vector. So if we have
vec1 = { 3, 2, 2 }
vec2 = { 4, 2, 3, 2, 5 }
Vec2 has all of the ints of vec1 and is bigger, so i need to delete vec1 in favor of vec2
The problem is as I mentioned the list of vectors can be very big, over 100, and the algorithm may need to run as many as 1000 times on a button click, with a different group of 100+ vectors over 1000 times. Hence the need for efficiency. I have considered the following:
Sorting the vectors may make life easier, but as I said, this has to be efficient, and i'd rather not sort if i didnt have to.
It's more complicated by the fact that the vectors aren't in any order with respect to their size. For example, if the vectors in the list were ordered by size:
vector_list = {
{ },
{ },
{ },
{ },
{ },
...
{ },
{ }
}
It might make life easier, but that seems like it would take a lot of effort and I'm not sure about the gain.
The best effort I've had so far to try and solve this problem is:
// list of vectors, just 4 for illustration, but in reality more like 100, with lengths from 5 to 15 integers long
std::vector<std::vector<int>> vector_list;
vector_list.push_back({9});
vector_list.push_back({3, 4, 2, 8, 1});
vector_list.push_back({4, 2});
vector_list.push_back({1, 3, 2, 4});
std::vector<int>::iterator it;
int i;
int j;
int k;
// to test if a smaller vector is a duplicate of a larger vector, i copy the smaller vector, then
// loop through ints in the larger vector, seeing if i can find them in the copy of the smaller. if i can,
// i remove the item from the smaller copy, and if the size of the smaller copy reaches 0, then the smaller vector
// was a duplicate of the larger vector and can be removed.
std::vector<int> copy;
// flag for breaking a for loop below
bool erased_i;
// loop through vector list
for ( i = 0; i < vector_list.size(); i++ )
{
// loop again, so we can compare every vector to every other vector
for ( j = 0; j < vector_list.size(); j++ )
{
// don't want to compare a vector to itself
if ( i != j )
{
// if the vector in i loop is at least as big as the vector in j loop
if ( vector_list[i].size() >= vector_list[j].size() )
{
// copy the smaller j vector
copy = vector_list[j];
// loop through each item in the larger i vector
for ( k = 0; k < vector_list[i].size(); k++ ) {
// if the item in the larger i vector is in the smaller vector,
// remove it from the smaller vector
it = std::find(copy.begin(), copy.end(), vector_list[i][k]);
if (it != copy.end())
{
// erase
copy.erase(it);
// if the smaller vector has reached size 0, then it must have been a smaller duplicate that
// we can delete
if ( copy.size() == 0 ) {
vector_list.erase(vector_list.begin() + j);
j--;
}
}
}
}
else
{
// otherwise vector j must be bigger than vector i, so we do the same thing
// in reverse, trying to erase vector i
copy = vector_list[i];
erased_i = false;
for ( k = 0; k < vector_list[j].size(); k++ ) {
it = std::find(copy.begin(), copy.end(), vector_list[j][k]);
if (it != copy.end()) {
copy.erase(it);
if ( copy.size() == 0 ) {
vector_list.erase(vector_list.begin() + i);
// put an extra flag so we break out of the j loop as well as the k loop
erased_i = true;
break;
}
}
}
if ( erased_i ) {
// break the j loop because we have to start over with whatever
// vector is now in position i
break;
}
}
}
}
}
std::cout << "ENDING VECTORS\n";
// TERMINAL OUTPUT:
vector_list[0]
[9]
vector_list[1]
[3, 4, 2, 8, 1]
So this function gives me the right results, as these are the 2 unique vectors. It also gives me the correct results if i push the initial 4 vectors in reverse order, so the smallest one comes last for example. But it feels so inefficient comparing every vector to every other vector. Plus i have to create these "copies" and try to reduce them to 0 .size() with every comparison I make. very inefficient.
Anyways, any ideas on how I could make this speedier would be much appreciated. Maybe some kind of organization by vector length, I dunno.... It seems wasteful to compare them all to each other.
Thanks!
Loop through the vectors and for each vector, map the count of unique values occurring in it. unordered_map<int, int> would suffice for this, let's call it M.
Also maintain a set<unordered_map<int, int>>, say S, ordered by the size of unordered_map<int, int> in decreasing order.
Now we will have to compare contents of M with the contents of unordered_maps in S. Let's call M', the current unordered_map in S being compared with M. M will be a subset of M' only when the count of all the elements in M is less than or equal to the count of their respective elements in M'. If that's the case then it's a duplicate and we'll not insert. For any other case, we'll insert. Also notice that if the size of M is greater than the size of M', M can't be a subset of M'. That means we can insert M in S. This can be used as a pre-condition to speed things up. Maintain the indices of vectors which weren't inserted in S, these are the duplicates and have to be deleted from vector_list in the end.
Time Complexity: O(N*M) + O(N^2*D) + O(N*log(N)) = O(N^2*D) where N is the number of vectors in vector_list, M is the average size of the vectors in vector_list and D is the average size of unordered_map's in S. This is for the worst case when there aren't any duplicates. For average case, when there are duplicates, the second complexity will come down.
Edit: The above procedure will create a problem. To fix that, we'll need to make unordered_maps of all vectors, store them in a vector V, and sort that vector in decreasing order of the size of unordered_map. Then, we'll start from the biggest in this vector and apply the above procedure on it. This is necessary because, a subset, say M1 of a set M2, can be inserted into S before M2 if the respective vector of M1 comes before the respective vector of M2 in vector_list. So now we don't really need S, we can compare them within V itself. Complexity won't change.
Edit 2: The same problem will occur again if sizes of two unordered_maps are the same in V when sorting V. To fix that, we'll need to keep the contents of unordered_maps in some order too. So just replace unordered_map with map and in the comparator function, if the size of two maps is the same, compare element by element and whenever the keys are not the same for the very first time or are same but the M[key] is not the same, put the bigger element before the other in V.
Edit 3: New Time Complexity: O(N*M*log(D)) + O(N*D*log(N)) + O(N^2*D*log(D)) = O(N^2*D*log(D)). Also you might want to pair the maps with the index of the respective vectors in vector_list so as to know which vector you must delete from vector_list when you find a duplicate in V.
IMPORTANT: In sorted V, we must start checking from the end just to be safe (in case we choose to delete a duplicate from vector_list as well as V whenever we encounter it). So for the last map in V compare it with the rest of the maps before it to check if it is a duplicate.
Example:
vector_list = {
{1, 2, 3},
{2, 3, 1},
{3, 2, 2},
{4, 2, 3, 2, 5},
{1, 2, 3, 4, 6, 2},
{2, 3, 4, 5, 6},
{1, 5}
}
Creating maps of respective vectors:
V = {
{1->1, 2->1, 3->1},
{1->1, 2->1, 3->1},
{2->2, 3->1},
{2->2, 3->1, 4->1, 5->1},
{1->1, 2->2, 3->1, 4->1, 6->1},
{2->1, 3->1, 4->1, 5->1, 6->1},
{1->1, 5->1}
}
After sorting:
V = {
{1->1, 2->2, 3->1, 4->1, 6->1},
{2->1, 3->1, 4->1, 5->1, 6->1},
{2->2, 3->1, 4->1, 5->1},
{1->1, 2->1, 3->1},
{1->1, 2->1, 3->1},
{1->1, 5->1},
{2->2, 3->1}
}
After deleting duplicates:
V = {
{1->1, 2->2, 3->1, 4->1, 6->1},
{2->1, 3->1, 4->1, 5->1, 6->1},
{2->2, 3->1, 4->1, 5->1},
{1->1, 5->1}
}
Edit 4: I tried coding it up. Running it a 1000 times on a list of 100 vectors, the size of each vector being in range [1-250], the range of the elements of vector being [0-50] and assuming the input is available for all the 1000 times, it takes around 2 minutes on my machine. It goes without saying that there is room for improvement in my code (and my machine).
My approach is to copy the vectors that pass the test to an empty vector.
May be inefficient.
May have bugs.
HTH :)
C++ Fiddle
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main(int, char **) {
using namespace std;
using vector_of_integers = vector<int>;
using vector_of_vectors = vector<vector_of_integers>;
vector_of_vectors in = {
{ 1, 4, 2, 3 }, // unique
{ 5, 9, 2, 1, 3, 3 }, // unique
{ 3, 2, 1 }, // exists
{ 2, 4, 2 }, // exists
{ 8, 2, 2, 4 }, // unique
{ 1, 1, 1 }, // exists
{ 1, 2, 2 }, // exists
{ 5, 8, 2 }, // unique
};
vector_of_vectors out;
// doesnt_contain_vector returns true when there is no entry in out that is superset of any of the passed vectors
auto doesnt_contain_vector = [&out](const vector_of_integers &in_vector) {
// is_subset returns true a vector contains all the integers of the passed vector
auto is_subset = [&in_vector](const vector_of_integers &out_vector) {
// contained returns true when the vector contains the passed integer
auto contained = [&out_vector](int i) {
return find(out_vector.cbegin(), out_vector.cend(), i) != out_vector.cend();
};
return all_of(in_vector.cbegin(), in_vector.cend(), contained);
};
return find_if(out.cbegin(), out.cend(), is_subset) == out.cend();
};
copy_if(in.cbegin(), in.cend(), back_insert_iterator<vector_of_vectors>(out), doesnt_contain_vector);
// show results
for (auto &vi: out) {
copy(vi.cbegin(), vi.cend(), std::ostream_iterator<int>(std::cout, ", "));
cout << "\n";
}
}
You could try something like this. I use std::sort and std::includes. Perhaps this is not the most effective solution.
// sort all nested vectors
std::for_each(vlist.begin(), vlist.end(), [](auto& v)
{
std::sort(v.begin(), v.end());
});
// sort vector of vectors by length of items
std::sort(vlist.begin(), vlist.end(), [](const vector<int>& a, const vector<int>& b)
{
return a.size() < b.size();
});
// exclude all duplicates
auto i = std::begin(vlist);
while (i != std::end(vlist)) {
if (any_of(i+1, std::end(vlist), [&](const vector<int>& a){
return std::includes(std::begin(a), std::end(a), std::begin(*i), std::end(*i));
}))
i = vlist.erase(i);
else
++i;
}

how to organize one vector by placing into another vector using for loop c++

I was wondering how I could possibly organize one vector by placing it into an another. (Note: They are vector of objects). What i have so far is:
double done;
for ( int i = 0; i < id; i++ )
{
done = guy[i].done();
int smallest = i;
for( int j = i + 1; j < id; j++ ){
if( done > guy[j].done() )
{
done = guy[j].done();
smallest = j;
}
}
newGuy.push_back( guy[smallest] );
}
This doesn't organize every part of the vector, and sometimes even copies the same guy into the newGuy. Any ideas?
If you are trying to sort the vector, you could define a custom less-than comparator for your objects, and use std::sort.
bool myComparison(const MyType& lhs, const MyType& rhs) {
return lhs.done() < rhs.done();
}
std::vector<MyType> guy = ....;
std::sort(guy.begin(), guy.end(), myComparison);
If you want it all to go to a new vector, then just copy the original, then sort the copy:
std::vector<MyType> newGuy = guy;
std::sort(newGuy.begin(), newGuy.end(), myComparison);
Because you are not removing your smallest person from the old array when you put it into the new one. Consider the values [5,4,3,2,1]
Your algorithm will on the first value for i find that the smallest is j=4 (value 1) and push 1 onto the new array, then it will do this for i=2 and so on until you have only [1,1,1,1,1]
Here is what you are doing, where the bold numbers are the ones being looped over, and the second array is the output array.
Pass 1:
[5 ,4, 3, 2, 1]
[1]
Pass 2:
[5, 4, 3, 2, 1]
[1,1]
Pass 3:
[5, 4, 3, 2, 1]
[1,1,1]
Pass 4:
[5, 4, 3, 2, 1]
[1,1,1,1]
Pass 5:
[5, 4, 3, 2, 1]
[1,1,1,1,1]
Just remove the item that you just found to be the smallest from the old vector when you add it to the new one each time. Of course as other people have pointed out it would actually be better to just use std's sorting algorithms