Duplicate Elimination c++ using unique_copy Algorithm (Exercise 16.9) - c++

I tried to create the duplicate elimination exercise using unique_copy algorithm. I need to enter 20 integers into an empty vector. However, the output said all zeros (0 0 0 ... 0 0 0) in the vector. What should I do so that I can find the unique variables in the vector using unique_copy algorithm? Exercise 16.9 of the textbook (C++ How to Program 9th Edition) says, "Use a back_inserter to enable the vector to grow as new items are added. Use the copy algorithm to display the unique values." (738)
Here is the code:
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iterator>
using namespace std;
typedef vector<int, allocator<int> > vec_t;
typedef insert_iterator<vec_t> vec_iter;
typedef ostream_iterator<int, char, char_traits<char> > os_iter;
int main()
{
int SIZE = 20;
int twenty[20] = {};
vec_t v20(twenty, twenty + 20);
int entry;
int current_index = 0;
bool duplicated = false;
for(int i = 0; i <= SIZE; i++)
{
cout << "Enter number: " << endl;
cin >> entry;
if(entry > 10 && entry < 100)
{
for(int u = 0; u < current_index; u++)
{
if(twenty[i] == entry)
{
cout << "You already entered these numbers " << endl;
duplicated = true;
break;
}
}
if(duplicated == false)
{
twenty[current_index] = entry;
current_index++;
}
}
else
{
cout << "Error: invalid number; you must enter between 10 and 100 " << endl;
i--;
}
}
for(int x = 0; x < current_index; x++)
{
cout << twenty[x] << endl;
vec_t outcome;
vec_iter ins (outcome, outcome.begin());
cout << "Vector: " << endl << " ";
copy(v20.cbegin(), v20.cend(), os_iter(cout, " "));
cout << endl;
unique_copy(v20.cbegin(), v20.cend(), ins);
cout << endl << "After unique_copy, outcome contains ";
copy(outcome.cbegin(), outcome.cend(), os_iter(cout, " "));
cout << endl;
}
return 0;
}
I hope you will help me solve problems.
ChonglinXu

Related

How to print values in descending order for every number entered?

I need to create a program that asks the user for N unique values and print the values in descending order for every number entered. The problem is it only outputs the number 0. Can anyone point out what is wrong with my code?
#include <iostream>
using namespace std;
int main(){
//declare the variables
int N, j, i, k, z, desc, temp, sorter[N];
bool found;
//Ask the user for N size array
cout << "Enter array size: ";
cin >> N;
while(N<5){
cout << "Invalid value. N must be greater than five(5)" << endl;
cout << "Enter array size: ";
cin >> N;
}
int list[N];
//Printing how many values they need to enter
cout << " " << endl;
cout << "Please enter " << N << " values" << endl;
//Code of the program
for (int i = 0; i < N; i++){
do{
found = false;
cout << "\n" << endl;
cout << "Enter value for index " << i << ": ";
cin >> temp;
for (int j = 0; j < i; j++)
if (list[j] == temp)
found = true;
if (found == true)
cout << "Value already exist";
else{
for(int k = 0; k < i; k++){
int key = sorter[k];
j = k - 1;
while(j >= 0 && key >= sorter[j]){
sorter[j + 1] = sorter[j];
j--;
}
sorter[j + 1] = key;
}
cout << "\nValues: ";
for(int z = 0; z <= i; z++){
cout << sorter[z] <<" ";
}
}
} while(found == true);
sorter[i] = temp;
}
You shouldn't be defining the array 'sorter[N]', the position, where you are currently, because you don't have the value of 'N', during compilation the arbitrary amount of space will be allocated to the the array.
solve the other compiling errors in your code.
What you want is just a 3-line code:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> vecOfNumbers = { 1,3,5,7,9,8,6,4,2 }; // scan these numbers if you want
std::sort(vecOfNumbers.begin(), vecOfNumbers.end());
std::copy(vecOfNumbers.rbegin(), vecOfNumbers.rend(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Make sure you understand it before using it

why isn't my vector pushbacking even and odd numbers

i tried to separate even and odd numbers using vectors from a array ==>
so i made a function that returns true is number is even and false for if number is odd
then i used an if else statement where if the function returns true then it pushbacks the value in a vector and if the function returns false then it pushbacks the value in another vector , finally i printed all the elements in the vector but the output does not show any element except it shows one in the odd vector.
#include <iostream>
#include <vector>
using namespace std;
bool sort(int arr[] , int i){
if(arr[i] %2 == 0){
return true;
}
return false;
}
int main(){
int n;
cin >> n;
int *arr = new int[n];
for(int i=1 ; i<=n ; i++){
arr[i-1] = i;
}
vector <int> even , odd;
int i=0 ;
if(sort(arr , i)){
even.push_back(arr[i]);
sort(arr , i+1);
}else{
odd.push_back(arr[i]);
sort(arr,i+1);
}
cout << "the even numbers are : " << endl;
for(auto element:even){
cout << element << " ";
}
cout << endl;
cout << "the odd numbers are : " << endl;
for(auto element:odd){
cout << element << " ";
}
}
As #TonyDelroy said, you have to make for loop around call to sort(arr, i). Also first loop should go up to i <= n instead of i < n.
Your fixed working code below (see also std::partition_copy variant afterwards):
Try it online!
#include <iostream>
#include <vector>
using namespace std;
bool sort(int arr[] , int i){
if(arr[i] %2 == 0){
return true;
}
return false;
}
int main(){
int n;
cin >> n;
int *arr = new int[n];
for(int i=1 ; i<=n ; i++){
arr[i-1] = i;
}
vector <int> even , odd;
for (int i = 0; i < n; ++i)
if (sort(arr, i))
even.push_back(arr[i]);
else
odd.push_back(arr[i]);
cout << "the even numbers are : " << endl;
for(auto element:even){
cout << element << " ";
}
cout << endl;
cout << "the odd numbers are : " << endl;
for(auto element:odd){
cout << element << " ";
}
}
Input:
10
Output:
the even numbers are :
2 4 6 8 10
the odd numbers are :
1 3 5 7 9
As #chris said you can also use std::partition_copy to implement your algorithm:
Try it online!
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
int n = 0;
std::cin >> n;
std::vector<int> arr(n), odd, even;
for (int i = 1; i <= n; ++i)
arr[i - 1] = i;
std::partition_copy(arr.cbegin(), arr.cend(),
std::back_insert_iterator(odd), std::back_insert_iterator(even),
[](auto const & x){ return (x & 1) == 1; });
std::cout << "the even numbers are : " << std::endl;
for (auto element: even)
std::cout << element << " ";
std::cout << std::endl << "the odd numbers are : " << std::endl;
for (auto element: odd)
std::cout << element << " ";
}
Input:
10
Output:
the even numbers are :
2 4 6 8 10
the odd numbers are :
1 3 5 7 9
You only push one element - the first.
Your partitioning code is equivalent to
if(sort(arr , 0)){
even.push_back(arr[0]);
sort(arr , 1);
}else{
odd.push_back(arr[0]);
sort(arr,1);
}
You need to loop over all the input numbers.
You can also simplify matters with a more generally useful evenness function that doesn't depend on an array:
bool is_even(int x) { return x % 2 == 0; }
and then there is no need to store all the inputs before processing them:
int main(){
vector <int> even , odd;
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
if (is_even(x)) {
even.push_back(x);
}
else {
odd.push_back(x);
}
}
cout << "the even numbers are : " << endl;
for (auto element:even){
cout << element << " ";
}
cout << endl;
cout << "the odd numbers are : " << endl;
for (auto element:odd){
cout << element << " ";
}
}

What should be the proper declaration of array while finding the largest number in array?

C++ This is my code in C++ for finding the largest number in array. When I was running in my IDE then there was no compilation error but it was not giving me output. I think the problem is in the declaration of array at line 8. I replaced the array declaration from line 8 to line 11 then it is working fine in my IDE. So I didn't get it that why the declaration of array was not working at line 8?
#include <bits/stdc++.h>
using namespace std;
int largest_in_array(int a[], int n);
int main() // main function
{
int n; // User will enter the size of array
int arr[n]; // Line 8
cout << "Enter the size of array: " << endl;
cin >> n;
// Line 11
cout << "\nEnter the elements of array: " << endl;
for (int i = 0; i < n; i++) // This loop will run for each element of array that user wants to enter
{
cout << "Enter the " << (i + 1) << " element:";
cin >> arr[i];
cout << endl;
}
cout << "Elements are: [";
for (int i = 0; i < n; i++) // Prints the elements of array
{
// cout << "Enter the " << (i + 1) << " element:";
cout << arr[i] << " ";
// cout << endl;
}
cout << "]";
int res = largest_in_array(arr, n); //Function call
cout << "\nLargest element in array is: " << arr[res] << endl;
return 0;
}
int largest_in_array(int a[], int n) // function that will return the index of largest element in array
{
int max = 0;
for (int i = 1; i < n; i++)
{
if (a[max] < a[i])
{
max = i;
}
}
return max;
}
You declare int arr[n]; before the user has entered a value into n. n has an indeterminate value when you read it and create arr.
You don't check that the user enters a positive value into n. Zero and negative sized arrays are not valid.
Other points:
bits/stdc++.h is not a standard header which makes your program not portable. Use the proper header files, like iostream etc.
arr[n] is a Variable Length Array (VLA) which is not part of standard C++. Make it a std::vector<int> arr(n); instead.
The use of std::endl is unnessesary. There is no need to flush the output streams here. Use \n instead.
Example:
#include <iostream>
#include <limits>
#include <vector>
int largest_in_array(const std::vector<int>& a) {
int max = 0;
for(int i = 1; i < a.size(); i++) {
if(a[max] < a[i]) {
max = i;
}
}
return max;
}
int main() // main function
{
int n; // User will enter the size of array
std::cout << "Enter the size of array:\n";
// check that input succeeds and that the value is valid
if(!(std::cin >> n) || n < 1) return 1;
std::vector<int> arr(n);
std::cout << "\nEnter the elements of array:\n";
for(int i = 0; i < n; i++)
{
std::cout << "Enter the " << (i + 1) << " element:";
if(!(std::cin >> arr[i])) {
std::cout << "invalid input, bye bye\n";
return 1;
}
}
std::cout << "Elements are: [";
for(int i = 0; i < n; i++)
{
std::cout << arr[i] << " ";
}
std::cout << "]";
int res = largest_in_array(arr); // Function call
std::cout << "\nLargest element in array is: " << arr[res] << '\n';
}
That said, you could however use the standard algorithm std::max_element instead of writing your own. It returns an iterator to the maximum element.
You could also make use of range-based for loop when you don't need to know the index in the array, as in your second loop.
Example:
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <limits>
#include <vector>
int main() {
int n; // User will enter the size of array
std::cout << "Enter the size of array:\n";
if(!(std::cin >> n) || n < 1) return 1;
std::vector<int> arr(n);
std::cout << "\nEnter the elements of array:\n";
for(int i = 0; i < n; i++) // This loop will run for each element of
// array that user wants to enter
{
std::cout << "Enter the " << (i + 1) << " element:";
if(!(std::cin >> arr[i])) {
std::cout << "invalid input, bye bye\n";
return 1;
}
}
std::cout << "Elements are: [";
for(auto value : arr) { // a range-based for loop
std::cout << value << ' ';
}
std::cout << "]\n";
auto res = std::max_element(arr.begin(), arr.end());
std::cout << "Largest element in array is: " << *res << '\n';
std::size_t index = std::distance(arr.begin(), res);
std::cout << "which has index " << index << '\n';
}
When you have int n on line 8 it is initialized when you use it to create the array. When n is initialized explicitly, it's value is undefined behavior. You may be creating an array larger than the n you inputted on line 10, resulting in the array having extra random junk, it may be smaller meaning your program read memory it really shouldn't, etc.

How to generate random numbers without duplicates using a loop in c++?

I am writing a random name generator without duplicates. I want to do it without other libaries like algorithm because I want to understand how to do that. Is there a way to do that with a loop or a vector?
I thaught of adding the names that have already been to a vector and then check all the elements of the vector with a while loop but I didn't know how I can do that.
#include <windows.h>
#include <conio.h>
#include <vector>
#include <ctime>
#include <iostream>
#include <ctime>
using namespace std;
int main() {
srand((unsigned)time(0));
int names = 1;
int a = 0;
int x = 0;
vector <string> vectornames;
cout << "How many names would you like to add: ";
int amount_of_names;
cin >> amount_of_names;
while (a < amount_of_names) {
cout << "Enter name " << names << ": ";
string name;
cin >> name;
vectornames.push_back(name);
names++;
a++;
}
while (x < amount_of_names) {
cout << "\n" << vectornames.at(x);
x++; }
cout << "\npress enter to continue: ";
getch();
system("cls");
int z = 0;
while (z < amount_of_names) {
int random_number = (rand() % amount_of_names);
if (vectornames.at(random_number) != vectornames.at(z)) {
cout << "Hello ";
cout << vectornames.at(z);
cout << "! You will get " << vectornames.at(random_number) << "\n";
vectornames.push_back(vectornames.at(random_number));
getch();
z++;
}}
cout << "\n\n";
return 0;
}
The last part has some problems, you select as many names are you have entered, don't know if that was intended lets just say it was. You add the selected names to the same vector, you don't check correctly for duplicates.
while (z < amount_of_names) { <-- same amount as was entered in original loop
int random_number = (rand() % amount_of_names);
if (vectornames.at(random_number) != vectornames.at(z)) { <--- doesn't check for duplicates
cout << "Hello ";
cout << vectornames.at(z);
cout << "! You will get " << vectornames.at(random_number) << "\n";
vectornames.push_back(vectornames.at(random_number)); <---- adding to same vector
getch();
z++;
}
}
Lets see what can be done without using algoritmes ... that means we need to implement std::find or use some other structure to keep check on what is already selected.
!!!Warning untested code!!!
bool Find(const std::string& needle, const std::vector<std::string>& haystack) const {
for(const auto& straw : haystack) {
if (straw == needle) {
return true;
}
}
return false;
}
And updated code, which use a different vector to store the used names.
std::vector<std::string> used;
while (z < amount_of_names) {
int random_number = (rand() % amount_of_names);
if (!Find(vectornames.at(random_number), used)) {
cout << "Hello ";
cout << vectornames.at(z);
cout << "! You will get " << vectornames.at(random_number) << "\n";
used.push_back(vectornames.at(random_number));
getch();
z++;
}
}

I'm trying to determine the domain and range of user input ordered pairs

I have the users input in a vector of pairs. I am trying to determine the domain by just removing the duplicate x values. Then I need to determine the range by all the unique values of y. I have looked into map. I cant seem to figure it out. This is homework so I would prefer to understand how to do it rather than just a solution. Thanks!
CODE:
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int main() {
vector<pair<int, int> > sample;
vector< vector<int> > relation;
vector< vector<int> > domain;
vector< vector<int> > range;
bool loop = true;
do {
int input;
int input2;
cout << "Enter the first INT in the ordered pair: ";
cin >> input;
cout << "Enter the second INT in the ordered pair: ";
cin >> input2;
if (input != -1 && input2 != -1) {
sample.push_back(make_pair(input, input2));
}
else if (input != -1 && input2 == -1) {
cout << "ERROR, must input 2 INTS for an ordered pair." << endl;
loop = false;
}
else if (input == -1) {
loop = false;
}
} while (loop == true);
map<int, int> s;
int size = sample.size();
for (unsigned i = 0; i < size; ++i) s.insert(sample[i]);
sample.assign(s.begin(), s.end());
cout << "TEST: { ";
for (int i = 0; i < s.size(); i++) {
cout << "(" << s[i].first << "," << s[i].second << ")" << ", ";
}
cout << "}" << endl;
cout << "Relation: { ";
for (int i = 0; i < sample.size(); i++) {
cout << "(" << sample[i].first << "," << sample[i].second << ")" << ", ";
}
cout << "}" << endl;
cout << "Domain: { ";
for (int i = 0; i < sample.size(); i++) {
cout << sample[i].first << ", ";
}
cout << "}" << endl;
cout << "Range: { ";
for (int i = 0; i < sample.size(); i++) {
cout << sample[i].second << ", ";
}
cout << "}" << endl;
return 0;
}
If all you want is the unique values of x and y (without worrying about the relationships between them), you should just be able to use a couple of sets (std::set).
Just create two empty sets, xset and yset then run through all the coordinates in your original vector.
For each coordinate, add the x value to xset and the y value to yset.
Then, when you're done, you have all the unique values in both sets and you can extract the smallest and largest (or all values) from each to give range and domain.
The following code (don't use this verbatim in assignments, you'll almost certainly be pinged for plagiarism) shows how this can be done:
#include <iostream>
#include <utility>
#include <vector>
#include <set>
using namespace std;
typedef pair < int, int > tPII;
typedef vector < tPII > tVPII;
typedef vector < int > tVI;
typedef set < int > tSI;
int main() {
// Test data to use.
tVPII sample;
tPII a ( 1, 2); sample.push_back (a);
tPII b ( 9, 99); sample.push_back (b);
tPII c (314158, 271828); sample.push_back (c);
tPII d ( 1, 77); sample.push_back (d);
tPII e ( 1, 99); sample.push_back (e);
// Place individual coordinates into sets.
cout << "input data:\n";
tSI xset, yset;
for (tVPII::iterator it = sample.begin(); it != sample.end(); ++it) {
cout << " (" << it->first << "," << it->second << ")\n";
xset.insert (it->first);
yset.insert (it->second);
}
// Construct range/domain vectors from sets.
tVI xvals;
tVI yvals;
for (tSI::iterator it = xset.begin(); it != xset.end(); ++it)
xvals.push_back (*it);
for (tSI::iterator it = yset.begin(); it != yset.end(); ++it)
yvals.push_back (*it);
// Output range/domain vectors.
cout << "x values:\n";
for (tVI::iterator it = xvals.begin(); it != xvals.end(); ++it)
cout << " " << *it << "\n";
cout << "y values:\n";
for (tVI::iterator it = yvals.begin(); it != yvals.end(); ++it)
cout << " " << *it << "\n";
}
The output of that shows how the information flows into the set (removing duplicates) and back out into individual vectors for the x and y values:
input data:
(1,2)
(9,99)
(314158,271828)
(1,77)
(1,99)
x values:
1
9
314158
y values:
2
77
99
271828
Keep in mind that this treats x and y values as totally separate. If you don't want to take into the account the y values for coordinates where x already exists, it's a slight modification:
// Place individual coordinates into sets,
// discount coordinates totally if x has already been seen.
cout << "input data:\n";
tSI xset, yset;
for (tVPII::iterator it = sample.begin(); it != sample.end(); ++it) {
cout << " (" << it->first << "," << it->second << ") - ";
if (xset.find (it->first) != xset.end()) {
cout << "duplicate.\n";
} else {
cout << "inserting.\n";
xset.insert (it->first);
yset.insert (it->second);
}
}
The output of that shows the changed behaviour:
input data:
(1,2) - inserting.
(9,99) - inserting.
(314158,271828) - inserting.
(1,77) - duplicate.
(1,99) - duplicate.
x values:
1
9
314158
y values:
2
99
271828