I'm running a test showing the benefits of sorting a 2d array, by columns, by pulling the data off into an individual array and sorting that array, then copying it back to the column. I'm wanting to run std::sort as a the sorting algorithm for every run. I'm trying to figure out how to run the loop in place first, before moving into the copying on and off the 2D array. An example of the input / output would be this.
#include <iostream>
#include <algorithm>
int main() {
int input[][5] = { { 13, 27, 4 , 1 , 11 },
{ 11, 19, 2 , 37, 1 },
{ 32, 64, 11, 22, 41 },
{ 71, 13, 27, -8, -2 },
{ 0 , -9, 11, 99, 13 } };
// std::sort something here.
int output[][5] = { { 0 , -9, 2 , -8, -2 },
{ 11, 13, 4 , 1 , 1 },
{ 13, 19, 11, 22, 11 },
{ 32, 27, 11, 37, 13 },
{ 71, 64, 27, 99, 41 } };
return 0;
}
Thanks for the help.
You may write your own iterator, something like:
#include <iterator>
template<typename Container>
class column_iterator : public std::iterator<std::random_access_iterator_tag,
typename std::decay<decltype(std::declval<Container>()[0][0])>::type>
{
typedef typename Container::iterator iterator;
typedef typename std::decay<decltype(std::declval<Container>()[0][0])>::type type;
public:
column_iterator(iterator it, int n) : it(it), n(n) {}
column_iterator& operator++() {++it; return *this;}
column_iterator& operator++(int) { auto res(*this); ++*this; return res;}
column_iterator& operator +=(std::ptrdiff_t offset) { it += offset; return *this;}
column_iterator operator +(std::ptrdiff_t offset) const { auto res(*this); res += offset; return res;}
column_iterator& operator--() {--it; return *this;}
column_iterator& operator--(int) { auto res(*this); --*this; return res;}
column_iterator& operator -=(std::ptrdiff_t offset) { it -= offset; return *this;}
column_iterator operator -(std::ptrdiff_t offset) const { auto res(*this); res -= offset; return res;}
type& operator*() { return (*it)[n];}
type* operator->() { return &(it)[n];}
bool operator == (const column_iterator& rhs) const { return it == rhs.it && n == rhs.n; }
bool operator != (const column_iterator& rhs) const { return !(*this == rhs); }
bool operator < (const column_iterator& rhs) const { return it < rhs.it; }
std::ptrdiff_t operator -(const column_iterator& rhs) const { return it - rhs.it; }
private:
iterator it;
int n;
};
template<typename Container>
column_iterator<Container> begin(Container& cont, int n)
{
return column_iterator<Container>(cont.begin(), n);
}
template<typename Container>
column_iterator<Container> end(Container& cont, int n)
{
return column_iterator<Container>(cont.end(), n);
}
Now, let's test it:
#include <algorithm>
#include <array>
#include <iostream>
#include <vector>
#include <cassert>
void display(const std::vector<std::array<int, 5>>& v)
{
for (auto rows : v) {
for (auto elem : rows) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
}
int main() {
std::vector<std::array<int, 5>> input {
{{ 13, 27, 4 , 1 , 11 }},
{{ 11, 19, 2 , 37, 1 }},
{{ 32, 64, 11, 22, 41 }},
{{ 71, 13, 27, -8, -2 }},
{{ 0 , -9, 11, 99, 13 }} };
for (int i = 0; i != 5; ++i) {
std::sort(begin(input, i), end(input, i));
}
display(input);
const std::vector<std::array<int, 5>> output {
{{ 0 , -9, 2 , -8, -2 }},
{{ 11, 13, 4 , 1 , 1 }},
{{ 13, 19, 11, 22, 11 }},
{{ 32, 27, 11, 37, 13 }},
{{ 71, 64, 27, 99, 41 }} };
assert(input == output);
return 0;
}
You can copy each column into a temp array,sort them and put them back into output array
for(j=0;j<5;++j)
{
for(i=0;i<5;++i)
{
temp[i]=input[i][j];
}
//sort temp[i]
//put it in output array
}
I finally gave up and decided to write my own version to compare with. I think I'm just going to keep all versions of the sorting algorithm similar to this.
#RichardPlunkett I tried creating my own compare function but was worried about it swapping entire rows.
#include <iostream>
#include <vector>
#include <random>
void sort (std::vector<std::vector<int> >& array, int start, int stop, int pos) {
if (stop - start < 2) return;
int mid = (start + stop) / 2;
int i = start, j = stop, pivot = array[mid][pos];
while (true) {
while (array[i][pos] < pivot) i++;
while (array[j][pos] > pivot) j--;
if (i > j) break;
std::swap(array[i++][pos], array[j--][pos]);
}
sort (array, start, j, pos);
sort (array, i, stop, pos);
}
int main() {
const int size = 10;
std::random_device rd;
std::default_random_engine generator(rd());
std::uniform_int_distribution<int> distribution(-10,10);
std::vector<std::vector<int> > test(size, std::vector<int>(size));
std::cout << "Unsorted array: \n";
for (int i=0;i<(int) test.size();++i) {
for (int j=0;j<(int) test[i].size();++j) {
test[i][j] = distribution(generator);
std::cout << test[i][j] << '\t';
}
std::cout << std::endl;
}
for (int i=0;i<size;++i)
sort(test, 0, size-1, i);
std::cout << "\nSorted array: \n";
for (int i=0;i<(int) test.size();++i) {
for (int j=0;j<(int) test[i].size();++j)
std::cout << test[i][j] << '\t';
std::cout << ' ' << std::endl;
}
return 0;
}
Related
Can I use a std::array<int, N> to alias parts of a int[] without invoking UB?
https://en.cppreference.com/w/cpp/container/array
"This container is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member."
Motivation: The copy function below is not under my control and needs to make a single assignment via references. Only a struct { int[N]; } like a std::array<int, N> can make that kind of "multiple object assignment"?
Is this UB?
Is there another way?
#include <iostream>
#include <array>
template <std::size_t N>
void print(int (&arr)[N], std::size_t number_rows, std::size_t number_cols) {
assert(number_rows * number_cols == N);
for (std::size_t r = 0; r != number_rows; ++r) {
for (std::size_t c = 0; c != number_cols; ++c) {
std::cout << arr[r * number_cols + c] << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
}
void copy(std::array<int, 4>& a, std::array<int, 4>& b) {
b = a;
}
int main() {
int vals[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
print(vals, 4, 4);
auto s1 = reinterpret_cast<std::array<int, 4>*>(&vals[0]);
auto s2 = reinterpret_cast<std::array<int, 4>*>(&vals[4]);
copy(*s2, *s1);
print(vals, 4, 4);
}
Output
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
5 6 7 8
5 6 7 8
9 10 11 12
13 14 15 16
Edit: The Wider problem
Thanks for all the comments / answers. By popular request I am posting the wider problem for more context.
I am going to do that in 2 levels.
Level 1
This is the next layer out of what I would like to do:
#include "range/v3/algorithm/remove.hpp"
#include "range/v3/view/chunk.hpp"
#include <vector>
int main() {
std::vector<int> v{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16
};
auto chunked = ranges::views::chunk(v, 4);
auto it = ranges::remove(chunked, 9, [](const auto& e) { return e[0]; }); // <== compile error
// expected result (xx = unspecified)
// std::vector<int> v{
// 1, 2, 3, 4,
// 5, 6, 7, 8,
// 13, 14, 15, 16,
// xx, xx, xx, xx
// };
// and it pointing at chunked[3] (ie the row of xx)
}
But ranges::remove complains that the ranges::view::chunk is "not permutable". This was confirmed here:
https://github.com/ericniebler/range-v3/issues/1760
So my next attempt was writing a "chunked range" which I could pass to ranges::remove. I did this in multiple ways. Several "worked" but are based on UB, including this way of using std::array<int,4> as a "chunk proxy" (and hence the OP above):
#include "range/v3/algorithm/remove.hpp"
#include "range/v3/view/chunk.hpp"
#include "range/v3/view/zip.hpp"
#include <iostream>
#include <iterator>
#include <vector>
class Integers {
public:
struct Iterator {
using chunk = std::array<int, 4>;
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = chunk;
using pointer = value_type*;
using reference = value_type&;
template <class ForwardIt, class UnaryPredicate, class ChunkedForwardIt>
ForwardIt remove_if_par(ForwardIt first, ForwardIt last, UnaryPredicate p,
ChunkedForwardIt chunked_first, std::ptrdiff_t chunk_size) {
auto first_orig = first;
first = std::find_if(first, last, p);
// advance chunked_first in lockstep. TODO this is linear compelxity unless random_access_iter
std::advance(chunked_first, std::distance(first_orig, first) * chunk_size);
if (first != last) {
ForwardIt i = first;
ChunkedForwardIt chunk_i = chunked_first;
while (++i != last) {
std::advance(chunk_i, chunk_size);
if (!p(*i)) {
*first++ = std::move(*i);
// move chunk
auto loop_chunk_i = chunk_i;
for (std::ptrdiff_t ci = 0; ci != chunk_size; ++ci)
*chunked_first++ = std::move(*loop_chunk_i++);
}
}
}
return first;
}
Iterator();
Iterator(int* ptr) : current_row_(reinterpret_cast<chunk*>(ptr)) {} // <== UB here
reference operator*() const { return *current_row_; }
pointer operator->() { return current_row_; }
Iterator& operator++() {
++current_row_;
return *this;
}
Iterator operator++(int) {
Iterator tmp = *this;
++(*this);
return tmp;
}
friend bool operator==(const Iterator& a, const Iterator& b) {
return a.current_row_ == b.current_row_;
}
friend bool operator!=(const Iterator& a, const Iterator& b) {
return a.current_row_ != b.current_row_;
}
private:
chunk* current_row_;
};
Iterator begin() { return Iterator(&data_[0]); }
Iterator end() { return Iterator(&data_[16]); }
int data_[16];
};
template <std::size_t N>
void print(int (&arr)[N], std::size_t number_rows, std::size_t number_cols) {
assert(number_rows * number_cols == N);
for (std::size_t r = 0; r != number_rows; ++r) {
for (std::size_t c = 0; c != number_cols; ++c) {
std::cout << arr[r * number_cols + c] << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
}
int main() {
Integers chunked{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
print(chunked.data_, 4, 4);
auto it = ranges::remove(chunked, 9, [](const auto& e) { return e[0]; });
print(chunked.data_, 4, 4);
Output (as desired but based on UB)
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
1 2 3 4
5 6 7 8
13 14 15 16
13 14 15 16
Level 2
The reason for being quite keen on using ranges, is because there is another layer outwards for my desired algorithm, in that there is actually a 1D parallel vector which I zipped together with the chunked one and then the remove condition is based on the 1D vector.
Note that both vectors are reasonably large here (~100-500k items), so I want to avoid making a copy. This is why I am not using | composition and the lazy ranges::views::filter, but using the eager ranges::remove instead which modifies the original containers (both need modifying).
The code below "works for me", but contains the UB as per OP:
#include "range/v3/algorithm/remove.hpp"
#include "range/v3/view/zip.hpp"
#include <cstddef>
#include <iostream>
#include <iterator>
#include <vector>
class Integers {
public:
struct Iterator {
using chunk = std::array<int, 4>;
using iterator_category = std::random_access_iterator_tag; // some requirements ommitted for brevity
using difference_type = std::ptrdiff_t;
using value_type = chunk;
using pointer = value_type*;
using reference = value_type&;
Iterator();
Iterator(int* ptr) : current_row_(reinterpret_cast<chunk*>(ptr)) {}
reference operator*() const { return *current_row_; }
pointer operator->() { return current_row_; }
Iterator& operator++() {
++current_row_;
return *this;
}
Iterator operator++(int) {
Iterator tmp = *this;
++(*this);
return tmp;
}
friend std::ptrdiff_t operator-(const Iterator& lhs, const Iterator& rhs) {
return lhs.current_row_ - rhs.current_row_;
}
friend bool operator==(const Iterator& a, const Iterator& b) {
return a.current_row_ == b.current_row_;
}
friend bool operator!=(const Iterator& a, const Iterator& b) {
return a.current_row_ != b.current_row_;
}
private:
chunk* current_row_;
};
Iterator begin() { return Iterator(&data_[0]); }
Iterator end() { return Iterator(&data_[16]); }
// fake the initialisation for brevity
std::vector<int> data_{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
};
void print(const auto& zipped) {
for (const auto& t: zipped) {
for (auto i: t.first) std::cout << i << ' ';
std::cout << " | " << t.second << '\n';
}
std::cout << '\n';
}
// no control over this api
void external_api(int* /* ptr */, std::size_t /* size */) {}
int main() {
Integers chunked;
std::vector<int> b{10, 20, 30, 40};
auto zipped = ranges::views::zip(chunked, b);
print(zipped);
auto it = ranges::remove(zipped, 30, [](const auto& e) { return e.second; });
auto relidx = it - zipped.begin();
chunked.data_.erase(chunked.data_.begin() + relidx * 4, chunked.data_.end());
b.erase(b.begin() + relidx, b.end());
print(zipped);
external_api(&chunked.data_[0], chunked.data_.size());
}
Output (as desired but based on UB):
1 2 3 4 | 10
5 6 7 8 | 20
9 10 11 12 | 30
13 14 15 16 | 40
1 2 3 4 | 10
5 6 7 8 | 20
13 14 15 16 | 40
Current best alternative
My best current alternative is to hand code both "zip" and "remove" using messy raw loops that deal with the "chunk 4" logic. Below is one version of this, which is basically a modified version of the std::remove implementation:
// no control over this api
void external_api(int* /* ptr */, std::size_t /* size */) {}
template <class ForwardIt, class UnaryPredicate, class ChunkedForwardIt>
ForwardIt remove_if_par(ForwardIt first, ForwardIt last, UnaryPredicate p,
ChunkedForwardIt chunked_first, std::ptrdiff_t chunk_size) {
auto first_orig = first;
first = std::find_if(first, last, p);
// advance chunked_first in lockstep. TODO this is linear compelxity unless random_access_iter
std::advance(chunked_first, std::distance(first_orig, first) * chunk_size);
if (first != last) {
ForwardIt i = first;
ChunkedForwardIt chunk_i = chunked_first;
while (++i != last) {
std::advance(chunk_i, chunk_size);
if (!p(*i)) {
*first++ = std::move(*i);
// move chunk
auto loop_chunk_i = chunk_i;
for (std::ptrdiff_t ci = 0; ci != chunk_size; ++ci)
*chunked_first++ = std::move(*loop_chunk_i++);
}
}
}
return first;
}
void print(const std::vector<int>& a, const std::vector<int>& chunked, std::size_t chunk_size) {
for (std::size_t i = 0; i != a.size(); ++i) {
std::cout << a[i] << " | ";
for (std::size_t j = 0; j != chunk_size; ++j)
std::cout << chunked[i * chunk_size + j] << ' ';
std::cout << '\n';
}
std::cout << '\n';
}
int main() {
std::vector<int> a{10, 20, 30, 40, 50, 60, 70};
std::vector<int> chunked{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28};
static constexpr std::ptrdiff_t chunk_size = 4;
print(a, chunked, chunk_size);
auto it = remove_if_par(
a.begin(), a.end(), [](auto e) { return e % 20 == 0; }, chunked.begin(), chunk_size);
print(a, chunked, chunk_size);
a.erase(it, a.end());
chunked.erase(chunked.begin() + (it - a.begin()) * chunk_size, chunked.end());
print(a, chunked, chunk_size);
external_api(&chunked[0], chunked.size());
}
Output (as desired and without UB)
10 | 1 2 3 4
20 | 5 6 7 8
30 | 9 10 11 12
40 | 13 14 15 16
50 | 17 18 19 20
60 | 21 22 23 24
70 | 25 26 27 28
10 | 1 2 3 4
30 | 9 10 11 12
50 | 17 18 19 20
70 | 25 26 27 28
50 | 17 18 19 20
60 | 21 22 23 24
70 | 25 26 27 28
10 | 1 2 3 4
30 | 9 10 11 12
50 | 17 18 19 20
70 | 25 26 27 28
I haven't checked, but I suspect that the assembly code generated for this "raw iterator loop" version is at least as good as any range based alternative; probably better.
Can I use a std::array<int, N> to alias parts of a int[] without invoking UB?
No.
Is this UB?
Yes.
Is there another way?
Depends on what parts of your scenario you can change.
The copy function below is not under my control
Simplest solution would be to not use the copy function that's not useful for your use case.
the std::array<int, N>& is the return value of the operator*() of a custom iterator over the raw int[]
Seems that there's probably no good way to implement such operator*().
This seems like a good opportunity to define a custom range adaptor with custom assignment operators that you could return from the custom iterator.
As you have noticed, chunked_view is not mutable. What you can do instead is to use adjacent<N> | stride(n) to create a mutable chunked view(assuming N is known at compile time):
std::vector data {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
std::vector b{10, 20, 30, 40};
constexpr std::size_t chunk_size = 4;
auto chunked_view = data
| std::views::adjacent<chunk_size>
| std::views::stride(chunk_size);
auto zipped_view = std::views::zip(chunked_view, b);
auto removed_range = std::ranges::remove(zipped_view, 30, [](auto pair){ return std::get<1>(pair); });
data.resize(data.size() - removed_range.size() * chunk_size);
b.resize(b.size() - removed_range.size());
Now data will be 1,2,3,4,5,6,7,8,13,14,15,16.
One thing to note is that adjacent creates a tuple of references of all the elements, so you can't iterate through a tuple. However, you can create a span or views::counted by using the address of the first element and chunk_size, since the underlying data were contiguous:
for (auto& [tuple, key] : zipped_view) {
for (auto i : std::span(&std::get<0>(tuple), chunk_size)) std::cout << i << ' ';
std::cout << " | " << key << '\n';
}
You can also remove all the temporary views if desired, since all you needed from the remove function is how many elements were removed:
std::vector data {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
std::vector b{10, 20, 30, 40};
constexpr std::size_t chunk_size = 4;
auto removal_size =
std::ranges::remove(
std::views::zip(
data | std::views::adjacent<chunk_size> | std::views::stride(chunk_size)
, b)
, 30, [](auto pair){ return std::get<1>(pair); }
).size();
data.resize(data.size() - removal_size * chunk_size);
b.resize(b.size() - removal_size);
I am trying to use std:copy to copy the 3D array to vector.
int myint[3][3][3] = { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },
{ { 11,12, 13 }, { 14, 15, 16 }, {17, 18, 19 } },
{ { 21, 22, 23 }, { 24, 25, 26 }, { 27, 28, 29 } } };
int favint[3][3][3];
I can copy the myint to favint as below
std::copy(&myint[0][0][0],
&myint[0][0][0] + (sizeof(myint) / sizeof(*myint)) * (sizeof(*myint) / sizeof(**myint))*(sizeof(**myint) / sizeof(***myint)),
&favint[0][0][0]);
I can copy the myint to myvector as below:
vector<vector<vector<int> > > myvector;
for (int k = 0; k<sizeof(myint) / sizeof(*myint); k++)
{
myvector.push_back(vector<vector<int> >());
for (int i = 0; i<sizeof(*myint) / sizeof(**myint); i++)
{
myvector[k].push_back(vector<int>());
for (int j = 0; j<sizeof(**myint) / sizeof(***myint); j++)
{
myvector[k][i].push_back(myint[k][i][j]);
}
}
}
Copy 3D array to a 3D array is simple using std:: copy. How can I use the std::copy to copy the myint to myvector? Is there any other simple way?
You might do something like:
std::vector<int> to_vector(const int (&a)[3])
{
return {std::begin(a), std::end(a)};
}
std::vector<std::vector<int>> to_vector(const int (&a)[3][3])
{
return {to_vector(a[0]), to_vector(a[1]), to_vector(a[2])};
}
std::vector<std::vector<std::vector<int>>> to_vector(const int (&a)[3][3][3])
{
return {to_vector(a[0]), to_vector(a[1]), to_vector(a[2])};
}
For generic (but compile time) values, template might help:
template <std::size_t N>
std::vector<int> to_vector(const int (&a)[N])
{
return {std::begin(a), std::end(a)};
}
template <std::size_t N1, std::size_t N2>
auto to_vector(const int (&a)[N1][N2])
-> std::vector<std::vector<int>>
{
std::vector<std::vector<int>> res;
res.reserve(N1);
for (const auto& inner_a : a) {
res.push_back(to_vector(inner_a));
}
return res;
}
template <std::size_t N1, std::size_t N2, std::size_t N3>
auto to_vector(const int (&a)[N1][N2][N3])
-> std::vector<std::vector<std::vector<int>>>
{
std::vector<std::vector<std::vector<int>>> res;
res.reserve(N1);
for (const auto& inner_a : a) {
res.push_back(to_vector(inner_a));
}
return res;
}
Demo
Simply use std::back_inserter
std::copy(&myint[0][0][0],
&myint[0][0][0] + sizeof myint / sizeof(int),
std::back_inserter(myvector));
My goal is to create an immutable function (functional programming) using "accumulate" in C++. I created a dummy list that generates 1's based on the position I send, which will be 6. So the list at the start contains {1,1,1,1,1,1}. I tried using accumulate to somehow use the information on this list and make the fibonacci sequence into a new list. The result has to be {1,1,2,3,5,8}
Here is what I have.
list<int> immutableFibonacci(int position)
{
const size_t fixedListSize(position);
list<int> newList(position, int(1));
list<int> copyList;
list<int>::iterator it = newList.begin();
if (position <=2)
{
return newList; //returns {1,1} or {1}
}
while (position>0)
{
advance(it, 1);
sum = accumulate(newList.begin(),it, 0);
copyList.push_back(sum);
position--;
}
return copyList;
}
What I have so far will return copyList as {1,2,3,4,5,6}. Can someone please push me in the right direction on what to do? I tried researching quite a bit.
this method creates a 'container-like' object which exposes iterators via begin() and end()
#include <iterator>
#include <iostream>
struct fib_iterator : std::iterator<std::forward_iterator_tag, long long>
{
fib_iterator(std::size_t torun = 0) : to_run(torun) {}
value_type operator*() const {
return value();
}
fib_iterator& operator++()
{
--to_run;
switch(preamble)
{
case 2:
--preamble;
return *this;
case 1:
--preamble;
return *this;
}
auto next = value();
x = y;
y = next;
return *this;
}
value_type value() const
{
switch(preamble)
{
case 2:
return 0;
case 1:
return 1;
}
return x + y;
}
bool operator==(const fib_iterator& r) const {
return to_run == r.to_run;
}
bool operator!=(const fib_iterator& r) const {
return to_run != r.to_run;
}
long long x = 0;
long long y = 1;
std::size_t preamble = 2;
std::size_t to_run;
};
struct fibonacci_sequence
{
fibonacci_sequence(std::size_t length) : length_(length) {}
fib_iterator begin() const { return { length_ }; }
fib_iterator end() const { return { }; }
std::size_t length_;
};
int main()
{
for (auto i : fibonacci_sequence(50))
std::cout << i << ", ";
std::cout << '\n';
}
sample output:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987,
1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393,
196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887,
9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141,
267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073,
4807526976, 7778742049,
How about this:
#include <iostream>
#include <vector>
#include <numeric>
#include <string>
#include <functional>
int main()
{
std::vector<int> v{1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
std::vector<int> s = std::accumulate(v.begin(), v.end(),std::vector<int>{},
[](const std::vector<int>& a, int b)
{
std::vector<int> d = a;
if(a.size()<2)
{
d.push_back(1);
}
else
{
auto start = d.rbegin();
auto first = *start;
start++;
auto second = *start;
d.push_back(first+second);
}
return d;
});
std::cout << "Fibo: " <<'\n';
for( auto c : s )
{
std::cout << c << "-";
}
std::cout << '\n';
}
But I also think it is a bit too much overhead, for something that simple.
EDIT: Remember to compile that with: g++ --std=c++14 fibo.cpp -o fibo.
EDIT: If you don't want to use the lambda function look here: How can I modify this Fibonacci code in C++ to use a function instead of lambda?
In Matlab, it is possible to do the following:
% init
a = 1:10;
b = 18:23;
% wrapping assignment
a([8:end 1:3]) = b;
Is something like this possible with Eigen? I'm hoping to make a member function for a circular buffer class that returns some reference to an Eigen type, perhaps something like:
VectorXd b(5);
b << 1,2,3,4,5 ;
CircularBuf a( 6 /*capacity*/ );
a.push(1);a.push(2);a.push(3);
// 3 elements in buf
a.pop();a.pop();
// 1 element in buf
// next line probably wraps around internal buffer, depending on impl
a.pushRef( b.size() /*number of elements in ref*/ ) = b;
I am not sure if this is what you are looking for...Following an answer I got from Jerry Coffin, I came up with this:
#include <iostream>
#include <vector>
#include <iterator>
template <class T>
class CircularVector {
typedef std::vector<T> DVector;
public:
CircularVector(const DVector& v) : v(v){}
T at(int i){return v.at(i);}
int size(){return v.size();}
class iterator :
public std::iterator < std::random_access_iterator_tag, T > {
CircularVector *vec;
int index;
public:
iterator(CircularVector &d, int index) : vec(&d), index(index) {}
iterator &operator++() { nextIndex(); return *this; }
iterator operator++(int) {
iterator tmp(*vec, index); nextIndex(); return tmp;
}
iterator operator+(int off) {
return iterator(*vec, (index + off)%vec->size());
}
iterator operator-(int off) {
return iterator(*vec, (index - off + vec->size())%vec->size());
}
T& operator*() { return (*vec).v[index]; }
bool operator!=(iterator const &other) { return index != other.index; }
//bool operator<(iterator const &other) { return index < other.index; }
private:
void nextIndex(){
++index;
if (index==vec->size()){index=0;}
}
};
iterator begin() { return iterator(*this, 0); }
//iterator end() { return iterator(*this, size()); }
private:
DVector v;
};
Your first example then can be written as:
int main() {
std::vector<int> a;
std::vector<int> b;
for(int i=1;i<11;i++){a.push_back(i);}
for(int i=18;i<24;i++){b.push_back(i);}
CircularVector<int> ca(a);
std::copy(b.begin(),b.end(),ca.begin()+7); // copy elements starting
// at index 8
for (int i=0;i<ca.size();i++){std::cout << ca.at(i) << std::endl;}
}
Actually, I was just curious to try it and I believe there are nicer ways to implement it. It is not the most efficient way to check if the index has to be wrapped each time it is increased. Obviously < and end() are not quite meaningful for a circular buffer and I decided not to implement them (e.g. for(it=begin();it<end();it++) would be an infinite loop. However, those are not needed to use it as input/output iterator.
I have another solution as described in my answer to this question. The code posted in the answer defines a custom expression for the circular shift, so you can benefit from Eigen's optimisations.
Given the circ_shift.h from the mentioned answer, you can do the following to achieve your goal: I hope this helps...
// main.cpp
#include "stdafx.h"
#include "Eigen/Core"
#include <iostream>
#include "circ_shift.h" // posted in the answer to the other quesiton.
using namespace Eigen;
int main()
{
VectorXi a(10), b(6);
a << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
b << 18, 19, 20, 21, 22, 23;
std::cout << "a = " << a.transpose() << std::endl << "b = " << b.transpose() << std::endl;
circShift(a, 3, 0).block(0, 0, b.size(), 1) = b;
std::cout << "now: a = " << a.transpose() << std::endl; // prints 21, 22, 23, 4, 5, 6, 7, 18, 19, 20
return 0;
}
sort(mMyClassVector.begin(), mMyClassVector.end(),
[](const MyClass & a, const MyClass & b)
{
return a.mProperty > b.mProperty;
});
I'd like to use a lambda function to sort custom classes in place of binding an instance method. However, the code above yields the error:
error C2564: 'const char *' : a function-style conversion to a built-in type can only take one argument
It works fine with boost::bind(&MyApp::myMethod, this, _1, _2).
Got it.
sort(mMyClassVector.begin(), mMyClassVector.end(),
[](const MyClass & a, const MyClass & b) -> bool
{
return a.mProperty > b.mProperty;
});
I assumed it'd figure out that the > operator returned a bool (per documentation). But apparently it is not so.
You can use it like this:
#include<array>
#include<functional>
using namespace std;
int main()
{
array<int, 10> arr = { 1,2,3,4,5,6,7,8,9 };
sort(begin(arr),
end(arr),
[](int a, int b) {return a > b; });
for (auto item : arr)
cout << item << " ";
return 0;
}
Can the problem be with the "a.mProperty > b.mProperty" line? I've gotten the following code to work:
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
#include <sstream>
struct Foo
{
Foo() : _i(0) {};
int _i;
friend std::ostream& operator<<(std::ostream& os, const Foo& f)
{
os << f._i;
return os;
};
};
typedef std::vector<Foo> VectorT;
std::string toString(const VectorT& v)
{
std::stringstream ss;
std::copy(v.begin(), v.end(), std::ostream_iterator<Foo>(ss, ", "));
return ss.str();
};
int main()
{
VectorT v(10);
std::for_each(v.begin(), v.end(),
[](Foo& f)
{
f._i = rand() % 100;
});
std::cout << "before sort: " << toString(v) << "\n";
sort(v.begin(), v.end(),
[](const Foo& a, const Foo& b)
{
return a._i > b._i;
});
std::cout << "after sort: " << toString(v) << "\n";
return 1;
};
The output is:
before sort: 83, 86, 77, 15, 93, 35, 86, 92, 49, 21,
after sort: 93, 92, 86, 86, 83, 77, 49, 35, 21, 15,
You can sort an array like this:
#include <bits/stdc++.h>
using namespace std;
int main() {
int q[] = {1, 3, 5, 7, 9, 2, 4, 6, 8 ,10};
sort(q, q + 10, [&](int A, int B) { return A < B; });
for (int i = 0; i < 10; i++)
cout << q[i] << ' ';
return 0;
}
before sort: 1 3 5 7 9 2 4 6 8 10
after sort: 1 2 3 4 5 6 7 8 9 10
I'd always like to use lambda to sort a array of struct in acm contests like this:
struct item {
int a, b;
};
vector<item> q;
sort(q.begin(), q.end(), [&](item t1, item t2) {
return t1.a < t2.a;
});