std::unique() to compare two vectors?

Pages: 12
Is it possible to have std::unique() compare two separate vectors?

For example:
- Vec #1 = {1, 2, 3, 4, 5}
- Vec #2 = {0, 2, 10, 11, 12, 13, 14, 15}

std::unique() would check both of the vectors and notice that they each have 2 as a duplicate so it would remove the 2 from both vectors but leave the rest untouched.

Thanks!
Did you even read any documentation for that standard function?

Short answer, no. For more information find and read some documentation.
jlb wrote:
Did you even read any documentation for that standard function?

Short answer, no. For more information find and read some documentation.

No need to be rude. I've spent over 6 hours straight trying to figure out how to do a very difficult problem I'm trying to solve and I've read countless documentation pages. So I apologize if I missed something / forgot something.

I was thinking just because I don't see a way doesn't mean it's not possible. Perhaps someone with more knowledge knows how (was my train of thought). Or that they would suggest a different function that does something similar.
Last edited on
Long answer is that it may be possible but it will take some work. You will need to either create a third vector and copy the elements of the other two vectors to the new vector (or if you won't need one of the two original vectors just append one vector into the other). Now once you have a vector that contains all the elements you will probably need to sort the vector before you try using std::unique.
A trick you can do for deleting the current iterator of a vector you are looping through is by making
1
2
for(auto it=cont.begin();it != cont.end(); ++it)
{} 

into
1
2
3
4
5
6
for(auto it=cont.begin();it != cont.end();)
{
  if(delete){
    cont.erase(it);
  }else{++it;}
}

Of course your condition to delete requires you to loop through another vector to know if deleting is necessary, and to delete that value from the 2nd vector as well.

The most efficient way (from my point of view) of doing this would be to ignore what I said before and use the method that std::remove uses, its more complicated, and you have to rewrite it to use 2 ranges (the implementation is originally ~10 lines of code), the core logic is still the same you are just avoiding cont.erase(it), performance may not be a requirement, and overall using the naive approach is still super fast.
Friendly reminder that std::vector::erase invalidates the iterator that's passed to it. You need to make sure to set it to the new iterator returned by erase.
https://en.cppreference.com/w/cpp/container/vector/erase#Example

-Albatross
<algorithm> is your friend here.

The operation you're looking for is closely related to std::set_symmetric_difference. It yields elements corresponding to the disjunctive union of two sets: elements not in both. Unfortunately, that function will not solve the problem in one step because it only has one output range.

You can compute v1 ∩ (v1 △ v2) and v2 ∩ (v1 △ v2); alternatively, compute v1 ⊖ (v1 ∩ v2) and v2 ⊖ (v1 ∩ v2). The latter approach is taken in the program below. Note that is the binary operation corresponding to the symmetric difference, and corresponds to set intersection:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <vector>
#include <iostream>
#include <algorithm>
#include <cassert>

template <typename T>
void print(T const& v)
{ 
  std::cout << "{ "; 
  for (auto elt : v) 
    std::cout << elt << ' ';
        
  std::cout << "}\n";
}

std::vector<int> set_difference(std::vector<int> const& v1,
                                std::vector<int> const& v2)
{
  std::vector <int> diff;
  std::set_difference
    (std::begin(v1), std::end(v1),
     std::begin(v2), std::end(v2), std::back_inserter(diff));
  return diff;
}

int main()
{
  std::vector const v1 { 1, 2, 3, 4, 5 };
  std::vector const v2 { 0, 2, 10, 11, 12, 13, 14, 15 };
  assert(std::is_sorted(std::begin(v1), std::end(v1)));
  assert(std::is_sorted(std::begin(v2), std::end(v2)));
    
  std::cout << "v1 = ";
  print(v1); 
    
  std::cout << "v2 = ";
  print(v2);

  std::vector<int> intersection; 
  std::set_intersection
    (std::begin(v1), std::end(v1), std::begin(v2), std::end(v2),
     std::back_inserter(intersection));
     
  std::cout << "v1 ∩ v2 = ";
  print(intersection);
  
  std::cout << "v1 ⊖ (v1 ∩ v2) = ";
  print(set_difference(v1, intersection));
     
  std::cout << "v2 ⊖ (v1 ∩ v2) = ";
  print(set_difference(v2, intersection));
}

http://coliru.stacked-crooked.com/a/7dba7692b7fd2528
Last edited on
Here's an asymptotically optimal implementation that solves the problem with O(1) memory complexity and one pass through each input range. It's essentially a loop fusion of std::remove with std::set_intersection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
template <typename ForwardIt1, typename ForwardIt2, typename Compare>
  std::pair <ForwardIt1, ForwardIt2> remove_intersection
    (ForwardIt1 v1_begin, ForwardIt1 v1_end,
     ForwardIt2 v2_begin, ForwardIt2 v2_end, Compare comp)
  {
    ForwardIt1 v1_remove = v1_begin;
    ForwardIt2 v2_remove = v2_begin;
    
    while (v1_begin != v1_end && v2_begin != v2_end)
    {
      if (comp(*v1_begin, *v2_begin))
        *v1_remove++ = std::move(*v1_begin++);
      else if (comp(*v2_begin, *v1_begin))
        *v2_remove++ = std::move(*v2_begin++);
      else
      {
        v1_begin++;
        v2_begin++;
      }
    }

    return { std::copy(std::make_move_iterator(v1_begin),
                       std::make_move_iterator(v1_end), v1_remove),
             std::copy(std::make_move_iterator(v2_begin),
                       std::make_move_iterator(v2_end), v2_remove) };
  }


Live demo:
http://coliru.stacked-crooked.com/a/0fc6bd669a18f08e
Last edited on
To Everyone:
Thank you everyone for your replies! Apologies for the late reply. I took a few days to finish some homework and life issues. Turns out the break was also good for me as I woke up today and realized:
1. I was looking at the problem incorrectly. I need to count how many duplicates there are print that.
2. I came up with an idea of how to solve this issue, similar to what jlb said. Although still having an issue with it (explained in my response to jlb below).

Unfortunately, that means my current question is no longer valid. Sorry :/ I see how much work you all put into responding. But I will still read all of them and try to learn from them! :)


jlb wrote:
Long answer is that it may be possible but it will take some work. You will need to either create a third vector and copy the elements of the other two vectors to the new vector (or if you won't need one of the two original vectors just append one vector into the other). Now once you have a vector that contains all the elements you will probably need to sort the vector before you try using std::unique.

Thanks. I woke up with a similar idea but with std::find and/or std::count (my explanation above explains why I'm using these instead of std::unique()). Although for some reason my solution using std::find() doesn't work and I can't figure out why.

Explanation of Program Purpose
Basically what I'm currently doing is user 1's info is being stored in the first half of the vector. Then user 2's info is being stored in the second half. Then I use std::find() on the second half and try to find each item from the first half one at a time (for loop).

My Function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Returns number of CDs both Jack AND Jill have:
int countDuplicates(const int &jackCDCount, const std::vector<int> &catalog) {
    // For every position in Jack's catalog of CDs, it will try to find the same CD in Jill's section of the vector.
    int sumOfDuplicates = 0;
    for (int i = 0; i < jackCDCount; ++i) {
        // Tries to find Jack's CD catalog number in Jill's CDs.
        // - If it finds it, it'll add to a sum of duplicate catalog numbers.
        // - If it does not find it, it'll do nothing.
        if (std::find(catalog.begin()+jackCDCount, catalog.end(), catalog[i]) == catalog[i]) {
            ++sumOfDuplicates;
        }
    }
    return sumOfDuplicates;    
}


Full Code:
http://cpp.sh/4h43k

I can't figure out why it's not working though. Do you know why it's not working?

poteto wrote:
The most efficient way (from my point of view) of doing this would be to ignore what I said before and use the method that std::remove uses, its more complicated, and you have to rewrite it to use 2 ranges (the implementation is originally ~10 lines of code), the core logic is still the same you are just avoiding cont.erase(it), performance may not be a requirement, and overall using the naive approach is still super fast.

Thanks for your suggestion! I appreciate the info and explaining the performance difference between them.

mbozzi wrote:
<algorithm> is your friend here.

The operation you're looking for is closely related to std::set_symmetric_difference. It yields elements corresponding to the disjunctive union of two sets: elements not in both. Unfortunately, that function will not solve the problem in one step because it only has one output range.

You can compute v1 ∩ (v1 △ v2) and v2 ∩ (v1 △ v2); alternatively, compute v1 ⊖ (v1 ∩ v2) and v2 ⊖ (v1 ∩ v2). The latter approach is taken in the program below. Note that △ is the binary operation corresponding to the symmetric difference, and ∩ corresponds to set intersection:
 
...

http://coliru.stacked-crooked.com/a/7dba7692b7fd2528

Thanks for your reply!

I have some questions:
1. Why did you use std::begin(v1) instead of v1.begin()? I read on:
https://en.cppreference.com/w/cpp/iterator/begin
"Returns exactly c.begin(), which is typically an iterator to the beginning of the sequence represented by c."
But there was also some other stuff it mentioned that I honestly did not understand.

2. Is there a reason to use this over the other, simpler, solutions mentioned by others? It is very hard for me to understand at my current level. But I also am willing to try learning something - if I have the time to.

3. Does ⊖ mean the numbers that are NOT in both vectors (so everything except 2)?

4. To clarify, your program (for your first msg) does these steps (in order):
    a. Creates the two vectors and makes sure they are sorted.
    
	b. Prints the vector's original information.
    
	c. Creates a new vector called intersection and stores copies of all data from v1 and v2 that are in both vectors (such as 2).
	Note to self: '∩' means it is in both data sets. 
        - This will check both vectors from step a for data that is the same (such as the 2 from both vectors). 
        - Then it will copy the data that is the same in both vectors (such as 2) and store it in the intersection vector.
            * If there are multiple of the same number, it will add all of those to the intersection vector.
			  For example, let's say in v1 there were {1, 2, 2, 2, 3, 4, 5}. Then in v2 there were {1}. Then the inersection vector
			  would have {1, 1, 2, 2, 2} right? And it preserves the order. So it would NOT be: {2, 1, 2, 2, 1} for example.
            * Note: I'm reading https://gyazo.com/b63aec527009a8534860ade9edc3b496
			  from https://en.cppreference.com/w/cpp/algorithm/set_intersection.
    
	d. Then program will use set_difference() function to compare v1 with intersection vector. The function will:
        * Create a new vector called diff.
        * Copy all items from v1 that are NOT in intersection vector then stores it into diff vec.
           - It does the copy part with std::set_difference() and it does the storing info part with std::back_inserter().
             https://en.cppreference.com/w/cpp/iterator/back_inserter
               * The purpose of std::back_inserter() is it's push_back() but allows adding multiple
                  of the same number at once. Although for this program I don't see why you'd use
                  it instead of push_back()?
        * Then function returns diff vector and prints result in main().
    
	e. Does same as part d but for v2.


Wow, when I first saw that I was thinking this is super difficult but I broke it down into smaller more manageable parts and it really helped. Also typing the steps helped a ton. :)
Edit: Now reading your second message and experiencing the "super difficult" part again. ._.
Last edited on
Since you really aren't interested in the quantity of unique numbers std::unique is really not the way to go.

I can't figure out why it's not working though. Do you know why it's not working?

Have you checked that your file reading is working correctly? It doesn't look correct to me. The thing that popped out at me is that you are only trying to handle one run through the file. According to the instructions it appears that there can be multiple data sets inside the file.
Your instructions:
The input consists of a sequence of test cases.


So the first thing to do is verify that you're reading the file correctly, it looks to me like that is your first failure.

Remember that the first line in each data set is the number of items each person has (3 3 in your example) so the first thing you need to do is read these values and then possibly (may not need this see note 1 below) create a vector for each person. And note that Jack and Jill may have a different amount of items.

Again your instructions:
The first line of each test case contains two positive integers N and M, each at most one million, specifying the number of CDs owned by Jack and by Jill, respectively.


Have you considered using a std::map<"catalog number", "number of duplicates"> instead?

Note 1: This can be done without creating the intermediate vectors, but having the vectors will make it easier to insure that you are reading the file correctly.

Oh and by the way your function definitions/declarations don't look quite right either.

void storeInputInVec(const unsigned int &numOfCDs, std::vector<unsigned int> &catalogOfCDs);
You are attempting to pass numOfCDs as a const before you have even read these values. Also passing a POD (Plain Old Data) by a const reference is usually not necessary, just pass by value instead. Also you will need to read the first line before you attempt to read the rest of the information.

int countDuplicates(const int &jackCDCount, const std::vector<unsigned int> &catalog); // counts & returns number of CDs both Jack AND Jill have.
Here you really don't even need the count since a std::vector knows it's size.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <vector>
#include <set>
using namespace std;

//================================================

int numDuplicates( const vector<int> &A, const vector<int> &B )
{
   set<int> working( A.begin(), A.end() );
   working.insert( B.begin(), B.end() );
   return A.size() + B.size() - working.size();
}

//================================================

int main()
{
   vector<int> Jack = { 0, 2, 3, 4, 5 };
   vector<int> Jill = { 0, 2, 10, 11, 12, 13, 14, 15 };
   cout << "There are " << numDuplicates( Jack, Jill ) << " duplicate(s)\n";
}
1. Why did you use std::begin(v1) instead of v1.begin()?
Only because std::begin came to mind first. There's no reason to choose one over the other in this limited case.

3. Does ⊖ mean the numbers that are NOT in both vectors (so everything except 2)?
Yes, you got it. means "set difference": a ⊖ b is the set of elements in a that are not in b, and v2 ⊖ (v1 ∩ v2) is the elements in v2 that are not in both v1 and v2.

2. Is there a reason to use this over the other, simpler, solutions mentioned by others?

What are those other solutions?
- I don't understand how @jlb's suggestion about std::unique can solve the original problem.
- I basically implemented a variation on @poteto's "efficient" suggestion in my second post.
- After that, the problem changed.

IMO, program 1 is a pretty clear description of intent behind some inscrutable syntax. The intent is:
Step 1: Compute the elements in both (std::set_intersection) v1 and v2.
Step 2: Compute the elements in v1 that are not in (set_difference) both v1 and v2.
Step 3: Compute the elements in v2 that are not in (set_difference) both v1 and v2.

Program 2 is an efficient approach: it will never allocate memory, and it only runs through the input data once. Contrast this to the program above, which does the same work more than once, and needs extra memory to store the set intersection (an intermediate result).

4. To clarify, your program (for your first msg) does these steps (in order)

Roughly like this:
 a. Create two sorted input vectors, v1 and v2.
 b. Print v1 and v2.
 c. Create a new vector called intersection filled with copies of elements that appear in both v1 and v2.
   Note to self: '∩' means an element is in both data sets.
   * std::set_intersection efficiently searches through both v1 and v2 for elements that are equal.
   for each pair of equal elements, one element is pushed-back into intersection.
   * std::set_intersection behaves like
    each pair of equal elements "cancels out". For example, given the input vectors
     v1 = { 1, 1, 2, 3, 4, 5, 8 }; v2 = { 1, 1, 2, 2, 6, 7, 8 };
    their intersection is { 1, 1, 2, 8 }, because set_intersection pairs elements that align like this:
     v1           = { 1, 1, 2,    3, 4, 5,       8 }
     v2           = { 1, 1, 2, 2,          6, 7, 8 }
     intersection = { 1, 1, 2,                   8 }
   Order is preserved when computing the intersection.

 d. Compute the elements in v1 that are not in intersection.
  * Create a new vector called diff.
  * std::set_difference efficiently searches through both v1 and intersection for elements in v1 that are not in
   intersection.
    - a copy of each such element is pushed-back into diff.
    - std::back_inserter allows us to avoid answering the question "how big do I make diff".
     This is useful, because we don't know precisely how many elements std::set_difference will produce.
     std::back_inserter allows std::set_difference to make diff as big as it requires.

 e. Does same as part d but for v2.

Edit: Now reading your second message and experiencing the "super difficult" part again.

It would be a good idea to study std::remove and std::set_intersection before trying to make sense of that.

The idea is to run through both input ranges in a manner similar to std::set_intersection.
Elements that belong to the intersection take the else clause and are "removed" as-if by the loop inside std::remove.
Finally, when the end of any input range is reached, trailing elements are shifted zero or more spaces left with std::copy to finish-up.

The result is a pair of iterators corresponding to the new ends of the sequences, just like std::remove.
Last edited on
To everyone:
Thank you all for your replies again! I'm very sorry about how long it takes me to reply. I'm overwhelmed by other homework I need to get done but I'll respond to each of you now. :)

First off, responding to jlb:
Update:
Thank you for all of your responses, with your help I was able to figure out my mistakes and improve upon my code. Switching to using two vectors instead of one really helped. Also, I improved my code further by switching to binary_search() instead of find() because the program could store up to 1 million catalog IDs per vector so that would work faster. :)

Also I appreciate you pointing out ways to improve my code rather than only to solve it.
Lastly, you mentioned it's not usually required to const reference PODs (Plain Old Date). The reference part makes sense and was something I had forgotten. However, the const part I'm wondering about because I read I should use const wherever possible on CPlusPlus.com (but I can't seem to find the link now). But if I recall correctly the reason was it makes it easier for other developers (and for yourself later) to more quickly understand what your code means by using const wherever possible.

_____________________________
lastchance wrote:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <vector>
#include <set>
using namespace std;

//================================================

int numDuplicates( const vector<int> &A, const vector<int> &B )
{
   set<int> working( A.begin(), A.end() );
   working.insert( B.begin(), B.end() );
   return A.size() + B.size() - working.size();
}

//================================================

int main()
{
   vector<int> Jack = { 0, 2, 3, 4, 5 };
   vector<int> Jill = { 0, 2, 10, 11, 12, 13, 14, 15 };
   cout << "There are " << numDuplicates( Jack, Jill ) << " duplicate(s)\n";
}

Jeez o_o that is ~1/2 the size of my code.
Although that said I also have assert() and auto testing set up. :P

Questions:
1.) Would this still be a good setup if each vector can contain up to 1 million numbers in it?
2.) To clarify, set will only allow inserting unique numbers. So you're:
- taking advantage of this feature by adding all numbers from the first vector into the set.
- Then you try adding all numbers from the second vector (but it won't add duplicate numbers).
- Then you add the sizes of the two original vectors together to equal all numbers in total (including duplicates) minus (-) all numbers that are not duplicate. Which will have the remaining amount be the number of duplicates. Pretty clever.

_____________________________
mbozzi wrote:
Only because std::begin came to mind first. There's no reason to choose one over the other in this limited case.

Yes, you got it. ⊖ means "set difference": a ⊖ b is the set of elements in a that are not in b, and v2 ⊖ (v1 ∩ v2) is the elements in v2 that are not in both v1 and v2.

Ah okay.

mbozzi wrote:
What are those other solutions?
- I don't understand how @jlb's suggestion about std::unique can solve the original problem.
- I basically implemented a variation on @poteto's "efficient" suggestion in my second post.
- After that, the problem changed.

Ah okay. Looking back you are correct, jlb's original proposed solution would've only half solved the problem (removing one duplicate not both).

mbozzi wrote:
IMO, program 1 is a pretty clear description of intent behind some inscrutable syntax. The intent is:
Step 1: Compute the elements in both (std::set_intersection) v1 and v2.
Step 2: Compute the elements in v1 that are not in (set_difference) both v1 and v2.
Step 3: Compute the elements in v2 that are not in (set_difference) both v1 and v2.

Program 2 is an efficient approach: it will never allocate memory, and it only runs through the input data once. Contrast this to the program above, which does the same work more than once, and needs extra memory to store the set intersection (an intermediate result).

4. To clarify, your program (for your first msg) does these steps (in order)


Roughly like this:
<explanation>

Ahh okay. Thanks that was very easy to understand. Also, to update the code to the more recent problem, it would just require removing the explanation in step d and printing the size of the intersection container. :)

mbozzi wrote:
Edit: Now reading your second message and experiencing the "super difficult" part again.

It would be a good idea to study std::remove and std::set_intersection before trying to make sense of that.

The idea is to run through both input ranges in a manner similar to std::set_intersection.
Elements that belong to the intersection take the else clause and are "removed" as-if by the loop inside std::remove.
Finally, when the end of any input range is reached, trailing elements are shifted zero or more spaces left with std::copy to finish-up.

The result is a pair of iterators corresponding to the new ends of the sequences, just like std::remove.

Hmm, thanks for explaining it but I'll definitely need to check cppreference later. Got to get ready for class but I hope to recreate my own code using std::set_interaction and maybe the other functions so I can gain a better understanding of what's going on and how to use it (without just copying your code). :P But may take a few days or so. My other hw is more pressing unfortunately. :(

Anyways, thank you all for responding. My issue is solved and I hope to practice with the new things I've learned from this post. :)



Last edited on
you mentioned it's not usually required to const reference PODs (Plain Old Date). The reference part makes sense and was something I had forgotten. However, the const part I'm wondering about because I read I should use const wherever possible on CPlusPlus.com (but I can't seem to find the link now).

If you're not passing by reference, it's less important whether or not a function parameter is defined as const or not. Any changes the function makes to the value of that parameter are to a local copy within the function; they can't affect the value in the calling code.

My opinion is that using const is still helpful to document that the function isn't supposed to change the value of that local copy - just as it would be useful to declare a local variable as const if it wasn't intended to be modified.

IIRC, it's legal to define a variable as const in the definition of a function, but to leave out the const in the declaration. This fits with what I've said above - making the parameter const is only important in the internal workings of the function, but of no relevance to the calling code that needs the declaration, if the variable is passed by value.
Last edited on
Here's basically std::set_intersection that only counts the size of the intersection (so no extra memory is required).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename ForwardIt1, typename ForwardIt2, typename Compare>
  std::size_t intersection_size
    (ForwardIt1 v1_begin, ForwardIt1 v1_end,
     ForwardIt2 v2_begin, ForwardIt2 v2_end, Compare comp)
  {
    std::size_t count = 0;  
      
    while (v1_begin != v1_end && v2_begin != v2_end)
    {
      if (comp(*v1_begin, *v2_begin))
        ++v1_begin;
      else if (comp(*v2_begin, *v1_begin))
        ++v2_begin;
      else
      {
        ++v1_begin;
        ++v2_begin;
        ++count;
      }
    }

    return count;
  }
Apologies for my late reply and I may be slow to reply again. I can only do this in my free time.

MikeyBoy wrote:
If you're not passing by reference, it's less important whether or not a function parameter is defined as const or not. Any changes the function makes to the value of that parameter are to a local copy within the function; they can't affect the value in the calling code.

My opinion is that using const is still helpful to document that the function isn't supposed to change the value of that local copy - just as it would be useful to declare a local variable as const if it wasn't intended to be modified.

IIRC, it's legal to define a variable as const in the definition of a function, but to leave out the const in the declaration. This fits with what I've said above - making the parameter const is only important in the internal workings of the function, but of no relevance to the calling code that needs the declaration, if the variable is passed by value.

Thank you for your reply & the information!

-----------------------
Okay so I've been working on my own setup similar to the first program you made mbozzi using std::set_intersection and std::back_inserter. However, there is an issue I can't seem to figure out.

I've explained the issue at the top of the code below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*
Current Bug:
If you input any double digit numbers it will act like each of the digits is a separate number when doing std::set_intersection()
    - Example input:
        6 6
        1 2 3 4 5 6
        2 4 5 10 13 14
    - Example Output:
        Numbers in both vectors: 2, 4, 5, 3

Everything is correct except it outputting the 3 at the end in the example above.
*/
#include <iostream>
#include <vector>
#include <algorithm>

// function declarations
void pushTovector(std::vector<unsigned int> &vector1, const size_t cdsSize);
int countDuplicateIds(const std::vector<unsigned int> &vector1, const std::vector<unsigned int> &vector2);


int main() {
    int jackCdCount = -1, jillCdCount = -1;
    std::cin >> jackCdCount >> jillCdCount;

    while (jackCdCount != 0 && jillCdCount != 0) {
        std::vector<unsigned int> jacksCds = {};
        std::vector<unsigned int> jillsCds = {};
        pushTovector(jacksCds, jackCdCount);
        pushTovector(jillsCds, jillCdCount);
        
        std::cout << countDuplicateIds(jacksCds, jillsCds) << '\n';

        std::cin >> jackCdCount >> jillCdCount; // preps for next loop.
    }

    return 0;
}


// function definitions:
void pushTovector(std::vector<unsigned int> &vector1, const size_t cdsSize) {
    for (unsigned int i = 0; i < cdsSize; ++i) {
        unsigned int catalogId = 0;
        std::cin >> catalogId;
        vector1.push_back(catalogId);
    }
}

int countDuplicateIds(const std::vector<unsigned int> &vector1, const std::vector<unsigned int> &vector2) {
    // Get Jill's input & Compare to Jack's container:
    std::vector<unsigned int> dupeNumsOfBoth;
    
    std::set_intersection(vector1.begin(), vector1.end(),
                          vector2.begin(), vector2.end(),
                          std::back_inserter(dupeNumsOfBoth)
                          );

    std::cout << "[Debug] Numbers in both vectors: ";
    int count = 0;
    for (int elem : dupeNumsOfBoth) {
        std::cout << elem << ", ";
        ++count;
    }
    return count;
}    


Help would be appreciated. Note I may be slow to reply. Thank you! :)
Well you asked it to output the number of duplicates ... so it did! That's the 3.
lastchance wrote:
Well you asked it to output the number of duplicates ... so it did! That's the 3.

But 3 and 13 aren't the same number. Yes, they both have the digit 3 but the numbers themselves aren't the same. How can I make it base it off the whole number not individual digits?

Please Note: Apologies for my late reply and I will be slow to reply again because school work.
Last edited on
That last '3' has nothing to do with 13, it is being caused by the cout in main() that is printing the number of duplicates you calculated inside the countDuplicate() function.
Pages: 12