Let A be a vector of vectors of type double, i.e. vector<vector<double> > A and B be the same but for integers, i.e. vector<vector<int> > B. Assume that size of A and B is the same (and sizes of every nested vectors are equal as well).
I would like to check if j is contained in i-th vector of B by using std::find, so I write std::find(B[i].begin(), B[i].end(), j) != B[i].end(). Now, if that is true I would like to return value in A corresponding to [i][position_of_j_found_in_B[i]]. How can I accomplish this?
My code is as follows:
class SparseMatrix
{
private:
vector<vector<double> > entries_;
vector<vector<int> > columnIndices_;
public:
SparseMatrix();
SparseMatrix(vector<vector<double> >,vector<vector<int> >);
~SparseMatrix();
// getters
vector<vector<double> > getEntries();
vector<vector<int> > getColIndices();
double operator()(const unsigned int&, const unsigned int&);
vector<int> size();
};
SparseMatrix::SparseMatrix() { };
SparseMatrix::SparseMatrix(vector<vector<double> > values, vector<vector<int> > colInd) : entries_(values), columnIndices_(colInd) { };
SparseMatrix::~SparseMatrix() { };
vector<vector<double> > SparseMatrix::getEntries() { return entries_; }
vector<vector<int> > SparseMatrix::getColIndices() { return columnIndices_; }
double SparseMatrix::operator()(const unsigned int i, const unsigned int j)
{
assert(i <= (*this).size()[0] && j <= (*this).size()[1]);
auto it = find(columnIndices_[i].begin(),columnIndices_[i].end(), j);
if(it != columnIndices_[i].end())
return entries_[i][it - columnIndices_[i].begin()];
return 0.0;
}
vector<int> SparseMatrix::size() // returns dimensions of the matrix
{
vector<int> dim(2); // stores dimensions of the matrix
dim[0] = columnIndices_.size(); // numbers of rows in a matrix
int temp = 0;
vector<vector<int> >::iterator i;
for(i=columnIndices_.begin(); i != columnIndices_.end(); ++i)
{
if(*max_element((*i).begin(),(*i).end()) > temp) // if maximal element in i-th vector of columnIndices_ is greater then current (temp)
temp = *max_element((*i).begin(),(*i).end()); // update current biggest with new one
}
dim[1] = temp;
return dim;
}
And my main() function is
int main(int argc, char const *argv[])
{
vector<vector<double> > values {{3.0, 1.0}, {2.0}, {5.0, 4.0}};
vector<vector<int> > columns {{1,3}, {1}, {2,3}};
SparseMatrix A(values,columns);
cout << "Matrix A has dimensions " << A.size()[0] << "x" << A.size()[1] << "." << endl; // works fine
cout << A.getEntries()[0][0] << " " << A(0,0) << endl; // I expect the same output...
return 0;
}
Here is solution the solution of original problem:
double foo(const vector<vector<double> >& X, const vector<vector<int> >& Y, unsigned int i, unsigned int j)
{
auto it = find(Y[i].begin(),Y[i].end(), j);
if (it != Y[i].end())
return X[i][it - Y[i].begin()];
return 0.0;
}
P.S. I pass vector by reference because for optimization, for the same reason I pass unsigned int by value.
Here is example of SparseMatrix implementation:
#include <cassert>
#include <vector>
#include <tuple>
#include <iostream>
#include <cmath>
#include <algorithm>
class SparseMatrix final {
public:
explicit SparseMatrix(const std::vector<double>& full_matrix) {
static constexpr double EPS = 1e-16;
const size_t N = std::sqrt(full_matrix.size());
assert((N * N) == full_matrix.size());
for (size_t i = 0; i < N; ++i)
for (size_t j = 0; j < N; ++j)
if (std::fabs(full_matrix[i * N + j]) > EPS)
data_.push_back(std::make_tuple(full_matrix[i * N + j], i, j));
}
double operator()(size_t i, size_t j) const {
auto it = std::find_if(data_.begin(), data_.end(),
[&i, &j](const std::tuple<double, size_t, size_t>& elm) {
return std::get<1>(elm) == i && std::get<2>(elm) == j;
});
return it == data_.end() ? 0.0 : std::get<0>(*it);
}
private:
std::vector<std::tuple<double, size_t, size_t>> data_;
};
int main()
{
SparseMatrix A({3.0, 0, 1.0,
2.0, 0, 0,
0, 5.0, 4.0});
std::cout << A(0, 0) << '\n';
}
Note this SparseMatrix good for study projects, but for every day usage,
the best way to use already existing classes for linear algebra for C++.
Related
I'm quite new to using vectors and coding C++ in general and still haven't fully grasped the language yet. My inquiries are as follows:
1. My main problem seems to be my transform line, why is that so?
2. How do I print the vector sums of A and B?
3. How do I overload the [][] operator for access and make it work? (i.e. the code should still work if Mat[1][3] = 4 is written)
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
class Matrix
{
public:
double x;
vector<vector<double> > I{ { 1, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 1 } };
vector<vector<double> > Initialization(vector<vector<double> > I, double x);
vector<vector<double> > Copy(vector<vector<double> > I);
void Print(vector<vector<double> > I);
};
vector<vector<double> > Matrix::Initialization(vector<vector<double> > I, double x)
{
for (int i = 0; i < I.size(); i++) {
for (int j = 0; j < I[i].size(); j++)
{
// new matrix
I[i][j] *= x;
}
}
return I;
};
vector<vector<double> > Matrix::Copy(vector<vector<double> > I)
{
vector<vector<double> > I_copy = I;
return I_copy;
};
void Matrix::Print(vector<vector<double> > I)
{
for (int i = 0; i < I.size(); i++) {
for (int j = 0; j < I[i].size(); j++)
{
cout << I[i][j] << " ";
}
cout << endl;
}
};
int main()
{
Matrix m;
vector<vector<double> > A;
vector<vector<double> > B;
cin >> m.x;
A = m.Initialization(m.I, m.x);
B = m.Copy(A);
m.Print(A);
m.Print(B);
B.resize(A.size());
transform(A.begin(), A.end(), B.begin(), A.begin(), plus<double>());
return 0;
}
I hope you can be patient in helping me fix my code and letting me understand why my syntax is incorrect and uncompilable. Thank you so much <3
As Jarod42 notes in the comments, you need something that adds std::vector<double>s, as well as something that adds doubles.
template <typename T>
std::vector<T> operator+(std::vector<T> lhs, const std::vector<T> & rhs)
{
std::transform(lhs.begin(), lhs.end(), rhs.begin(), lhs.begin(), [](const T & a, const T & b){ return a + b; });
return lhs;
}
Note that we take a copy of the left hand side, but only reference the right hand side. This also gives us somewhere to write the result to.
The usage is then very simple
int main()
{
std::vector<std::vector<double> > A { { 0, 1 }, { 1, 0 } };
std::vector<std::vector<double> > B { { 1, 0 }, { 0, 1 } };
std::vector<std::vector<double> > C { { 1, 1 }, { 1, 1 } };
std::cout << std::boolalpha << (A + B == C) << std::endl;
}
See it live!
I am trying to find repeated points from a given 10 points, where each points has x and y values. I have written the below code but can not get correct results. The output should be {3,5},{4,2},{2,4},{7,8}
#include <iostream>
#include<stdlib.h>
using namespace std;
struct point
{
int x;
int y;
};
void distinctPoints(point arr[], int size)
{
cout<<"Repeated Points"<<endl;
cout<<"x, y"<<endl;
for(int i = 0; i< size; i++)
for(int j = i+1; j< size; j++)
{
if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y))
{
cout<<arr[j].x <<", "<<arr[j].y<<endl;
break;
}
}
}
int main()
{ int size=10;
point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
distinctPoints(points, size);
return 0;
}
Your approach (once corrected, as VHS's answer did) could be fine for a small number of points, but, with a bigger set of data, an O(N2) algorithm could be too inefficient.
You can take advantage of the average costant time that takes inserting an element in a std::unordered_set, even if you are required to write a comparison function and an hash function for your class.
The algorithm presented below uses two unordered_set's:
uniques ends up storing all the elements that are present in the source container, without repetitions.
repeated stores a unique instance of only the elements that are present multiple times.
An element is copied to the output only if it's already present in uniques, but not in repeated.
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <iterator>
struct point
{
int x, y;
bool operator== (point const& b) const
{
return x == b.x && y == b.y;
}
};
namespace std {
template<> struct hash<point>
{
std::size_t operator() (point const& p) const
{
return (std::hash<int>{}(p.x) << 1) ^ std::hash<int>{}(p.y);
}
};
}
std::ostream& operator<< (std::ostream& os, point const& pt)
{
return os << '(' << pt.x << ", " << pt.y << ')';
}
template<class InputIt, class OutputIt>
OutputIt copy_repeated_values(InputIt first, InputIt last, OutputIt dest)
{
using value_type = typename InputIt::value_type;
std::unordered_set<value_type> uniques, repeated;
return std::copy_if(
first, last, dest, [&] (value_type const& value) {
return
not uniques.insert(value).second &&
repeated.insert(value).second;
}
);
}
int main()
{
std::vector<point> points {
{3,5}, {4,2}, {2,4}, {3,5}, {7,8}, {7,8}, {4,2}, {7,8}, {3,5}, {2,4}
};
copy_repeated_values(
std::begin(points), std::end(points),
std::ostream_iterator<point>(std::cout, " ")
);
std::cout << '\n';
}
The output is:
(3, 5) (7, 8) (4, 2) (2, 4)
I have tweaked your distinctPoints method so that it doesn't print the duplicates multiple times even if the dups appear more than twice. See the following edits:
void distinctPoints(point arr[], int size)
{
point dups[size];
cout<<"Distinct Points"<<endl;
cout<<"x, y"<<endl;
for(int i = 0; i < size; i++)
for(int j = 0; j < size; j++) {
if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y)) {
if(j < i) {
break;
}
else if( j == i) {
continue;
}
else {
cout<<arr[i].x <<", "<<arr[i].y<<endl;
break;
}
}
}
}
This should do what you are trying to achieve, I am making use of set and maps in c++ which takes care of unique entries.
The map keeps track of already visited points.
#include <iostream>
#include<stdlib.h>
#include <set>
#include <map>
using namespace std;
struct point
{
int x;
int y;
};
map<pair<int, int>, int> mapCountOfPoints;
set<pair<int, int> > disPoints;
void distinctPoints(point arr[], int size)
{
for(int i=0; i<size; i++) {
pair<int, int> temp = make_pair(arr[i].x, arr[i].y);
if(mapCountOfPoints.find(temp) != mapCountOfPoints.end()) {
disPoints.insert(temp);
} else {
mapCountOfPoints[temp] = 1;
}
}
// Now we will iterate over the set to get the distinct set of points
for(set<pair<int, int>>::iterator it=disPoints.begin(); it!=disPoints.end(); it++) {
cout<<it->first<<" "<<it->second<<endl;
}
}
int main()
{ int size=10;
point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
distinctPoints(points, size);
return 0;
}
Hope this helps!
I have written an implementation of Donald Knuth's Algorithm X for solving exact cover problems and applied it to Sudoku for the purpose of solving Project Euler Problem 96. My code is a translation from Python into C++ of Ali Assaf's implementation of the same algorithm.
My version is solves most of the grids contained in this text file, but it hangs for Grid 06.
Grid 06
100920000
524010000
000000070
050008102
000000000
402700090
060000000
000030945
000071006
I have used a bunch of exploratory cout statements, but I have not been able to figure out what is causing the program to hang.
Please let me know if you need more information to be able to understand my code.
#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution);
void select_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r);
void deselect_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r);
// square boxes only
static const int BOX_SIZE = 3; // standard sudoku grid
static const int SIZE = BOX_SIZE*BOX_SIZE;
int main() {
int top_left_sum = 0;
// initialize the sparse matrix representation of the sudoku problem
map<int, set<int>> C; // constraints/columns
for (int i = 0; i < 4*SIZE*SIZE; i++) {
C[i] = set<int>();
}
map<int, array<int, 4>> R; // subsets/rows
for (int i = 0; i < SIZE*SIZE*SIZE; i++) {
// i is the subset index and encodes location and number on grid
int index = i/SIZE;
int row = i/(SIZE*SIZE);
int column = (i/SIZE) % SIZE;
int box = BOX_SIZE*(row/BOX_SIZE) + column/BOX_SIZE;
int value = i % SIZE;
// there are 4 constaints satisfied by each number placement
array<int, 4> subset;
// insert the keys of constraints that subset satisfies
subset[0] = (index); // row-column
subset[1] = (SIZE*SIZE + SIZE*row + value); // row-number
subset[2] = (2*SIZE*SIZE + SIZE*column + value); // column-number
subset[3] = (3*SIZE*SIZE + SIZE*box + value); // box-number
R.insert(pair<int, array<int, 4>>(i, subset));
for (auto c : subset) {
C[c].insert(i);
}
}
ifstream ifs("../sudoku.txt");
string line;
while (getline(ifs, line)) {
if (line[0] == 'G') {
map<int, set<int>> X = C;
map<int, array<int, 4>> Y = R;
vector<int> solution;
for (int i = 0; i < SIZE; i++) {
getline(ifs, line);
for (int j = 0; j < SIZE; j++) {
if (line[j] != '0') {
int r = SIZE*SIZE*i + SIZE*j + line[j] - '1';
solution.push_back(r);
vector<set<int>> cs;
select_row(&X, &Y, &cs, r);
}
}
}
solve(&X, &Y, &solution);
sort(solution.begin(), solution.end());
top_left_sum += 100*(solution[0] % SIZE + 1)
+ 10*(solution[1] % SIZE + 1)
+ solution[2] % SIZE + 1;
// display solution
for (size_t i = 0; i < solution.size(); i++) {
if (i % 9 == 0) cout << endl;
cout << solution[i] % 9 + 1 << ' ';
} cout << endl << endl;
}
}
ifs.close();
cout << top_left_sum << endl;
return 0;
}
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution) {
if ((*X).empty()) return true;
// find the column with the minimum number of nonzero elements
map<int, set<int>>::iterator c_min = (*X).begin();
for (map<int, set<int>>::iterator c = ++(*X).begin();
c != (*X).end(); ++c) {
if ((*c).second.size() < (*c_min).second.size()) {
c_min = c;
}
}
// for each row pointed to by c_min, call solve recursively
for (auto r : (*c_min).second) {
(*solution).push_back(r);
vector<set<int>> cs;
select_row(X, Y, &cs, r);
if (solve(X, Y, solution)) return true;
deselect_row(X, Y, &cs, r);
(*solution).pop_back();
}
return false;
}
void select_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r) {
for (auto j : (*Y)[r]) {
for (auto i : (*X)[j]) {
for (auto k : (*Y)[i]) {
if (k != j) (*X)[k].erase(i);
}
}
(*cs).push_back((*X)[j]);
(*X).erase(j);
}
return;
}
void deselect_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r) {
for (array<int, 4>::reverse_iterator j = (*Y)[r].rbegin();
j != (*Y)[r].rend(); ++j) {
(*X)[*j] = (*cs).back();
(*cs).pop_back();
for (auto i : (*X)[*j]) {
for (auto k : (*Y)[i]) {
if (k != *j) (*X)[k].insert(i);
}
}
}
return;
}
As PaulMackenzie pointed out, the problem with my code was that I was erasing objects which still had pointers to them initialized, specifically the integers inside the set (*c_min).second that I iterate over in my solve function.
I fixed this by making a copy of (*c_min).second and iterating over the copy.
The fixed version of the solve function looks like this:
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution) {
if ((*X).empty()) return true;
// find the column with the minimum number of nonzero elements
map<int, set<int>>::iterator c_min = (*X).begin();
for (map<int, set<int>>::iterator c = ++(*X).begin();
c != (*X).end(); ++c) {
if ((*c).second.size() < (*c_min).second.size()) {
c_min = c;
}
}
set<int> c = (*c_min).second; // ADDED LINE
// for each row pointed to by c_min, call solve recursively
for (auto r : c) { // CHANGED LINE
(*solution).push_back(r);
vector<set<int>> cs;
select_row(X, Y, &cs, r);
if (solve(X, Y, solution)) return true;
deselect_row(X, Y, &cs, r);
(*solution).pop_back();
}
return false;
}
I am working on a N dimensional grid.
I would like to generate nested loops depending on any dimension (2D, 3D, 4D, etc...).
How can I do that in an elegant and fast way ? Below a simple illustration of my problem.
I am writing in C++ but I think this kind of question can be useful for other languages.
I need to know the indices (i,j,k...) in my do stuff part.
Edit : lower_bound and upper_bound represents the indexes in the grid so they are always positive.
#include <vector>
int main()
{
// Dimension here is 3D
std::vector<size_t> lower_bound({4,2,1});
std::vector<size_t> upper_bound({16,47,9});
for (size_t i = lower_bound[0]; i < upper_bound[0]; i ++)
for (size_t j = lower_bound[1]; j < upper_bound[1]; j ++)
for (size_t k = lower_bound[2]; k < upper_bound[2]; k ++)
// for (size_t l = lower_bound[3]; l < upper_bound[3]; l ++)
// ...
{
// Do stuff such as
grid({i,j,k}) = 2 * i + 3 *j - 4 * k;
// where grid size is the total number of vertices
}
}
Following may help:
bool increment(
std::vector<int>& v,
const std::vector<int>& lower,
const std::vector<int>& upper)
{
assert(v.size() == lower.size());
assert(v.size() == upper.size());
for (auto i = v.size(); i-- != 0; ) {
++v[i];
if (v[i] != upper[i]) {
return true;
}
v[i] = lower[i];
}
return false;
}
And use it that way:
int main() {
const std::vector<int> lower_bound({4,2,1});
const std::vector<int> upper_bound({6,7,4});
std::vector<int> current = lower_bound;
do {
std::copy(current.begin(), current.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while (increment(current, lower_bound, upper_bound));
}
Live demo
An iterative approach could look like this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> lower_bound({-4, -5, -6});
std::vector<int> upper_bound({ 6, 7, 4});
auto increase_counters = [&](std::vector<int> &c) {
for(std::size_t i = 0; i < c.size(); ++i) {
// This bit could be made to look prettier if the indices are counted the
// other way around. Not that it really matters.
int &ctr = c .rbegin()[i];
int top = upper_bound.rbegin()[i];
int bottom = lower_bound.rbegin()[i];
// count up the innermost counter
if(ctr + 1 < top) {
++ctr;
return;
}
// if it flows over the upper bound, wrap around and continue with
// the next.
ctr = bottom;
}
// end condition. If we end up here, loop's over.
c = upper_bound;
};
for(std::vector<int> counters = lower_bound; counters != upper_bound; increase_counters(counters)) {
for(int i : counters) {
std::cout << i << ", ";
}
std::cout << "\n";
}
}
...although whether this or a recursive approach is more elegant rather depends on the use case.
#include <iostream>
#include <vector>
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f)
{
std::vector<int> temp;
process(lower, upper, f, 0, temp);
}
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f,
int index, std::vector<int>& current)
{
if (index == lower.size())
{
f(current);
return;
}
for (int i = lower[index]; i < upper[index]; ++i)
{
current.push_back(i);
process(lower, upper, f, index + 1, current);
current.pop_back();
}
}
int main()
{
// Dimension here is 3D
std::vector<int> lower_bound({-4, -5, 6});
std::vector<int> upper_bound({6, 7, 4});
// Replace the lambda below with whatever code you want to process
// the resulting permutations.
process(lower_bound, upper_bound, [](const std::vector<int>& values)
{
for (std::vector<int>::const_iterator it = values.begin(); it != values.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
});
}
Probably some typos an whatnot, but I'd flatten the whole range.
This is based on the idea that the range can be described as
x_0 + d_0*(x_1+d_1*(x_2+d_2....)
So we can roll our own that way
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
//ranges
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
}
Edit: to be more generic:
template <typename D>
void multi_for(const std::vector<int>& lower_bound, const std::vector<int> upper_bound, D d) {
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
size_t numel = std::accumulate(ranges.begin(), ranges.end(), std::multiplies<int,int>{});
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
d(idx,indexes);
}
}
//main
size_t* grid;//initialize to whateer
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
auto do_stuff = [grid](size_t idx, const std::vector<int> indexes) {
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
};
multi_for(lower_bound,upper_bound,do_stuff);
A recursive function may help you achieve what you want.
void Recursive( int comp )
{
if(comp == dimension)
{
// Do stuff
}
else
{
for (int e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
Some additions may be necessary in the function signature if you need to know the current indices (i,j,k,...) in your "Do Stuff" section.
This is a clean way to have access to these indices
void Recursive( int comp, int dimension )
{
static std::vector<int> indices;
if( comp == 0 ) // initialize indices
{
indices.clear();
indices.resize(dimension, 0);
}
if(comp == dimension -1)
{
// Do stuff
}
else
{
int& e = indices[comp];
for (e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
This is however not usable along multiple threads, due to the shared static vector.
My comparison function for STL sort is failing. I was wanting to pass in a column variable to sort on a column. I am still new to programming so Boost just buries me in more things I don't understand. This doesn't have any error checking etc.
e.g.
int columnToSort = 1;
sort(vec2d.begin(), vec2d.end(),
[columnToSort](const vector< int >& a, const vector< int >& b){ return a[columnToSort] < b[columnToSort]; } );
Error =
no matching function for call to ‘sort(std::vector >::iterator, std::vector >::iterator, main()::&,...etc..
If I try to make it a class that takes a 2dvector and an integer columnToSort
I get the same error:
The following Does work:
bool compareFunction0(const vector<int>& a, const vector<int>& b )
{
return( a[0] < b[0] );
}
void vec2dSort( vector< vector<int> > &refVec2d, int sortCol )
{
//check to see if sortCol is out of bounds
sort(refVec2d.begin(), refVec2d.end(), compareFunction0 );
}
Full Source is below. Problems areas are
/////////////////////////////// MARKED LIKE THIS ////////////////////////////
#include <iostream> // std::cout
#include <algorithm> // std::sort
#include <vector> // std::vector
#include <cstdlib> // rand()
#include <ctime> // rand()
using namespace std;
void printVec2d( vector< vector<int> > &refVec2d )
{
vector<int>::iterator itCol;
vector< vector<int> >::iterator itRow;
for(itRow = refVec2d.begin(); itRow != refVec2d.end(); ++itRow)
{
for(itCol = itRow->begin(); itCol != itRow->end(); ++itCol)
cout << (*itRow)[0] << ":" << *itCol << "\t";
cout << endl;
}
}
bool compareFunction0(const vector<int>& a, const vector<int>& b )
{
return( a[0] < b[0] );
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////// THIS WORKS but compareFunction0 has hard coded column////////////////
//////////////////////////////////////////////////////////////////////////////////////
void vec2dSort( vector< vector<int> > &refVec2d, int sortCol )
{
//check to see if sortCol is out of bounds
//sort(refVec2d.begin(), refVec2d.end(), [](const vector< int >& a, const vector< int >& b){ return a[sortCol] < b[sortCol]; } );
sort(refVec2d.begin(), refVec2d.end(), compareFunction0 );
}
class SortVec2d
{
private:
int sortCol;
public:
SortVec2d( vector< vector<int> >&, int);
~SortVec2d();
bool comparison(const vector<int>&, const vector<int>& );
};
bool SortVec2d::comparison(const vector<int>& a, const vector<int>& b )
{
return( a[0] < b[0] ); // I want to do return( a[sortCol] < b[sortCol] )
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////// THIS DOESN'T WORK "no such comparison function"//////////////////////
//////////////////////////////////////////////////////////////////////////////////////
SortVec2d::SortVec2d( vector< vector<int> > &refVec2d, int sortColumn )
{
int sortCol = sortColumn;
//sort(refVec2d.begin(), refVec2d.end(), comparison );
//sort(refVec2d.begin(), refVec2d.end(), [](const vector< int >& a, const vector< int >& b){ return a[0] < b[0]; } );
}
int randBetween(int min, int max)
{
return (rand()%(max-min))+min;
}
int main()
{
vector<int> vecRow ;
vector< vector<int> > vec2d;
int rowSize = 3;
for(int c = 0; c < 10; ++c)
{
for(int r = 0; r < rowSize; ++r)
vecRow.push_back( randBetween(0,255) );
vec2d.push_back(vecRow);
vecRow.clear();
}
cout << "New 2d Vector Created: " << endl;
printVec2d(vec2d);
sort(vec2d.begin(), vec2d.end(), [](const vector< int >& a, const vector< int >& b){ return a[1] < b[1]; } );
cout << "2d Vector Sorted on Col 1: " << endl;
printVec2d(vec2d);
vec2dSort( vec2d, 0);
cout << "2d Vector Sorted on Col 0: " << endl;
printVec2d(vec2d);
return 0;
}
Use a capture in your lambda to accept the column number to sort on.
int columnToSort = 2;
sort(vec2d.begin(), vec2d.end(), [columnToSort](const vector< int >& a, const vector< int >& b)
{
return a[columnToSort] < b[columnToSort];
});