iter_swap yields wrong result - c++

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void myfunction(int i)
{
cout<<" "<<i;
};
void multiply(int a)
{
a*2;
}
int main()
{
int t[]={10,5,9,6,2,4,7,8,3,1};
vector<int> v1(t,t+10);
for_each(v1.begin(),v1.end(),multiply);
iter_swap(v1.begin(), t+9);
for_each(v1.begin(),v1.end(),myfunction);
return 0;
}
Hello, I actually have question about this code.
when I run this, I see the result is 1 5 9 6 2 4 7 8 3 1 and I am not sure why the last element is still 1 even though I assigned the statement iter_swap(v1.begin(), t+9); in the middle.

Given iter_swap(v1.begin(), t+9);, you're swapping the 1st element of the std::vector v1 and the 10th element of the array t. v1 and t are two independent objects. And you're printing out the elements of v1 as for_each(v1.begin(),v1.end(),myfunction);, but the 10th element of v1 is not changed.
You might want
iter_swap(v1.begin(), v1.end()-1); // swap the 1st and 10th element of v1
for_each(v1.begin(),v1.end(),myfunction);

I have looked through your code and the output is correct,
for_each(v1.begin(), v1.end(), multiply);
The output for the code above is v1 = 10,5,9,6,2,4,7,8,3,1 while
t is also the same t = 10,5,9,6,2,4,7,8,3,1
iter_swap(v1.begin(), t + 9);
When you swap v1.begin and t+9 u are swapping 10 in v1 with 1 in t9 hence the final output
1 5 9 6 2 4 7 8 3 1
You can try swapping the first and last elements.
iter_swap(v1.begin(), v1.end()-1);
for_each(v1.begin(),v1.end(),myfunction);

Related

Efficient way to enumerate unique undirected paths

Given a subset of nodes {1,2,...,N} is there any STL or boost function that returns unique undirected tours over all of them?
std::next_permutation() gives all N! directed tours, where 1-2-...-N is different from N-N-1-...-2-1.
However, in this case, I don't want both of them, but only one of them. Essentially, I would like to enumerate only N! / 2 of the tours.
The following code that uses std::next_permutation() and unordered_set works, but is there anything more efficient? The following code essentially generates all N! directed tours and discards half of them after checking against an unordered_set().
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <boost/functional/hash.hpp>
template <typename T, typename U> bool unorderedset_val_there_already_add_if_not(std::unordered_set<T, U>& uos, T& val) {
if (uos.find(val) != uos.end())
return true;//val already there
uos.insert(val);
return false;//Value is new.
}
int main() {
std::vector<int> sequence{ 1, 2, 3};
std::unordered_set<std::vector<int>, boost::hash<std::vector<int>>> uos;
do {
printf("Considering ");
for (std::size_t i = 0; i < sequence.size(); i++)
printf("%d ", sequence[i]);
printf("\n");
std::vector<int> rev_sequence = sequence;
std::reverse(rev_sequence.begin(), rev_sequence.end());
if (unorderedset_val_there_already_add_if_not(uos, sequence) || unorderedset_val_there_already_add_if_not(uos, rev_sequence)) {
printf("Already there by itself or its reverse.\n");
}
else {
printf("Sequence and its reverse are new.\n");
}
} while (std::next_permutation(sequence.begin(), sequence.end()));
getchar();
}
That is, given {1,2,3}, I only want to enumerate (1-2-3), (1-3-2) and (2-1-3). The other three permutations (2-3-1), (3-1-2) and (3-2-1) should not be enumerated because their reverse sequence have already been enumerated.
If you want to stay with next_permutation rather than make own generator routine, the simplest way is filter out a half of permutation with some condition.
Very simple one: the last element should be larger than the first one.
#include <vector>
#include <algorithm>
#include "stdio.h"
int main() {
std::vector<int> sequence{ 1, 2, 3, 4};
do {
if (sequence[sequence.size()-1] > sequence[0]) {
for (std::size_t i = 0; i < sequence.size(); i++)
printf("%d ", sequence[i]);
printf("\n");
}
} while (std::next_permutation(sequence.begin(), sequence.end()));
getchar();
}
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 4 1 3
3 1 2 4
3 2 1 4
Possible own implementation:
Generate all pairs (start; end) where start < end
Generate all permutations of `n-2` values without start and end
For every permutation make {start, permutation.., end}
1 ... 2 + permutations of {3, 4}
1 3 4 2
1 4 3 2
1 ... 3 + permutations of {2,4}
1 2 4 3
1 4 2 3
...
3 ... 4 + permutations of {1, 2}
3 1 2 4
3 2 1 4
...

How to print array elements above and below minor dioganal?

I need your help. In C++ there is a two dimensional array. How to print array elements above and below minor dioganal?
I need to print array elements above minor diognal with minor dioganal elements
elements above minor dioganal:
For example :
1 2 3
4 5 6
7 8 9
The output should be:
1 2 3
4 5
7
1 2 3 4 5 7 in any order.
elements below minor dioganal:
Output should be:
3
5 6
7 8 9
3 5 6 7 8 9 in any order.
This should be rather simple.
For above minor diagonal, we need to print in the first row all values, then one less, then one less and so on.
For below minor diagonal, we need to print in the first row starting with column offset 3, then one less, then one less and so on.
For printing, we will use stateful lambdas.
Including the generation of some test data and some debug output the programm will be very small.
Please see:
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <algorithm>
#include <numeric>
constexpr size_t Dimension = 3U;
int main() {
// Define 2D vector of requested size
std::vector<std::vector<int>> array(Dimension, std::vector<int>(Dimension));
// Fill with some consecutive test values
std::for_each(array.begin(), array.end(), [i = 1](std::vector<int>& v) mutable {
std::iota(v.begin(), v.end(), i); i += Dimension; });
// Show result for above minor diagonal
std::cout << "\n\nAbove minor:\n\n";
std::for_each(array.begin(), array.end(), [o = Dimension](std::vector<int>& v) mutable {
std::copy_n(v.begin() , o, std::ostream_iterator<int>(std::cout, " ")); --o;});
// Show result for below minor diagonal
std::cout << "\n\nBelow minor:\n\n";
std::for_each(array.begin(), array.end(), [o = (Dimension-1)](std::vector<int> & v) mutable {
std::copy(v.begin()+o, v.end(), std::ostream_iterator<int>(std::cout, " ")); --o;});
return 0;
}

Why using std::sort() ) gives me garbage values?

I was trying to solve a problem where I had to sort so I used the standard library std::sort function but I get a wrong output in the 2nd test case:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,i;
cin>>n;
int arr[n-1];
for(i=1;i<=n-1;i++)
cin>>arr[i];
int size=sizeof(arr)/sizeof(arr[1]);
sort(arr,arr+size);
for(i=1;i<=n-1;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
return 0;
}
I/P:
2
5
1 2 5 4
10
1 2 3 4 5 6 7 8 10
Expected O/P:
1 2 4 5
1 2 3 4 5 6 7 8 10
Actual O/P:
1 2 4 5
2 3 4 5 6 7 8 2013562 10
First of all, int arr[n-1]; is a variable length array. That's not actually part of C++, even though some compilers will tolerate it nevertheless. In most cases you can just use std::vector<int>(n-1); instead.
But look at this loop:
for(i=1;i<=n-1;i++)
cin>>arr[i];
You're starting at 1 and got all the way up to n-1, however your array goes from arr[0] to arr[n-2]. So you got undefined behavior because you're writing one past the size of the array, and you also don't write to the first position (leading to more undefined behavior when you try to sort with this uninitialized value still present).
Instead, the loop should be for(i=0;i<n-1;i++) The same applies to where you're printing it. You can then sort the vector this way:
sort(arr.begin(), arr.end());
Also note that by doing n-1 you're always reading in and handling one less value that the user inputs, I'm not sure if that's your intention. If you want that, you could also just decrease n by one after reading it in instead of writing n-1 in multiple places.

How can I sort a map according to a property of its values?

I've created a map having a vector as below:
map<int,vector<int>> mymap;
How can I sort this map according to the nth value of the vector contained by map?
You can't. You can provide a custom comparator to make the underlying data get sorted another way than the default, but this only relates to keys, not values. If you have a requirement for your container's elements to exist in some specific, value-defined order, then you're using the wrong container.
You can switch to a set, and take advantage of the fact that there is no distinction there between "key" and "value", and hack the underlying sorting yourself:
template <std::size_t N>
struct MyComparator
{
typedef std::pair<int, std::vector<int>> value_type;
bool operator()(const value_type& lhs, const value_type& rhs)
{
return lhs.second.at(N) < rhs.second.at(N);
}
};
/**
* A set of (int, int{2,}) pairs, sorted by the 2nd element in
* the 2nd item of each pair.
*/
std::set<std::pair<int, std::vector<int>>, MyComparator<1>> my_data;
int main()
{
my_data.insert(std::make_pair(1, std::vector<int>{0,5,0,0}));
my_data.insert(std::make_pair(2, std::vector<int>{0,2,0,0}));
my_data.insert(std::make_pair(3, std::vector<int>{0,1,0,0}));
my_data.insert(std::make_pair(4, std::vector<int>{0,9,0,0}));
for (const auto& el : my_data)
std::cout << el.first << ' ';
}
// Output: 3 2 1 4
(live demo)
However, if you still need to perform lookup on key as well, then you're really in trouble and need to rethink some things. You may need to duplicate your data or provide an indexing vector.
map<int,vector<int>> mymap;
How can i sort this map according to the nth value of the vector contained by map?
That's only possible if you're prepared to use that nth value as the integer key too, as in consistently assigning:
mymap[v[n - 1]] = v;
If you're doing that, you might consider a set<vector<int>>, which removes the redundant storage of that "key" element - you would then need to provide a custom comparison though....
If you envisage taking an existing populated map that doesn't have that ordering, then sorting its elements - that's totally impossible. You'll have to copy the elements out to another container, such as a set that's ordered on the nth element, or a vector that you std::sort after populating.
If I have understood correctly you can (build) add elements to the map the following way
std::vector<int> v = { 1, 2, 3 };
std::vector<int>::size_type n = 2;
mymap[v[n]] = v;
Here is an example
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <ctime>
int main()
{
std::srand( ( unsigned )time( 0 ) );
const size_t N = 10;
std::map<int, std::vector<int>> m;
for ( size_t i = 0; i < N; i++ )
{
std::vector<int> v( N );
std::generate( v.begin(), v.end(), []{ return std::rand() % N; } );
m[v[0]] = v;
}
for ( auto &p : m )
{
for ( int x : p.second ) std::cout << x << ' ';
std::cout << std::endl;
}
return 0;
}
The output is
0 1 7 8 1 2 9 0 0 9
1 6 3 1 3 5 0 3 1 5
3 8 0 0 0 7 1 2 9 7
5 9 5 0 7 1 2 0 6 3
6 4 7 5 4 0 0 4 2 0
7 9 8 6 5 5 9 9 4 5
8 3 8 0 5 9 6 6 8 3
9 5 4 7 4 0 3 5 1 9
Take into account that as there can be duplicated vectors (that is that have the same value of the n-th element (in my example n is equal to 0) then some vectors will not be added to the map. If you want to have duplicates then you should use for example std::multimap
Also you can build a new map according to the criteria based on an existent map.
You can abuse the fact a c++ map uses a tree sorted by its keys. This means that you can either create a new map, with as keys the values you wish it to be sorted on, but you can also create a vector with references to the items in your map, and sort that vector (or the other way around: you could have a sorted vector, and use a map to create an index on your vector). Be sure to use a multimap in the case of duplicate keys.

std::next_permutation missing one entry

Following program is missing one permutation entry.
#include <iostream>
#include <vector>
#include <algorithm>
int main ( int argc, char **argv) {
std::vector<int> temp;
temp.push_back(10);
temp.push_back(2);
temp.push_back(4);
temp.push_back(4);
do {
std::copy(temp.begin(),temp.end(),std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
}while ( std::next_permutation (temp.begin(), temp.end()));
}
Following is the output of the program
10 2 4 4
10 4 2 4
10 4 4 2
why it is missing one entry which is
2 4 4 10
This is because that permutation is the first ordering for the list of number that you have.
You would need to sort the original array, then this permutation will be listed as the very first one.
std::vector<int> temp;
temp.push_back(10);
temp.push_back(2);
temp.push_back(4);
temp.push_back(4);
std::sort(temp.begin(),temp.end() );
Alternatively, you could just push the elements in sorted order, but for practical purposes, you should always sort if you want to generate all possible permutations.
It's actually missing a few other valid permutations: 2 10 4 4 and 2 4 10 4, and 4 4 10 2 for example.
As to why they are missing: it says, right there in the documentation:
Return value
true if the function could rearrange the object as a lexicographically greater permutation. Otherwise, the function returns false to indicate that the arrangement is not greater than the previous, but the lowest possible (sorted in ascending order).
So the while loop ends after 10 4 4 2, because that is the lexicographically greatest permutation (the one that's "biggest" when you compare them left-to-right, i.e. the one that's in descending order). After printing that one, next_permutation fails to get to the 'next' permutation, and wraps around to the "beginning" permutation of 2 4 4 10; but that is not printed because the function also returned false.