How to make an infinite sequence in C++ - c++

I'm using Visual Studio 2012 so C++11 is mostly OK...
boost is also fine, but I would prefer to avoid other libreries, at least not widley used ones.
I want to create a forward only iterator that returns an infinite sequence, in the most elegant way possible. For example a sequence of all the natural numbers.
Basically I want the C++ equivilent of this f# code:
let nums =
seq { while true do
yield 1
yield 2
}
the above code basically creates an enumerator that returns [1;2;1;2...]
I know I could do this by writing a class, but there's got to be a shorter way with all the new lambdas and all...

Is this what you want:
#include <iostream>
#include <vector>
int main()
{
auto nums = []
{
static unsigned x = 2;
return ( x++ % 2 ) + 1;
};
std::vector< int > v{ nums(), nums(), nums(), nums(), nums() };
for( auto i : v )
{
std::cout << i;
}
return 0;
}
or I have misunderstood the question?

The simpler thing, if you can depend on boost is to write something like this:
int i = 0;
auto gen = boost::make_generator_iterator([=]() { return i++; });
C++14 version:
auto gen = boost::make_generator_iterator([i=0]() { return i++;});
Documentation is here.
P.S.: I'm not sure if it will work without result_type member, which C++03 functor would need.

I've written a library called Pipeline using which you can write such things easily, as:
auto infinite_seq = generate(1, [](int i) { return (i % 2) + 1; });
Now infinite_seq is a deferred-range which means it will generate the values and give you when you ask for it. If you ask for 10 values, it will generate exactly 10 values — this can be expressed as:
auto values = infinite_seq | take(10);
Or you can write this:
auto values = generate(1, [](int i) { return (i % 2) + 1; }) | take(10);
for(auto i : values)
//working with i
Have a look at the documentation of generate.

Standard C++ has no real iterator generators which help you avoid writing the class manually. You can take a look at my range library for such an iterator generator to get going. This code essentially allows you to write
for (auto i : range(1))
…
which generates the infinite sequence 1, 2, 3, …. Boost.Iterator contains tools for transforming one iterator output into another, related output. You could use that to repeatedly cycle over elements from a two-item container (containing the elements 1 and 2, in your case).

When you have a hammer in your hand, everything around looks like a nail. Lambdas and other C++11 features are sure cool, but you should choose valid tools for problems. In this case I see nothing simpler and more elegant than short class with overloaded operators:
class MyInfiniteIter
{
private:
unsigned int i;
public:
MyInfiniteIter()
{
i = 0;
}
int operator *() {
return i;
}
int operator++ () {
i++;
if (i == 10)
i = 0;
return i;
}
};
int main(int argc, char * argv[])
{
for (MyInfiniteIter i;; ++i)
{
printf("%d\n", *i);
}
}

Here is C++14 index_sequence comes helping:
#include <iostream>
#include <vector>
namespace std
{
template< int ...i> struct index_sequence{};
template< int N, int ...i>
struct make_seq_impl : make_seq_impl< N-1, N-1,i...> {};
template< int ...i>
struct make_seq_impl<0,i...>{ typedef index_sequence<i...> type; };
template< int N >
using make_index_sequence = typename make_seq_impl<N>::type;
} // namespace std
typedef std::vector<int> integer_list;
template< typename F, int ...i >
integer_list make_periodic_list_impl(F f, std::index_sequence<i...> )
{
// { 1 2 1 2 1 2... }
return { f(i) ... };
}
template< int N , typename F>
integer_list make_periodic_list(F f)
{
return make_periodic_list_impl(f, std::make_index_sequence<N>{} );
}
int main()
{
std::vector<int> v = make_periodic_list<20>([](int i){return 1 + (i&1);});
for( auto e : v ) std::cout << e << ' ';
}

Related

Sort Integers by The Number of 1 Bits . I used one sort function to sort the vector ? But why sort is not working?

Sort Integers by The Number of 1 Bits
Leetcode : Problem Link
Example Testcase :
Example 1:
Input: arr = [0,1,2,3,4,5,6,7,8]
Output: [0,1,2,4,8,3,5,6,7]
Explantion: [0] is the only integer with 0 bits.
[1,2,4,8] all have 1 bit.
[3,5,6] have 2 bits.
[7] has 3 bits.
The sorted array by bits is [0,1,2,4,8,3,5,6,7]\
Example 2:
Input: arr = [1024,512,256,128,64,32,16,8,4,2,1]
Output: [1,2,4,8,16,32,64,128,256,512,1024]
Explantion: All integers have 1 bit in the binary representation, you should just sort them in ascending order.
My Solution :
class Solution {
public:
unsigned int setBit(unsigned int n){
unsigned int count = 0;
while(n){
count += n & 1;
n >>= 1;
}
return count;
}
vector<int> sortByBits(vector<int>& arr) {
map<int,vector<int>>mp;
for(auto it:arr){
mp[setBit(it)].push_back(it);
}
for(auto it:mp){
vector<int>vec;
vec=it.second;
sort(vec.begin(),vec.end()); //This Sort Function of vector is not working
}
vector<int>ans;
for(auto it:mp){
for(auto ele:it.second){
ans.push_back(ele);
}
}
return ans;
}
};
In my code why sort function is not working ?
[1024,512,256,128,64,32,16,8,4,2,1]
For the above testcase output is [1024,512,256,128,64,32,16,8,4,2,1] because of sort function is not working. It's correct output is [1,2,4,8,16,32,64,128,256,512,1024]
Note : In the above example testcase every elements of the testcase has only one set-bit(1)
As your iteration in //This sort function ...
refers to mp as the copy of the value inside the map, sort function will not sort the vector inside it, but the copy of it. Which does not affecting the original vector<int> inside the mp. Therefore, no effect occurs. You should refer the vector inside the map as a reference like this:
class Solution {
public:
unsigned int setBit(unsigned int n) {
unsigned int count = 0;
while (n) {
count += n & 1;
n >>= 1;
}
return count;
}
vector<int> sortByBits(vector<int>& arr) {
map<int, vector<int>>mp;
for (auto it : arr) {
mp[setBit(it)].push_back(it);
}
for (auto& it : mp) {
sort(it.second.begin(), it.second.end()); //Now the sort function works
}
vector<int>ans;
for (auto it : mp) {
for (auto ele : it.second) {
ans.push_back(ele);
}
}
return ans;
}
};
Although there is more design problem inside your solution, this will be a solution with minimized modification.
vector<int>vec is a copy of a copy of the one in the map which is then discarded. Try:
for(auto& entry:mp){
vector<int>&vec=entry.second;
sort(vec.begin(),vec.end());
}
Your other for loops should also use references for efficiency but it won't affect the behaviour.
I assume the OP is just learning, so fiddling with various data structures etc. can carry some educational value. Still, only one of the comments pointed out that the starting approach to the problem is wrong, and the whole point of the exercise is to find a custom method of comparing the numbers, by number of bits first, then - by value.
Provided std::sort is allowed (OP uses it), I guess the whole solution comes down to, conceptually, sth likes this (but I haven't verified it against LeetCode):
template <typename T>
struct Comp
{
std::size_t countBits(T number) const
{
size_t count;
while(number) {
count += number & 1;
number>>=1;
}
return count;
}
bool operator()(T lhs, T rhs) const
{
/*
auto lb{countBits(lhs)};
auto rb{countBits(rhs)};
return lb==rb ? lhs < rhs : lb < rb;
* The code above is the manual implementation of the line below
* that utilizes the standard library
*/
return std::tuple{countBits(lhs), lhs} < std::tuple{countBits(rhs), rhs};
}
};
class Solution {
public:
void sortByBits(vector<int>& arr) {
std::sort(begin(arr), end(arr), Comp<int>{});
}
};
Probably it can improved even further, but I'd take it as starting point for analysis.
Here is memory efficient and fast solution. I don't know why you are using map and extra vector. we can solve this questions without any extra memory efficiently. We just have to make a Comparator function which will sort elements according to our own requirements. Please let me know in comments if you require further help in code (or if you find difficult to understand my code). I am using __builtin_popcount() function which will return me number of set bits in a number.
bool sortBits(const int a, const int b){ //Comparator function to sort elements according to number of set bits
int numOfBits1 = __builtin_popcount(a);
int numOfBits2 = __builtin_popcount(b);
if(numOfBits1 == numOfBits2){ //if number of set bits are same, then sorting the elements according to magnitude of element (greater/smaller element)
return a < b;
}
return (numOfBits1 < numOfBits2); //if number of set bits are not same, then sorting the elements according to number of set bits in element
}
class Solution {
public:
vector<int> sortByBits(vector<int>& arr) {
sort(arr.begin(),arr.end(), sortBits);
return arr;
}
};
The problem is already evaluated and the fix is aready explained.
I want to give 2 additional/alternative solution proposals.
In C++17 we have the std::bitset count function. Please see here
And in C++20 we have directly the std::popcount function. Please see here.
(Elderly and grey haired people like me would also find 5 additional most efficient solutions in the Book "Hackers Delight")
Both variants lead to a one statement solution using std::sort with a lambda.
Please see:
#include <algorithm>
#include <vector>
#include <iostream>
#include <bitset>
// Solution
class Solution {
public:
std::vector<int> sortByBits(std::vector<int>& arr) {
std::sort(arr.begin(), arr.end(), [](const unsigned int i1, const unsigned int i2)
{ size_t c1{ std::bitset<14>(i1).count() }, c2{ std::bitset<14>(i2).count() }; return c1 == c2 ? i1 < i2 : c1 < c2; });
//{ int c1=std::popcount(i1), c2=std::popcount(i2); return c1 == c2 ? i1 < i2 : c1 < c2; });
return arr;
}
};
// Test
int main() {
std::vector<std::vector<int>> testData{
{0,1,2,3,4,5,6,7,8},
{1024,512,256,128,64,32,16,8,4,2,1}
};
Solution s;
for (std::vector<int>& test : testData) {
for (const int i : s.sortByBits(test)) std::cout << i << ' ';
std::cout << '\n';
}
}

Iterating over odd (even) elements only in a range-based loop

Suppose we have a plain array (or other container which supports range-based loops):
const int N = 8;
int arr[N] = {0, 1, 2, 3, 4, 5, 6, 7};
Using indexes or iterators, we can loop over odd elements and increment the index by two:
for (int i = 0; i < N; i+=2)
{
std::cout << arr[i] << std::endl;
}
How can I get a similar result by using a range-based loop and avoiding explicit iterators/indexes and iteration skipping? Something like this:
for (const auto& v: odd_only(arr))
{
std::cout << v << std::endl;
}
What does a simple and elegant solution look like? Does the standard library contain something like this?
There's no support for what you request – but you might write your own even_only and odd_only implementations.
Basic idea is to wrap around the normal iterator of the container in question and do a double increment internally each time we increment once externally:
template <typename C, bool IsOdd>
class even_odd_only
{
C& c;
public:
class iterator
{
public:
// all the definitions required for iterator!
// most if not all might simply be derived from C::iterator...
// copy/move constructor/assignment as needed
// core of the wrapper: increment twice internally!
// just doing += 2 is dangerous, though, we might increment beyond
// the end iterator (undefined behaviour!)additionally, += 2 only
// is possible for random access iterators (so we limit usability)
void operator++() { ++b; if(b != e) ++b; }
// operator* and operator-> (both return *b), post-increment
// (defined in terms of pre-increment), etc...
// comparison: only needs to compare b iterators!
private:
C::iterator b;
C::iterator e; // needed for comparison to avoid incrementing beyond!
iterator(C::iterator b, C::iterator e) : b(b), e(e) { }
};
// const_iterator, too; possibly make a template of above
// and derive const and non-const iterators from?
even_odd_only(C& c) : c(c) { }
iterator begin()
{
using std::begin;
using std::end;
using std::empty;
auto b = begin(c);
// should be self-explanatory:
// skip first element in odd variant (if there is)
if constexpr(IsOdd) { if(!empty(c)) { ++b; } }
return iterator(b, end(c));
};
iterator end()
{
using std::end;
return iterator(end(c), end(c));
}
};
template <typename T>
using even_only = even_odd_base<T, false>;
template <typename T>
using odd_only = even_odd_base<T, true>;
As is, it would work even with non-random-access and even non-bidirectional iterators. But especially for RA-iterators, it's less efficient than the classic loop (due to the intermediate if in operator++).
Defining comparison iterators: always operator== and operator!=, only for random access operators you can additionally have operator[<|>|<=|>=] (→ std::enable_if).
You'll find more details about how to write an iterator here – keep in mind when you encounter, though, that std::iterator itself is deprecated now.
As for what you are currently asking; I do not believe anything exists yet. Now as for iterating over a container by some integer N we can do the following; we can write our own for_each type of function. I've written one below and it works like a gem! You may also want to look into the std::advance function as well for it can be another possible implementation. I was checking that out myself as I was writing this function. However; as for c arrays I'm not sure there is much one can do without a bunch of extra code such as class templates, wrappers, etc. Here is my function.
#include <array>
#include <vector>
#include <iterator>
template<typename Container, typename Function>
void for_each_by_n( Container&& cont, Function f, unsigned increment_by = 1) {
if ( increment_by == 0 ) return; // must check this for no op
using std::begin;
auto it = begin(cont);
using std::end;
auto end_it = end(cont);
while( it != end_it ) {
f(*it);
for ( unsigned n = 0; n < increment_by; ++n ) {
if ( it == end_it ) return;
++it;
}
}
}
int main() {
std::array<int,8> arr{ 0,1,2,3,4,5,6,7 };
std::vector<double> vec{ 1.2, 1.5, 1.9, 2.5, 3.3, 3.7, 4.2, 4.8 };
auto l = [](auto& v) { std::cout << v << ' '; };
for_each_by_n(arr, l); std::cout << '\n';
for_each_by_n(vec, l); std::cout << '\n';
for_each_by_n(arr, l, 2); std::cout << '\n';
for_each_by_n(arr, l, 4); std::cout << '\n';
for_each_by_n(vec, l, 3); std::cout << '\n';
for_each_by_n(vec, l, 5); std::cout << '\n';
for_each_by_n(arr, l, 8); std::cout << '\n';
for_each_by_n(vec, l, 8); std::cout << '\n';
// sanity check to see if it doesn't go past end.
for_each_by_n(arr, l, 9); std::cout << '\n';
for_each_by_n(vec, l, 9); std::cout << '\n';
return 0;
}
-Output-
0 1 2 3 4 5 6 7
1.2 1.5 1.9 2.5 3.3 3.7 4.2 4.8
0 2 4 6
0 4
1.2 2.5 4.2
1.2 3.7
0
1.2
0
1.2
What I like about this example above is that not only can you increment through a loop by some integer N; the above function also takes a function pointer, function object, functor, or lambda and it will perform the required action.
In your case you was trying to loop through your container by 2 for ever odd or every even index and within the loop you were printing the results. Here in my example; I'm printing the results in the form of a lambda that is being passed to this function.
However the only caveat with this particular implementation is that it will always start from index 0. You could easily expand on this by introducing another integer parameter as to an offset of where the iteration will begin; but I'll leave that up to you to do as an exercise.
For the time being we have to settle for what C++11 through C++17 has to offer. In the near future we should have many new and powerful features with the release of C++20.
There is a ready-made solution for this problem in the Range-v3. I think this can be useful if you don’t want to write your own implementation or need more flexibility (f.e. arbitrary stride)
#include <range/v3/all.hpp>
void example()
{
int data[8] = {0, 1, 2, 3, 4, 5, 6, 7};
for (auto i : ranges::view::stride(data, 2))
{
std::cout << i << std::endl;
}
}
(copied from #hlt comment)
This isn't really an answer to the question, but—for what it is worth—whenever I run into a limitation of ranged-for, I look for a standard algorithm solution. Like...
#include <algorithm>
#include <iostream>
#include <iterator>
#include <utility>
int main()
{
int arr[] {0, 1, 2, 3, 4, 5, 6, 7};
std::copy_if(
std::begin(arr), std::end(arr),
std::ostream_iterator<int>(std::cout, "\n"),
[is_odd_element = true](int n) mutable {
return std::exchange(is_odd_element, not is_odd_element);
});
}

Pick out the least recurring number in an array

I need help picking out the least recurring element in an array. I can't think of any robust algorithm, is there any function defined in the c++ library that does that?
If there is an algorithm that you can come up with, please share. Not the code necessarily, but the idea
'Define least recurring' - suppose an array say a[4] holds 2,2,2,4. 4 is the least recurring element
Uses some C++14 features for brevity but easily adapted to C++11:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
template <typename I>
auto leastRecurring(I first, I last) {
unordered_map<iterator_traits<I>::value_type, size_t> counts;
for_each(first, last, [&counts](auto e) { ++counts[e]; });
return min_element(begin(counts), end(counts), [](auto x, auto y) { return x.second < y.second; })->first;
}
int main() {
const int a[] = {2, 2, 2, 3, 3, 4};
cout << leastRecurring(begin(a), end(a)) << endl;
}
Using only std goodies (live demo on Coliru):
// Your original vector
auto original = { 2, 2, 2, 4, 4 };
// Sort numbers and remove duplicates (in a copy, because std::unique modifies the contents)
std::vector<int> uniques(original);
std::sort(std::begin(uniques), std::end(uniques));
auto end = std::unique(std::begin(uniques), std::end(uniques));
// Count occurences of each number in the original vector
// The key is the number of occurences of a number, the value is the number
std::map<int, int> population;
for (auto i = uniques.begin(); i != end; ++i) {
population.emplace(std::count(std::begin(original), std::end(original), *i), *i);
}
// The map is sorted by key, therefore the first element is the least recurring
std::cout << population.begin()->second;
Note that in the example you gave, the array is already sorted. If you know that this will always be the case, you can get rid of the call to std::sort.
If two numbers have the same population count, the greater one will be kept.
from collections import Counter
def leastFrequentToken(tokens):
counted = Counter(tokens)
leastFrequent = min(counted, key=counted.get)
return leastFrequent
Essentially, create a map of token:count, find the smallest value in the map and return its key.
Assuming the 'numbers' are ints:
// functor to compare k,v pair on value
typedef std::pair<int, size_t> MyPairType;
struct CompareSecond
{
bool operator()(const MyPairType& left, const MyPairType& right) const
{
return left.second < right.second;
}
};
vector<int> tokens[4] = { 2, 2, 2, 4 };
map<int, size_t> counted;
for (vector<int>::iterator i=tokens.begin(); i!=tokens.end(); ++i)
{
++counted[*i];
}
MyPairType min
= *min_element(counted.begin(), counted.end(), CompareSecond());
int leastFrequentValue = min.second;
C++ translation using these SO question answers:
C++ counting instances / histogram using std::map,
Finding minimum value in a Map
in C++11, assuming your type support strict weak ordering (for std::sort), following may help: https://ideone.com/poxRxV
template <typename IT>
IT least_freq_elem(IT begin, IT end)
{
std::sort(begin, end);
IT next = std::find_if(begin, end, [begin](decltype(*begin) el) { return el != *begin; });
IT best_it = begin;
std::size_t best_count = next - begin;
for (IT it = next; it != end; it = next) {
next = std::find_if(it, end, [it](decltype(*begin) el) { return el != *it; });
const std::size_t count = next - it;
if (count < best_count) {
best_count = count;
best_it = it;
}
}
return best_it;
}

map triple of unsigned int's to double -- is it the most optimal/efficient way?

I face the following task:
map triplet of unsigned int's to a value, which is either zero or positive (double); And be able for a given triplet obtain the double or say that it's actually zero;
I have the following simplification:
first (let's call it I) and second (let's cal it J) ints are in known ranges (from zero to IMAX and JMAX).
For the third index (K), I know an estimate of triplets (third index is scattered), say ESTIMATE;
During calculation the number of triplets growths, more precisely, for a given I and K, the number of third indices can increase.
So far I see the following solution:
keep vector of vectors of map:
vector< vector < map <unsinged int, unsigned int>>> tri_map_;
//^I ^J ^K ^index
if 'index' is not zero, obtain the value from supplementary vector:
vector< double> values;
values[index];
The whole thing to be initialized as:
tri_map_.resize(IMAX);
for (int i=0;i<IMAX;++i) tri_map_[i].resize(JMAX);
What do you think about that solution? Is there a better way to do it?
The thing I don't like is that it seems I can't do something like 'reserve' for
the map. Is there a way to try to allocate enough memory (cos I have an estimate for the third index) and check if there is enough memory for that? Apart from that I'm satisfied with it.
EDIT1:
IMAX ~ hundrets
JMAX ~ 10^5
EDIT2:
trying to incorporate the solution of sehe, but for
unordered_set and for pair;
So, that's where I have a problem specialization of ‘template<class _Tp> struct std::tr1::hash’ in different namespace :
...
EDIT3: the following works, will investigate its speed.
Thanks everyone for suggestions and advices!
#include <tr1/functional>
#include <vector>
#include <map>
#include <tr1/unordered_set>
#include <list>
#include <set>
#include <tr1/array>
#include <iostream>
struct pair_int {
unsigned int first;
unsigned int second;
bool operator< (pair_int const& o) const {
if ( first < o.first )
return true;
if ( first > o.first )
return false;
return second < o.second;
}
bool operator==(pair_int const& o) const {
return ( (first==o.first)&&(second==o.second) );
}
};
namespace std {
namespace tr1 {
template<> struct hash<pair_int> {
unsigned int operator()(pair_int const& key) const {
return ~key.first + 17u*key.second;
}
};
}
}
class pair_storage {
public:
pair_storage() {};
~pair_storage();
....
private:
pair_int pair_ij_;
std::map<pair_int,double>::iterator pairMapIterator_;
std::vector< std::map<pair_int,double> > pairMapVector_;
std::vector< std::tr1::unordered_set< pair_int > > pairMapVectorZero_;
};
Can't compile it with -std=c++0x cos I have some problems in some parts of big code...
It looks to me you are looking for
std::map
std::multimap
std::unordered_map
std::unordered_multimap
Here is a simple example of using std::unordered_multimap (which will require the specialization of std::hash<> for your key type, and is therefore the slightly more involved way to write it):
#include <tuple>
#include <unordered_map>
#include <cassert>
#include <iostream>
struct triplet
{
unsigned a,b,c;
bool operator< (triplet const& o) const { return std::tie(a,b,c) < std::tie(o.a,o.b,o.c); }
bool operator==(triplet const& o) const { return std::tie(a,b,c) ==std::tie(o.a,o.b,o.c); }
};
namespace std {
template<> struct hash<triplet> {
unsigned int operator()(triplet const& key) const {
return ~key.a + 17u*key.b + 17u*key.c; // totally made that up, could be better, I suppose
}
};
}
static std::ostream& operator<<(std::ostream& os, triplet const& key) {
return os << '[' << key.a << ',' << key.b << ',' << key.c << ']';
}
int main()
{
std::unordered_multimap<triplet, double> map;
// insert items dynamically
map.insert({ triplet{ /*I*/ 1, /*J*/ 2, /*K*/ 3 }, 0.1 } );
map.insert({ triplet{ /*I*/ 4, /*J*/ 5, /*K*/ 6 }, 0.2 } );
map.insert({ triplet{ /*I*/ 7, /*J*/ 8, /*K*/ 9 }, 0.3 } );
map.insert({ triplet{ /*I*/ 1, /*J*/ 2, /*K*/ 0 }, 0.4 } ); // duplicate (I,J) ok
map.insert({ triplet{ /*I*/ 1, /*J*/ 2, /*K*/ 0 }, 0.5 } );
assert(0 == map.count(triplet {1,5,6}));
assert(1 == map.count(triplet {4,5,6}));
auto range = map.equal_range(triplet { 1,2,0 });
for (auto it=range.first; it!=range.second; ++it)
std::cout << it->first << ": " << it->second << "\n";
}
Output (as seen on http://ideone.com/pm8Oz):
[1,2,0]: 0.4
[1,2,0]: 0.5
struct Triple
{
unsigned int A;
unsigned int B;
unsigned int C;
};
map<Triple, double> mapping;
Regarding the question "is it the most optimal/efficient way?":
Try using hash_map or unordered_map; that might be faster than map (or may be not, depending on your use case).
Regarding the question "Is there a way to try to allocate enough memory...?":
You can use unordered_map::max_load_factor to adjust memory/performance trade-off; this is just like preallocation.
Oh, and you can also use unordered_set to store elements that map to zero. That might reduce memory consumption for no performance cost.

Transform-and-Accumulate

Have anybody written a C++ STL-compliant algorithm that combines std::transform and std::accumulate into a single pass algorithm supporting both the unary, binary and perhaps even (n-ary!) variant, say std::transformed_accumulate? I want this because I have found this pattern highly reusable in for example linear algebra for example in (l1-)norm calculations. The l1-norm calculates the sum of the absolute values of the elements.
Uhm... My bet is that you can do that by embedding your transformation into the binary predicate, tranform the element and accumulate after the transformation.
struct times2accumulator {
int operator()( int oldvalue, int newvalue ) const {
return oldvalue + 2*newvalue;
}
};
int r = std::accumulate( v.begin(), v.end(), 2, times2accumulator() );
That functor would be equivalent to:
struct times2 {
int operator()( int x ) {
return 2*x;
}
};
std::vector<int> tmp; tmp.reserve( v.size() );
std::transform( v.begin(), v.end(), std::back_inserter(tmp), times2 );
int r = std::accumulate( tmp.begin(), tmp.end(), 0 );
Of course this could be made generic, just pass the transformation functor to a generic base functor:
template <typename Transform>
struct transform_accumulator_t {
Transform t;
transform_accumulator_t( Transform t ) : t(t) {}
int operator()( int oldvalue, int newvalue ) const {
return oldvalue + t(newvalue);
}
};
// syntactic sugar:
template <typename T>
transform_accumulator_t<T> transform_accumulator( T t ) {
return transform_accumulator_t<T>(t);
}
int r = std::accumulate(v.begin(), v.end(), 0, transform_accumulator(times2));
And you could also generalize on the type in the container... or even create a more generic transform_accumulator that takes both an accumulator and a transformation functors and applies them in order. Actual implementation left as an exercise for the reader.
Although it may not exactly fit the original intent, std::inner_product is basically your binary version. You pass it an initial value, two ranges, and two functors, and it applies them as:
T acc = initial_value;
while (begin1 != end1) {
acc = binary_op1(acc, binary_op2(begin1, begin2);
++begin1;
++begin2;
return acc;
So, for your L1 you'd do something on this general order:
norm = std::inner_product(input1.begin(), input1.end(),
input2.begin(), input2.end(),
std::plus<int>(), std::abs);
Only that doesn't quite work -- right now, it's trying to pass std::abs where you really need a binary function that combines the two inputs, but I'm not sure how the two inputs are really supposed to be combined.
std::partial_sum is fairly close to your unary version, except that along with accumulating a result, it (attempts to) write out each intermediate result, not just the final result. To just get the final result, you'd have to write (and pass an instance of) a kind of do-nothing iterator that just holds a single value:
template<class T, class Dist=size_t, class Ptr = T*, class Ref = T&>
class unique_it : public std::iterator<std::random_access_iterator_tag, T, Dist, Ptr, Ref> {
T &value;
public:
unique_it(T &v) : value(v) {}
T &operator*() { return value; }
unique_it &operator++() { return *this; }
unique_it &operator+(size_t) { return *this; }
unique_it &operator++(int) { return *this; }
};
template <class T>
unique_it<T> make_res(T &v) { return unique_it<T>(v); }
With this, your L1 normalization would look something like this:
int main(){
double result=0.0;
double inputs[] = {1, -2, 3, -4, 5, -6};
std::partial_sum(
inputs, inputs+6,
make_res(result),
[](double acc, double v) {return acc + std::abs(v);});
std::cout << result << "\t";
return 0;
}
If you want to use some parallelism, I made a quick version using OpenMP :
template <class T,
class InputIterator,
class MapFunction,
class ReductionFunction>
T MapReduce_n(InputIterator in,
unsigned int size,
T baseval,
MapFunction mapper,
ReductionFunction reducer)
{
T val = baseval;
#pragma omp parallel
{
T map_val = baseval;
#pragma omp for nowait
for (auto i = 0U; i < size; ++i)
{
map_val = reducer(map_val, mapper(*(in + i)));
}
#pragma omp critical
val = reducer(val, map_val);
}
return val;
}
It is fast but there is certainly room for optimisation, especially around for (auto i = 0U; i < size; ++i) I think. (But I couldn't figure how to make an iterator-only version with OpenMP, any help would be appreciated!).
On a quick test with 1000000 elements array, and the computation iterated 1000 times to have a mean value, I made some comparisons.
Version 1 :
for (auto i = 0U; i < size; ++i)
val += std::pow(in[i][0], 2) + std::pow(in[i][1], 2);
score when compiled with:
g++ : 30 seconds
g++ -O3 : 2.6 seconds
Version 2 :
This version is the most optimized for this computation I think. (It gives the best result).
#pragma omp parallel reduction( + : val )
{
double map_val = 0.0;
#pragma omp for
for (int i=0; i < size; ++i)
{
map_val += std::pow(in[i][0], 2) + std::pow(in[i][1], 2);
}
val += map_val;
}
g++ -O3 : 0.2 seconds (it's the best one)
Version 3
This version uses the MapReduce_n function template I shown earlier :
double val = MapReduce_n(in, size, 0.0, [] (fftw_complex val)
{
return std::pow(val[0], 2.0) + std::pow(val[1], 2.0);
}, std::plus<double>());
g++ -O3 : 0.4 seconds, so there is a slight overhead for not using directly the OMP reduce directly. However, it doesn't allows custom operators, so at one point you (sadly) have to trade speed for genericity.
I am surprised noone said how to do this with Boost.Range:
accumulate(v | transformed((int(*)(int))&std::abs), 0);
where v is a Singe Pass Range (ie, any STL container). The abs overload has to be specified, otherwise this would be as elegant as Haskell.
As of C++17 there is also std::transform_reduce, which also has the benefit of being parallelizable.
https://en.cppreference.com/w/cpp/algorithm/transform_reduce