How to sort with a lambda? - c++

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

Related

C++ template and std::any how to execute any generic function with generic parameters of different length and type

#include <iostream>
#include <vector>
#include <string>
#include <type_traits>
#include <map>
#include <any>
using namespace std;
int func1(int a, int b, int c) {
return a + b + c;
}
int func1Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]), b = any_cast<int>(params["b"]), c = any_cast<int>(params["c"]);
return func1(a,b,c);
}
double func2(int a, int b) {
return a * b;
}
double func2Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]), b = any_cast<int>(params["b"]);
return func2(a,b);
}
int func3(int a, string b) {
return a + b.length();
}
int func3Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]);
string b = any_cast<string>(params["b"]);
return func3(a,b);
}
int func4(int a, vector<int> b) {
int sum = 0;
for (const auto& x : b) sum += x;
return a + sum;
}
int func4Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]);
auto b = any_cast<vector<int>>(params["b"]);
return func4(a,b);
}
typedef map<string, vector<map<string, any>>> FeatureMap;
vector<vector<std::any>> executor(map<string, vector<map<string, any>>> featureMap)
{
vector<vector<std::any>> res;
for (auto it=featureMap.begin(); it!=featureMap.end(); it++)
{
vector<std::any> currentRes;
if (it->first=="func1") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func1Wrapper(*paramIt));
}
if (it->first=="func2") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func2Wrapper(*paramIt));
}
if (it->first=="func3") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func3Wrapper(*paramIt));
}
if (it->first=="func4") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func4Wrapper(*paramIt));
}
res.push_back(currentRes);
}
return res;
}
int main()
{
FeatureMap fm;
fm["func1"] = { {{"a", 1}, {"b", 2}, {"c", 3}} , {{"a", 3}, {"b", -4}, {"c", 5}} };
fm["func2"] = { {{"a", 2}, {"b", 2}} , {{"a", 3}, {"b", -4}} };
fm["func3"] = { {{"a", 3}, {"b", "hello"s}} , {{"a", 3}, {"b", "123"s}} };
fm["func4"] = { {{"a", 4}, {"b", vector<int>({1,2,3})}}, {{"a", 3}, {"b", vector<int>({3,4,5})}} };
auto res = executor(fm);
auto func1Res = res[0], func2Res = res[1], func3Res = res[2], func4Res = res[3];
cout << any_cast<int>(func1Res[0]) << " " << any_cast<int>(func1Res[1]) << "\n";
cout << any_cast<double>(func2Res[0]) << " " << any_cast<double>(func2Res[1]) << "\n";
cout << any_cast<int>(func3Res[0]) << " " << any_cast<int>(func3Res[1]) << "\n";
cout << any_cast<int>(func4Res[0]) << " " << any_cast<int>(func4Res[1]) << "\n";
return 0;
}
I am converting a Python library to C++, it uses dict() everywhere.
A 1-1 conversion is like the code above: an executor accept a list of function, each function can have different parameter types and length. I store the parameters in a map<string, std::any> params, and for each function I have to manually extract the parameter then manually call the function (like func1Wrapper).
This code is very tedious to use and update. More importantly, it's very slow since there are map and std::any everywhere. I wish to use template to do as much thing as possible at compile time.
Is there anyway to convert the above code to using template? The executor should be able to accept any function with any parameter (different length, different types, ...). Instead of using a map<string, std::any> params, a user must give the function parameters in the correct order.
Edit: if the above is impossible, then what should I use to achieve similar functionality? Basically, the executor should be able to perform:
vector<vector<std::any>> res;
vector<vector<vector<std::any>> param_list;
for (i=0; i<function_list.size(); i++):
{
vector<std::any> currentRes;
for (j=0; j<param_list[i].size(); j++)
currentRes.push_back(function_list[i](param_list[i][j]));
res.push_back(currentRes);
}
while using as much compile-time stuffs as possible.
The executor should be able to accept any function with any parameter (different length, different types, ...).
You can use a combination of perfect forwarding and variadic templates as shown below. In the program shown, the function template forwardToArbitFunc<> accepts any number of function call arguments and forwards each of them to another function(which is also passed as the first argument to the function template).
#include <iostream>
#include<string>
//this function template forwards its arguments to arbitrary function
template<typename T, typename... Ts> void forwardToArbitFunc(T g,Ts&&... xs)
{
g(std::forward<Ts>(xs)...); // forward all xs to g()
}
void func()
{
std::cout<<"parameterless func called"<<std::endl;
}
void func2(int a)
{
std::cout<<"one parameter func2 called"<<std::endl;
}
void func3(std::string a, int b)
{
std::cout<<"two parameter func3 called"<<std::endl;
}
void func4(std::string a, std::string b, float c, double d)
{
std::cout<<"four parameter func4 called"<<std::endl;
}
int main()
{
forwardToArbitFunc(func);
forwardToArbitFunc(func2, 3);
forwardToArbitFunc(func3, "some string", 5);
forwardToArbitFunc(func4, "some string", "another string", 4.4, 5.5);
return 0;
}
Demo

Square and round brackets operator, how to choose overloads?

I want to access to some class data using operator[] but depending on the index type into the square brackets return one kind of data or other. As a simplified example:
struct S
{
int &operator []( int index ) { std::cout << "[i]"; return i_buffer[index]; }
short &operator [](short index) { std::cout << "[s]"; return s_buffer[index]; }
private:
int i_buffer[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};
There's no way to write a short literal, so the only way to choose the short overload is by casting:
S s;
std::cout << s[9] << '\n'; // prints [i]9
std::cout << s[(short)9] << '\n'; // prints [s]999
But I don't like it and I was wondering if there's different options.
What I've tried?
Tagged parameter.
First I've tried to use "tags":
struct S
{
enum class i_type : std::int32_t {};
enum class s_type : std::int32_t {};
int &operator [](i_type index)
{ std::cout << "[i]"; return i_buffer[static_cast<int>(index)]; }
short &operator [](s_type index)
{ std::cout << "[s]"; return s_buffer[static_cast<int>(index)]; }
private:
int i_buffer[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};
That works but is still a little verbose:
S s;
std::cout << s[9] << '\n'; // error, no possible overload to be taken
std::cout << s[S::i_type{9}] << '\n'; // prints [i]9
std::cout << s[S::s_type{9}] << '\n'; // prints [s]999
Template.
As a crazy workaround I wanted to try to template the operator:
struct S
{
template <typename T>
T &operator [](T) { std::cout << "???"; return 0; }
private:
int i_buffer[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};
template <>
int &S::operator [](int index) { std::cout << "[i]"; return i_buffer[index]; }
template <>
short &S::operator [](short index) { std::cout << "[s]"; return s_buffer[index]; }
The template version behaves as the original code, but there's no easy way to specify a type parameter along with the operator[]:
S s;
std::cout << s[9] << '\n'; // prints [i]9 like before
std::cout << s[(short)9] << '\n'; // prints [s]999 like before
std::cout << s<short>[9] << '\n'; // s is not template
std::cout << s[9]<short> << '\n'; // nonsense
// Correct but utterly verbose and hard to write and read
std::cout << s.operator[]<short>(9) << '\n';
Question.
All the issues described also happens with operator(), I want to know if there's more alternatives that I'm not aware of?
I think that using a named method is a much better idea than using operator[] in your situation, as it would be easier to understand that two separate buffers are being accessed by reading the source code.
Regardless, if you want to use your operator[] approach, you could use strong typedefs and user defined literals to have type-safety with minimal syntactic overhead:
BOOST_STRONG_TYPEDEF(std::size_t, int_index)
BOOST_STRONG_TYPEDEF(std::size_t, short_index)
struct S
{
auto& operator[](int_index i) { /* ... */ }
auto& operator[](short_index i) { /* ... */ }
};
auto operator "" _ii(unsigned long long int x) { return int_index{x}; }
auto operator "" _si(unsigned long long int x) { return short_index{x}; }
You can then call your methods as follows:
S s;
auto& some_int = s[15_ii];
auto& some_short = s[4_si];
wandbox example
I think I'd use std::tie from the <tuple> library and then write a little helper to find the correct reference type:
#include <tuple>
#include <iostream>
template<class As, class...Ts>
auto& as(std::tuple<const Ts&...>ts)
{
return std::get<As const&>(ts);
};
template<class As, class...Ts>
auto& as(std::tuple<Ts&...>ts)
{
return std::get<As &>(ts);
};
struct S
{
// both cost and mutable version provided for completeness.
auto operator[](std::size_t i) const {
return std::tie(i_buffer[i], s_buffer[i]);
}
auto operator[](std::size_t i) {
return std::tie(i_buffer[i], s_buffer[i]);
}
private:
int i_buffer[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};
int main()
{
auto s = S();
const auto x = S();
std::cout << "short is : " << as<short>(s[5])<< '\n';
std::cout << "int is : " << as<int>(s[5])<< '\n';
std::cout << "short is : " << as<short>(x[6])<< '\n';
std::cout << "int is : " << as<int>(x[6])<< '\n';
}
This way, the code is explicit but still succinct.
expected output:
short is : 555
int is : 5
short is : 666
int is : 6
Having read the further comments, I might choose to store the matrix in (say) row-wise form and then provide a col-wise wrapper.
A barely functional example:
#include <tuple>
#include <iostream>
#include <array>
template<std::size_t Rows, std::size_t Cols>
struct RowWiseMatrix
{
auto& operator[](std::size_t i) { return data_[i]; }
std::array<std::array<double, Cols>, Rows> data_;
};
template<std::size_t Rows, std::size_t Cols>
struct ColumnProxy
{
ColumnProxy(std::array<std::array<double, Cols>, Rows>& data, std::size_t col)
: data_(data), col_(col)
{
}
auto& operator[](std::size_t i) { return data_[i][col_]; }
std::array<std::array<double, Cols>, Rows>& data_;
std::size_t col_;
};
template<std::size_t Rows, std::size_t Cols>
struct ColWiseProxy
{
ColWiseProxy(RowWiseMatrix<Rows, Cols>& mat) : underlying_(mat) {}
auto operator[](std::size_t i) { return ColumnProxy<Rows, Cols> { underlying_.data_, i }; }
RowWiseMatrix<Rows, Cols>& underlying_;
};
template<std::size_t Rows, std::size_t Cols>
auto& rowWise(RowWiseMatrix<Rows, Cols>& mat)
{
return mat;
};
template<std::size_t Rows, std::size_t Cols>
auto colWise(RowWiseMatrix<Rows, Cols>& mat)
{
return ColWiseProxy<Rows, Cols>(mat);
};
int main()
{
auto m = RowWiseMatrix<3, 3> {
std::array<double, 3>{ 1, 2, 3 },
std::array<double, 3>{ 4, 5, 6},
std::array<double, 3>{ 7, 8, 9}
};
std::cout << rowWise(m)[0][2] << '\n';
std::cout << colWise(m)[0][2] << '\n';
}
Expected output:
3
7
I agree with Vittorio Romeo that the best solution is a named method.
However here is a solution:
template <class T> struct S_proxy {
T* data;
T& operator[](std::size_t i) { return data[i]; }
};
struct S
{
auto i_type() { return S_proxy<int>{i_buffer}; };
auto s_type() { return S_proxy<short>{s_buffer}; };
private:
int i_buffer[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};
and use:
S s;
return s.s_type()[2];
If i_type and s_type are supposed to have a meaning by themselves, it is possible to add semantics to operators []. Something like
#include <iostream>
struct Month {
explicit Month(int m)
: m(m)
{
}
int m;
};
struct Day {
explicit Day(short d)
: d(d)
{
}
short d;
};
struct S {
int& operator[](const Month& mes)
{
std::cout << "[i]";
return i_bufer[mes.m];
}
short& operator[](const Day& dis)
{
std::cout << "[s]";
return s_bufer[dis.d];
}
private:
int i_bufer[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
short s_bufer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};
int main()
{
S s;
std::cout << s[Month(9)] << '\n'; // muestra [i]9
std::cout << s[Day(9)] << '\n'; // muestra [s]999
}

How can I use function in C++ to create a sequence?

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?

Eigen C++ wrapping assignment

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

Sorting 2d Arrays using std::sort (column based)

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