strange behavior while sorting vector of pairs - c++

I am populating the following vector with non-negative integers for a codejam problem:
vector<pair<int,pair<int,int> > > v;
Following way of sorting fails the submission:
sort(v.begin(),v.end(),[](auto a,auto b){
return a.first < b.first;
});
But if i just change the sorting as below:
sort(v.begin(),v.end());
The submission passes.
What's wrong with the lamda function that I am using for sorting?
Thanks

Your lambda only takes the first element into account, but obivously a pair consists of two elements. With your lambda pairs with identical first but different second elements will be considered as equal. Thus their relative order after sorting is unspecified.
If you want to sort data like the following:
{1, {1, 1}},
{0, {2, 2}},
{1, {3, 3}},
Then the first and last item are considered equal and sorting can either produce
{0, {2, 2}},
{1, {1, 1}},
{1, {3, 3}},
or
{0, {2, 2}},
{1, {3, 3}},
{1, {1, 1}},
But std::pair's default comparison operator compares the first and second element.

Related

C++ Unordered map initializer map not initializing properly

I'm relatively new to hash maps. I have the following code in my program:
std::unordered_map<int, int> XY ({
{0, 0}, {0, 3}, {0, 6},
{3, 0}, {3, 3}, {3, 6},
{6, 0}, {6, 3}, {6, 6}
});
For some reason, the map only contains the first three pairs ({0, 0}, {0, 3}, and {0, 6}). Even when I cout the bucket count, it outputs 11. Yet, there's still only three in my map.
How do I fix this? It seems unreasonable to do a bunch of .insert()'s.

Generate all possible ordered subset from a set

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.

Mathematica: adding a list of lists elementwise

I have a list of lists of numbers. I add them into one list by adding all of the first elements together, all of the second elements together, etc. For example, if my list were { {1,2,3}, {1,2,3}, {1,2,3,4} } I would want to end up with {3,6,9,4}. How do I do this in Mathematica?
a = {{1, 2, 3}, {1, 2, 3}, {1, 2, 3, 4}};
Total#PadRight#a
{3, 6, 9, 4}
Among its many useful features, Flatten will transpose a 'ragged' array (see here for a nice explanation, or check out the 'applications' subsection of the documentation on Flatten)
Total /# Flatten[#, {{2}}] &#{{1, 2, 3}, {1, 2, 3}, {1, 2, 3, 4}}
{3, 6, 9, 4}
If all the rows were the same length then adding the rows would do this.
So make all the rows the same length by appending zeros and then add them.
lists = {{1, 2, 3}, {1, 2, 3}, {1, 2, 3, 4}};
max = Max[Length /# lists]; min = Min[Length /# lists];
zeros = Table[0, {max - min}];
Plus ## Map[Take[Join[#, zeros], max] &, lists]

Iteratively calculate the power set of a set or vector

While there are plenty of examples on how to generate the actual power set of a set, I can't find anything about iteratively (as in std::iterator) generating the power set. The reason why I would appreciate such an algorithm is the size of my base set. As the power set of a n-element set has 2^n elements, I would quickly run out of memory when actually computing the set. So, is there any way to create an iterator for the power set of a given set? Is it even possible?
If it would be easier, an iterator that creates sets of ints would be fine - I could use them as indices for the actual set/vector.
As I actually work on a std::vector, random access would be possible if neccessary
Using for_each_combination from Combinations and Permutations one can easily iterate through all members of the power set of a std::vector<AnyType>. For example:
#include <vector>
#include <iostream>
#include "../combinations/combinations"
int
main()
{
std::vector<int> v{1, 2, 3, 4, 5};
std::size_t num_visits = 0;
for (std::size_t k = 0; k <= v.size(); ++k)
for_each_combination(v.begin(), v.begin()+k, v.end(),
[&](auto first, auto last)
{
std::cout << '{';
if (first != last)
{
std::cout << *first;
for (++first; first != last; ++first)
std::cout << ", " << *first;
}
std::cout << "}\n";
++num_visits;
return false;
});
std::cout << "num_visits = " << num_visits << '\n';
}
This visits each power set member of this vector, and executes the functor, which simply counts the number of visits and prints out the current power set:
{}
{1}
{2}
{3}
{4}
{5}
{1, 2}
{1, 3}
{1, 4}
{1, 5}
{2, 3}
{2, 4}
{2, 5}
{3, 4}
{3, 5}
{4, 5}
{1, 2, 3}
{1, 2, 4}
{1, 2, 5}
{1, 3, 4}
{1, 3, 5}
{1, 4, 5}
{2, 3, 4}
{2, 3, 5}
{2, 4, 5}
{3, 4, 5}
{1, 2, 3, 4}
{1, 2, 3, 5}
{1, 2, 4, 5}
{1, 3, 4, 5}
{2, 3, 4, 5}
{1, 2, 3, 4, 5}
num_visits = 32
The syntax I've used above is C++14. If you have C++11, you will need to change:
[&](auto first, auto last)
to:
[&](std::vector<int>::const_iterator first, std::vector<int>::const_iterator last)
And if you are in C++98/03, you will have to write a functor or function to replace the lambda.
The for_each_combination function allocates no extra storage. This is all done by swapping members of the vector into the range [v.begin(), v.begin()+k). At the end of each call to for_each_combination the vector is left in its original state.
If for some reason you want to "exit" the for_each_combination early, simply return true instead of false.

How to filter vector elements relative to other ones?

I a vector of vectors, each representing a a set (in the mathematical sense). For example:
{{1, 3}, {4, 9, 14}, {1, 3}, {1, 4, 8, 9, 10, 14, 16}, {1, 3, 9}, {4, 9, 17, 22}}
I want to make the most efficient C++ possible function capable of filtering (in place, if possible) the vector in order to remove every item that contains another.
For example, here:
{1, 3} is contained by {1, 3} and {1, 3, 9}
{4, 9, 14} is contained by {1, 4, 8, 9, 10, 14, 16}
The resulting vector would then be:
{{1, 3}, {4, 9, 14}, {4, 9, 17, 22}}
As I'm beginning with C++ don't really have any clue of how to do this efficiently. I found, on other answers here, the erase / remove idiom, which doesn't seem to be very appropriate here, except by passing erase a closure as predicate. Which doesn't seem really idiomatic in C++.
Please note that keeping the original ordering doesn't matter, nor does the ordering of values inside each set.
Given what I learnt so far, thanks to your very helpful comments, the solution I came up with is:
struct std::vector<size_t> colset;
bool less_colsets(const colset& a, const colset& b) {
return a.size() < b.size();
}
void sort_colsets(std::list<colset>& l) {
l.sort(less_colsets);
}
void strip_subsets(std::list<colset>& l) {
sort_colsets(l);
for (std::list<colset>::iterator i = l.begin(); i != l.end(); ++i) {
std::list<colset>::iterator j = next(i, 1);
while (j != l.end()) {
if (includes((*j).begin(), (*j).end(), (*i).begin(), (*i).end())) {
j = l.erase(j);
}
else {
++j;
}
}
}
}
Note that I replaced the outermost std::vector by std::list which is much more optimised for element removal anywhere.
This seems to work as expected, though I'd need some more tests to prove this. The next step will be to use a more efficient comparison function than includes, which would take into account the fact that each vector is lexically ordered (which the program guarantees). I'll try this tomorrow.
Edit: Looks like std::includes already takes care of this fact. YAY!
Thanks everybody.