Numbering elements in vector - c++

I have a vector of integers. For example: 26 58 32 47 . I need to replace them with their number in that sequence. In this case it would be: 4 1 3 2 . I tried this code:
int n = 1;
vector <int> vietos;
for (vector <int>::iterator i = vieta.begin(); i != vieta.end(); i++) {
for (vector <int>::iterator j = vieta.begin(); j != vieta.end(); j++) {
if (*i > *j)
n++;
}
vietos.push_back(n);
cout << n << " ";
n = 1;
}
Having numbers 23 25 38 28 26 28 (Note: In this case I number them in reverse order!) I get: 1 2 6 4 3 4 which is good except for two numbers are equal.
Maybe there is some way to number elements in vector using STL algorithms?

In my opinion the simplest way is to use std::reference_wrapper. The code will look simple and very clear.
Here is the program that demonstrates the approach.
Enjoy!:)
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> v = { 23, 25, 38, 28, 26, 28 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
// Introducing a local block scope that the auxiliary vector would be automatically deleted
{
std::vector<std::reference_wrapper<int>> vr( v.begin(), v.end() );
std::stable_sort( vr.begin(), vr.end() );
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[i].get() = i + 1;
}
}
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
The output is
23 25 38 28 26 28
1 2 6 4 3 5
If you need to get the reverese order all you need is to add to the code functional object
std::greater<std::reference_wrapper<int>>()
in the call of std::stable_sort
For example
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> v = { 23, 25, 38, 28, 26, 28 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
// Introducing a local block scope that the auxiliary vector would be automatically deleted
{
std::vector<std::reference_wrapper<int>> vr( v.begin(), v.end() );
std::stable_sort( vr.begin(), vr.end(),
std::greater<std::reference_wrapper<int>>() );
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[i].get() = i + 1;
}
}
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
The output is
23 25 38 28 26 28
6 5 1 2 4 3
Is not it the best solution is it? :)
EDIT: Maybe there is no sense to use std::stable_sort with the functional object. It will be enough to use for loop setting numbers in the reverse order. Something as
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[vr.size() + i - 1].get() = i + 1;
}

In that case, you should increment when the value is greater than or equal to rather than just greater than, try this:
(*i >= *j)

If you were to replace the iterators with integers, i.e.: (I assume < isn't defined on iterators, but it could be)
for (int i = 0; i < vietos.size(); i++)
You could increment n as well when elements to the left are equal, i.e. when
vietos[i] > vietos[j] || (vietos[i] == vietos[j] && j < i).
Alternatively, you could create a vector<pair<int, int> >, with each pair containing the element and its index, then sort that, and iterate through the sorted vector, setting the index in the pair in the original vector to the index in the sorted vector.
This would give an O(n log n) running time, as opposed to the O(n²) of the above.
Pseudo-code:
vector arr
vector<pair> pairs
for i = 0 to n
pairs.insert(arr[i], i)
sort pairs
for i = 0 to n
arr[pairs[i].second] = i

Related

Insert an element in a descending sorted array and keep array sorted

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);
}

the numbers appearing closest to integer x in the vector<int> v1 must be printed first

Below there is a tabular view of a sorted vector.
vector v1= {1 , 8 ,10 ,16}
int x=9;
You are given a task to reorder vector v1 by following a rule.
You will be given a integer x.
The rule is:
You will print all the elements of the vector, such that, the numbers appearing closest to x in the vector v1 must be printed first.
For example the reordered vector must be 8,10,16,1.
sample examples:
x=15 . . .v1={-100,1,12,15,100} . . . output:{15,12,1,100,-100}
x=99 . . .v1={-100,1,12,15,100} . . . output:{100,15,12,1,-100}
x=-1 . . .v1={-100,1,12,15,100} . . . output:{1,12,15,-100,100}
In case there are two numbers that are equally closer to x, in that case, print smaller element first
for example:
x=0 . . .v1={-100,-50,50,100} . . . output:{**-50**,50,**-100**,100}
I used a naive approach, but it is too slow for larger ranges.
while(0 < v1.size()) {
for (int j = 0; j <= v1.back(); j++) {
if (x - j >= 0 && find(all(v1), x - j) != v1.end()) {
b = x - j; break;
}
if (x + j <= v1.back() && find(all(v1), x + j) != v1.end()) {
b = x + j; break;
}
}
cout<<b;
auto it2 = find(all(v1), b);
v1.erase(it2);
}
Please, if you can, suggest me a faster code.
My code is way too slow.
Elaborating on what Aconcagua suggested:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct sortClosestToFunctor {
explicit sortClosestToFunctor(int x) : m_x{x} {}
bool operator()(int const lhs, int const rhs) const {
int dx = std::abs(lhs - m_x);
int dy = std::abs(rhs - m_x);
return (dx < dy) or (dx == dy and lhs < rhs);
}
private:
int m_x;
};
int main() {
std::vector<int> v1{1, 8, 10, 16};
int x = 9;
// using functor
std::sort(v1.begin(), v1.end(), sortClosestToFunctor(9));
// using lambda
std::sort(v1.begin(), v1.end(), [x](int const lhs, int const rhs) {
int dx = std::abs(lhs - m_x);
int dy = std::abs(rhs - m_x);
return (dx < dy) or (dx == dy and lhs < rhs);
});
// 8 10 16 1
std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " "));
}
Well, you need an appropriate comparator, then you can simply use std::sort:
std::vector<int> numbers;
int referenceValue; // = ...
std::sort
(
numbers.begin, numbers.end,
[/* ... */](int x, int y) { /* ... */ }
);
You'll get the vector sorted into exactly the order you need, no need to find and remove elements from, you can just iterate over it afterwards. std::sort guarantees O(n(log(n)) (since C++11), so that should be fast enough (faster you cannot get on sorting anyway...).
Question now is: how would such a comparator look like?
Well, at very first, it will need to have the reference value available, so it will capture it:
[referenceValue](int x, int y) { /* ... */ }
As it's a simple int, capturing by value is fine, more complex types you might prefer to capture by reference instead.
The comparator should implement 'less' semantics, so it should return true if x goes before y. So we can have:
int dx = std::abs(x - referenceValue);
int dy = std::abs(y - referenceValue);
return dx < dy || dx == dy && x < y;
// if x has smaller distance: ^^^^^^^
// or, in case of equality, the smaller one ^^^^^^^^^^^^^^^^^^^^
That's it, you're done...
Untested code, if you happen to find a bug, please fix it yourself ;)
My five cents. A straightforward approach without sorting a vector.
I am sure that it is a bad idea to sort the vector if the only task is to output it in some order. Otherwise the original vector will be changed (Why?! This is not required in the assignment.) or a copy of the vector will be created.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
std::ostream & closest_output( const std::vector<int> &v,
const int &value,
std::ostream &os = std::cout )
{
auto it = std::lower_bound( std::begin( v ), std::end( v ), value );
if ( it == std::begin( v ) )
{
for ( auto last = std::end( v ); it != last; ++it )
{
os << *it << ' ';
}
}
else if ( it == std::end( v ) )
{
for ( auto first = std::begin( v ); it != first; )
{
os << *--it << ' ';
}
}
else
{
auto next = it, first = std::begin( v ), last = std::end( v );
while ( it != first && next != last )
{
if ( *next - value < value - *std::prev( it ) )
{
os << *next++ << ' ';
}
else
{
os << *--it << ' ';
}
}
while ( it != first ) os << *--it << ' ';
while ( next != last ) os << *next++ << ' ';
}
return os;
}
int main()
{
std::vector<int> v1 = { 1 , 8 ,10 ,16 };
int value = 9;
closest_output( v1, value ) << '\n';
std::vector<int> v2 = { -100, 1, 12, 15, 100 };
value = 15;
closest_output( v2, value ) << '\n';
value = 99;
closest_output( v2, value ) << '\n';
value = 1;
closest_output( v2, value ) << '\n';
return 0;
}
The program output is
8 10 16 1
15 12 1 100 -100
100 15 12 1 -100
1 12 15 100 -100
Let's consider if x = 9 and vector = {1, 8, 10, 16},
Then upper bound of x in vector is 10,
Now if you traversal toward begin or toward end of the vector from upper bound the distance will increase with respect to x in both direction, because vector is sorted.
Following two step will produce required output,
Find distance between x and left element, and between right element and x then if left distance is less then or equal to right distance then print left element otherwise print right element,
If left element is printed then move one element previous to left element and if right element is printed then move next element from right element.
Now let`s apply these steps,
Here x = 9, vector = {1, 8, 10, 16} and upper bound = 10
left element = 8, right element = 10
(9 - 8) <= (10 - 9) is true, so print 8, and now left element = 1
left element = 1, right element = 10
(9 - 1) <= (10 - 9) is false, so print 10, and now right element = 16
left element = 1, right element = 16
(9 - 1) <= (16 - 9) is false, so print 16, and now right element = end of
vector
left element = 1, right element = end of vector
so print 1
These steps will produce expected output : {8, 10, 16, 1}
Try this implementation,
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
template <typename ForwardIterator>
void print(ForwardIterator first, ForwardIterator last){
for(; last != first; ++first)
cout<< *first<< " ";
}
void printClostestFirst(const std::vector<int>& vec, const int piotValue){
std::vector<int>::const_iterator mid = std::upper_bound(vec.cbegin(), vec.cend(), piotValue);
if(vec.cend() == mid){
print(vec.crbegin(), vec.crend());
return;
}
else if(vec.begin() == mid){
print(vec.cbegin(), vec.cend());
return;
}
std::vector<int>::const_reverse_iterator left = vec.crbegin() + std::distance(mid, vec.cend());
std::vector<int>::const_iterator right = mid;
std::vector<int>::const_reverse_iterator leftEnd = vec.crend();
std::vector<int>::const_iterator rightEnd = vec.cend();
int leftDist = 0;
int rightDist = 0;
while(leftEnd != left && rightEnd != right){
leftDist = piotValue - *left;
rightDist = *right - piotValue;
if(leftDist <= rightDist){
cout<< *left<< " ";
++left;
}
else{
cout<< *right<< " ";
++right;
}
}
if(leftEnd != left)
print(left, leftEnd);
else
print(right, rightEnd);
}
int main(int , char *[]){
cout<< "x = 9 . . .vec = { 1, 8, 10, 16 } . . . output: { ";
printClostestFirst({1, 8, 10, 16}, 9);
cout<< "}\n";
cout<< "x = 15 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, 15);
cout<< "}\n";
cout<< "x = 99 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, 99);
cout<< "}\n";
cout<< "x = -1 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, -1);
cout<< "}\n";
cout<< "x = 0 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,-50,50,100}, 0);
cout<< "}\n";
}
output:
x = 9 . . .vec = { 1, 8, 10, 16 } . . . output: { 8 10 16 1 }
x = 15 . . .vec = { -100,1,12,15,100 } . . . output: { 15 12 1 100 -100 }
x = 99 . . .vec = { -100,1,12,15,100 } . . . output: { 100 15 12 1 -100 }
x = -1 . . .vec = { -100,1,12,15,100 } . . . output: { 1 12 15 -100 100 }
x = 0 . . .vec = { -100,1,12,15,100 } . . . output: { -50 50 -100 100 }

dividing duplicates by the counter of duplicates

the program i'm trying to write gets info from user, check duplicate in weight and count those duplicates.
For example,
{10, 40, 30, 40, 30} each 40 and 30 is duplicated 2 times
so it should be {10, 20, 15, 20, 15}
and this is my code:
struct Data {
int id;
double weight
}
std::sort(p, p + num, acompare);
for (int i = 0; i < num; i += counter) {
for (counter = 1; i + counter<num&& p[i + counter].weight== p[i].weight; )
counter++; // count consecutives dups
if (counter>1) { // if more than one, process the dups.
cntArr[i] = counter;
cntArr[counter] = counter;
} else
cntArr[i] = 1;
}
for (int i = 0; i < num; i++) {
cout << p[i].id << ":" << p[i].weight/ (double) cntArr[i] << endl;
}
and the result is like this
input :
1 100
2 100
3 100
4 80
5 80
output :
4 40
5 -9.79969e-08
1 33.3333
2 33.3333
3 -1.18744e-07
How do i fix this?
It's a bit hard to debug the specific problem in your code, as it isn't complete (can't copy-paste it to an editor and build it). In particular, not sure what are p, cntArray, and how they are initialized.
However, fundamentally, this code could be made shorter and more efficient. Instead of sorting (immediate Θ(n log(n)) complexity), use an std::unordered_map to store the multiplicity of each element. Shorter, fewer potential bugs, and (expected) linear complexity.
#include <vector>
#include <unordered_map>
#include <iostream>
#include <algorithm>
int main() {
const std::vector<int> a{10, 40, 30, 40, 30};
std::unordered_map<int, std::size_t> counts;
std::for_each(std::begin(a), std::end(a), [&](int e){ ++counts[e]; });
std::for_each(std::begin(a), std::end(a),
[&](int e){ std::cout << e / static_cast<double>(counts[e]) << std::endl; });
}
Outputs:
$ ./a.out
10
20
15
20
15

Permutations &/ Combinations using c++

I need a different version of permutations for my code. I could able to achieve what I want but it is not generic enough. my algorithm keeps going bigger along with my requirements. But that should not be.
This is not a home work for any one, I need it for one my critical projects, wondering if any pre-defined algorithms available from boost or any other.
Below is the standard version of next_permutation using c++.
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation
int main ()
{
int myints[] = {1,2,3};
do
{
std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
} while ( std::next_permutation(myints,myints+3) );
return 0;
}
That gives below output :
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
But my requirement is :- Let's say I have 1 to 9 numbers :
1,2,3,4,5,6,7,8,9
And I need a variable length of permutations and in only ASCENDING order and with out DUPLICATES.
Let's say i need 3 digit length of permutations then i need output as below.
123
124
125
.
.
.
128
129
134 // After 129 next one should be exactly 134
135 // ascending order mandatory
136
.
.
.
148
149
156 // exactly 156 after 149, ascending order mandatory
.
.
.
489 // exactly 567 after 489, because after 3rd digit 9, 2nd digit
567 // will be increased to 49? , so there is no possibility for
. // 3rd digit, so first digit gets incremented to 5 then 6 then
. // 7, in ascending order.
.
.
.
789 // and this should be the last set I need.
My list may contain upto couple of hundred's of numbers and variable length can be 1 to up to Size of the list.
My own algorithm is working for specific variable length, and a specific size, when they both changes, i need to write huge code. so, looking for a generic one.
I am not even sure if this is called as Permutations or there is a different name available for this kind of math/logic.
Thanks in advance.
musk's
Formally, you want to generate all m-combinations of the set [0;n-1].
#include <iostream>
#include <vector>
bool first_combination (std::vector<int> &v, int m, int n)
{
if ((m < 0) || (m > n)) {
return false;
}
v.clear ();
v.resize (m);
for (int i = 0; i < m; i++) {
v[i] = i;
}
return true;
}
bool next_combination (std::vector<int> &v, int m, int n)
{
for (int i = m - 1; i >= 0; i--) {
if (v[i] + m - i < n) {
v[i]++;
for (int j = i + 1; j < m; j++) {
v[j] = v[j - 1] + 1;
}
return true;
}
}
return false;
}
void print_combination (const std::vector<int> &v)
{
for (size_t i = 0; i < v.size(); i++) {
std::cout << v[i] << ' ';
}
std::cout << '\n';
}
int main ()
{
const int m = 3;
const int n = 5;
std::vector<int> v;
if (first_combination (v, m, n)) {
do {
print_combination (v);
} while (next_combination (v, m, n));
}
}
You can use this code and the linked article as inspiration.
This task can be done with a simple iterative algorithm. Just increment the first element that can be incremented and rescale the elements before it until there is no element to be incremented.
int a[] = {0,1,2,3,4,5,6,7,8,9}; // elements: must be ascending in this case
int n = sizeof(a)/sizeof(int);
int digits = 7; // number of elements you want to choose
vector<int> indexes; // creating the first combination
for ( int i=digits-1;i>=0;--i ){
indexes.push_back(i);
}
while (1){
/// printing the current combination
for ( int i=indexes.size()-1;i>=0;--i ){
cout << a[indexes[i]] ;
} cout << endl;
///
int i = 0;
while ( i < indexes.size() && indexes[i] == n-1-i ) // finding the first element
++i; // that can be incremented
if ( i==indexes.size() ) // if no element can be incremented, we are done
break;
indexes[i]++; // increment the first element
for ( int j=0;j<i;++j ){ // rescale elements before it to first combination
indexes[j] = indexes[i]+(i-j);
}
}
Output:
0123456
0123457
0123458
0123459
0123467
0123468
0123469
0123478
0123479
0123489
0123567
0123568
0123569
0123578
0123579
0123589
0123678
0123679
0123689
0123789
0124567
0124568
0124569
0124578
0124579
0124589
0124678
0124679
0124689
0124789
0125678
0125679
0125689
0125789
0126789
0134567
0134568
0134569
0134578
0134579
0134589
0134678
0134679
0134689
0134789
0135678
0135679
0135689
0135789
0136789
0145678
0145679
0145689
0145789
0146789
0156789
0234567
0234568
0234569
0234578
0234579
0234589
0234678
0234679
0234689
0234789
0235678
0235679
0235689
0235789
0236789
0245678
0245679
0245689
0245789
0246789
0256789
0345678
0345679
0345689
0345789
0346789
0356789
0456789
1234567
1234568
1234569
1234578
1234579
1234589
1234678
1234679
1234689
1234789
1235678
1235679
1235689
1235789
1236789
1245678
1245679
1245689
1245789
1246789
1256789
1345678
1345679
1345689
1345789
1346789
1356789
1456789
2345678
2345679
2345689
2345789
2346789
2356789
2456789
3456789

Slicing a vector

I have a std::vector. I want to create iterators representing a slice of that vector. How do I do it? In pseudo C++:
class InterestingType;
void doSomething(slice& s) {
for (slice::iterator i = s.begin(); i != s.end(); ++i) {
std::cout << *i << endl;
}
}
int main() {
std::vector v();
for (int i= 0; i < 10; ++i) { v.push_back(i); }
slice slice1 = slice(v, 1, 5);
slice slice2 = slice(v, 2, 4);
doSomething(slice1);
doSomething(slice2);
return 0;
}
I would prefer not to have to copy the elements to a new datastructure.
You'd just use a pair of iterators:
typedef std::vector<int>::iterator vec_iter;
void doSomething(vec_iter first, vec_iter last) {
for (vec_iter cur = first; cur != last; ++cur) {
std::cout << *cur << endl;
}
}
int main() {
std::vector v();
for (int i= 0; i < 10; ++i) { v.push_back(i); }
doSomething(v.begin() + 1, v.begin() + 5);
doSomething(v.begin() + 2, v.begin() + 4);
return 0;
}
Alternatively, the Boost.Range library should allow you to represent iterator pairs as a single object, but the above is the canonical way to do it.
I learnt Python before I learnt C++. I wondered if C++ offered slicing of vectors like slicing in Python lists. Took a couple of minutes to write this function that allows you to slice a vector analogous to the way its done in Python.
vector<int> slice(const vector<int>& v, int start=0, int end=-1) {
int oldlen = v.size();
int newlen;
if (end == -1 or end >= oldlen){
newlen = oldlen-start;
} else {
newlen = end-start;
}
vector<int> nv(newlen);
for (int i=0; i<newlen; i++) {
nv[i] = v[start+i];
}
return nv;
}
Usage:
vector<int> newvector = slice(vector_variable, start_index, end_index);
The start_index element will be included in the slice, whereas the end_index will not be included.
Example:
For a vector v1 like {1,3,5,7,9}
slice(v1,2,4) returns {5,7}
Taken from here:
std::vector<myvector::value_type>(myvector.begin()+start, myvector.begin()+end).swap(myvector);
Usage example:
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> indexes{3, 6, 9};
for( auto index : indexes )
{
int slice = 3;
std::vector<int> bar{1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int>( bar.begin() + index - slice, bar.begin() + index ).swap(bar);
std::cout << "bar index " << index << " contains:";
for (unsigned i=0; i<bar.size(); i++)
std::cout << ' ' << bar[i];
std::cout << '\n';
}
return 0;
}
Outputs:
bar index 3 contains: 1 2 3
bar index 6 contains: 4 5 6
bar index 9 contains: 7 8 9
As others have said, you can represent the "slice" as pair of iterators. If you are willing to use Boost, you can use the range concept. Then you will have even begin()/end() member functions available and the whole thing looks a lot like a container.
use boost range adapters. they are lazy:
operator|() is used to add new behaviour lazily and never modifies its
left argument.
boost::for_each(v|sliced(1,5)|transformed(doSomething));
doSomething needs to take range as input. a simple (may be lambda) wrapper would fix that.
You can represent those "slices" with a pair of iterators.
You don't need a pair of iterators to slice a vector. Three indexes will do because it allows you to create slices with steps:
static const int arr[] = {16,2,77,29,42};
vector<int> v (arr, arr + sizeof(arr) / sizeof(arr[0]) );
vector<int>::iterator i;
const int step = 2;
const int first = 0;
const int last = v.size()-1;
int counter=first;
for (i = v.begin()+first; counter<last; i+=step, counter+=step) {
// Do something with *i
cout << *i << endl;
}
Prints:
16
77
In this code, a counter is needed to track the position because not all iterators can do this.
It is possible to use slices with std::valarray. Which is an STL analogue of numpy.array in python. It support different vectorized operations like min, max, +,-, *, /, etc.
More info here.
std::slice(start, length, stride) allows to select and modify slices of an array without copying (documentation here).
The slicing would look like this:
std::valarray<int> foo (9);
for (int i=0; i<9; ++i) foo[i]=i; // 0 1 2 3 4 5 6 7 8
// | | | | |
std::slice myslice=std::slice(1,5,1); // v v v v v
foo[myslice] *= std::valarray<int>(10,3); // 0 10 20 30 40 50 6 7 8
Or with stride=2:
std::valarray<int> foo (9);
for (int i=0; i<9; ++i) foo[i]=i; // 0 1 2 3 4 5 6 7 8
// | | |
std::slice myslice=std::slice(1,3,2); // v v v
foo[myslice] *= std::valarray<int>(10,3); // 0 10 2 30 4 50 6 7 8
// | | |
foo[std::slice (0,3,3)] = 99; // v v v
// 99 10 2 99 4 50 99 7 8
std::cout << "foo:";
for (std::size_t n=0; n<foo.size(); n++)
std::cout << ' ' << foo[n];
std::cout << '\n';