Converting R split() function to C++ - c++

Consider the reproducible example in R:
test <- c(1:12)
> test
[1] 1 2 3 4 5 6 7 8 9 10 11 12
The expected result:
test.list <- split(test, gl(2, 3))
> test.list
$`1`
[1] 1 2 3 7 8 9
$`2`
[1] 4 5 6 10 11 12
I am trying to write equivalent code in C++ to produce and return the two vectors that resulted from the test.list. Note that, I am in the embarrassing novice stage in C++.

We can use the nice answer by #jignatius and make it an R-callable function. For simplicity I keep it at NumericVector; we have a boatload of answers here that show show to switch between NumericVector and IntegerVector based on the run-time payload.
Code
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::List mysplit(Rcpp::NumericVector nums, int n, int size) {
std::vector<std::vector<double>> result(n);
int i = 0;
auto beg = nums.cbegin();
auto end = nums.cend();
while (beg != nums.cend()) {
//get end iterator safely
auto next = std::distance(beg, end) >= size ? beg + size : end;
//insert into result
result[i].insert(result[i].end(), beg, next);
//advance iterator
beg = next;
i = (i + 1) % n;
}
Rcpp::List ll;
for (const auto&v : result)
ll.push_back(v);
return ll;
}
/*** R
testvec <- 1:12
mysplit(testvec, 2, 3)
*/
Output
> Rcpp::sourceCpp("~/git/stackoverflow/68858728/answer.cpp")
> testvec <- 1:12
> mysplit(testvec, 2, 3)
[[1]]
[1] 1 2 3 7 8 9
[[2]]
[1] 4 5 6 10 11 12
>
There is a minor error in the original question in that we do not need a call to gl(); just the two scalars are needed.

Try this, which creates a vector of vectors containing the elements from the source in alternating chunks:
#include <iostream>
#include <vector>
template<typename T>
std::vector<std::vector<T>> split(std::vector<T> nums, int n, int size)
{
std::vector<std::vector<T>> result(n);
int i = 0;
auto beg = nums.cbegin();
auto end = nums.cend();
while (beg != nums.cend()) {
//get end iterator safely
auto next = std::distance(beg, end) >= size ? beg + size : end;
//insert into result
result[i].insert(result[i].end(), beg, next);
//advance iterator
beg = next;
i = (i + 1) % n;
}
return result;
}
int main()
{
std::vector<int> vnums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto vectors = split(vnums, 2, 3);
for (const auto& v : vectors)
{
for (auto num : v) {
std::cout << num << " ";
}
std::cout << std::endl;
}
}
Demo

Related

How to interleave two vectors of different sizes?

I have two vectors
vector<int> first_v = {1, 4, 9, 16, 8, 56};
vector<int> second_v = {20, 30};
And the goal is to combine those vectors in specific order like that (basically program first prints one value of the first_v vector and then one value of second_v vector):
Expected Output:
1 20 4 30 9 16 8 56
I'm very close to solution but the problem is that if one vector is shorter than another, then program will print '0'.
Problem output:
1 20 4 30 9 0 16 0
Here is the code I tried to solve this problem
merge_vect(first_v, second_v);
vector<int> merge_vect(const vector<int> & a, const vector<int> & b){
vector<int> vec(a.size() + b.size());
for (int i = 0; i < vec.size(); i++){
cout << a[i] << " ";
cout << b[i] << " ";
}
return vec;
}
What can I do in order to solve this problem?
You could keep one iterator to each vector and add from the vector(s) that have not reached their end() iterator.
Example:
#include <iostream>
#include <vector>
std::vector<int> merge_vect(const std::vector<int>& avec,
const std::vector<int>& bvec)
{
std::vector<int> result;
result.reserve(avec.size() + bvec.size());
for(auto ait = avec.begin(), bit = bvec.begin();
ait != avec.end() || bit != bvec.end();)
{
if(ait != avec.end()) result.push_back(*ait++);
if(bit != bvec.end()) result.push_back(*bit++);
}
return result;
}
int main() {
std::vector<int> first_v = {1, 4, 9, 16, 8, 56};
std::vector<int> second_v = {20, 30};
auto result = merge_vect(first_v, second_v);
for(auto val : result) std::cout << val << ' ';
}
Output:
1 20 4 30 9 16 8 56
A possible optimization could copy from both vectors for as long as both have elements and then copy the rest from the larger vector in one go:
std::vector<int> merge_vect(const std::vector<int>& avec,
const std::vector<int>& bvec)
{
std::vector<int> result;
result.reserve(avec.size() + bvec.size());
auto ait = avec.begin(), bit = bvec.begin();
// copy while both have more elements:
for(; ait != avec.end() && bit != bvec.end(); ++ait, ++bit) {
result.push_back(*ait);
result.push_back(*bit);
}
// copy the rest
if(ait != avec.end()) result.insert(result.end(), ait, avec.end());
else if(bit != bvec.end()) result.insert(result.end(), bit, bvec.end());
return result;
}

implementation of max filter of each size

I need your help, because for now I have no idea how to continue.
I got a task, that I need to implement in C++ for a given array.
The task is like this, for this array for example: [1,2,3,4]
I need to make a max filter with size 1-4, like this:
First step: performing filter of size 1 on the array , and we will get: [1,2,3,4]
Second step:performing filter of size 2 on the array , and we will get: [1,2,3]
Third step:performing filter of size 3 on the array , and we will get: [1,2]
Fourth step:performing filter of size 4 on the array , and we will get: [1]
After all of this, I need to perform a minimum function on each array that I filtered, and I need to return the sum of all the minimums, for example:
the minimum for first filtered array is:1
minimum for second filtered array:1
minimum for third filtered array:1
minimum for forth filtered array:1
return 1+1+1+1=4
The difficulty is that I need to execute all this program in less than 2 seconds for every array size from 1 to 1000000.
Thanks for your help.
Does this code help?
void print(const std::vector<int>& vec) {
for (const auto& i : vec) {
std::cout << i << ' ';
}
std::cout << '\n';
}
template <typename it>
it minimum(it start, it end)
{
auto min = start;
for (start; start != end; ++start)
{
if (*start < *min)
min = start;
}
return min;
}
std::vector<int> filter(const std::vector<int>& v, int size)
{
std::vector<int> ret;
for(int i=0; i <= v.size() - size; i++)
{
ret.push_back(*minimum(v.begin()+i, v.begin()+(i+size)));
}
return ret;
}
int main()
{
const std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8};
int sum = 0;
for(int filter_size = 1; filter_size <= 4; filter_size++)
{
const std::vector<int> filtered = filter(v, filter_size);
print(filtered);
sum += (*minimum(filtered.begin(), filtered.end()));
}
std::cout << "sum=" << sum << '\n';
return 0;
}
Output is:
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7
1 2 3 4 5 6
1 2 3 4 5
sum=4

set_difference not always returns the right answer

I am currently working on an evolutionary algorithm. I write a program to implement the crossover function, i.e., exchange k elements between vectors A and B. Here is the code:
#include <algorithm>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <iterator>
#include <random>
#include <set>
#include <vector>
using namespace std;
vector<int> reservoir_sampling(vector<int> input, int k)
{
vector<int> output(k);
int i;
for (i = 0; i < k; i++)
{
output[i] = input[i];
}
srand(time(nullptr));
while(i < input.size())
{
int j = rand() % (i+1);
if (j < k)
{
output[j] = input[i];
}
i++;
}
return output;
}
template<typename T>
void vprintf(vector<T> V)
{
for (T v : V)
{
cout << v << " ";
}
cout << endl;
}
void test()
{
// crossover between A and B at k points
vector<int> A = {0, 1, 2, 3, 4, 5};
vector<int> B = {6, 7, 8, 9};
printf("A: ");
vprintf(A);
printf("B: ");
vprintf(B);
int k = 2;
vector<int> outers = reservoir_sampling(A, k);
vector<int> inners = reservoir_sampling(B, k);
printf("outers: ");
vprintf(outers);
printf("inners: ");
vprintf(inners);
// uS = A + inners
vector<int> uS;
set_union(A.begin(), A.end(), inners.begin(), inners.end(), inserter(uS, uS.end()));
sort(uS.begin(), uS.end());
printf("uS = A + inners: ");
vprintf(uS);
// dS = uS - outers
vector<int> dS;
set_difference(uS.begin(), uS.end(), outers.begin(), outers.end(), inserter(dS, dS.end()));
sort(dS.begin(), dS.end());
printf("dS = uS - outers: ");
vprintf(dS);
}
int main()
{
test();
return 0;
}
Sometimes, the output is right, like:
A: 0 1 2 3 4 5
B: 6 7 8 9
outers: 3 4
inners: 9 7
uS = A + inners: 0 1 2 3 4 5 7 9
dS = uS - outers: 0 1 2 5 7 9
Sometimes, the output is not right, like:
A: 0 1 2 3 4 5
B: 6 7 8 9
outers: 3 1
inners: 9 7
uS = A + inners: 0 1 2 3 4 5 7 9
dS = uS - outers: 0 1 2 4 5 7 9
It turns out set_union is always OK, but set_difference is not. I don't have any clue where I am wrong. Almighty users of SO, please help me out!
You violate the preconditions of std::set_union and std::set_difference:
Constructs a sorted union beginning at d_first consisting of the set of elements present in one or both sorted ranges [first1, last1) and [first2, last2).
Copies the elements from the sorted range [first1, last1) which are not found in the sorted range [first2, last2) to the range beginning at d_first.
The reservoir_sampling function does not produce a sorted vector in the general case. The behaviour of your program is undefined.
The standard library provides std::sample function for random sampling. It preserves the relative order of selected elements if you give it a pair of forward or random access iterators.
template<typename T>
std::vector<T> sampling(const std::vector<T>& input, std::size_t k) {
std::vector<T> output;
output.reserve(k);
std::sample(input.begin(), input.end(), std::back_inserter(output),
k, std::mt19937{std::random_device{}()});
// the relative order of elements in output is the same as in input
return output;
}

How to Move certain elements of std::vector to a new index within the vector?

I am porting some old hand rolled array processing classes I wrote to now use the std library containers. One method I am having trouble porting is what I call "ChangeRecordOrder" for lack of a better term. I need a standard library replacement.
Its definition is:
template <class T>
void ChangeRecordOrder( std::vector<T> IN OUT &inputVector,
uint newInsertIndex,
std::vector<uint> IN const &indexesToMoveToNewIndex );
For example (Pseudo code):
MyVector<uint> = {0,10,20,30,40,50,60,70,80,90}
IndexesToMove = {2,4}
NewIndex = 6
After call to ChangeRecordOrder( MyVector, NewIndex, IndexesToMove ):
MyVector<uint> == {0,10,30,50,20,40,60,70,80,90}
Note that the elements at 2 and 4 (20 and 40), were moved to index 6 of the original vector (in front of 60).
Of course I would like to do this in place, and not use another temporary vector. I also dont mind the requirement that the IndexesToMove vector needs to be sorted before calling.
I couldn't find an std lib algorithm for this. The algorithm that I had before worked on the raw memory and did not use c++ move semantics.
Thank you!
template <typename t> void move(std::vector<t>& v, size_t oldIndex, size_t newIndex)
{
if (oldIndex > newIndex)
std::rotate(v.rend() - oldIndex - 1, v.rend() - oldIndex, v.rend() - newIndex);
else
std::rotate(v.begin() + oldIndex, v.begin() + oldIndex + 1, v.begin() + newIndex + 1);
}
test: https://coliru.stacked-crooked.com/a/5c31007000b9eeba
int main()
{
std::vector<int> v{ 3, 4, 5, 6, 7, 8, 9 };
move(v, 1, 4);
move(v, 4, 1);
move(v, 3, 3);
}
output:
move 1 to 4: 3 [4] 5 6 7 8 9
result: 3 5 6 7 [4] 8 9
move 4 to 1: 3 5 6 7 [4] 8 9
result: 3 [4] 5 6 7 8 9
move 3 to 3: 3 4 5 [6] 7 8 9
result: 3 4 5 [6] 7 8 9
You're looking for std::rotate.
#include<vector>
#include<iostream>
#include<algorithm>
int main() {
std::vector<int> values{0, 10, 20, 30, 40, 50, 60, 70, 80, 90};
std::vector<size_t> indexes_to_move{2,4};
size_t destination_index = 6;
if(destination_index > values.size()) throw std::runtime_error("Come on, bro.");
for(auto const& val : values) std::cout << val << ',';
std::cout << std::endl;
for(size_t _index = 0; _index < indexes_to_move.size(); _index++) {
size_t index = indexes_to_move[indexes_to_move.size() - _index - 1]; //We need to iterate in reverse.
if(index >= values.size()) throw std::runtime_error("We dun goofed.");
if(index >= destination_index) throw std::runtime_error("We goofed in a different way.");
std::rotate(values.begin() + index, values.begin() + index + 1, values.begin() + destination_index);
destination_index--;
}
for(auto const& val : values) std::cout << val << ',';
std::cout << std::endl;
return 0;
}
This yields the following output, according to ideone.com:
0,10,20,30,40,50,60,70,80,90,
0,10,30,50,20,40,60,70,80,90,
Here is a solution, that moves each of the non-selected elements at most once:
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> values{0, 10, 20, 30, 40, 50, 60, 70, 80, 90};
vector<size_t> IndexesToMove{2,4};
size_t NewIndex = 6;
//check that your indices are sorted, non-empty, in the correct range, etc.
// move one element in front of the next element to move
// then move those two elements in front of the next element to move
// ...
auto it_next = values.begin() + IndexesToMove.front();
for(size_t i = 0; i < IndexesToMove.size() -1; i++) {
auto it_first = it_next - i;
it_next = values.begin() + IndexesToMove[i+1];
rotate(it_first, it_first + i + 1 , it_next);
}
// move the collected elements at the target position
rotate(it_next - IndexesToMove.size() + 1, it_next + 1, values.begin() + NewIndex);
}
Readability is admittedly not too good. It couldprobably be improved by better variable names and/or putting some of it into a separate function
The above two examples had issues with different input (noted above). I worked out the algorithm to handle the different cases and it passed my unit tests. It can probably be improved for speed.
template <class CONTAINER_TYPE>
void ChangeRecordOrder( CONTAINER_TYPE IN OUT &values,
uint newIndex,
std::vector<uint> IN const &indexesToMove )
{
// Make a copy of the indexesToMove as we need to do fixups to them in certain cases
std::vector<uint> temporaryIndexes = indexesToMove;
for ( uint i=0; i<temporaryIndexes.size(); i++ )
{
uint indexToMove = temporaryIndexes[i];
if ( indexToMove < newIndex )
{
uint leftIndex = indexToMove;
uint rightIndex = newIndex -1;
uint newFirst = leftIndex + 1;
std::rotate( values.begin() + leftIndex, values.begin() + newFirst, values.begin() + rightIndex +1);
// fix up indexes
for( uint j=i+1; j<temporaryIndexes.size(); j++ )
{
uint &futureIndex = temporaryIndexes[j];
if ( futureIndex > leftIndex && futureIndex <=rightIndex )
--futureIndex;
}
}
else if ( indexToMove > newIndex )
{
uint leftIndex = newIndex;
uint rightIndex = indexToMove;
uint newFirst = indexToMove;
std::rotate( values.begin() + leftIndex, values.begin() + newFirst, values.begin() + rightIndex +1);
// fix up indexes
for( uint j=i+1; j<temporaryIndexes.size(); j++ )
{
uint &futureIndex = temporaryIndexes[j];
if ( futureIndex > leftIndex && futureIndex <=rightIndex )
++futureIndex;
}
++newIndex;
}
}
}

Combinations in a range of numbers in C++

I would like to build a C++ program that show all the possible combinations depending on the number of elements taken by a N factor.
Let's suppose a vector vec[6] with elements 1 2 3 4 5 6 on it.
Using the combination formula, 6! / 4! (6 - 4)! = 15 possibilities
I want to generate a function which gives the result of all 15 possibilities taken 4 by 4 with no repetition, as example:
1 2 3 4
1 2 3 5
1 2 3 6
2 3 4 5
and so on...
I am using this code for now, but i want to use numbers from my vector (v[6]).
#include <algorithm>
#include <iostream>
#include <string>
void comb(int N, int K)
{
std::string bitmask(K, 1); // K leading 1's
bitmask.resize(N, 0); // N-K trailing 0's
// print integers and permute bitmask
do {
for (int i = 0; i < N; ++i) // [0..N-1] integers
{
if (bitmask[i]) std::cout << " " << i;
}
std::cout << std::endl;
} while (std::prev_permutation(bitmask.begin(), bitmask.end()));
}
int main()
{
comb(6, 4);
}
Would you please guys give me a help? I'd like to know where i could change the code so that i can use my own vector.
i'm generating this vector v[i] and sorting it with a bubble sort, like this:
void order (int d[], int n){
int i, j;
for (i = 1; i < n; i++)
for (j = 0; j < n-1; j++)
if (d[j] > d[j+1])
swap (d[j],d[j+1]);
for (i = 0; i < n; i++)
cout << d[i] << " ";
}
after that sorting, i want to put my vector into the comb function.
how could i make it is possible?
Here's a C++14 solution that uses a free, open source library to do the work:
#include "combinations"
#include <iomanip>
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v{1, 2, 3, 4, 5, 6};
int state = 0;
for_each_combination(v.begin(), v.begin() + 4, v.end(),
[&state](auto first, auto last)
{
std::cout << std::setw(2) << ++state << " : ";
while (true)
{
std::cout << *first;
if (++first == last)
break;
std::cout << ' ';
}
std::cout << '\n';
return false;
});
}
This outputs:
1 : 1 2 3 4
2 : 1 2 3 5
3 : 1 2 3 6
4 : 1 2 4 5
5 : 1 2 4 6
6 : 1 2 5 6
7 : 1 3 4 5
8 : 1 3 4 6
9 : 1 3 5 6
10 : 1 4 5 6
11 : 2 3 4 5
12 : 2 3 4 6
13 : 2 3 5 6
14 : 2 4 5 6
15 : 3 4 5 6
The source code for the library can be copy/pasted from the above link and inspected for how it works. This library is extremely high performance compared to solutions using std::prev_permutation. The implementation is relatively simple for this function, but the library also contains more functionality that grows increasingly complicated to implement (but just as easy to use):
template <class BidirIter, class Function>
Function
for_each_combination(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_reversible_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_circular_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_reversible_circular_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
The library has several pleasant features including:
Your input sequence (vector or whatever) need not be sorted.
You can prematurely break out of the loop at any time by returning true.
If you don't break out of the loop early, the sequence is always returned to its original state.
The functor always receives iterators to the first k elements of the sequence, so it is possible to also operate on the elements not selected if you tell the functor about the total length of the sequence.
Feel free to use the library as is, or study and take what you need from its implementation. The link above contains a tutorial-like description, and a detailed specification of each function.
Start with subset S = {1,2,3,...,k}, that's the first subset. Generate the next subset by examining elements from the right (start with the last), and increment it if you can (if it is < N), and return that as the next subset. If you can't increment it, look at the element to the left until you find one you can increment. Increment it, and set the elements to the right sequentially from that point. Below are the 3 element subsets of {1,2,3,4,5} (N=5,k=3,there are 10 subsets):
{1,2,3}, {1,2,4}, {1,2,5}, {1,3,4}, {1,3,5}, {1,4,5}, {2,3,4}, {2,3,5}, {2,4,5}, {3,4,5}
#include <iostream>
#include <vector>
std::ostream& operator<<(std::ostream& o, std::vector<int>& a)
{
o << "{";
for (std::vector<int>::const_iterator it = a.begin(); it != a.end(); ++it) {
o << *it;
if (it + 1 < a.end()) o << ",";
}
return o << "}";
}
int main()
{
const int N = 7;
const int k = 4;
std::vector<int> A(k);
// initialize
for (int i = 0; i < k; ++i) {
A[i] = i + 1;
}
std::cout << A << std::endl;
int h = 0;
bool done = false;
do {
++A[k-h-1];
for (int t = k - h; t < k; ++t) {
A[t] = A[t-1] + 1;
}
if (A[k-h-1] < N - h) {
// last element can be incremented, stay there...
h = 0;
} else {
// last element at max, look back ...
++h;
}
done = (A[0] == N - k + 1);
std::cout << A << std::endl;
} while (!done);
}
Pretty simple recursive implementation:
struct Combs
{
vector<int> scombs;
template <typename F>
void call_combs(int n, int k, F f)
{
if (k == 0) {
f();
}
else {
scombs.push_back(n - 1);
call_combs(n - 1, k - 1, f);
scombs.resize(scombs.size() - 1);
if (k < n) {
call_combs(n - 1, k, f);
}
}
}
};
...
Combs combs;
const auto& coco = combs.scombs;
combs.call_combs(6, 4, [&coco](){
copy(coco.cbegin(), coco.cend(), ostream_iterator<int>(cout));
cout << endl;
});