Please help me use C++ to parse an array and only display numbers that are unique. I have written a program which answers most of the question below.
Question:
Use a one-demensional array to solve the following problem. Read in 20 numbers, each of which is between 10 and 100, inclusive. As each number is read, validate and store it in the array only if it isn't a duplicate of a number already read. After reading all the values, display only the unique values that the user entered. Provide for the "worst case" in which all 20 number are different. Use the smallest possible array to solve this problem.
What I've done:
My program creates a 20 item array. Prompts user for data, validates it and displays it. I have tried several way to only display unique data, however I have not accomplished what the question asks.
Sample User Input:
11, 12, 12, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
My Program Output:
{ 11, 12, 12, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }
Correct Program Output:
{ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }
Any advice where to go with this. See below for code. Thank you for your help!
#include <iostream>
#include <array> // needed for c++11 arrays
using namespace std;
int main()
{
const int arraySize = 20; // limit array length to 20
array <int, arraySize userArray> = {};
//Populate array with user input and validate it to be between 10 and 100
for (int i = 0; i < userArray.size(); i++)
{
cout << "Enter a number between 10 and 100" << endl;
cin >> userArray[i]; // get user input assign it to proper array subscript
while(userArray[i] > 100 || userArray[i] < 10)//validate user input to be between 10 and 100
{
cout << "Number needs to be between 10 and 100. Enter a new number" << endl;
cin >> userArray[i]; //reassign the proper array subscript if needed
}
}
cout << endl;
//display the information to look like an array
//result looks like [ v, w, x, y, z ]
cout << "[ ";
//display array values
for (int i = 0; i < userArray.size() - 1; i++)
{
cout << userArray[i] << ", ";
}
//properly display last array item
cout << userArray[(userArray.size() - 1)] << " ]" << endl;
return 0; }
If you can use std::vector, then you can use following solution.
template <typename Type>
std::vector<Type> unique_entries (std::vector<Type> vec) {
for (auto iter = vec.begin (); iter != vec.end (); ++iter) {
auto f = std::find_if (iter+1, vec.end (), [&] (const Type& val) {
return *iter == val; // (X)
});
if (f != vec.end ()) {
vec.erase (std::remove (iter+1, vec.end (), *iter), vec.end ());
}
}
return vec;
}
template <typename T>
void show (std::vector<T> vec) {
for (const auto& v : vec) {
std::cout << v << " ";
}
std::cout << std::endl;
}
And example would be like that:
std::vector<int> vec {11, 12, 12, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27};
std::vector<short> vec2 {1, 1, 1, 2, 3, 2, 1, 2, 1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 10};
std::vector<std::string> vec3 {"a", "a", "a", "aa", "b", "b", "bb", "c"};
show (vec);
show (unique_entries (vec));
show (vec2);
show (unique_entries (vec2));
show (vec3);
show (unique_entries (vec3));
And the output:
11 12 12 12 13 14 15 15 16 17 18 19 20 21 22 23 24 25 26 27
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
1 1 1 2 3 2 1 2 1 2 3 2 1 2 3 2 1 2 10
1 2 3 10
a a a aa b b bb c
a aa b bb c
Look at the line (X), basically you can use this unique_entries for all types which offer operator==, but you have to keep in mind that this will probably fail if you use this function for floating point types.
Hope this is what you are looking for........... Basically I use an another array to store the elements already entered by the user. So when the user enters a number it checks whether it is already in the array of 'entered elements' or not.
#include<iostream>
#define MAX 20
using namespace std;
int main()
{
int list[MAX],visitedElements[MAX];
int noElements,element,currentIndex;
bool flag=false;
cout<<"Enter total no. of elements(MAX=20):"<<endl;
cin>>noElements;
for(int i=0; i<noElements; i++)
{
visitedElements[i] = -1;
}
for(int i=0;i<noElements;i++)
{
currentIndex=i;
cout<<"Enter Element:"<<endl;
cin>>element;
for(i=0;i<currentIndex;i++)
{
if(visitedElements[i] == element)
{
flag==true;
break;
}
}
if(flag == false)
{
list[i]=element;
visitedElements[i] = element;
}
flag = false;
}
cout<<"Elements in list are"<<endl;
for(int i=0 ; i<noElements ;i++)
cout<<list[i]<<endl;
return 0;
}
#include <iostream>
using namespace std;
int main(){
int tab[10];
int i=0,j;
int number=0;
int counter=1;
bool flag=true;
int tries=0;
while(tries<10){
do{
cin>>number;
tries++;
if((number>100)||(number<10)){
cout<<"Wrong number, has to be between 10 and 100"<<endl;
}
}
while((number>100)||(number<10));
flag=true;
if(i==0){
tab[i]=number;
}
else{
for(j=0; j<counter; j++){
if(tab[j]==number){
flag=false;
i--;
break;
}
}
}
if(flag==true){
tab[i]=number;
counter++;
}
i++;
}
for(i=0; i<counter-1; i++){
cout<<tab[i]<<", ";
}
}
I kinda meesed it up probably. I'm new to programing but this is my solution.
So. You said it has to take 20 digits, mine takes 10, after 10 inputs it will list the array. So if my input is "10, 10, 10, 12, 13, 15, 15, 18, 22, 22"
the output is: "10, 12, 13, 15, 18, 22"
I could probably erase half of the code but like i said I'm a beginner and i was writing it in a hurry.
EDIT: Ups, small mistake in the array declaration. I was testing it for 5 elements and forgot to make a bigger array.
The question asked to use one array, so I would loop over the numbers already in the array after reading in each number and check for duplicates. It would look something like this:
#include <iostream>
constexpr int ARRAY_SIZE = 20;
int main()
{
int userArray[ARRAY_SIZE], validNumbers = 0;
for(int i = 0; i < ARRAY_SIZE; i++)
{
int num;
bool isGood = true;
std::cin >> num;
//code to check if input is in range here
for(int j = 0; j < validNumbers; j++)
{
if(userArray[j] == num)
{
isGood = false;
break;
}
}
if(isGood)
{
userArray[validNumbers] = num;
validNumbers++;
}
}
//userArray now contains all unique numbers in the order that they were entered
for(int i = 0; i < validNumbers; i++)
{
std::cout << userArray[i];
if(i < validNumbers - 1)
{
std::cout << ' ';
}
}
std::cout << '\n';
}
inside of your for loop, instead of makign the cin go directly into the array, add another int variable and set it to equal the input
cin >> variable
then make a for loop that iterates through your current array to make sure its not a duplicate; use the line below as your for loop
for(int j = 0; j < i; j++)
if the number is already in the array, just continue. Else, add it in.
Also, instead of using a for loop in the beginning, I would use a while loop with
while(i < arraysize)
Then deincrement array size every time you see a duplicate and only increment i when you add an element
Related
Assuming we have a sorted descending vector, like:
vector<int> array {26, 21, 13, 11, 8, 3, 2}.
I would like to insert a new and different element to the ones already present, so that descending sort of vector is kept.
Example flow:
I want to insert element 22, basically added at index 1, thus vector would be: 26, 22, 21, 13, 11, 8, 3, 2
I want to insert element 17, basically added at index 3, thus vector would be: 26, 22, 21, 17, 13, 11, 8, 3, 2
I want to insert element 1, basically added at a new index, thus vector would be: 26, 22, 21, 17, 13, 11, 8, 3, 2, 1
I want to insert element 43, basically added at index 0, thus vector would be: 43, 26, 22, 21, 17, 13, 11, 8, 3, 2, 1
A fast sample implementation in C++ would be:
#include<iostream>
#include<vector>
#include <chrono>
using namespace std;
using namespace std::chrono;
int get_Index_Insert(const vector<int>& array, int lengthArray, int insertValue)
{
int whereInsert = lengthArray;
for (int i = 0; i < lengthArray; i++)
{
if (array[i] < insertValue)
{
whereInsert = i;
break;
}
}
return whereInsert;
}
int get_Index_Insert2(const vector<int>& array, int lengthArray, int insertValue)
{
int whereInsert = lengthArray;
// Break out early if these cases:
if (lengthArray == 0 || (array[lengthArray - 1] > insertValue))
return whereInsert;
// Otherwise do your binary magic:
int low = 0;
int high = lengthArray - 1;
while (low <= high)
{
int mid = low + (high - low) / 2;
if (array[mid] > insertValue)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
whereInsert = high + 1;
return whereInsert;
}
vector<int> insert_Value(const vector<int>& arrayInput, int insertValue)
{
vector<int> arrayOutput;
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert(arrayInput, lenghtArray, insertValue);
// Add it now:
for (int i = 0; i < whereInsert; i++)
arrayOutput.push_back(arrayInput[i]);
arrayOutput.push_back(insertValue);
for (int i = whereInsert + 1; i < lenghtArray + 1; i++)
arrayOutput.push_back(arrayInput[i - 1]);
return arrayOutput;
}
vector<int> insert_Value2(const vector<int>& arrayInput, int insertValue)
{
vector<int> arrayOutput;
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert2(arrayInput, lenghtArray, insertValue);
// Add it now:
for (int i = 0; i < whereInsert; i++)
arrayOutput.push_back(arrayInput[i]);
arrayOutput.push_back(insertValue);
for (int i = whereInsert + 1; i < lenghtArray + 1; i++)
arrayOutput.push_back(arrayInput[i - 1]);
return arrayOutput;
}
int main()
{
{
// START TIME
auto start = high_resolution_clock::now();
vector<int> array{ 26, 21, 13, 11, 8, 3, 2 };
array = insert_Value(array, 22);
array = insert_Value(array, 17);
array = insert_Value(array, 1);
array = insert_Value(array, 43);
auto stop = high_resolution_clock::now();
// END TIME
// Show time:
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function 1, linear search: " << duration.count() << " microseconds" << endl;
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl;
}
{
// START TIME
auto start = high_resolution_clock::now();
vector<int> array{ 26, 21, 13, 11, 8, 3, 2 };
array = insert_Value2(array, 22);
array = insert_Value2(array, 17);
array = insert_Value2(array, 1);
array = insert_Value2(array, 43);
auto stop = high_resolution_clock::now();
// END TIME
// Show time:
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function 2, binary search: " << duration.count() << " microseconds" << endl;
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl;
}
cout << endl << endl << endl;
return 0;
}
Other info that may help in deciding recommended method:
I cannot use anything else than class vector from STL; (only using it as a holder + it's push_back function, nothing else as helper function from it);
I will not have more than a 1000 elements ever in the vector.
Is there any way better to do it than above? in less complexity involved? Any source material I may have missed and that might help is very much appreciated also.
EDIT:
After some more investigations and using binary search method while seeking index position for actual element insertion (thanks to the debates from comments), edited my above sample a bit, testing execution time of a "get_Index_Insert2(...) function using early returns and binary search.
Times received (microseconds), after 3 runs:
Time taken by function 1, linear search: 60 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 33 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 1, linear search: 61 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 34 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 1, linear search: 61 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 34 microseconds
43 26 22 21 17 13 11 8 3 2 1
Instead of creating a new vector you can use the insert function to put the new value into the existing list at the desired index. See https://en.cppreference.com/w/cpp/container/vector/insert
void insert_Value(const vector<int>& arrayInput, int insertValue)
{
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert(arrayInput, lenghtArray, insertValue);
arrayInput.insert(whereInsert, insertValue);
}
#include <algorithm>
#include<iostream>
#include<vector>
using namespace std;
std::vector<int>::const_iterator get_Index_Insert(const vector<int>& array ,int insertValue) {
return std::find_if(array.cbegin(),array.cend(),[insertValue](int aValue) { return aValue < insertValue;});
}
void insert_Value(vector<int>& arrayInput, int insertValue, std::vector<int>::const_iterator aIt)
{
arrayInput.insert(aIt,insertValue);
}
int main()
{
vector<int> array{26, 21, 13, 11, 8, 3, 2 };
auto myIt = get_Index_Insert(array,22);
insert_Value(array,22,myIt);
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl << endl << endl;
return 0;
}
This is only an idea, then it can be enhanced
You don't need to pass the size of the vector, std::vector already have a member function size().
I think you overcomplicated things. You just have to iterate over the vector and compare each element with the value you want to insert. If the comparison evaluates to false, then you found where to insert the new element.
You may implement the function the following way:
template <typename val_t, typename Compare>
void insert_ordered(std::vector<val_t> & vec, const val_t & val, Compare comp)
{
bool inserted(false);
for(typename std::vector<val_t>::iterator it = vec.begin(); !inserted && (it != vec.end()); ++it)
{
if(!comp(*it, val))
{
vec.insert(it, val);
inserted = true;
}
}
if(!inserted)
vec.push_back(val);
}
It takes the vector, the value to instert and the comparison function you want.
For your use case, it may be used like this:
int main()
{
std::vector<int> v {26, 21, 13, 11, 8, 3, 2};
insert_ordered(v, 22, std::greater<int>());
insert_ordered(v, 17, std::greater<int>());
insert_ordered(v, 1, std::greater<int>());
insert_ordered(v, 43, std::greater<int>());
for(const int & i : v)
std::cout << i << ' ';
return 0;
}
Output:
43 26 22 21 17 13 11 8 3 2 1
Live example
If, for some reason, you can't use std::greater, you can define your own comparator like this:
auto desc_comp = [](const int & lhs, const int & rhs)
{
return lhs > rhs;
};
And use it like this:
insert_ordered(v, 22, desc_comp);
Edit:
If you don't mind having several exit points in the function, it can be simplified as:
template <typename val_t, typename Compare>
void insert_ordered(std::vector<val_t> & vec, const val_t & val, Compare comp)
{
for(typename std::vector<val_t>::iterator it = vec.begin(); it != vec.end(); ++it)
{
if(!comp(*it, val))
{
vec.insert(it, val);
return;
}
}
vec.push_back(val);
}
I use this script to print odd number from 1 to 30.
#include <iostream>
using namespace std;
int main( ) {
int i = 1 ;
// whele loop from 1 to 30
while (i <= 30) {
cout << i<< " , ";
i = i + 2;
}
return 0;
}
So the output Will be 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29
What i must to do if i want to add Even number after 4 Odd numbers. The output Will be like 1, 3, 5, 7, 10, 11, 13, 15, 17, 20, 21, 23, 25, 27, 30.
I hope someone can help me with this problem. Thank you
At each iteration you print a number as you are doing now, however, every 5th iterations what you do is a bit different. This is a condition you need to test in each iteration: if true, print like this, if false, print like that.
Start with the loop as you did. Since you using a counting variable that you always increment, a for loop seems more natural than a while.
int main() {
for(int i = 1; i <= 30; i += 2) {
cout << i << " , ";
}
return 0;
}
Now you add the condition test. For that, you can introduce another variable (numOddNumbers) to keep track of how many odd numbers you have printed.
int main() {
int numOddNumbers = 0;
for(int i = 1; i <= 30; i += 2) {
if(numOddNumbers > 0 && numOddNumbers % 4 == 0) {
cout << i + 1 << " , ";
numOddNumbers = 0;
} else {
cout << i << " , ";
numOddNumbers++;
}
}
return 0;
}
For the condition we can use numOddNumbers % 4 == 0 to check that numOddNumbers is amultiple of 4, but since we do not want the condition to be true when numOddNumbers == 0 we also make sure that numOddNumbers > 0.
Notice that differently from i, the numOddNumbers variable is only incremented when the condition is false, since that is when we print an odd number.
This code will print
1 , 3 , 5 , 7 , 10 , 11 , 13 , 15 , 17 , 20 , 21 , 23 , 25 , 27 , 30 ,
Note: An interesting exercise for you is to simplify this code to use just the counting variable, without the extra numOddNumbers variables. The pattern is well defined and you know that the difference is in every 5th itertion.
I can offer the solution of your problem.
#include <iostream>
#include <vector>
using namespace std;
void showContentVector(vector<int>& input)
{
for(int i=0; i<input.size(); ++i)
{
cout<<input[i]<<", ";
}
return;
}
void oddEvenNumbers(int start, int stop, int quantity, vector<int>& input)
{
if(start>stop)
{
return;
}
if(start%2!=0)
{
input.push_back(start);
++quantity;
}
if(quantity==4)
{
start+=3;
input.push_back(start);
quantity=0;
}
oddEvenNumbers(start+1, stop, quantity, input);
return;
}
void solve()
{
vector<int> inputVector;
oddEvenNumbers(0, 30, 0, inputVector);
cout<<"inputVector <- ";
showContentVector(inputVector);
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
inputVector <- 1, 3, 5, 7, 10, 11, 13, 15, 17, 20, 21, 23, 25, 27, 30,
If you will need an explanation of the solution, write the corresponding comment.
#include <iostream>
using namespace std;
int main(void) {
int i = 1;
int step = 1;
while (i <= 30) {
if (step % 5 == 0) {
cout << (i + 1) << ",";
}else{
cout << i << ",";
}
i += 2;
step++;
}
return 0;
}
For example, if the user enters the number 21, I want all the polite numbers listed. so for 21, the output would be 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21. I am new for loops and I am having a difficult time trying to get this to work. I cant include any global variables for this assignment. Any help would be greatly appreciated. Thank you.
Seems like you are just excluding the numbers which are squares, which would not produce the right answer.
You can either create an array upto upValue with initial value set to 0 and mark all the powers of 2 as 1 using this for loop:
for(int j=1;j<=upValue;j*=2){
arr[j]=1;
}
now you have flagged all the powers of two and then iterate over the all values from 1 to upValue and print the ones that are set to 0;
The following program does what you want it to do.
#include <iostream>
#include <math.h>
void politeNo(int input)
{
// Print all initial input Polite number
for (int n = 1; n <= input; ++n)
{
// Calculate nth Polite number
int result = (int)(n +
(log((n + (log(n) /
log(2))))) /
log(2));
// Display calculated result
std::cout << " " << result;
if (result == input){break; }
}
}
int main()
{
int upValue = 0;
std::cout<<" What is the upper value ?";
std::cin >> upValue; //Stores user input into upValue
while (upValue < 1) //Validate user input of upper limit
{
std::cout << "What is the upper value? (must be an integer > 0) ";
std::cin >> upValue;
}
politeNo(upValue);
return 0;
}
Output:
1 3 5 6 7 9 10 11 12 13 14 15 17 18 19 20 21
Beginner in C++ here and learning arrays. The program below is supposed to separate positive and negative numbers in an array. However, it is returning random numbers in both the splitPos and splitNeg functions.
Could someone ever so kindly advice and show me what is incorrect in the functions and what can be done to omit these random digits so that only positive and negative digits are returned respectively by the program for each function/loop? I am obviously not seeing and/or understanding what is incorrect.
Thank you so very much for your help and time in advance!!!
#include <iostream>
using namespace std;
//function prototypes
int splitNeg(int[], int[], int);
int splitPos(int[], int[], int);
void displayArr(int[], int);
int main()
{
const int SIZE = 20;
int usedPos, usedNeg;
int origArr[SIZE] = { 4, -7, 12, 6, 8, -3, 30, 7, -20, -13, 17, 6, 31, -4, 3, 19, 15, -9, 12, -18 };
int posArray[SIZE];
int negArray[SIZE];
usedPos = splitPos(origArr, posArray, SIZE);
usedNeg = splitNeg(origArr, negArray, SIZE);
cout << "Positive Values: " << endl;
displayArr(posArray, usedPos);
cout << endl;
cout << "Negative Values: " << endl;
displayArr(negArray, usedNeg);
return 0;
}
int splitPos(int origArr[], int posArray[], int SIZE)
{
int j = 0;
for (int i = 0; i < SIZE; i++ && j++)
{
if (origArr[i] >= 0)
posArray[j] = origArr[i];
}
return j;
}
int splitNeg(int origArr[], int negArray[], int SIZE)
{
int k = 0;
for (int i = 0; i < SIZE; i++ && k++)
{
if (origArr[i] < 0)
negArray[k] = origArr[i];
}
return k;
}
void displayArr(int newArray[], int used)
{
for (int i = 0; i < used; i++)
cout << newArray[i] << endl;
return;
}
If you change your for-loops a bit:
int splitPos(int origArr[], int posArray[], int SIZE)
{
int j = 0;
for (int i = 0; i < SIZE; i++)
{
if (origArr[i] >= 0)
posArray[j++] = origArr[i];
}
return j;
}
int splitNeg(int origArr[], int negArray[], int SIZE)
{
int k = 0;
for (int i = 0; i < SIZE; i++)
{
if (origArr[i] < 0)
negArray[k++] = origArr[i];
}
return k;
}
you will get the result you desire.
The counter variables of your target arrays only get increased if you find a value that matches the criterion of being less (or greater) than 0.
I honestly do not understand what you tried to achieve with a ... hmmm.. "combined" increase like i++ && j++, this goes into short circuit evaluation.
j and k must be incremented only when the correct value is copied to posArray and negArray, by definition.
If the value is the wrong sign, j and k, obviously, should remain unchanged, since the number of values with the right sign, in the corresponding output array, does not change on this iteration.
This is not what the code is doing. It is incrementing them on every iteration of the loop, except for the one where i is 0.
There is a standard algorithm made just for that. It is named std::partition.
Your code with that algorithm will look like this:
struct SplitPosAndNegResult {
std::vector<int> negatives;
std::vector<int> positives;
};
auto splitPosAndNeg(std::array<int, SIZE> orig) {
// Here `it` is the first element of the second partition (positives)
auto it = std::partition(orig.begin(), orig.end(), [](int i){ return i < 0; });
return SplitPosAndNegResult{
std::vector<int>(orig.begin(), it), // negative numbers
std::vector<int>(it, orig.end()) // positive numbers
};
}
Then, use it like that:
int main () {
auto result = splitPosAndNeg({ 4, -7, 12, 6, 8, -3, 30, 7, -20, -13,
17, 6, 31, -4, 3, 19, 15, -9, 12, -18});
for (int n : result.positives) {
std::cout << n << ' ';
}
std::cout << std::endl;
for (int n : result.negatives) {
std::cout << n << ' ';
}
std::cout << std::endl;
}
This program will output this:
7 30 8 17 6 31 6 3 19 15 12 12 4
-18 -7 -9 -4 -13 -3 -20
Here's a live example at Coliru.
All the answers in this post are good, but I'm disappointed that none of them talk about the STL algorithms!
A good c++ programmer must know the language but he have to know also the C++ library.
look the following code:
#include <iostream>
#include <array>
#include <algorithm>
#include <string>
using namespace std;
template<typename T>
void print(const string& desc, T first, T last)
{
cout << desc;
for_each(first, last,
[](const auto& i ) { cout << i << ' ';});
cout << endl;
}
int main()
{
array<int, 20> originalArray = { 4, -7, 12, 6, 8, -3, 30, 7, -20, -13, 17, 6, 31, -4, 3, 19, 15, -9, 12, -18 };
print("original array is ", begin(originalArray), end(originalArray));
auto it = partition(begin(originalArray), end(originalArray),
[](int n) { return n >= 0; });
print("now original array is ", begin(originalArray), end(originalArray));
print("positives are: ", begin(originalArray), it);
print("negatives are: ", it, end(originalArray));
return 0;
}
More generally you want partition your set with a predicate.
Look to my code do you find any if or for? It's impossible make mistakes this way!
The only thing that does matter in the whole code is auto it = partition(begin(originalArray), end(originalArray), [](int n) { return n >= 0; }); that can be read as: partition from start to finish of originalArray elements that are positive.
#include<iostream>
using namespace std;
int main(){
int a[10]={9,4,-3,-2,1,-1,5,7,-9,-5};
int low=0;
int high=10-1;
while(low<high){
while(a[low]>=0){
low++;
}
while(a[high]<=0){
high--;
}
if(low<high){
int temp=a[low];
a[low]=a[high];
a[high]=temp;
}
}
for(int i=0;i<10;i++){
cout<<a[i]<<" ";
}
}
Time Complexity: O(n)
Suppose we're given an array of integers. A[n], for instance
A[11]={10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
and a list of prime numbers, B[k], for instance
B[2]={3, 5}
For each element, b_i in B[k], we find the elements in A[n] that are divisible by it and combine them into an equivalence class, and if an element in A[n] is not divisible by any element in B[k], then it's an equivalence class consisting of a single element. For instance, in the above example, the equivalence classes would be
{12, 15, 18}
{10, 15, 20}
{11}
{13}
{14}
{16}
{17}
{19}
(15 was repeated as it's divisible by both 3 and 5), where first equivalence class consists of numbers in A[n] divisible by 3, and second are the ones divisible by 5, and the rest are elements that are co-prime to 3 and 5. Basically, given A[n] and B[k], I want to calculate how many equivalence sets can be created, and in the above example, it would be 8.
and what I came up with is the following:
for(j=0; j<n; j++){
check[j]=true;
}
for(i=0; i<k; i++){
helper=0;
for(j=0; j<n; j++){
if(check[j]==true){
if(A[j]%B[i]==0){
check[j]==false;
helper++;
}
}
}
if(helper>0){
count++;
}
}
for(j=0; j<n; j++){
if(check[j]==true){
count++;
}
}
check is the array of boolean that returns false if it already belongs to some equivalence class and true if it does not belong to an equivalence class yet.
this calculates the number of equivalence sets divisible by elements in B[k], but now, I'm not sure what to do with singleton sets as check array members are all re-set to true after the loop.
(I tried
for(j=0; j<n; j++){
if(check[j]==true){
count++;
}
}
after the above loop, but it only adds n to the count)
Can someone help me on this? Is there a more efficient way of doing it? Also, what should I do with the singleton sets?
Thanks.
PS. Since 15 is repeated in 2 sets, it's not technically an equivalence class. Sorry about it.
Same code sample rewritten using standard containers:
#include <iostream>
#include <map>
#include <set>
using namespace std;
int A[]= { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
int B[]= { 3, 5 };
typedef set<int> row;
int
main()
{
map<int, row> results;
// Fill
for (auto i = begin(A); i != end(A); ++i)
for (auto j = begin(B); j != end(B); j++)
{
if (*i % *j)
results[*i] = row();
else
{
if (results.find(*j) == results.end())
results[*j] = row();
results[*j].insert(*i);
}
}
// Cleanup
for (auto j = begin(B); j != end(B); j++)
for (auto i : results[*j])
results.erase(i);
// Dump
for (auto i : results)
{
cout << "{ ";
if (i.second.size())
for (auto j = i.second.begin(), nocomma = --i.second.end(); j != i.second.end(); ++j)
cout << *j << (j == nocomma ? " " : ", ");
else
cout << i.first << " ";
cout << "}" << endl;
}
return 0;
}
The output:
{ 12, 15, 18 }
{ 10, 15, 20 }
{ 11 }
{ 13 }
{ 14 }
{ 16 }
{ 17 }
{ 19 }