Finding permutation and combination in C++ - c++

I want to find a series of numbers of dynamic length in C++. Suppose I have 2 groups of numbers: arr1[3] = {1, 3, 8} and arr2[4] = {2, 9}, then the expected output is:
'1, 2',
'1, 9',
'3, 2',
'3, 9',
'8, 2',
'8, 9'.
However, if there are 3 groups now : arr1[3] = {1, 3, 8}, arr2[2] = {2, 9} and arr3[5] = {1, 3, 9} then the output should be:
'1, 2, 1',
'1, 2, 3',
'1, 2, 9',
'1, 9, 1',
'1, 9, 3',
'1, 9, 9',
'3, 2, 1',
'3, 2, 3',
'3, 2, 9',
'3, 9, 1',
'3, 9, 3',
'3, 9, 9',
and so on...
So there will 3 x 2 x 3 = 18 outcomes. I got the outcome for 2 groups and 3 groups using respective numbers of for loops.
See this code for 2 groups:
for(int i=1;i<=5;i++) {
for (int j=1;j<=5;j++) {
cout << i << "," << j << "," << endl;
}
}
But then I have to use different codes for different value of group number and have to use switch statement or if-else statement to choose that portion of code.
This will be a great help. Thanks in advance!

I used vector instead of arrays, as they are way easier to deal with.
The trick is to enumerate, in lexicographic order, the positions in the arrays, then display the values at those positions:
#include <vector>
#include <iostream>
using std::vector;
void permutate(vector<vector<int>> values)
{
// the positions in each vector
vector<size_t> pos(values.size());
do
{
// display one of each array at current position
for(size_t i = 0; i < values.size(); ++i)
{
std::cout << values[i][pos[i]] << ", ";
}
std::cout << std::endl;
// increment the last array's display position
size_t p = 0;
pos[p]++;
// while we get to the end of current array, return to 0 and carry to next position
while(pos[p] == values[p].size())
{
pos[p] = 0;
p++;
pos[p]++;
// return when the last array's position get to its size
if (p == values.size())
{
return;
}
}
}
while(true);
}
int main()
{
vector<int> arr1 = {1, 3, 8};
vector<int> arr2 = {2, 9};
vector<int> arr3 = {1, 3, 9};
vector<vector<int>> allThree = {arr1, arr2, arr3};
permutate(allThree);
}
A good exercise, next, would be to template it so you accept std::vector<std::vector<T>>

Related

C++ How to add two arrays of unequal sizes using the for loop?

So the aim is to take two arrays as shown below
int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int k[4] = {1, 2, 3, 4};
and add each element of k to each element of x in a loop as shown
1 2 3 4 5 6 7 8 9 10
+1 +2 +3 +4 +1 +2 +3 +4 +1 +2
This should give us a final array [2, 4, 6, 8, 6, 8, 10, 12, 10, 12].
Any suggestions as to how I could achieve this in C++
Loop through the indexes of the larger array, using the modulus (%) operator to wrap-around the indexes when accessing the smaller array.
int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int k[4] = {1, 2, 3, 4};
int res[10];
for (int i = 0; i < 10; ++i) {
res[i] = x[i] + k[i % 4];
}
Online Demo
With % you can have the wrap-around behavior and with std::size(from C++17 onwards) the size of the array.
#include <algorithm>
#include <iostream>
int main()
{
int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int k[4] = {1, 2, 3, 4};
for(int i = 0; i < std::size(x); ++i)
{
x[i] = x[i] + k[i%std::size(k)];
}
//lets confirm if x has the right elmennts
for(const int& element: x)
{
std::cout<< element<<std::endl;
}
}
Note that here i have not used a separate array to store the resulting array. Instead the elements are added into the original array x. Storing the result in a new array is trivial.

Creating all possible combinations sorted by sum

Given an arbitrary set of numbers S = {1..n} and size k, I need to print all possible combinations of size k ordered by the sum of the combinations.
Let's say S = {1, 2, 3, 4, 5} and k = 3, a sample output would be:
1 2 3 = 6
1 2 4 = 7
1 2 5 = 8
1 3 4 = 8
1 3 5 = 9
2 3 4 = 9
2 3 5 = 10
1 4 5 = 10
2 4 5 = 11
3 4 5 = 12
The first idea that came to my mind is to sort S (if not already sorted) and then perform a BFS search, having a queue of combinations sorted by sum. This is because I want to generate the next combination only if requested (iterator like). But this seems like an overkill and I think that there should be an easier solution. How can this be solved?
Edit:
This is my original idea:
1. Sort S
2. Pick the first k numbers and add them to the queue as a single node (because this is the combination with the smallest sum)
3. While the queue is not empty - pop the first node, output it, and generate successors.
Generating successors:
1. Start with the first number in the node. Make a copy of a node. Find the smallest unselected value that is > than the number, and assign this value.
2. Verify that this node hasn't been seen and calculate the sum.
3. Add the node to the queue.
4. Repeat 1-3 for all of the remaining numbers in the node.
Example:
Queue q = { {1, 2, 3} = 6 }
Pop front, output
1 2 3 = 6
Generate {4, 2, 3} = 9, {1, 4, 3} = 8, {1, 2, 4} = 7
Seen { {1, 2, 3}, {4, 2, 3}, {1, 4, 3}, {1, 2, 4} }
Queue q = { {1, 2, 4} = 7, {1, 4, 3} = 8, {4, 2, 3} = 9 }
Pop front, output
1 2 3 = 6
1 2 4 = 7
Generate {3, 2, 4} = 9 (seen - discard), {1, 3, 4} = 8 (seen - discard), {1, 2, 5} = 8 }
Seen { {1, 2, 3}, {4, 2, 3}, {1, 4, 3}, {1, 2, 4}, {1, 2, 5} }
Queue q = { {1, 2, 5} = 8, {1, 4, 3} = 8, {4, 2, 3} = 9 }
Pop front, output
1 2 3 = 6
1 2 4 = 7
1 2 5 = 8
Generate {3, 2, 5} = 10, {1, 3, 5} = 9
Seen { {1, 2, 3}, {4, 2, 3}, {1, 4, 3}, {1, 2, 4}, {1, 2, 5}, {3, 2, 5}, {1, 3, 5} }
Queue q = { {1, 4, 3} = 8, {1, 5, 3} = 9, {1, 3, 5} = 9, {3, 2, 5} = 10, {1, 4, 5} = 10, {4, 2, 5} = 11 }
...
...
javascript sample like below;
<!DOCTYPE html>
<html>
<head>
<meta charset = utf-8>
<title>s{1..n} by k</title>
</head>
<body>
<header>s{1..n} by k</header>
<form action="#" onsubmit="return false;">
s:<input type="text" id="sArrayObj" name="sArrayObj" value="4 5 1 8 9 3 6 7"/><br/>
n:<input type="text" id="kVarObj" name="kVarObj" value="3"/><br/>
<button id="scan" name="scan" onclick="scanX()"> CALCULATE </button><br/>
<textarea id="scanned" name="scanned" cols=40 rows=20>
</textarea>
</form>
<script>
const headFactorial = n => {
if ( n > 1 ) return n * headFactorial( n - 1 );
else return 1;
}
const tailFactorial = n => {
if ( n === 1 ) return 1;
else return n * tailFactorial( n - 1 );
}
const combinations = ( collection, combinationLength ) => {
let head, tail, result = [];
if ( combinationLength > collection.length || combinationLength < 1 ) { return []; }
if ( combinationLength === collection.length ) { return [ collection ]; }
if ( combinationLength === 1 ) { return collection.map( element => [ element ] ); }
for ( let i = 0; i < collection.length - combinationLength + 1; i++ ) {
head = collection.slice( i, i + 1 );
tail = combinations( collection.slice( i + 1 ), combinationLength - 1 );
for ( let j = 0; j < tail.length; j++ ) { result.push( head.concat( tail[ j ] ) ); }
}
return result;
}
const sumArr = (anArr) => {
var s=0;
for (j=0; j < anArr.length; j++) s += 1*anArr[j];
return s;
}
function scanX(){
sArray = document.getElementById("sArrayObj").value.split(" ");
kVar = document.getElementById("kVarObj").value;
sArray.sort();
resultObj= document.getElementById("scanned");
resultObj.value = "";
//for (i=0;kVar > i;i++){
// resultObj.value+=sArray[i]+' ';
//}
resultArr = combinations(sArray, kVar);
for (i=0;i<resultArr.length;i++){
resultObj.value += resultArr[i]+"="+sumArr(resultArr[i])+"\n";
}
return false;
}
</script>
</body>
</html>

Trying to find the minimum element of 2D vector with lambda

I'm currently trying to find the minimum element of a 2D vector. I'm trying to practice using C++11 lambda functions and figured this might be good practice, but can't seem to get it compiling.
I'm aware that I could do the following:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int result = std::numeric_limits<int>::max();
for(const auto& row : matrix)
{
int minElemInRow = *std::min_element(row.begin(), row.end());
result = std::min(result , minElemInRow);
}
return result;
but was wondering if the same could be done with a lambda function. Currently, this is my best attempt:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
return *std::min_element(matrix.begin(), matrix.end(),
[](const auto& row)
{
return *std::min_element(row.begin(), row.end());
});
I get the error: error C2672: 'operator __surrogate_func': no matching overloaded function found
How I feel it should be working is that the outer min_element will pass in a row at a time (which is just a reference to a vector), from which I can return the smallest, which will then be compared against other rows.
I thought that the problem might be that the lambda would be receiving an iterator to a vector of ints rather than a reference to the vector of ints, but dereferencing doesn't seem to be helping.
Is there a better way to be doing what I'm trying to do?
#assembly_wizard pointed out that min_element wants a predicate which can compare two of the item passed it. That is two rows. This leads to the following code:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
auto i = std::min_element(matrix.begin(), matrix.end(),
[](const auto& lhs, const auto& rhs)
{
return *std::min_element(lhs.begin(), lhs.end()) <
*std::min_element(rhs.begin(), rhs.end());
});
This will find the row with the smallest element. Though I can make that work by wrapping it in yet another std::min_element, that's getting way more complex than to be remotely helpful. If anyone has a better suggestion, I'd love to hear it!
I've compiled a working version that does what I've mentioned in the comments:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
std::vector<int> row_minimums(matrix.size());
std::transform(matrix.begin(), matrix.end(), row_minimums.begin(), [](const auto& row) {
return *std::min_element(row.begin(), row.end());
});
auto i = *std::min_element(row_minimums.begin(), row_minimums.end());
std::cout << "Minimum element is: " << i << std::endl;
}
See it in action on godbolt
This will take the minimum of each row separately, so we get row_minimums which is a vector of ints, and then it takes the minimum of these to get the final result between all the rows.
The only thing making this code worse than the for loop version, is that it keeps all of the row_minimums in memory at once, before running min_element on them. Unfortunately I don't know of a way to do this simultaneously, but I'm not the greatest STL expect, so maybe there is a way.
Other options you might consider is first concatenating the 2D matrix into a 1D vector and then using min_element on it, or the option you've included in your edit where you call min_element 3 times.
Also, this SO answer seems to have interesting info regarding solutions using the boost library which might be better, but I'm not sure exactly what they are.
Just a little simpler:
With std::for_each you iterate over each vector in matrix, and obtain the minimum element of them. As min is captured by reference, you get the min of all of them.
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int min = std::numeric_limits<int>::max();
std::for_each(matrix.begin(), matrix.end(),
[&min](const auto& v)
{
min = std::min(*min_element(v.begin(), v.end()), min);
}
);
std::cout << "Minimum element is: " << min << std::endl;
}

generating a set of sets that appear in every set

I have an array of arrays of things
typedef std::vector<thing> group;
std::vector<group> groups;
things could be compared like so
int comparison(thing a, thing b);
where the return value is 0, 1 or 2
0 means that the things are not alike
1 means that they are alike and a is more specific or equal to b
2 means that they are alike and b is more specific or equal to a
and I am looking for a function that would return me a group that contains all things that appear in every group.
std::getgroup(groups.begin(), groups.end(), myComparisonFunction);
the problem is I have no idea what this function may be called, if it does even exist, or what the closest thing to it would be.
Eventually, what you want is an intersection. Luckily, there is std::set_intersection which almost does what you need. Here's a simple example on std::vector<std::vector<int>>. You can easily change it to work with your thing:
#include <iostream>
#include <vector>
#include <algorithm>
std::vector<int> getGroup(const std::vector<std::vector<int>>& groups) {
std::vector<int> group;
std::vector<int> temp = groups[0];
std::sort(temp.begin(), temp.end());
for ( unsigned i = 1; i < groups.size(); ++i ) {
group = std::vector<int>();
std::vector<int> temp2 = groups[i];
std::sort(temp2.begin(), temp2.end());
std::set_intersection(temp2.begin(), temp2.end(),
temp.begin(), temp.end(),
std::back_inserter(group));
temp = group;
}
return group;
}
int main() {
std::vector<std::vector<int>> groups = { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{1, 2, 3, 5, 6, 7, 8, 10},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{1, 3, 4, 5, 6, 9, 10},
{1, 2, 6, 7, 8, 9, 10},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} };
for ( auto g : getGroup(groups) )
std::cout << g << "\n";
return 0;
}
This will print:
1
6
10

c++ - Arranging vector elements in a specific order

I'm beginning programming, so sorry for my lack of knowledge.
How can I set elements in vector in a specific order? I would like to swap elements in the way that there won't be same elements next to each other.
For example vector contains:
{1, 2, 2, 2, 3, 3, 4, 4, 4}
and I'd like it to be like:
{1, 2, 4, 3, 4, 2, 3, 2, 4}
Thanks for help.
edit:
Hello again, I found not the best solution, maybe you can take a look and correct it?
map<unsigned,unsigned> Map;
for(vector<unsigned>::iterator i=V.begin();i!=V.end();++i)
{
map<unsigned,unsigned>::iterator f=Map.find(*i);
if(f==Map.end()) Map[*i]=1;
else ++f->second;
}
for(bool more=true;more;)
{
more=false;
for(map<unsigned,unsigned>::iterator i=Map.begin();i!=Map.end();++i)
{
if(i->second)
{
--i->second;
cout<<i->first<<", ";
more=true;
}
}
}
Now, for { 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 } it gives me { 1, 2, 3, 4, 2, 3, 4, 2, 4, 4, 4, 4 } instead of e.g { 4, 1, 4, 2, 4, 3, 4, 2, 4, 3, 4, 2 }. How can it be done? Thanks
credits: _13th_Dragon
Count the occurrences of each value.
Starting with the most-frequent value, alternate it with less-frequent values.
In order to achieve (1), one can simply use std::map<V, unsigned>. However, for the second, one needs an ordered set of std::pair<V, unsigned int>, ordered by the second value. Since we want to keep track of how many times we need to use a given value, the second value cannot be constant. Also, we don't want to change the order if we happen to decrease the count of a given value much. All in all we get
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
// In the pair, first is the original value, while
// second is the number occurrences of that value.
typedef std::pair<int, unsigned> value_counter;
int main(){
std::vector<int> sequence = { 0, 1, 3, 3, 4, 1, 2, 2, 2, 2 , 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 };
std::map<int, unsigned> count;
for( auto i : sequence){
count[i]++;
}
std::vector<value_counter> store( count.size() );
std::copy(count.begin(), count.end(), store.begin());
// Sort by the second value
std::sort(store.begin(), store.end(),
[](const value_counter& a, const value_counter& b){
return a.second > b.second;
});
std::vector<int> result;
// We need two indices, one for the current value
// and the other one for the alternative
for(unsigned i = 0, j = 1; i < store.size(); ++i){
while(store[i].second > 0){
result.push_back(store[i].first);
store[i].second--;
if(store[i].second == 0)
continue;
if( j <= i)
j = i + 1;
while(j < store.size() && store[j].second == 0)
++j;
if(j >= store.size()){
std::cerr << "Not enough elements for filling!" << std::endl;
return 1;
}
else {
result.push_back(store[j].first);
store[j].second--;
}
}
}
for( auto r : result){
std::cout << r << " ";
}
}
Instead of using a typedef you could create an alternative counter which has better names than first and second, but that makes copying from the map a little bit more verbose.