using std::sort and std::next_permutation - c++

I have the following code which i wrote and works perfectly. I just have trouble understanding why it works. More specifically, why must we first sort the array in order to use std::next_permutation, can it not start from any configuration ?
And the part which bothers me the most is that I don't understand why we must write
sort(sides, sides+3) and next_permutation(sides, sides+3) why the "+3"! because I have three elements in the array ? What if i was using an arbitrary number of elements ?
bool valid(int sides[], ofstream &outfile)
{
int i = 0;
for(; i < 3; i++) {
if(sides[i] <= 0) {
outfile << "This is not a valid triangle because it\n "
<< "contains negative sides or contains a\n"
<< "side length of 0\n\n";
return false;
}
}
do{
std::sort(sides,sides+3);
if(sides[0] + sides[1] > sides[2])
;
else{
outfile << "This is not a valid triangle because "
<< sides[0] << " + " << sides[1]
<< " is not greater than " << sides[2];
return false;
}
}while(std::next_permutation(sides,sides+3));
return true;
}

Euclidian geometry tells us that:
the sum of two sides is always greater than the remaining side
Lets take a triangle ABC.
AB = 3
BC = 5
AC = 4
std::sort will sort the sides into ascending order. So that the array will contain the shorter sides first.
after sort
side[0] = AB = 3
side[1] = AC = 4
side[2] = BC = 5
std::next_permutation returns the next possible combination of the sides.For instance:
AC = 3
BC = 5
AB = 4
A quick example:
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation, std::sort
int main () {
int myints[] = {1,2,3};
std::sort (myints,myints+3);
std::cout << "The 3! possible permutations with 3 elements:\n";
while ( std::next_permutation(myints,myints+3) )
{
std::cout << myints[0] << ' ' << myints[1];
std::cout << ' ' << myints[2] << '\n';
}
std::cout << "After loop: " << myints[0] << ' ';
std::cout << myints[1] << ' ' << myints[2] << '\n';
return 0;
}
Further reading: http://www.cplusplus.com/reference/algorithm/next_permutation/

the std::next_permutation documentation
Transform range to next permutation Rearranges the elements in the
range [first,last) into the next lexicographically greater
permutation.
so unless you start sorted you won't go through all permutations
So if you start with
1,2,3
that last permutation would be
3,2,1
if you start from
3,1,2
only one more permutation will be found and not all

Take a look at the results of std::next_permuntation when you don't sort it:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
enum class sort { no, yes };
void show_permutations(std::string s, sort option) {
if (sort::yes == option) {
std::sort(std::begin(s), std::end(s));
}
do {
std::cout << s << '\n';
} while (std::next_permutation(std::begin(s), std::end(s)));
}
int main() {
show_permutations("3412", sort::yes);
std::cout << "Now without sorting...\n";
show_permutations("3412", sort::no);
}
Examine the output to see if you notice anything interesting:
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
Now without sorting...
3412
3421
4123
4132
4213
4231
4312
4321
The sequence created without sorting is the same as just the very end of the sequence created with sorting. What does that imply about the importance of the input's ordering?
What do you think would happen if you put the sorting code inside the loop?
void show_permutations(std::string s, sort option) {
do {
if (sort::yes == option) {
std::sort(std::begin(s), std::end(s));
}
std::cout << s << '\n';
} while (std::next_permutation(std::begin(s), std::end(s)));
}
Notice that your program sorts the triangle sides inside the next_permutation loop similar to this code sorting the input string inside the loop.

Related

Most 'functional' way to sum pairs of elements from a vector using C++17 or later?

I'd like some suggestions for the most terse and 'functional' way to gather pairs of successive elements from a vector (1st and 2nd, 3rd and 4th, etc.) using modern C++. Assume the vector is of arbitrary but even length. For the examples I'm pulling together, I'm summing the elements of each pair but that's not the main problem. I should add I'll use STL only, no Boost.
In Python I can zip them into 2-tuples via an iterator with
s = range(1,11)
print([(x + y) for x,y in zip(*[iter(s)] * 2)])
In Perl 5 I can peel off pairs with
use List::Util qw/pairs sum/;
use feature 'say';
#s = 1 .. 10;
say sum #$_ foreach (pairs #s);
In Perl 6 I can shove them two at a time into a block with
my #s = 1 .. 10;
for #s -> $x, $y { say $x + $y; }
and in R I can wrap the vector into a 2-column array and sum the rows with
s <- 1:10
print(apply(matrix(s, ncol=2, byrow=TRUE), 1, sum))
I am not fluent in C++ and my solution uses for(;;). That feels too much like C.
#include <iostream>
#include <vector>
#include <numeric> // std::iota
int main() {
std::vector<int> s(10);
std::iota(s.begin(), s.end(), 1);
for (auto p = s.cbegin(); p != s.cend(); p += 2)
std::cout << (*p + *(p + 1)) << std::endl;
}
The output of course should be some variant of
3
7
11
15
19
Using range-v3:
for (auto v : view::iota(1, 11) | view::chunk(2)) {
std::cout << v[0] + v[1] << '\n';
}
Note that chunk(2) doesn't give you a compile-time-fixed size view, so you can't do:
for (auto [x,y] : view::iota(1, 11) | view::chunk(2)) { ... }
Without using range-v3 I was able to do this with either a function or a lambda template. I'll show the lambda version here.
#include <iostream>
#include <string>
#include <vector>
template<typename T>
auto lambda = [](const std::vector<T>& values, std::vector<T>& results) {
std::vector<T> temp1, temp2;
for ( std::size_t i = 0; i < values.size(); i++ ) {
if ( i & 1 ) temp2.push_back(values[i]); // odd index
else temp1.push_back(values[i]); // even index
}
for ( std::size_t i = 0; i < values.size() / 2; i++ )
results.push_back(temp[i] + temp[2]);
};
int main() {
std::vector<int> values{ 1,2,3,4,5,6 };
for (auto i : values)
std::cout << i << " ";
std::cout << '\n';
std::vector<int> results;
lambda<int>(values, results);
for (auto i : results)
std::cout << i << " ";
std::cout << '\n';
std::vector<float> values2{ 1.1f, 2.2f, 3.3f, 4.4f };
for (auto f : values2)
std::cout << f << " ";
std::cout << '\n';
std::vector<float> results2;
lambda<float>(values2, results2);
for (auto f : results2)
std::cout << f << " ";
std::cout << '\n';
std::vector<char> values3{ 'a', 'd' };
for (auto c : values3)
std::cout << c << " ";
std::cout << '\n';
std::vector<char> results3;
lambda<char>(values3, results3);
for (auto c : results3)
std::cout << c << " ";
std::cout << '\n';
std::vector<std::string> values4{ "Hello", " ", "World", "!" };
for (auto s : values4)
std::cout << s;
std::cout << '\n';
std::vector<std::string> results4;
lambda<std::string>(values4, results4);
for (auto s : results4)
std::cout << s;
std::cout << '\n';
return EXIT_SUCCESS;
}
Output
1 2 3 4 5 6
3 7 11
1.1 2.2 3.3 4.4
3.3 7.7
a d
┼
Hello World!
Hello World!
At the risk of sounding like I'm trying to be clever or annoying, I say this is the answer:
print(sums(successive_pairs(range(1,11))));
Now, of course, those aren't built-in functions, so you would have to define them, but I don't think that is a bad thing. The code clearly expresses what you want in a functional style. Also, the responsibility of each of those functions is well separated, easily testable, and reusable. It isn't necessary to use a lot of tricky specialized syntax to write code in a functional style.

vector element compare c++

This program takes a word from text and puts it in a vector; after this it compares every element with the next one.
So I'm trying to compare element of a vector like this:
sort(words.begin(), words.end());
int cc = 1;
int compte = 1;
int i;
//browse the vector
for (i = 0; i <= words.size(); i++) { // comparison
if (words[i] == words[cc]) {
compte = compte + 1;
}
else { // displaying the word with comparison
cout << words[i] << " Repeated : " << compte; printf("\n");
compte = 1; cc = i;
}
}
My problem in the bounds: i+1 may exceed the vector borders. How to I handle this case?
You need to pay more attention on the initial conditions and bounds when you do iteration and comparing at the same time. It is usually a good idea to execute your code using pen and paper at first.
sort(words.begin(), words.end()); // make sure !words.empty()
int cc = 0; // index of the word we need to compare.
int compte = 1; // counting of the number of occurrence.
for( size_t i = 1; i < words.size(); ++i ){
// since you already count the first word, now we are at i=1
if( words[i] == words[cc] ){
compte += 1;
}else{
// words[i] is going to be different from words[cc].
cout << words[cc] << " Repeated : " << compte << '\n';
compte = 1;
cc = i;
}
}
// to output the last word with its repeat
cout << words[cc] << " Repeated : " << compte << '\n';
Just for some additional information.
There are better ways to count the number of word appearances.
For example, one can use unordered_map<string,int>.
Hope this help.
C++ uses zero-based indexing, e.g., an array of length 5 has indices: {0, 1, 2, 3, 4}. This means that index 5 is outside of the range.
Similarly, given an array arr of characters:
char arr[] = {'a', 'b', 'c', 'd', 'e'};
The loop for (int i = 0; i <= std::size(arr); ++i) { arr[i]; } will cause a read from outside of the range when i is equal to the length of arr, which causes undefined behaviour. To avoid this the loop must stop before i is equal to the length of the array.
for (std::size_t i = 0; i < std::size(arr); ++i) { arr[i]; }
Also note the use of std::size_t as type of the index counter. This is common practice in C++.
Now, let's finish with an example of how much easier this can be done using the standard library.
std::sort(std::begin(words), std::end(words));
std::map<std::string, std::size_t> counts;
std::for_each(std::begin(words), std::end(words), [&] (const auto& w) { ++counts[w]; });
Output using:
for (auto&& [word, count] : counts) {
std::cout << word << ": " << count << std::endl;
}
My problem in the bounds: i+1 may exceed the vector borders. How to I
handle this case?
In modern C++ coding, the problem of an index going past vector bounds can be avoided. Use the STL containers and avoid using indices. With a little effort devoted to learning how to use containers this way, you should never see these kind of 'off-by-one' errors again! As a benefit, the code becomes more easily understood and maintained.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int main() {
// a test vector of words
vector< string > words { "alpha", "gamma", "beta", "gamma" };
// map unique words to their appearance count
map< string, int > mapwordcount;
// loop over words
for( auto& w : words )
{
// insert word into map
auto ret = mapwordcount.insert( pair<string,int>( w, 1 ) );
if( ! ret.second )
{
// word already present
// so increment count
ret.first->second++;
}
}
// loop over map
for( auto& m : mapwordcount )
{
cout << "word '" << m.first << "' appears " << m.second << " times\n";
}
return 0;
}
Produces
word 'alpha' appears 1 times
word 'beta' appears 1 times
word 'gamma' appears 2 times
https://ideone.com/L9VZt6
If some book or person is teaching you to write code full of
for (i = 0; i < ...
then you should run away quickly and learn modern coding elsewhere.
Same repeated words counting using some C++ STL goodies via multiset and upper_bound:
#include <iostream>
#include <vector>
#include <string>
#include <set>
int main()
{
std::vector<std::string> words{ "one", "two", "three", "two", "one" };
std::multiset<std::string> ms(words.begin(), words.end());
for (auto it = ms.begin(), end = ms.end(); it != end; it = ms.upper_bound(*it))
std::cout << *it << " is repeated: " << ms.count(*it) << " times" << std::endl;
return 0;
}
https://ideone.com/tPYw4a

Improving the time complexity of all permutations of a given string

The problem is generally posed as given a string, print all permutations of it. For eg, the permutations of string ABC are ABC, ACB, BAC, BCA, CAB, CBA.
The standard solution is a recursive one, given below.
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
This, runs into O(n*n!). Is this the best we can do or is there someway to make this faster?
You can use std::next_permutation. Please, notice it works correctly only on sorted array.
Good points about this solution:
1) It is standard
2) It is non-recursive
Here is an example (http://www.cplusplus.com/reference/algorithm/next_permutation/):
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation, std::sort
int main () {
int myints[] = {1, 2, 3};
std::sort (myints, myints + 3);
std::cout << "The 3! possible permutations with 3 elements:\n";
do {
std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
} while (std::next_permutation (myints, myints + 3));
std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
return 0;
}
The very result you are looking for contains n*n elements, so this is the best you can get!
Suppose you have n elements and you are looking for kth permutation 0 <= k <= n-1.
Create a list elements with all elements and an empty list result
while elements not empty:
Set p = k % elements.size and k = k / elements.size
Remove elements[p] and append it to result
We visit each element from elements only once so it's O(n).
std::next_permutation does the job:
#include <algorithm>
#include <iostream>
int main () {
char s[] = "BAC";
// let's begin with the lowest lexicographically string.
std::sort(std::begin(s), std::end(s) - 1); // '- 1' : ignore '\0'
do {
std::cout << s << std::endl;
} while (std::next_permutation(std::begin(s), std::end(s) - 1));
return 0;
}

Does Boost c++ library interval_map supports remove?

Does the interval_map (in icl) library provide support for deletion? Can I look up the range based on iterator and delete the range?
============ party.cpp from boost example ===============
partyp->add( // add and element
make_pair(
interval<ptime>::right_open(
time_from_string("2008-05-20 19:30"),
time_from_string("2008-05-20 23:00")),
mary_harry));
party += // element addition can also be done via operator +=
make_pair(
interval<ptime>::right_open(
time_from_string("2008-05-20 20:10"),
time_from_string("2008-05-21 00:00")),
diana_susan);
party +=
make_pair(
interval<ptime>::right_open(
time_from_string("2008-05-20 22:15"),
time_from_string("2008-05-21 00:30")),
peter);
==========
My question is can i add a remove statement like
party -=
interval<ptime>::right_open(
time_from_string("2008-05-20 20:10"),
time_from_string("2008-05-21 00:00"));
I just want to remove the range. Any method is fine.
I know this is an old post, but I had the same question and I've finally found an answer.
Looking at the docs I would guess that the Subtractability of an interval_map and the aggregate on overlap capabilities guarantee that the substraction works as a delete operation.
It turned out to be a very fruitful concept to propagate the addition
or subtraction to the interval_map's associated values in cases where
the insertion of an interval value pair into an interval_map resulted
in a collision of the inserted interval value pair with interval value
pairs, that are already in the interval_map. This operation
propagation is called aggregate on overlap.
Let's say I have to match intervals of unix timestamps to some record ids (integers).
Working from this answer I've come up with this MWE:
// interval_map_mwe.cpp
#include <map>
#include <set>
#include <climits>
#include <boost/icl/interval.hpp>
#include <boost/icl/interval_map.hpp>
// Set of IDs that cover a time interval
typedef std::set<unsigned int> IDSet_t;
// interval tree from intervals of timestamps to a set of ids
typedef boost::icl::interval_map<time_t, IDSet_t> IMap_t;
// a time interval
typedef boost::icl::interval<time_t> Interval_t;
#include <iostream>
// from https://stackoverflow.com/a/22027957
inline std::ostream& operator<< (std::ostream& S, const IDSet_t& X)
{
S << '(';
for (IDSet_t::const_iterator it = X.begin(); it != X.end(); ++it) {
if (it != X.begin()) {
S << ',';
}
S << *it;
}
S << ')';
return S;
}
int main(int argc, const char *argv[])
{
(void)argc; // suppress warning
(void)argv; // suppress warning
IMap_t m;
IDSet_t s;
s.insert(1);
s.insert(2);
m += std::make_pair(Interval_t::right_open(100, 200), s);
s = IDSet_t();
s.insert(3);
s.insert(4);
m += std::make_pair(Interval_t::right_open(200, 300), s);
s = IDSet_t();
s.insert(5);
s.insert(6);
m += std::make_pair(Interval_t::right_open(150, 250), s);
std::cout << "Initial map: " << std::endl;
std::cout << m << std::endl;
// find operation
IMap_t::const_iterator it = m.find(175);
std::cout << "Interval that covers 175: ";
std::cout << it->first << std::endl;
std::cout << "Ids in interval: " << it->second << std::endl;
// partially remove 5 from interval (160,180)
s = IDSet_t();
s.insert(5);
m -= std::make_pair(Interval_t::right_open(160, 180), s);
std::cout << "map with 5 partially removed:" << std::endl;
std::cout << m << std::endl;
// completelly remove 6
s = IDSet_t();
s.insert(6);
// Note: maybe the range of the interval could be shorter if you can somehow obtain the minimum and maximum times
m -= std::make_pair(Interval_t::right_open(0, UINT_MAX), s);
std::cout << "map without 6: " << std::endl;
std::cout << m << std::endl;
// remove a time interval
m -= Interval_t::right_open(160, 170);
std::cout << "map with time span removed: " << std::endl;
std::cout << m << std::endl;
return 0;
}
Compiling with g++ 4.4.7:
g++ -Wall -Wextra -std=c++98 -I /usr/include/boost148/ interval_map_mwe.cpp
The output I get is
Initial map:
{([100,150)->{1 2 })([150,200)->{1 2 5 6 })([200,250)->{3 4 5 6 })([250,300)->{3 4 })}
Interval that covers 175: [150,200)
Ids in interval: (1,2,5,6)
map with 5 partially removed:
{([100,150)->{1 2 })([150,160)->{1 2 5 6 })([160,180)->{1 2 6 })([180,200)->{1 2 5 6 })([200,250)->{3 4 5 6 })([250,300)->{3 4 })}
map without 6:
{([100,150)->{1 2 })([150,160)->{1 2 5 })([160,180)->{1 2 })([180,200)->{1 2 5 })([200,250)->{3 4 5 })([250,300)->{3 4 })}
map with time span removed:
{([100,150)->{1 2 })([150,160)->{1 2 5 })([170,180)->{1 2 })([180,200)->{1 2 5 })([200,250)->{3 4 5 })([250,300)->{3 4 })}
Note: The numbers in the MWE can be considered random. I find it easier to reason about the example with small numbers.

How to store intermediate values of circular buffer iterator?

I am a using a boost regex on a boost circular buffer and would like to "remember" positions where matches occur, what's the best way to do this? I tried the code below, but "end" seems to store the same values all the time! When I try to traverse from a previous "end" to the most recent "end" for example, it doesn't work!
boost::circular_buffer<char> cb(2048);
typedef boost::circular_buffer<char>::iterator ccb_iterator;
boost::circular_buffer<ccb_iterator> cbi(4);
//just fill the whole cbi with cb.begin()
cbi.push_back(cb.begin());
cbi.pushback(cb.begin());
cbi.pushback(cb.begin());
cbi.pushback(cb.begin());
typedef regex_iterator<circular_buffer<char>::iterator> circular_regex_iterator;
while (1)
{
//insert new data in circular buffer (omitted)
//basically reads data from file and pushes it back to cb
boost::circular_buffer<char>::iterator start,end;
circular_regex_iterator regexItr(
cb.begin(),
cb.end() ,
re, //expression of the regular expression
boost::match_default | boost::match_partial);
circular_regex_iterator last;
while(regexItr != last)
{
if((*regexItr)[0].matched == false)
{
//partial match
break;
}
else
{
// full match:
start = (*regexItr)[0].first;
end = (*regexItr)[0].second;
//I want to store these "end" positions to to use later so that I can
//traverse the buffer between these positions (matches).
//cbi stores positions of these matches, but this does not seem to work!
cbi.push_back(end);
//for example, cbi[2] --> cbi[3] traversal works only first time this
//loop is run!
}
++regexItr;
}
}
This isn't quite as much an answer as an attempt to reconstruct what you're doing. I'm making a simple circular buffer initialized from a string, and I traverse regex matches through that buffer and print the matched ranges. All seems to work fine.
I would not recommend storing the ranges themselves in a circular buffer; or at the very least the ranges should be stored in pairs.
Here's my test code:
#include <iostream>
#include <string>
#include <boost/circular_buffer.hpp>
#include <boost/regex.hpp>
#include "prettyprint.hpp"
typedef boost::circular_buffer<char> cb_char;
typedef boost::regex_iterator<cb_char::iterator> cb_char_regex_it;
int main()
{
std::string sample = "Hello 12 Worlds 34 ! 56";
cb_char cbc(8, sample.begin(), sample.end());
std::cout << cbc << std::endl; // (*)
boost::regex expression("\\d+"); // just match numbers
for (cb_char_regex_it m2, m1(cbc.begin(), cbc.end(), expression); m1 != m2; ++m1)
{
const auto & mr = *m1;
std::cout << "--> " << mr << ", range ["
<< std::distance(cbc.begin(), mr[0].first) << ", "
<< std::distance(cbc.begin(), mr[0].second) << "]" << std::endl;
}
}
(This uses the pretty printer to print the raw circular buffer; you can remove the line marked (*).)
Update: Here's a possible way to store the matches:
typedef std::pair<std::size_t, std::size_t> match_range;
typedef std::vector<match_range> match_ranges;
/* ... as before ... */
match_ranges ranges;
for (cb_char_regex_it m2, m1(cbc.begin(), cbc.end(), expression); m1 != m2; ++m1)
{
const auto & mr = *m1;
ranges.push_back(match_range(std::distance(cbc.begin(), mr[0].first), std::distance(cbc.begin(), mr[0].second)));
std::cout << "--> " << mr << ", range " << ranges.back() << std::endl;
}
std::cout << "All matching ranges: " << ranges << std::endl;