Counting partitions in C++ using STL - c++

Imagine I have a container C containing elements of some type T and a predicate with which to determine if any two variables of type T are "equivalent". E.g. if T is int I might have a predicate eqv = [](int a, int b){ return a % 5 == b % 5; } such that two integers are equivalent under eqv if they have the same remainder when divided by five.
Given such a container and a predicate, is there some STL function (e.g. from algorithm) which which I can elegantly (i.e. without writing a lot of code myself) determine the number of partitions of C under eqv?
For example, if eqv is as above and C is std::vector<int>{1,2,3,6,7,8} I would like to obtain the result 3 (because the equivalence classes are {1,6}, {2,7} and {3,8}).

Two approaches, depending on what you can also do with T:
if you can somehow order these equivalence classes, then create a std::set. The sorting of objects of type T needs to be a non-total order, where all elements which are equivalent under your predicate are neither less nor not less than the other elements of their class. Insert all elements, then count the set's size.
if you can somehow compute a hash of these equivalence classes, then create a std::unordered_set with the template parameter KeyEqual set to your predicate. Insert all elements, then count the set's size.
If you only have the predicate, then I guess you're stuck with counting:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> elements = {1, 2, 3, 6, 7, 8};
unsigned int size = 0;
while (elements.size() > 0)
{
int const current = elements.front();
auto pred = [&current] (auto const & other) {
return (current % 5) == (other % 5);
};
elements.erase(std::remove_if(begin(elements), end(elements), pred), end(elements));
++size;
}
std::cout << size << " equivalence classes" << std::endl;
}
Isn't that much code, after all.

Related

how to use upper_bound to find out the last variable that satisfies a certain condition

I'm trying to use a log(n) method to find out the last variable that satisfies a certain condition. I looked at the documentation and found
these in the algorithm section (http://www.cplusplus.com/reference/algorithm/)
Binary search (operating on partitioned/sorted ranges):
lower_bound: Return iterator to lower bound (function template )
upper_bound: Return iterator to upper bound (function template )
equal_range: Get subrange of equal elements (function template )
binary_search: Test if value exists in sorted sequence (function template )
I think to do what I'm trying to do, I should use upper_bound/lower_bound.
In this case, I'm trying to find out the last index of the number that is smaller or equal to 3. (3). I know there are simpler ways such as looping through the whole array, but I want to learn how to use upper_bound. I know that the comparator needs 2 numbers but I don't need 2 numbers so I'm not sure what to do.
#include <bits/stdc++.h>
using namespace std;
vector<int> a = {0,1,2,3,4,5};
bool check(int base) {
if (a.at(base) <= 3) {
return true;
}
return false;
}
int main() {
int c;
sort(a.begin(), a.end());
c = distance(a.begin(), upper_bound(a.begin(), a.end(), check));
cout<<c;
return 0;
}
How would I correctly do this?
The comparator compares the number you are searching for 3 with the numbers in the vector. That's why it needs two parameters. You've hard coded the number 3 in your comparator, when you are supposed to pass it as an argument to upper_bound.
It's also the function that orders the vector, so if you are going to use one, you should also pass it to sort.
Your code could look like this
bool check(int x, int y) {
return x < y;
}
int main() {
int c;
sort(a.begin(), a.end(), check);
c = distance(a.begin(), upper_bound(a.begin(), a.end(), 3, check));
}
But since in this case check is just the default less-than operation, you can leave it out completely.
int main() {
int c;
sort(a.begin(), a.end());
c = distance(a.begin(), upper_bound(a.begin(), a.end(), 3));
}
See reference here

how to sort an array in descending order using a boolean function?

Since I am new in competitive programming so I am finding this a bit difficult. I encountered a code and I am not able to figure it out, need some help to understand it.
#include<iostream>
#include<algorithm>
using namespace std;
bool mycompare(int a ,int b){
return a>b;
}
int main(){
int a[]={5,4,3,1,2,6,7};
int n =sizeof(a)/sizeof(int);
sort(a,a+n,mycompare);
for(int i=0; i<n;i++){
cout<<a[i]<<"";
}
return 0;
}
output:
7 6 5 4 3 2 1
How does this code work more specifically what does the mycompare function do in the code?
My doubt is that why haven't we passed any arguments in the mycompare() function inside the main() function since the prototype of the function is
bool mycompare(int a, int b);
A comparison-based sorting algorithm sorts the elements solely by pair-wise comparison, i.e., if a < b holds, then a has to be placed before b.
This is a fine approach, but if you limit yourself to using <, it only allows you to sort elements in an ascending order. What if you want to have them in descending order, or any other ordering? This is where the concept of a Comparator (or a Compare callable in the context of the C++ standard) comes into play: It is a binary predicate bool compare(element a, element b) that is supposed to replace the < operator, i.e., a < b becomes compare(a, b) instead. This generalization allows you to encapsulate all types of orderings, in your question you already provided an example where the comparison uses a greater-than operator >, which gives you the aforementioned descending sorted order.
As for how this works internally in C++, the details can be rather complicated, but you can look at it as this:
mycompare without any parameters is a function pointer, i.e. a pointer to the memory address where the machine code for mycompare starts. You can do something like
auto func_pointer = mycompare;
func_pointer(1, 2); // calls mycompare(1, 2)
By giving this function pointer as a parameter to std::sort, you replace the default < comparison function by your own. The way C++ works internally gives the additional advantage that this function call can most likely be inlined, i.e., the compiler avoids the function call can be avoided by copying the code from mycompare into the std::sort invocation, which can speed up your code significantly.
std::sort takes a RandomIt (random iterator) as the first and second arguments that must satisfy the requirements of ValueSwappable and LegacyRandomAccessIterator. Instead of using a Plain-Old-Array of int, you want to use std::array which can then provide the iterators with the member functions .begin() and .end().
Using a proper container from the C++ standard template library makes sorting with std::sort trivial. You need not even provide a custom compare function to sort in descending order as std::less<int>() is provided for you (though your purpose may be to provide the compare function)
Your prototype for mycompare will work fine as is, but preferably the parameters are const type rather than just type, e.g.
bool mycompare(const int a, const int b)
{
return a > b;
}
The implementation using the array container is quite trivial. Simply declare/initialize your array a and then call std::sort (a.begin(), a.end(), mycompare); A complete working example would be:
#include <iostream>
#include <algorithm>
#include <array>
bool mycompare(const int a, const int b)
{
return a > b;
}
int main (void) {
std::array<int, 7> a = { 5, 4, 3, 1, 2, 6, 7 };
std::sort (a.begin(), a.end(), mycompare);
for (auto& i : a)
std::cout << " " << i;
std::cout << '\n';
}
Example Use/Output
$ ./bin/array_sort
7 6 5 4 3 2 1
Sorting the Plain Old Array*
If you must use a Plain-Old-Array, then you can use plain-old-pointers as your random iterrators. While not a modern C++ approach, you can handle the plain-old-array with std::sort. You can make use of the builtin std::greater<type>() for a descending sort or std::less<type>() for an ascending sort.
An implementation using pointers would simply be:
#include <iostream>
#include <algorithm>
int main (void) {
int a[] = { 5, 4, 3, 1, 2, 6, 7 };
size_t n = sizeof a / sizeof *a;
#if defined (ASCEND)
std::sort (a, a + n, std::less<int>());
#else
std::sort (a, a + n, std::greater<int>());
#endif
for (size_t i = 0; i < n; i++)
std::cout << " " << a[i];
std::cout << '\n';
}
(same output unless -DASCEND is added as a define on the commandline, and then an ascending sort will result from the use of std::less<int>())
Look things over and let me know if you have further questions.

how to sum up a vector of vector int in C++ without loops

I try to implement that summing up all elements of a vector<vector<int>> in a non-loop ways.
I have checked some relevant questions before, How to sum up elements of a C++ vector?.
So I try to use std::accumulate to implement it but I find it is hard for me to overload a Binary Operator in std::accumulate and implement it.
So I am confused about how to implement it with std::accumulate or is there a better way?
If not mind could anyone help me?
Thanks in advance.
You need to use std::accumulate twice, once for the outer vector with a binary operator that knows how to sum the inner vector using an additional call to std::accumulate:
int sum = std::accumulate(
vec.begin(), vec.end(), // iterators for the outer vector
0, // initial value for summation - 0
[](int init, const std::vector<int>& intvec){ // binaryOp that sums a single vector<int>
return std::accumulate(
intvec.begin(), intvec.end(), // iterators for the inner vector
init); // current sum
// use the default binaryOp here
}
);
In this case, I do not suggest using std::accumulate as it would greatly impair readability. Moreover, this function use loops internally, so you would not save anything. Just compare the following loop-based solution with the other answers that use std::accumulate:
int result = 0 ;
for (auto const & subvector : your_vector)
for (int element : subvector)
result += element;
Does using a combination of iterators, STL functions, and lambda functions makes your code easier to understand and faster? For me, the answer is clear. Loops are not evil, especially for such simple application.
According to https://en.cppreference.com/w/cpp/algorithm/accumulate , looks like BinaryOp has the current sum on the left hand, and the next range element on the right. So you should run std::accumulate on the right hand side argument, and then just sum it with left hand side argument and return the result. If you use C++14 or later,
auto binary_op = [&](auto cur_sum, const auto& el){
auto rhs_sum = std::accumulate(el.begin(), el.end(), 0);
return cur_sum + rhs_sum;
};
I didn't try to compile the code though :). If i messed up the order of arguments, just replace them.
Edit: wrong terminology - you don't overload BinaryOp, you just pass it.
Signature of std::accumulate is:
T accumulate( InputIt first, InputIt last, T init,
BinaryOperation op );
Note that the return value is deduced from the init parameter (it is not necessarily the value_type of InputIt).
The binary operation is:
Ret binary_op(const Type1 &a, const Type2 &b);
where... (from cppreference)...
The type Type1 must be such that an object of type T can be implicitly converted to Type1. The type Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to Type2. The type Ret must be such that an object of type T can be assigned a value of type Ret.
However, when T is the value_type of InputIt, the above is simpler and you have:
using value_type = std::iterator_traits<InputIt>::value_type;
T binary_op(T,value_type&).
Your final result is supposed to be an int, hence T is int. You need two calls two std::accumulate, one for the outer vector (where value_type == std::vector<int>) and one for the inner vectors (where value_type == int):
#include <iostream>
#include <numeric>
#include <iterator>
#include <vector>
template <typename IT, typename T>
T accumulate2d(IT outer_begin, IT outer_end,const T& init){
using value_type = typename std::iterator_traits<IT>::value_type;
return std::accumulate( outer_begin,outer_end,init,
[](T accu,const value_type& inner){
return std::accumulate( inner.begin(),inner.end(),accu);
});
}
int main() {
std::vector<std::vector<int>> x{ {1,2} , {1,2,3} };
std::cout << accumulate2d(x.begin(),x.end(),0);
}
Solutions based on nesting std::accumulate may be difficult to understand.
By using a 1D array of intermediate sums, the solution can be more straightforward (but possibly less efficient).
int main()
{
// create a unary operator for 'std::transform'
auto accumulate = []( vector<int> const & v ) -> int
{
return std::accumulate(v.begin(),v.end(),int{});
};
vector<vector<int>> data = {{1,2,3},{4,5},{6,7,8,9}}; // 2D array
vector<int> temp; // 1D array of intermediate sums
transform( data.begin(), data.end(), back_inserter(temp), accumulate );
int result = accumulate(temp);
cerr<<"result="<<result<<"\n";
}
The call to transform accumulates each of the inner arrays to initialize the 1D temp array.
To avoid loops, you'll have to specifically add each element:
std::vector<int> database = {1, 2, 3, 4};
int sum = 0;
int index = 0;
// Start the accumulation
sum = database[index++];
sum = database[index++];
sum = database[index++];
sum = database[index++];
There is no guarantee that std::accumulate will be non-loop (no loops). If you need to avoid loops, then don't use it.
IMHO, there is nothing wrong with using loops: for, while or do-while. Processors that have specialized instructions for summing arrays use loops. Loops are a convenient method for conserving code space. However, there may be times when loops want to be unrolled (for performance reasons). You can have a loop with expanded or unrolled content in it.
With range-v3 (and soon with C++20), you might do
const std::vector<std::vector<int>> v{{1, 2}, {3, 4, 5, 6}};
auto flat = v | ranges::view::join;
std::cout << std::accumulate(begin(flat), end(flat), 0);
Demo

Understanding boost::disjoint_sets

I need to use boost::disjoint_sets, but the documentation is unclear to me. Can someone please explain what each template parameter means, and perhaps give a small example code for creating a disjoint_sets?
As per the request, I am using disjoint_sets to implement Tarjan's off-line least common ancestors algorithm, i.e - the value type should be vertex_descriptor.
What I can understand from the documentation :
Disjoint need to associate a rank and a parent (in the forest tree) to each element. Since you might want to work with any kind of data you may,for example, not always want to use a map for the parent: with integer an array is sufficient. You also need a rank foe each element (the rank needed for the union-find).
You'll need two "properties" :
one to associate an integer to each element (first template argument), the rank
one to associate an element to an other one (second template argument), the fathers
On an example :
std::vector<int> rank (100);
std::vector<int> parent (100);
boost::disjoint_sets<int*,int*> ds(&rank[0], &parent[0]);
Arrays are used &rank[0], &parent[0] to the type in the template is int*
For a more complex example (using maps) you can look at Ugo's answer.
You are just giving to the algorithm two structures to store the data (rank/parent) he needs.
disjoint_sets<Rank, Parent, FindCompress>
Rank PropertyMap used to store the size of a set (element -> std::size_t). See union by rank
Parent PropertyMap used to store the parent of an element (element -> element). See Path compression
FindCompress Optional argument defining the find method. Default to find_with_full_path_compression See here (Default should be what you need).
Example:
template <typename Rank, typename Parent>
void algo(Rank& r, Parent& p, std::vector<Element>& elements)
{
boost::disjoint_sets<Rank,Parent> dsets(r, p);
for (std::vector<Element>::iterator e = elements.begin();
e != elements.end(); e++)
dsets.make_set(*e);
...
}
int main()
{
std::vector<Element> elements;
elements.push_back(Element(...));
...
typedef std::map<Element,std::size_t> rank_t; // => order on Element
typedef std::map<Element,Element> parent_t;
rank_t rank_map;
parent_t parent_map;
boost::associative_property_map<rank_t> rank_pmap(rank_map);
boost::associative_property_map<parent_t> parent_pmap(parent_map);
algo(rank_pmap, parent_pmap, elements);
}
Note that "The Boost Property Map Library contains a few adaptors that convert commonly used data-structures that implement a mapping operation, such as builtin arrays (pointers), iterators, and std::map, to have the property map interface"
This list of these adaptors (like boost::associative_property_map) can be found here.
For those of you who can't afford the overhead of std::map (or can't use it because you don't have default constructor in your class), but whose data is not as simple as int, I wrote a guide to a solution using std::vector, which is kind of optimal when you know the total number of elements beforehand.
The guide includes a fully-working sample code that you can download and test on your own.
The solution mentioned there assumes you have control of the class' code so that in particular you can add some attributes. If this is still not possible, you can always add a wrapper around it:
class Wrapper {
UntouchableClass const& mInstance;
size_t dsID;
size_t dsRank;
size_t dsParent;
}
Moreover, if you know the number of elements to be small, there's no need for size_t, in which case you can add some template for the UnsignedInt type and decide in runtime to instantiate it with uint8_t, uint16_t, uint32_tor uint64_t, which you can obtain with <cstdint> in C++11 or with boost::cstdint otherwise.
template <typename UnsignedInt>
class Wrapper {
UntouchableClass const& mInstance;
UnsignedInt dsID;
UnsignedInt dsRank;
UnsignedInt dsParent;
}
Here's the link again in case you missed it: http://janoma.cl/post/using-disjoint-sets-with-a-vector/
I written a simple implementation a while ago. Have a look.
struct DisjointSet {
vector<int> parent;
vector<int> size;
DisjointSet(int maxSize) {
parent.resize(maxSize);
size.resize(maxSize);
for (int i = 0; i < maxSize; i++) {
parent[i] = i;
size[i] = 1;
}
}
int find_set(int v) {
if (v == parent[v])
return v;
return parent[v] = find_set(parent[v]);
}
void union_set(int a, int b) {
a = find_set(a);
b = find_set(b);
if (a != b) {
if (size[a] < size[b])
swap(a, b);
parent[b] = a;
size[a] += size[b];
}
}
};
And the usage goes like this. It's simple. Isn't it?
void solve() {
int n;
cin >> n;
DisjointSet S(n); // Initializing with maximum Size
S.union_set(1, 2);
S.union_set(3, 7);
int parent = S.find_set(1); // root of 1
}
Loic's answer looks good to me, but I needed to initialize the parent so that each element had itself as parent, so I used the iota function to generate an increasing sequence starting from 0.
Using Boost, and I imported bits/stdc++.h and used using namespace std for simplicity.
#include <bits/stdc++.h>
#include <boost/pending/disjoint_sets.hpp>
#include <boost/unordered/unordered_set.hpp>
using namespace std;
int main() {
array<int, 100> rank;
array<int, 100> parent;
iota(parent.begin(), parent.end(), 0);
boost::disjoint_sets<int*, int*> ds(rank.begin(), parent.begin());
ds.union_set(1, 2);
ds.union_set(1, 3);
ds.union_set(1, 4);
cout << ds.find_set(1) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(2) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(3) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(4) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(5) << endl; // 5
cout << ds.find_set(6) << endl; // 6
}
I changed std::vector to std::array because pushing elements to a vector will make it realloc its data, which makes the references the disjoint sets object contains become invalid.
As far as I know, it's not guaranteed that the parent will be a specific number, so that's why I wrote 1 or 2 or 3 or 4 (it can be any of these). Maybe the documentation explains with more detail which number will be chosen as leader of the set (I haven't studied it).
In my case, the output is:
2
2
2
2
5
6
Seems simple, it can probably be improved to make it more robust (somehow).
Note: std::iota Fills the range [first, last) with sequentially increasing values, starting with value and repetitively evaluating ++value.
More: https://en.cppreference.com/w/cpp/algorithm/iota

How to compare vectors with Boost.Test?

I am using Boost Test to unit test some C++ code.
I have a vector of values that I need to compare with expected results, but I don't want to manually check the values in a loop:
BOOST_REQUIRE_EQUAL(values.size(), expected.size());
for( int i = 0; i < size; ++i )
{
BOOST_CHECK_EQUAL(values[i], expected[i]);
}
The main problem is that the loop check doesn't print the index, so it requires some searching to find the mismatch.
I could use std::equal or std::mismatch on the two vectors, but that will require a lot of boilerplate as well.
Is there a cleaner way to do this?
Use BOOST_CHECK_EQUAL_COLLECTIONS. It's a macro in test_tools.hpp that takes two pairs of iterators:
BOOST_CHECK_EQUAL_COLLECTIONS(values.begin(), values.end(),
expected.begin(), expected.end());
It will report the indexes and the values that mismatch. If the sizes don't match, it will report that as well (and won't just run off the end of the vector).
Note that if you want to use BOOST_CHECK_EQUAL or BOOST_CHECK_EQUAL_COLLECTIONS with non-POD types, you will need to implement
bool YourType::operator!=(const YourType &rhs) // or OtherType
std::ostream &operator<<(std::ostream &os, const YourType &yt)
for the comparison and logging, respectively.
The order of the iterators passed to BOOST_CHECK_EQUAL_COLLECTIONS determines which is the RHS and LHS of the != comparison - the first iterator range will be the LHS in the comparisons.
A bit off-topic, however, when sometimes one needs to compare collections of floating-point numbers using comparison with tolerance then this snippet may be of use:
// Have to make it a macro so that it reports exact line numbers when checks fail.
#define CHECK_CLOSE_COLLECTION(aa, bb, tolerance) { \
using std::distance; \
using std::begin; \
using std::end; \
auto a = begin(aa), ae = end(aa); \
auto b = begin(bb); \
BOOST_REQUIRE_EQUAL(distance(a, ae), distance(b, end(bb))); \
for(; a != ae; ++a, ++b) { \
BOOST_CHECK_CLOSE(*a, *b, tolerance); \
} \
}
This does not print the array indexes of mismatching elements, but it does print the mismatching values with high precision, so that they are often easy to find.
Example usage:
auto mctr = pad.mctr();
std::cout << "mctr: " << io::as_array(mctr) << '\n';
auto expected_mctr{122.78731602430344,-13.562000155448914};
CHECK_CLOSE_COLLECTION(mctr, expected_mctr, 0.001);
Since Boost 1.59 it is much easier to compare std::vector instances. See this documentation for version 1.63 (which is nearly equal in this respect to 1.59).
For example if you have declared std::vector<int> a, b; you can write
BOOST_TEST(a == b);
to get a very basic comparison. The downside of this is that in case of failure Boost only tells you that a and b are not the same. But you get more info by comparing element-wise which is possible in an elegant way
BOOST_TEST(a == b, boost::test_tools::per_element() );
Or if you want a lexicographic comparison you may do
BOOST_TEST(a <= b, boost::test_tools::lexicographic() );
How about BOOST_CHECK_EQUAL_COLLECTIONS?
BOOST_AUTO_TEST_CASE( test )
{
int col1 [] = { 1, 2, 3, 4, 5, 6, 7 };
int col2 [] = { 1, 2, 4, 4, 5, 7, 7 };
BOOST_CHECK_EQUAL_COLLECTIONS( col1, col1+7, col2, col2+7 );
}
example
Running 1 test case...
test.cpp(11): error in "test": check { col1, col1+7 } == { col2, col2+7 } failed.
Mismatch in a position 2: 3 != 4
Mismatch in a position 5: 6 != 7
* 1 failure detected in test suite "example"
You can use BOOST_REQUIRE_EQUAL_COLLECTIONS with std::vector<T>, but you have to teach Boost.Test how to print a std::vector when you have a vector of vectors or a map whose values are vectors. When you have a map, Boost.Test needs to be taught how to print std::pair. Since you can't change the definition of std::vector or std::pair, you have to do this in such a way that the stream insertion operator you define will be used by Boost.Test without being part of the class definition of std::vector. Also, this technique is useful if you don't want to add stream insertion operators to your system under test just to make Boost.Test happy.
Here is the recipe for any std::vector:
namespace boost
{
// teach Boost.Test how to print std::vector
template <typename T>
inline wrap_stringstream&
operator<<(wrap_stringstream& wrapped, std::vector<T> const& item)
{
wrapped << '[';
bool first = true;
for (auto const& element : item) {
wrapped << (!first ? "," : "") << element;
first = false;
}
return wrapped << ']';
}
}
This formats the vectors as [e1,e2,e3,...,eN] for a vector with N elements and will work for any number of nested vectors, e.g. where the elements of the vector are also vectors.
Here is the similar recipe for std::pair:
namespace boost
{
// teach Boost.Test how to print std::pair
template <typename K, typename V>
inline wrap_stringstream&
operator<<(wrap_stringstream& wrapped, std::pair<const K, V> const& item)
{
return wrapped << '<' << item.first << ',' << item.second << '>';
}
}
BOOST_REQUIRE_EQUAL_COLLECTIONS will tell you the index of the mismatched items, as well as the contents of the two collections, assuming the two collections are of the same size. If they are of different sizes, then that is deemed a mismatch and the differing sizes are printed.