I have this problem: Given a vector with n numbers, sort the numbers so that the even ones will be on odd positions and the odd numbers will be on even positions. E.g. If I have the vector 2 6 7 8 9 3 5 1, the output should be 2 7 6 9 8 3 5 1 . The count should start from 1. So on position 1 which is actually index 0 should be an even number, on position 2 which is actually index 1 should be an odd number and so on. Now this is easy if the odd and even numbers are the same, let's say 4 even number and 4 odd numbers in the vector, but what if the number of odd numbers differs from the number of even numbers like in the above example? How do I solve that. I attached the code with one of the tries I did, but it doesn't work. Can I get some help please. I ask you to keep it simple that means only with vectors and such. No weird methods or anything cause I'm a beginner and I only know the basics. Thanks in advance!
I have to mention that n initial is globally declared and is the number of vector elements and v_initial is the initial vector with the elements that need to be rearranged.
The task says to add the remaining numbers to the end of the vector. Like if there are 3 odd and 5 even numbers, The 2 extra even numbers should be thrown at the end of the vector
void vector_pozitii_pare_impare(int v_initial[])
{
int v_pozitie[50],c1=0,c2=1;
for (i = 0; i < n_initial; i++)
{
if (v_initial[i] % 2 == 0)
{
bool isTrue = 1;
for (int k = i + 1; k < n_initial; k++)
{
if (v_initial[k] % 2 != 0)
isTrue = 0;
}
if (isTrue)
{
v_pozitie[c1] = v_initial[i];
c1++;
}
else
{
v_pozitie[c1] = v_initial[i];
c1 += 2;
}
}
else
{
bool isTrue = 1;
for (int j = i + 1; j < n_initial; j++)
{
if (v_initial[j] % 2 == 0)
{
isTrue = 0;
}
if (isTrue)
{
v_pozitie[c2] = v_initial[i];
c2++;
}
else
{
v_pozitie[c2] = v_initial[i];
c2 += 2;
}
}
}
}
This may not be a perfect solution and it just popped out right off my mind without being tested or verified, but it's just to give you an idea.
(Let A,B,C,D be odd numbers and 0,1,2 even numbers correspondingly)
Given:
A 0 B C D 1 2 (random ordered list of odd/even numbers)
Wanted:
A 0 B 1 C 2 D (input sequence altered to match the wanted odd/even criteria)
Next, we invent the steps required to get from given to wanted:
// look at 'A' -> match, next
// Result: A 0 B C D 1 2
// look at '0' -> match, next
// Result: A 0 B C D 1 2
// look at 'B' -> match, next
// Result: A 0 B C D 1 2
// look at 'C' -> mismatch, remember index and find first match starting from index+1
// Result: A 0 B C D ->1<- 2
// now swap the numbers found at the remembered index and the found one.
// Result: A 0 B 1 D C 2
// continue until the whole list has been consumed.
As I said, this algorithm may not be perfect, but my intention is to give you an example on how to solve these kinds of problems. It's not good to always think in code first, especially not with a problem like this. So you should first think about where you start, what you want to achieve and then carefully think of how to get there step by step.
I feel I have to mention that I did not provide an example in real code, because once you got the idea, the execution should be pretty much straight forward.
Oh, and just a small remark: Almost nothing about your code is C++.
A simple solution, that is not very efficient would be to split the vector into 2 vectors, that contain even and uneven numbers and then always take one from the even, one from the uneven and then the remainder, from the one that is not completely entered.
some c++ (that actually uses vectors, but you can use an array the same way, but need to change the pointer arithmetic)
I did not test it, but the principle should be clear; it is not very efficient though
EDIT: The answer below by #AAAAAAAAARGH outlines a better algorithmic idea, that is inplace and more efficient.
void change_vector_even_uneven(std::vector<unsigned>& in_vec){
std::vector<unsigned> even;
std::vector<unsigned> uneven;
for (auto it = in_vec.begin(); it != in_vec.end(); it++){
if ((*it) % 2 == 0)) even.push_back(*it);
else uneven.push_back(*it);
}
auto even_it = even.begin();
auto uneven_it = uneven.begin();
for (auto it = in_vec.begin(); it != in_vec.end(); it++){
if (even_it == even.end()){
(*it) = (*uneven_it);
uneven_it++;
continue;
}
if (uneven_it == uneven.end()){
(*it) = (*even_it);
even_it++;
continue;
}
if ((it - in_vec.begin()) % 2 == 0){
(*it) = (*even_it);
even_it++;
}
else{
(*it) = (*uneven_it);
uneven_it++;
}
}
}
The solutions is simple. We sort the even and odd values into a data structure. In a loop, we iterate over all source values. If they are even (val & 2 == 0) we add them at the end of a std::deque for evens and if odd, we add them to a std::deque for odds.
Later, we we will extract the the values from the front of the std::deque.
So, we have a first in first out principle.
The std::deque is optimized for such purposes.
Later, we make a loop with an alternating branch in it. We, alternatively extract data from the even queue and then from the odd queue. If a queue is empty, we do not extract data.
We do not need an additional std::vector and can reuse the old one.
With that, we do not need to take care for the same number of evens and odds. It will of course always work.
Please see below one of millions of possible solutions:
#include <iostream>
#include <vector>
#include <deque>
int main() {
std::vector testData{ 2, 6, 7, 8, 9, 3, 5, 1 };
// Show initial data
std::cout << "\nInitial data: ";
for (const int i : testData) std::cout << i << ' ';
std::cout << '\n';
// We will use a deques to store odd and even numbers
// With that we can efficiently push back and pop front
std::deque<int> evenNumbers{};
std::deque<int> oddNumbers{};
// Sort the original data into the specific container
for (const int number : testData)
if (number % 2 == 0)
evenNumbers.push_back(number);
else
oddNumbers.push_back(number);
// Take alternating the data from the even and the odd values
bool takeEven{ true };
for (size_t i{}; !evenNumbers.empty() && !oddNumbers.empty(); ) {
if (takeEven) { // Take even numbers
if (not evenNumbers.empty()) { // As long as there are even values
testData[i] = evenNumbers.front(); // Get the value from the front
evenNumbers.pop_front(); // Remove first value
++i;
}
}
else { // Now we take odd numbers
if (not oddNumbers.empty()) { // As long as there are odd values
testData[i] = oddNumbers.front(); // Get the value from the front
oddNumbers.pop_front(); // Remove first value
++i;
}
}
// Next take the other container
takeEven = not takeEven;
}
// Show result
std::cout << "\nResult: ";
for (const int i : testData) std::cout << i << ' ';
std::cout << '\n';
return 0;
}
Here is yet another solution (using STL), in case you want a stable result (that is, the order of your values is preserved).
#include <algorithm>
#include <vector>
auto ints = std::vector<int>{ 2, 6, 7, 8, 9, 3, 5, 1 };
// split list to even/odd sections -> [2, 6, 8, 7, 9, 3, 5, 1]
const auto it = std::stable_partition(
ints.begin(), ints.end(), [](auto value) { return value % 2 == 0; });
auto results = std::vector<int>{};
results.reserve(ints.size());
// merge both parts with equal size
auto a = ints.begin(), b = it;
while (a != it && b != ints.end()) {
results.push_back(*a++);
results.push_back(*b++);
}
// copy remaining values to end of list
std::copy(a, it, std::back_inserter(results));
std::copy(b, ints.end(), std::back_inserter(results));
The result ist [2, 7, 6, 9, 8, 3, 5, 1]. The complexity is O(n).
This answer, like some of the others, divides the data and then reassembles the result. The standard library std::partition_copy is used to separate the even and odd numbers into two containers. Then the interleave function assembles the result by alternately copying from two input ranges.
#include <algorithm>
#include <iostream>
#include <vector>
template <typename InIt1, typename InIt2, typename OutIt>
OutIt interleave(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt dest)
{
for (;;) {
if (first1 == last1) {
return std::copy(first2, last2, dest);
}
*dest++ = *first1++;
if (first2 == last2) {
return std::copy(first1, last1, dest);
}
*dest++ = *first2++;
}
}
void reorder_even_odd(std::vector<int> &data)
{
auto is_even = [](int value) { return (value & 1) == 0; };
// split
std::vector<int> even, odd;
std::partition_copy(begin(data), end(data), back_inserter(even), back_inserter(odd), is_even);
// merge
interleave(begin(even), end(even), begin(odd), end(odd), begin(data));
}
int main()
{
std::vector<int> data{ 2, 6, 7, 8, 9, 3, 5, 1 };
reorder_even_odd(data);
for (int value : data) {
std::cout << value << ' ';
}
std::cout << '\n';
}
Demo on Compiler Explorer
As suggested, I am using vectors and STL.
No need to be a great mathematician to understand v_pozitie will start with pairs of odd and even and terminate with the integers not in the initial pairs.
I am then updating three iterators in v_positie (no need of temporary containers to calculate the result) : even, odd and end,(avoiding push_back) and would code this way :
#include <vector>
#include <algorithm>
void vector_pozitii_pare_impare(std::vector<int>& v_initial, std::vector<int>& v_pozitie) {
int nodd (0), neven (0);
std::for_each (v_initial.begin (), v_initial.end (), [&nodd] (const int& n) {
nodd += n%2;
});
neven = v_initial.size () - nodd;
int npair (neven < nodd ?neven:nodd);
npair *=2;
std::vector<int>::iterator iend (&v_pozitie [npair]), ieven (v_pozitie.begin ()), iodd (&v_pozitie [1]);
std::for_each (v_initial.begin (), v_initial.end (), [&iend, &ieven, &iodd, &npair] (const int& s) {
if (npair) {
switch (s%2) {
case 0 :
*ieven++ = s;
++ieven;
break;
case 1 :
*iodd++ = s;
++iodd;
break;
}
--npair;
}
else *iend++ = s;
});
}
int main (int argc, char* argv []) {
const int N = 8;
int tab [N] = {2, 6, 7, 8, 9, 3, 5, 1};
std::vector<int> v_initial (tab, (int*)&tab [N]);
std::cout << "\tv_initial == ";
std::for_each (v_initial.begin (), v_initial.end (), [] (const int& s) {std::cout << s << " ";});
std::cout << std::endl;
std::vector<int> v_pozitie (v_initial.size (), -1);
vector_pozitii_pare_impare (v_initial, v_pozitie);
std::cout << "\tv_pozitie == ";
std::for_each (v_pozitie.begin (), v_pozitie.end (), [] (const int& s) {std::cout << s << " ";});
std::cout << std::endl;
}
I have read and understood how Mergesort works (as a text) and now I'm trying to code it. I have finished the part where you divide the data (I use vectors) until it has each size of 1. Now I have written code for another required part in Mergesort, I don't know how to call it but I just call it "compare and ordering part".
You have 2 vectors and this part is supposed to compare the very first elements, take the smaller element, then remove the chosen element and put it inside a new vector. Doing that untill both vectors have size 0.
I'm sorry for the long code but I really don't see why the very last element is ignored by the code? : /
I have added some comments so maybe it is easier to follow what I tried to do.
I tried as input:
vector<int> v1 = {1,4,5,9};
vector<int> v2 = {2,3,6,7,8};
Output:
1 2 3 4 5 6 7 8 0
vector<int> sortit(vector<int> &left, vector<int> &right) {
vector<int> sorted(left.size() + right.size());
int i = 0;
while (left.size() > 0 && right.size() > 0) {
if (left.at(0) <= right.at(0)) {
sorted.at(i) = left.at(0); // putting the smaller element into the new vector
left.erase(left.begin()); // removing this smaller element from the (old) vector
}
else if (right.at(0) <= left.at(0)) {
sorted.at(i) = right.at(0); // see comment above
right.erase(right.begin()); // see comment above
}
else if (left.size() <= 0 && right.size() > 0) { // if left vector has no elements, then take all elements of the right vector and put them into the new vector
while (right.size() > 0) {
sorted.at(i) = right.at(0);
right.erase(right.begin());
}
}
else if (right.size() <= 0 && left.size() > 0) { // the same just for the right vector
while (left.size() > 0) {
sorted.at(i) = left.at(0);
left.erase(left.begin());
}
}
i++;
}
return sorted;
}
The check of whether one of the arrays has exhausted and other array has remaining elements should be outside the main while loop.
So, try to put the below two checks outside.
else if (left.size() <= 0 && right.size() > 0)
else if (right.size() <= 0 && left.size() > 0)
Think of what will happen when one array has (1) and other (2,3), On adding 1 to the sorted vector, the while(left.size() > 0 && right.size() > 0) condition is false and the loop breaks. So the other elements are ignored.
don't know how to call [the] "compare and ordering part"
Conventionally: merge
sorry for the long code
use a
first = *left <= *right ? left : right
and manipulate that, avoiding code replication.
don't see why the very last element is ignored by the code?
left.at(0) <= right.at(0)
and
right.at(0) <= left.at(0)
cover all possible comparison results (equality twice): no further else will get evaluated.
Moving "the move parts" to follow "the proper merge" as suggested by Msk, note that the preliminary checks are dispensable - just use "the move loops".
There is a lot to say about your code (starting with commentation) - see code reviews of C++ merge implementations for ideas.
If you want code you are in control of reviewed at CR#SE, be sure to be on topic and write a Good Question.
The code could be simplified:
vector<int> sortit(vector<int> &left, vector<int> &right) {
vector<int> sorted(left.size() + right.size());
int i = 0;
while (1) {
if (left.at(0) <= right.at(0)) {
sorted.at(i++) = left.at(0);
left.erase(left.begin());
if(left.size == 0){
do{
sorted.at(i++) = right.at(0);
right.erase(right.begin());
}while(right.size != 0);
return;
}
} else {
sorted.at(i++) = right.at(0);
right.erase(right.begin());
if(right.size == 0){
do{
sorted.at(i++) = left.at(0);
left.erase(left.begin());
}while(left.size != 0);
return;
}
}
}
return sorted;
}
rather than erasing elements of vectors, indexing could be used instead:
vector<int> sortit(vector<int> &left, vector<int> &right) {
vector<int> sorted(left.size() + right.size());
int i = 0;
int ll = 0;
int rr = 0;
while (1) {
if (left[ll] <= right[rr]) {
sorted[i++] = left[ll++];
if(ll == left.size){
do{
sorted[i++] = right[rr++];
}while(rr != right.size);
break;
}
} else {
sorted[i++] = right[rr++];
if(rr == right.size){
do{
sorted[i++] = left[ll++];
}while(ll != left.size);
break;
}
}
}
return sorted;
}
I am trying to go through my map of patient IDs, find the sequential ones that match, and find the difference squared for each pair of results (for the same patient). However I am having some trouble with the "itid" iterator in the line, "for (itid = nx; itid != mymap.end(); itid++) {" and I'm not sure why. When I take out the code with "itid" it works just fine. I am a programming beginner, so any advice would be greatly appreciated!
map <int,struct testInfo> mymap;
map <int,struct testInfo>:: iterator it;
pair<map<int,struct testInfo>::iterator,bool> ret;
map <int,struct testInfo>:: iterator itid;
int arraySize = 10000;
double diffsq[arraySize];
int count = 1;
for ( it=mymap.begin() ; it != mymap.end(); it++ ) {
auto nx = next(it);
//comparing each patientID to the next patientID
if ((it->second.patientID == nx->second.patientID) && it->second.patientID != 0) {
for (itid = nx; itid != mymap.end(); itid++) {
if ((it->second.patientID == itid->second.patientID) && it->second.patientID != 0) {
diffsq[count] = pow((it->second.result - itid->second.result), 2);
count++;
} else
itid = mymap.end();
}
}
}
I think it is because the next give a constant iterator and itid is not constant... try it in same way as you have done auto nx try same for itid.
auto itid = nx inside the for loop.
I am trying to calculate the prime numbers using a set but when I do the calculation my iterator is jumping randomly.
I am trying to implement this method for an value of N=10.
Choose an integer n. This function will compute all prime numbers up
to n. First insert all numbers from 1 to n into a set. Then erase all
multiples of 2 (except 2); that is, 4, 6, 8, 10, 12, .... Erase all
multiples of 3, that is, 6, 9, 12, 15, ... . Go up to sqrt(n) . The
remaining numbers are all primes.
When I run my code, it erases 1 and then pos jumps to 4? I am not sure why this happens instead of it going to the value 2 which is the 2nd value in the set?
Also what happens after I erase a value that the iterator is pointing to, what does the iterator point to then and if I advance it where does it advance?
Here is the code:
set<int> sieveofEratosthenes(int n){ //n = 10
set<int> a;
set<int>::iterator pos = a.begin();
//generate set of values 1-10
for (int i = 1; i <= n; i++) {
a.insert(i);
if(pos != a.end())
pos++;
}
pos = a.begin();
//remove prime numbers
while (pos != a.end())
{
cout << "\nNew Iteration \n\n";
for (int i = 1; i < sqrt(n); i++) {
int val = *pos%i;
cout << "Pos = " << *pos << "\n";
cout << "I = " << i << "\n";
cout << *pos << "/" << i << "=" << val << "\n\n";
if (val == 0) {
a.erase(i);
}
}
pos++;
}
return a;
}
Your implementation is incorrect in that it is trying to combine the sieve algorithm with the straightforward algorithm of trying out divisors, and it does so unsuccessfully. You do not need to test divisibility to implement the sieve - in fact, that's a major contributor to the beauty of the algorithm! You do not even need multiplication.
a.erase(1);
pos = a.begin();
while (pos != a.end()) {
int current = *pos++;
// "remove" is the number to remove.
// Start it at twice the current number
int remove = current + current;
while (remove <= n) {
a.erase(remove);
// Add the current number to get the next item to remove
remove += current;
}
}
Demo.
When erasing elements inside a loop you have to be carefull with the indices. For example, when you erase the element at position 0, then the next element is now at position 0. Thus the loop should look something like this:
for (int i = 1; i < sqrt(n); /*no increment*/) {
/* ... */
if (val == 0) {
a.erase(i);
} else {
i++;
}
}
Actually, you also have to take care that the size of the set is shrinking while you erase elements. Thus you better use iterators:
for (auto it = a.begin(); i != a.end(); /*no increment*/) {
/* ... */
if (val == 0) {
a.erase(it);
} else {
it++;
}
}
PS: the above is not exactly what you need for the sieve, but it should be sufficient to demonstrate how to erase elements (I hope so).
I'm looking for a class that categorizes floating point numbers into arbitrary bins. The bins. The desired syntax would be something like:
std::vector<double> bin_vector;
// ..... fill the vector with 1, 1.4, 5, etc not evenly spaced values
Binner bins(bin_vector);
for (std::vector<double>::const_iterator d_itr = some_vector.begin();
d_itr != some_vector.end(); d_itr++) {
int bin = bins.categorize(*d_itr);
// bin would be 0 for x < 1, 1 for 1 < x < 1.4, etc
// do something with bin
}
Unfortunately, due to portability requirements I'm limited to boost and stl. I've rolled my own O(log n) solutions using maps and overloading < for a custom range object, but that solution seemed bug prone and ugly at best.
Is there some simple stl or boost object solution to this?
Use a std::map, mapping interval boundaries to bin numbers. Then use .upper_bound() to find the bin.
Here is an untested generic algorithm that takes an input vector of arbitrary length M and a sorted vector of N-1 bin boundaries, and that returns a vector of N bin counts. Bin i counts the values in the interval [breaks[i-1], breaks[i]). The types T1 and T2 should be mutually comparable. Complexity is equal to O(M * log (N)).
#include<algorithm> // std::is_sorted, std::lower_bound
#include<cassert> // assert
#include<iterator> // std::distance
#include<vector> // std::vector
template<typename T1, typename T2>
std::vector<std::size_t> bin_count(const std::vector<T1>& input, const std::vector<T2>& breaks)
{
// breaks is a sorted vector -INF < a0 < a1 < ... < aN-2 < +INF
assert(std::is_sorted(breaks.begin(), breaks.end()));
auto N = breaks.size() + 1;
std::vector<std::size_t> output(N, 0);
if (N == 1) {
// everything is inside [-INF, INF)
output[0] = input.size();
return output;
}
for(auto it = input.begin(), it != input.end(); ++it) {
if (*it < breaks.front()) {
// first bin counts values in [-INF, a0)
++output[0];
break;
}
if (*it >= breaks.back()) {
// last bin counts values in [aN-1, +INF)
++output[N-1];
break;
}
const auto break_it = std::lower_bound(breaks.begin(), breaks.end(), *it);
bin_index = std::distance(breaks.begin(), break_it) + 1;
++output[bin_index];
}
return output;
}