std::vector<vector<float>> tmp = {{1,10,5,4},{2,5,5,1},{3,2,4,3},{4,9,7,8}};
I want to order this vector by the 4th(last) value in vector value. So the outcome will be like :
{{2,5,5,1},{3,2,4,3},{1,10,5,4},{4,9,7,8}};
Use std::sort with a suitable lambda for the comparator:
std::sort(begin(tmp), end(tmp), [](auto const& inner1, auto const& inner2)
{
// Note: No checking if the sizes are zero, should really be done
return inner1.back() < inner2.back();
});
That should do it:
#include <algorithm>
#include <vector>
int main() {
std::vector<std::vector<float>> tmp = {
{1, 10, 5, 4}, {2, 5, 5, 1}, {3, 2, 4, 3}, {4, 9, 7, 8}};
std::sort(tmp.begin(),tmp.end(), [](auto a, auto b){return a[3]<b[3];} );
}
Related
I was wondering how one can search for overlaps in a vector of tuples.
For example, I have the vector<tuple<int, int, int>> combo;, and the elements of the vector is:
{10, 101, 1},
{10, 102, 2},
{12, 102, 3},
{14, 90, 4},
{1, 10, 101},
{2, 10, 102},
{3, 12, 102},
{4, 14, 90},
{101, 1, 10},
{102, 2, 10},
{102, 3, 12},
{90, 4, 14}
Here, you can tell that the bottom 8 tuples are just repeats of the first 4, except the integers are reordered in a different way. I want to find the non-overlapping combinations of the elements, not the permutations of the elements.
If the 1st index of the tuple is called left, second if called middle, and third is called right, then in other words, left, middle, and right can overlap with itself, but not with the other 2 indexes.
Convert the elements to a canonical representation. This allows you use a set data structure or similar to identify duplicates.
I'm assuming here you're trying to find permutations that do not result in one of the elements remaining in place, i.e. for values { a, b, c} the matching permutations would be
{ a, b, c }
{ b, c, a }
{ c, a, b }
Furthermore I'm assuming even if multiple values are the same, they could be considered as listed in any order, i.e. { 1, 1, 2 } would match { 1, 2, 1 } even though the first element remains equal, since we could consider the first element to be the second one in the original.
This allows us use the lexicographically minimal alternative that as the canonical representation.
The following code uses std::array<int, 3> for convenience.
#include <array>
#include <iostream>
#include <map>
#include <vector>
using ValueType = std::array<int, 3>;
constexpr ValueType ToCanonical(ValueType const& original)
{
ValueType p1{ original[1], original[2], original[0] };
ValueType p2 { original[2], original[0], original[1] };
return (std::min)({ original, p1, p2 });
}
int main(void) {
std::vector<ValueType> const values
{
{10, 101, 1},
{10, 102, 2},
{12, 102, 3},
{14, 90, 4},
{1, 10, 101},
{2, 10, 102},
{3, 12, 102},
{4, 14, 90},
{101, 1, 10},
{102, 2, 10},
{102, 3, 12},
//{90, 4, 14},
//{10, 101, 1},
//{101, 10, 1},
//{10, 1, 101},
//{1, 101, 10},
//{1, 1, 2},
//{1, 2, 1},
//{2, 1, 1},
};
std::map<ValueType, size_t> indices;
for (size_t i = 0; i != values.size(); ++i)
{
auto insertResult = indices.try_emplace(ToCanonical(values[i]), i);
if (!insertResult.second)
{
std::cout << "The element at index " << i << " is a duplicate of the element at index " << insertResult.first->second << '\n';
}
}
return 0;
}
What is the right way to implement the function below to allow the caller to iterate over the range it returns?
#include <set>
#include <ranges>
std::set<int> set{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto find_range(int a)
{
//What type should I return?
return std::make_tuple(set.lower_bound(a - 3), set.upper_bound(a + 3));
}
int main()
{
for (int x : find_range(5)) {...}
}
The function returns a couple of iterators pointing to 2 and 9, so the loop should iterate over 2, 3, 4, 5, 6, 7, 8.
You can return a subrange like this
auto find_range(int a)
{
return std::ranges::subrange(set.lower_bound(a - 3),
set.upper_bound(a + 3));
}
Here's a demo.
I'm currently trying to find the minimum element of a 2D vector. I'm trying to practice using C++11 lambda functions and figured this might be good practice, but can't seem to get it compiling.
I'm aware that I could do the following:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int result = std::numeric_limits<int>::max();
for(const auto& row : matrix)
{
int minElemInRow = *std::min_element(row.begin(), row.end());
result = std::min(result , minElemInRow);
}
return result;
but was wondering if the same could be done with a lambda function. Currently, this is my best attempt:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
return *std::min_element(matrix.begin(), matrix.end(),
[](const auto& row)
{
return *std::min_element(row.begin(), row.end());
});
I get the error: error C2672: 'operator __surrogate_func': no matching overloaded function found
How I feel it should be working is that the outer min_element will pass in a row at a time (which is just a reference to a vector), from which I can return the smallest, which will then be compared against other rows.
I thought that the problem might be that the lambda would be receiving an iterator to a vector of ints rather than a reference to the vector of ints, but dereferencing doesn't seem to be helping.
Is there a better way to be doing what I'm trying to do?
#assembly_wizard pointed out that min_element wants a predicate which can compare two of the item passed it. That is two rows. This leads to the following code:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
auto i = std::min_element(matrix.begin(), matrix.end(),
[](const auto& lhs, const auto& rhs)
{
return *std::min_element(lhs.begin(), lhs.end()) <
*std::min_element(rhs.begin(), rhs.end());
});
This will find the row with the smallest element. Though I can make that work by wrapping it in yet another std::min_element, that's getting way more complex than to be remotely helpful. If anyone has a better suggestion, I'd love to hear it!
I've compiled a working version that does what I've mentioned in the comments:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
std::vector<int> row_minimums(matrix.size());
std::transform(matrix.begin(), matrix.end(), row_minimums.begin(), [](const auto& row) {
return *std::min_element(row.begin(), row.end());
});
auto i = *std::min_element(row_minimums.begin(), row_minimums.end());
std::cout << "Minimum element is: " << i << std::endl;
}
See it in action on godbolt
This will take the minimum of each row separately, so we get row_minimums which is a vector of ints, and then it takes the minimum of these to get the final result between all the rows.
The only thing making this code worse than the for loop version, is that it keeps all of the row_minimums in memory at once, before running min_element on them. Unfortunately I don't know of a way to do this simultaneously, but I'm not the greatest STL expect, so maybe there is a way.
Other options you might consider is first concatenating the 2D matrix into a 1D vector and then using min_element on it, or the option you've included in your edit where you call min_element 3 times.
Also, this SO answer seems to have interesting info regarding solutions using the boost library which might be better, but I'm not sure exactly what they are.
Just a little simpler:
With std::for_each you iterate over each vector in matrix, and obtain the minimum element of them. As min is captured by reference, you get the min of all of them.
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int min = std::numeric_limits<int>::max();
std::for_each(matrix.begin(), matrix.end(),
[&min](const auto& v)
{
min = std::min(*min_element(v.begin(), v.end()), min);
}
);
std::cout << "Minimum element is: " << min << std::endl;
}
I'm looking for some pointers on inserting or pushing a vector into another vector.
The idea is I have vec1 = {1, 2, 3} for example.
Then I want to insert this into vec2 before next vec1 = {4, 5, 6} turns up.
The problem is I don't want vec 2 to read {1, 2, 3, 4, 5, 6}, I want it to read
vec2 = {1, 2, 3},
{4, 5, 6},... etc
Is this possible or I'm I completely mad. Any help will be great.
Thanks.
You can use a vector of vector of integers. Like this :
std::vector<std::vector<int>> vecofvecs = { {1,2,3}, {4,5,6} };
You can also use this :
#include <vector>
int main()
{
std::vector<std::vector<int>> vecofvecs;
std::vector<int> subvec1 = { 1,2,3 };
std::vector<int> subvec2 = { 4,5,6 };
vecofvecs.push_back(subvec1);
vecofvecs.push_back(subvec2);
return 0;
}
I'm aware how to generate all possible subsets from a set incorporating bit twiddling. For instance,
//Get if nth position's bit is set
bool IsBitSet(int num, int bit)
{
return 1 == ((num >> bit) & 1);
}
int subsetMaxIterCount = pow(2, someList.size());
for (int i = 0; i < subsetMaxIterCount; i++) {
vector<A> subset;
for (size_t i = 0; i < jobList.size(); i++)
{
if (IsBitSet(jobSubsetIdx, i)) {
//Add to subset here
}
}
//Here we have a subset for some i
}
However, this doesn't take into account of ordering.
For instance, if I had a set of {1, 2, 3}, the above algorithm generates subsets of:
{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1,2,3}
What I need in reality is this
{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1,2,3}, {2, 1}, {2, 1, 3}, {2, 3, 1}, {3, 1}, {3, 2}, {3, 1, 2}, {3, 2, 1}
Not sure if the above list is exhaustive. What's an effective algorithm in generating something like this? (Is this all possible subsets with permutation by the way?)
The way we generate the subsets using bit twiddling, every subset is sorted within it e.g. {1, 2, 3}, {2, 3}, {1, 3}. You can generate permutation for each subset using next_permutation
vector<vector<int>> mySubsetGenerator(vector<vector<int>>& subsets) {
vector<vector<int>> extendedSubset;
for(int i = 0; i < subsets.size(); ++i) {
do {
extendedSubset.push_back(subsets[i]);
} while(next_permutation(subsets[i].begin(), subsets[i].end()));
}
return extendedSubset;
}
Moreover, you can use only backtracking to generate all possible permutations by taking one or more elements of array.