C++11 Lambda custom comparator slows down sorting - sorting

Custom lambda Comparator slower than normal function c++11. I experienced this a few times. But, Still Couldn't figure out the reason why this is so. Does anyone experience this and know the cause behind it?
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 1;
vector<int> v(N);
vector<int> sorted(N);
map<int, int> counts;
long long start;
void startClock() {
start = clock();
}
void stopClock() {
cout << float( clock () - start ) / CLOCKS_PER_SEC << endl;
}
void copyOriginal() {
for (int i = 0; i < N; ++i)
sorted[i] = v[i];
}
void sortWLambda(map<int, int>& counts) {
cout << "sorting with lambda" << endl;
sort(sorted.begin(), sorted.end(), [counts](const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
});
}
bool comparator(const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
}
void sortWoLambda() {
cout << "sorting w/o lambda" << endl;
sort(sorted.begin(), sorted.end(), comparator);
}
int main() {
for (int i = 0; i < N; ++i) {
int num = rand() % 1234;
counts[num]++;
v[i] = num;
}
copyOriginal();
startClock();
sortWLambda(counts);
stopClock();
copyOriginal();
startClock();
sortWoLambda();
stopClock();
return 0;
}
sorting with lambda 6.28 sec
sorting w/o lambda 0.17 sec

pass by reference made the difference for lambda.
I tried this..
sort(sorted.begin(), sorted.end(), [&counts](const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
});
now this takes same time as normal function
Passing by constant reference in the lambda capture list this helped me too!

Related

Overloading + operator in Eigen

I need to overload the + operation like this a + b = max(a,b).
And accordingly I need it to work for matrix addition and matrix multiplication and some other operations (trace, power,etc.). Here \bigoplus is max operation
What's the best way to do this with Eigen? I read about eigen extension here, but I don't understand how to do that for my task.
Currently I have this:
#include <iostream>
#include <Eigen/Dense>
#include <algorithm>
using namespace Eigen;
namespace MaxAlgebra {
template <typename T>
T operator+(const T& a,const T& b) {
T c(a.rows(),a.cols());
for (uint i = 0; i < a.rows(); ++i) {
for (uint j = 0; j < a.cols(); ++j) {
c(i,j) = std::max(a(i,j),b(i,j));
}
}
return c;
}
template <typename T>
T operator*(const T& a,const T& b){
T c(a.rows(),b.cols());
for (uint i = 0; i < a.rows(); ++i) {
for (uint j = 0; j < b.cols(); ++j) {
std::vector<uint> values;
for (uint k = 0; k < a.cols(); ++k) {
values.push_back(a(i,k) * b(k,j));
}
c(i,j) = *std::max_element(begin(values),end(values));
}
}
return c;
}
template <typename T>
uint trace(const T& a) {
std::vector<uint> values;
for (uint i = 0; i < a.rows(); ++i) {
values.push_back(a(i,i));
}
return *std::max_element(begin(values),end(values));
}
}
int main() {
MatrixXd x(2,2);
MatrixXd y(2,2);
x(0,0) = 3;
x(1,0) = 2;
x(0,1) = 1;
x(1,1) = 2;
y(0,0) = 2;
y(1,0) = 1;
y(0,1) = 2;
y(1,1) = 3;
MatrixXd c = MaxAlgebra::operator*(x,y);
std::cout << "Here is the matrix a:\n" << x << std::endl;
std::cout << "Here is the matrix b:\n" << y << std::endl;
std::cout << "Here is the matrix c:\n" << c << std::endl;
return 0;
}
If I understand your algebra correctly, you could simply create a custom scalar type. This seems to work:
template<class T>
struct MaxAlg
{
T scalar;
MaxAlg() = default;
MaxAlg(T scalar) noexcept // implicit conversion for convenience
: scalar(scalar)
{}
explicit operator T() const noexcept
{ return scalar; }
MaxAlg& operator+=(MaxAlg o) noexcept
{
scalar = std::max(scalar, o.scalar);
return *this;
}
friend MaxAlg operator+(MaxAlg left, MaxAlg right) noexcept
{ left += right; return left; }
MaxAlg& operator*=(MaxAlg o) noexcept
{
scalar *= o.scalar;
return *this;
}
friend MaxAlg operator*(MaxAlg left, MaxAlg right) noexcept
{ left *= right; return left; }
friend bool operator==(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar == right.scalar; }
friend bool operator!=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar != right.scalar; }
friend bool operator<(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar < right.scalar; }
friend bool operator<=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar <= right.scalar; }
friend bool operator>(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar > right.scalar; }
friend bool operator>=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar >= right.scalar; }
friend std::ostream& operator<<(std::ostream& left, MaxAlg right)
{ return left << right.scalar; }
};
template<class T, Eigen::Index Rows, Eigen::Index Cols>
using MaxAlgMatrix = Eigen::Matrix<MaxAlg<T>, Rows, Cols>;
template<class T, Eigen::Index Rows, Eigen::Index Cols>
using MaxAlgArray = Eigen::Array<MaxAlg<T>, Rows, Cols>;
using MaxAlgMatrixXd = MaxAlgMatrix<double, Eigen::Dynamic, Eigen::Dynamic>;
using MaxAlgVectorXd = MaxAlgMatrix<double, Eigen::Dynamic, 1>;
using MaxAlgArrayXXd = MaxAlgArray<double, Eigen::Dynamic, Eigen::Dynamic>;
using MaxAlgArrayXd = MaxAlgArray<double, Eigen::Dynamic, 1>;
int main()
{
Eigen::MatrixXd a = Eigen::MatrixXd::Random(10, 10);
Eigen::MatrixXd b = Eigen::MatrixXd::Random(10, 10);
MaxAlgMatrixXd maxalg_a = a.cast<MaxAlg<double> >();
MaxAlgMatrixXd maxalg_b = b.cast<MaxAlg<double> >();
std::cout << (maxalg_a * maxalg_b).cast<double>() << "\n\n";
std::cout << (maxalg_a.array() + maxalg_b.array()).cast<double>() << "\n\n";
std::cout << a.cwiseMax(b) << "\n\n";
}
This disables Eigen's vectorization but the compiler can still do it when you compile with -O3 and it is a lot less work.

c++ random set seed failed

I am trying to set seed to the c++ std::default_random_engine:
#include<random>
#include<time.h>
#include<iostream>
using namespace std;
void print_rand();
int main() {
for (int i{0}; i < 20; ++i) {
print_rand();
}
return 0;
}
void print_rand() {
default_random_engine e;
e.seed(time(0));
cout << e() << endl;
}
It seems that the printed numbers are same, how could I set the seed to generate the random number according to the time?
You have to seed only once instead of every time the function is called. Then you will get different values. I will move the functionality to main() to demonstrate this.
#include<random>
#include<time.h>
#include<iostream>
int main() {
std::default_random_engine e;
e.seed(time(0));
for (int i{0}; i < 20; ++i) {
std::cout << e() << std::endl;
}
return 0;
}
See Live Demo
As #P.W. said, you should seed only once. A minimal change in that direction would be using a static variable with the seed given to the constructor:
#include<random>
#include<time.h>
#include<iostream>
void print_rand();
int main() {
for (int i{0}; i < 20; ++i) {
print_rand();
}
return 0;
}
void print_rand() {
static std::default_random_engine e(time(0));
cout << e() << endl;
}

Vector Initializer_list

I am trying to implement a vector using my own class so I can not do the initialiser list part
# include <iostream>
# include <exception>
# include<initializer_list>
template <class T>
class vector {
public:
T* a;
T n;
int pos, c;
vector() { a = 0; n = 0; }
vector(T n) : n(n) { a = new T[n]; }
vector(std::initializer_list <vector> l) {
a = new T[int(sizeof(l))];
for (int f : l)
*(a + f) = l.begin() + f;
}
void push_back(T k) {
int i = k;
*(a + n) = k;
}
vector& operator= (vector&& th) {
this->a = th.a;
th.a = nullptr; return (*this);
}
vector& operator=(vector& k)
{
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
I am just trying to use pointer offset notation to take the initializer list items into the dynamic array but I get errors VS 17 IDE
Severity Code Description Project File Line Suppression
Error C2440 '=': cannot convert from 'const _Elem *' to 'T'
Error C2440 'initializing': cannot convert from 'const _Elem' to 'int'
Hello Nimrod!
#include <iostream>
#include <exception>
#include <initializer_list>
// normally people don't place a space between '#' and 'include'
template <class T>
class vector {
public:
T* a;
int n;
// probably it is length the vector
// change T to int
int pos, c;
vector() {
a = nullptr;
// do not use '0' to instruct null pointer
n = 0;
}
vector(int n): n(n) { a = new T[n]; }
vector(std::initializer_list<T> l) {
a = new T[l.size()];
// redundant force cast from size_t to int
for (int i = 0; i < l.size(); i++) {
a[i] = l.begin()[i];
}
// for (int f : l) # it seems that you wrote JavaScript before?
// *(a + f) = l.begin() + f;
}
void push_back(T k) {
// assigns "T k" to "int i"? it's confusing
// int i = k;
// *(a + n) = k;
}
// probably still many problems
vector& operator=(vector&& th) {
this->a = th.a;
th.a = nullptr;
return (*this);
}
vector& operator=(vector& k) {
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
You still need more practice. XP
In your context of code, template variable for initializer_list should be T rather than int.
Range for loop with initializer_list<T> will fetch the values
in the list. Therefore it should belong to T.

Why do I get future_error with async?

I need to start execution of vector of tasks in parallel and wait until finished. Here is how I did this, but I get future_error on MSVC. Small utility to split vector into parts:
template<typename T>
vector<vector<T>> split(const vector<T>& vec, size_t n) {
vector<vector<T>> outVec;
size_t length = vec.size() / n;
size_t remain = vec.size() % n;
size_t begin = 0;
size_t end = 0;
for (size_t i = 0; i < std::min(n, vec.size()); ++i) {
end += (remain > 0) ? (length + !!(remain--)) : length;
outVec.push_back(std::vector<T>(vec.begin() + begin, vec.begin() + end));
begin = end;
}
return outVec;
};
launch async execution:
template <typename T, typename R, typename F>
void execInParallel(vector<T> &tasks, vector<R> &res, F&&f, int cores) {
function<int(int &t)> fn(std::forward<F>(f));
auto parts = split(tasks, cores);
vector<future<vector<R>>*> threads;
for (auto part: parts) {
future<vector<R>> thrd=async(launch::async, [&](vector<T> tasks) {
vector<R> rs;
for (auto&t : tasks) {
rs.push_back(fn(t));
}
return rs;
}, part);
threads.push_back(&thrd);
}
for (auto&thrd : threads) {
vector<R> rs = thrd->get();
for (auto &r : rs)
res.push_back(r);
}
};
test on stupid example:
int main(){
vector<int> tasks,res;
tasks.push_back(1);
tasks.push_back(7);
tasks.push_back(19);
execInParallel(tasks,res, [&](int&t) {
return t+8;
}, 2);
return 0;
}
May be I am inventing a bicycle? Is there anything like that in C++11 or boost out of the box? Any example available?

Memory Limit Exceeded with Segment Tree in SPOJ Posters?

Given a horizontal section of wall , and N layers of paints applied from co-ordinates Xi to Yi , Output the distinct number of layers visible.
Here is the problem link http://www.spoj.com/problems/POSTERS/
Here is my solution http://ideone.com/gBJKnL
Approach :
I tried solving the problem by lazily updating child node values through a Segment Tree , the most recent value replaces the older one in their lazy updates. This way only the recent paint gets applied into the horizontal cross-section. although the code works fine on custom test cases , It takes a lot of memory and gets aborted by the Online Judge .
#include <iostream>
#include <set>
#include <vector>
#define MAX 10000000+100
typedef long long int ll;
using namespace std;
ll Tree[3*MAX],lazy[MAX*2];
void Update(ll s,ll start,ll end,ll left,ll right,ll value)
{
if(lazy[s]!=0)
{
Tree[s]=(lazy[s]*(end-start+1));
if(start!=end)lazy[2*s+1]=lazy[s],lazy[s*2+2]=lazy[s];
lazy[s]=0;
}
if(start>end||left>end||right<start)return;
if(start>=left&&end<=right)
{
Tree[s] = (value*(end-start+1));
if(start!=end)
{
lazy[2*s+1]=value;
lazy[2*s+2]=value;
}
return ;
}
ll mid=(start+end)/2;
Update(2*s+1,start,mid,left,right,value);
Update(2*s+2,mid+1,end,left,right,value);
Tree[s] = Tree[s*2+1]+Tree[2*s+2];
}
ll Read(ll s,ll start,ll end,ll left,ll right)
{
if(start>end||start>right||end<left)return 0;
if(lazy[s]!=0)
{
Tree[s]=(lazy[s]*(end-start+1));
if(start!=end)
{
lazy[2*s+1]=lazy[s];
lazy[2*s+2]=lazy[s];
}
lazy[s]=0;
}
if(start>=left&&end<=right)return Tree[s];
else return (Read(2*s+1,start,(start+end)/2,left,right)+Read(2*s+2,1+((start+end)/2),end,left,right));
}
int main() {
// your code goes here
ll t;
cin>>t;
while(t--)
{
ll n,z=1,li=-1;
cin>>n;
vector<pair<ll,ll> > b;
for(ll i=0;i<n;i++)
{
ll u,v;
li = max(li,v);
cin>>u>>v;
b.push_back(make_pair(u-1,v-1));
}
for(auto v: b)
Update(0,0,li+2,v.first,v.second,z++);
set<ll> a;
for(ll i=0;i<li+2;i++)cout<<Read(0,0,li+2,i,i)<<" ",a.insert(Read(0,0,li+2,i,i));
cout<<endl;
cout<<a.size()-1<<endl;
}
return 0;
}
Here is how you should be doing it:
#include <bits/stdc++.h>
#define mx 400005
using namespace std;
int tr[mx], lz[mx];
int t, n, l, r;
void update(int node, int s, int e, int l, int r, int val)
{
if(lz[node]!=0)
{
tr[node]=lz[node];
if(s!=e)
{
lz[node*2]=lz[node];
lz[node*2+1]=lz[node];
}
lz[node]=0;
}
if(s>e || r<s || l>e)
return;
if(s>=l && e<=r)
{
tr[node]=val;
if(s!=e)
{
lz[2*node]=val;
lz[2*node+1]=val;
}
return;
}
int m=s+(e-s)/2;
update(2*node,s,m,l,r,val);
update(2*node+1,m+1,e,l,r,val);
tr[node]=val;
//tr[node]=max(tr[2*node],tr[2*node+1]);
}
int query(int node, int s, int e, int l, int r)
{
if(r<s || e<l)
return 0;
if(lz[node]!=0)
{
tr[node]=lz[node];
if(s!=e)
{
lz[node*2]=lz[node];
lz[node*2+1]=lz[node];
}
lz[node]=0;
}
if(l<=s && r>=e)
return tr[node];
int m=s+(e-s)/2;
return query(2*node,s,m,l,r)+query(2*node+1,m+1,e,l,r);
}
int main()
{
//cout << "Hello world!" << endl;
cin>>t;
while(t--)
{
for(int i=0; i<mx; i++) tr[i]=0;
cin>>n;
int lr[n+1][2];
map<int,bool> mark;
vector<int> vec;
//int c=0;
for(int i=0; i<n; i++)
{
cin>>l>>r;
lr[i][0]=l;
lr[i][1]=r;
if(mark[l]==0)
{
vec.push_back(l);
mark[l]=1;
}
if(mark[r]==0)
{
vec.push_back(r);
mark[r]=1;
}
}
sort(vec.begin(), vec.end());
map<int,int> mp;
int c=1;
for(int i=0; i<vec.size(); i++)
mp[vec[i]]=c++;
for(int i=0; i<n; i++)
{
//cout<<mp[lr[i][0]]<<" "<<mp[lr[i][1]]<<"\n";
update(1,1,vec.size(),mp[lr[i][0]],mp[lr[i][1]],i+1);
}
set<int> ans;
for(int i=1; i<=vec.size(); i++)
{
//cout<<query(1,1,vec.size(),i,i)<<" ";
ans.insert(query(1,1,vec.size(),i,i));
}
int k = ans.size();
if(ans.find(0) != ans.end())
k--;
printf("%d\n",k);
}
return 0;
}

Resources