How to print array elements above and below minor dioganal? - c++

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;
}

Related

iter_swap yields wrong result

#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);

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 detect all possible subsets from a given vector?

I'm writing a function which should detect all possible subsets from a main vector and push them to another vector. The elements in the subsets are also added to each other before being pushed into the new vector(s1).
At the moment what my code does is the following..
For example, lets say myvec = {1,2,3}, then v1 = {1,3,6,2,5,3}. It only sums consecutive numbers. However I also want it to sum up combinations like 1 & 3 which would add a 4 to the vector v1. At the moment, I have not been able to modify my algorithm in a way that I can achieve that. Any help will be appreciated!
for (k=0; k<myvec.size(); k++) {
total = 0;
for (m=k; m<int_vec.size(); m++) {
total += myvec[m];
v1.push_back(total);
}
}
One way to think about the power set of a given (ordered) set is to think of its elements (the subsets) as bit vectors where the n-th bit is set to 1 if and only if the n-th element from the set was chosen for this subset.
So in your example, you'd have a 3 bit vector that could be represented as an unsigned integer. You'd “count the bit vector” up from 0 (the empty set) to 7 (the entire set). Then, in each iteration, you pick those elements for which the respective bit is set.
As can be readily seen, the power set explodes rapidly which will make it impractical to compute explicitly for any set with more than a dozen or so elements.
Casting these thoughts into C++, we get the following.
#include <climits> // CHAR_BIT
#include <iostream> // std::cout, std::endl
#include <stdexcept> // std::invalid_argument
#include <type_traits> // std::is_arithmetic
#include <vector> // std::vector
template<typename T>
std::vector<T>
get_subset_sums(const std::vector<T>& elements)
{
static_assert(std::is_arithmetic<T>::value, "T must be arithmetic");
if (elements.size() > CHAR_BIT * sizeof(unsigned long))
throw std::invalid_argument {"too many elements"};
const std::size_t power_size {1UL << elements.size()};
std::vector<T> subset_sums {};
subset_sums.reserve(power_size);
for (unsigned long mask = 0UL; mask < power_size; ++mask)
{
T sum {};
for (std::size_t i = 0; i < elements.size(); ++i)
{
if (mask & (1UL << i))
sum += elements.at(i);
}
subset_sums.push_back(sum);
}
return subset_sums;
}
int
main()
{
std::vector<int> elements {1, 2, 3};
for (const int sum : get_subset_sums(elements))
std::cout << sum << std::endl;
return 0;
}
You might want to use a std::unordered_set for the subset-sums instead of a std::vector to save the space (and redundant further processing) for duplicates.
The program outputs the numbers 0 (the empty sum), 1 (= 1), 2 (= 2), 3 (= 1 + 2), 3 (= 3), 4 (= 1 + 3), 5 (= 2 + 3) and 6 (= 1 + 2 + 3). We can make this more visual.
mask mask
(decimal) (binary) subset sum
–––––––––––––––––––––––––––––––––––––––––––––––––
0 000 {} 0
1 001 {1} 1
2 010 {2} 2
3 011 {1, 2} 3
4 100 {3} 3
5 101 {1, 3} 4
6 110 {2, 3} 5
7 111 {1, 2, 3} 6

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.