Recurssion issue in generating permutation in c++ - c++

i have two n in c++ and i want to generate permutation of the numbers in those vectors in such a way for each permutation of the first vector i have all the permutations of all the other vectors.
Say i have two vectors with number 2 9 and the other vector will be 5 6. then my result should be...
2 9 5 6
2 9 6 5
9 2 5 6
9 2 6 5
means that the total number of permutations i have got will be
total perms = (# of permutations of the 1st vector times number of permutations of the second vector times number of permutations of the third vector and so on).
I have written the below code and i am struck in to recursion stack... It is actually printing 6 times for the case of 2 vectors each have the size of 2 each.
mySwap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
}
swaps the two int elements
void myPerm(vector<vector<int>> myItems, int start, int end,int vectorIndex){
int j;
if(start == end){
for(int k = vectorIndex +1; k < items.size(); ++k){
myPerm(myItems, 0, myItems[k].size()-1,k);
}
for(int z = 0; z < myItems.size(); ++z){
for(int l = 0; l < myItems[z].size(); ++z){
std::cout << myItems[z][l];
}
}
}
else{
for(int j = start; j <= end; j++){
mySwap(&myItems[vectorIndex][start],&myItems[vectorIndex][j]);
myPerm(myItems,start + 1, end,vectorIndex);
mySwap(&myItems[vectorIndex][start],&myItems[vectorIndex][j]);
}
}
}
above code that generates permutations recursively...
int main(){
vector<vector<int>> myItems;
int k = 0;
for(int i =0; i < 2; ++i){
myItems.push_back(vector<int>);
}
for(int j =0; j < 2; ++j){
myItems[i].push_back(k++);
}
myPerm(items,0,items[0].size()-1,0);
return;
}
my main function.
Please give me some hint or solve this this for the generic case as the above code prints the permutations for the six which originally should be 4 times.
Thanks

Considering this is not a homework you can simply use stl algorithm next_permutation instead of what you have.
This is the code for your sample input.
int main()
{
std::vector<int> v1 , v2 , v3;
v1.push_back( 2 );
v1.push_back( 9 );
v2.push_back( 5 );
v2.push_back( 6 );
std::sort( v1.begin() , v1.end() );
std::sort( v2.begin() , v2.end() );
do
{
v3 = v2;
do
{
std::for_each( v1.begin() , v1.end() , [](int x) { std::cout << x << " ";} );
std::for_each( v3.begin() , v3.end() , [](int x) { std::cout << x << " ";} );
std::cout << std::endl;
}
while ( std::next_permutation(v3.begin() , v3.end() ) );
}
while ( std::next_permutation(v1.begin() , v1.end() ) );
return 0;
}
This does it for two vectors... I am sure you can generalize it further.

Thanks for all the ideas specially for the STL function next_permutation. I don't know it earlier.
I was able to write the code i want it correctly...
Here is my code
void perm(std::vector<std::vector <int>> &items, int level){
if(level == 0){
for (int i = 0; i < items.size(); i++)
for (int j = 0; j < items[i].size(); j++)
std::cout << items[i][j];
std::cout<<std::endl;
while(next_permutation(items[level].begin(), items[level].end())){
for (int i = 0; i < items.size(); i++)
for (int j = 0; j < items[i].size(); j++)
std::cout << items[i][j];
std::cout<<std::endl;
}
}
else{
if(level > 0)
perm(items,level-1);
while(next_permutation(items[level].begin(), items[level].end())){
if(level > 0)
perm(items,level-1);
}
}
}

For this problem recursion could be omitted entirely by using next_permutation. Here's some untested code that is arguably more elegant:
void myPerm(std::vector<std::vector<int>>& myItems)
{
for (int i = 0; i < myItems.size(); i++)
std::sort(myItems[i].begin(), myItems[i].end());
int level;
do
{
printAll(myItems);
level = myItems.size() - 1;
while (!next_permutation(myItems[level].begin(), myItems[level].end()))
level--;
}
while (level >= 0);
}
Nice thing about next_permutation is that it returns false as it "wraps around" given set, and so the set is sorted and ready for the next round of permutations.

Related

Trying to make a simple Array sorter with input numbers

I'm very new to C++ or even coding. I was trying to make a simple array sorter, where the I first input the number of elements that will be in the array and then input the elements. My outcome should be the array sorted in ascending order. I have not thought about the case if elements inserted are same. So I would love to get some help from you folks.
The main error that I'm facing is that only the first unsorted element is sorted while the rest are either interchanged or left the same.
int main(){
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
for (int i = 0;i<x;i++){
cin>>A[i];
}
for(int i=0;i<x;i++)
cout<<A[i]<<",";
int count=0;
if(count <= (x-1)){
for (int i=0;i<(x-1);i++){
if(A[i]>A[i+1]){
int a;
a = A[i];
A[i] = A[(i+1)];
A[i+1] = a;
}
else if(A[i]<A[i+1])
count++;
}
}
cout<<"Sorted array:";
for(int i=0;i<x;i++)
cout<<A[i]<<",";
return 0;
}
You declared a variable length array
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
because its size is not a compile-time constant.
However variable length arrays are not a standard C++ feature though some compilers have their own language extensions that support variable length arrays,
It is better to use the class template std::vector.
Another problem is that it seems you are trying to use the bubble sort method to sort the array. But this method requires two loops.
Here is a demonstration program that shows how the bubble sort algorithm can be implemented.
#include <iostream>
int main()
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( a ) / sizeof( *a );
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
for (size_t last = N, sorted = N; not ( last < 2 ); last = sorted)
{
for (size_t i = sorted = 1; i < last; i++)
{
if (a[i] < a[i - 1])
{
// std::swap( a[i-1], a[i] );
int tmp = a[i - 1];
a[i - 1] = a[i];
a[i] = tmp;
sorted = i;
}
}
}
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Let us try the following method:
find the largest element in the array and move it to the end, by swapping with the last element;
repeat with the array but the last element, and so on.
To find the largest element in A[0..m-1], scan the array and keep an index to the largest so far, let l. This index can be initialized to 0.
// Move the largest to the end
int l= 0;
for (int i= 1; i < m; i++)
{
if (A[i] > A[l]) l= i;
}
// A[l] is the largest in A[0..m-1]
Swap(A[l], A[m-1]);
// A[m-1] is the largest in A[0..m-1]
To sort, repeat with decreasing m. You can stop when the subarray just holds one element:
// Sort
for (int m= n-1; m > 1; m--)
{
// Move the largest to the end
....
}
Writing the Swap operation and assembling the whole code is your task. Also check
correctness of the Move for the limit cases m= 0, 1, 2.
correctness of the Sort for the limit cases n= 1, 2, 3.
how you could instrument the code to verify that the Move does its job.
how you could instrument the code to verify that the Sort does its job.
what happens in case of equal keys.
Your code can be fixed a bit to make it working.
Just replace if (count <= (x - 1)) with while (count < (x - 1)) and also set count = 0; at start of loop, plus replace else if (A[i] < A[i + 1]) with just else. And your code becomes working!
Necessary fixes I did in code below. Also I did formatting (indents and spaces) to make code looks nicer. Rest remains same.
As I see you have a kind of Bubble Sort.
Try it online!
#include <iostream>
using namespace std;
int main() {
int x;
cout << "Enter no. of elements" << endl;
cin >> x;
int A[x];
for (int i = 0; i < x; i++) {
cin >> A[i];
}
for (int i = 0; i < x; i++)
cout << A[i] << ",";
int count = 0;
while (count < (x - 1)) {
count = 0;
for (int i = 0; i < (x - 1); i++) {
if (A[i] > A[i + 1]) {
int a;
a = A[i];
A[i] = A[(i + 1)];
A[i + 1] = a;
} else
count++;
}
}
cout << "Sorted array:";
for (int i = 0; i < x; i++)
cout << A[i] << ",";
return 0;
}
Input:
10
7 3 5 9 1 8 6 0 2 4
Output:
7,3,5,9,1,8,6,0,2,4,Sorted array:0,1,2,3,4,5,6,7,8,9,
If you are taking the size of array as input from user you have to create your array dynamically in c++ like
int *array=new int(x)
and after taking the inputs of the elements just run a nested loop from 0 to size and
the inner loop from 0 to size-1 and check if(A[i]>A[i+1]) if true then swap the values else continue

How to get top 3 values from a vector smaller than a particular value?

I have a vector {42.195 42.195 39.025 40.075 34.220 42.195 39.750}. Here I want to get top 3 values just smaller than 42.195. Below is my approach.
I sorted the vector in descending order.
Initialize an output vector and a counter=0.
Then I traversed through the vector and checked if an element is not equal to 42.195. If it is so, increment the counter. If counter value is <= 3, push that element in the output vector. Once the counter value becomes greater than 3, break out of the for loop and return the output vector.
The above approach looks logically fine, but the code is not working fine while comparing each element with 42.195 value. Please help me.
#include<bits/stdc++.h>
#include<vector>
using namespace std;
int validateData(vector<float> &arr){
for(int i = 0 ; i < arr.size() ; i++){
if(arr[i] <= 0.0){
cout<<"\nInvalid data";
return -1;
}
}
return 0;
}
vector <float> getTop3(vector<float>& arr){
if(validateData(arr) == -1)
cout<<"\nCannot perform operation";
else {
vector<float> output;
int count = 0;
cout<<"Sorted values are: \n";
sort(arr.begin(), arr.end(), greater<float>());
for(int i = 0 ; i < arr.size() ; i++){
cout<<arr[i]<<" ";
}
for(int i = 0 ; i < arr.size() ; i++){
if(arr[i] != 42.195) {
count++;
if(count <= 3)
output.push_back(arr[i]);
else
break;
}
}
cout<<"\nOutput vector is\n";
for(int i = 0 ; i < output.size() ; i++){
cout<<output[i]<<" ";
}
return output;
}
}
int main(int argc, char *argv[]){
vector<float> arr;
cout<<"Arguments are:\n";
for(int i = 1 ; i < argc ; i++){
arr.push_back(stof(argv[i]));
}
for(int i = 0 ; i < arr.size() ; i++){
cout<<arr[i]<<" ";
}
cout<<"\n";
//Function call
getTop3(arr);
}
Below is the output.
std::partition followed by std::nth_element can do the job:
std::vector<float> get_top3(std::vector<float> v, float threshold)
{
auto end = std::partition(v.begin(), v.end(), [&](auto f){ return f < threshold; });
if (std::distance(v.begin(), end) <= 3) return {v.begin(), end};
std::nth_element(v.begin(), v.begin() + 3, end, std::greater<>{});
return {v.begin(), v.begin() + 3};
}
int main() {
std::vector<float> arr = {42.195, 42.195, 39.025, 40.075, 34.220, 42.195, 39.750};
for (auto f : get_top3(arr, 42.195))
std::cout << f << " ";
}
Demo
One of your issue is that: 42.195 != 42.195f.

Finding majority element in an array ( getting wrong output for particular cases with long integer input)

I was solving a Majority_element problem, where I would be provided an int 'n' followed by an array whose size is n, as input. If any element's frequency in the array is more than n/2, then return 1, otherwise, return 0. Now, my program works correctly for small values of integer elements, but it's giving a false output for bigger int values.
Here's the source code
#include <algorithm>
#include <iostream>
#include <vector>
using std::vector;
int get_majority_element(vector<int> &a) {
int count{};
std::sort(a.begin(),a.end());
for( size_t i{}; i<a.size() ; ++i ){ //counter
for( size_t j = i+1 ; j<a.size() ; ++j ){
if( a.at(i) == a.at(j) ){
count += 1; // may have to inclue a count nullifier if two elements are repeated
}
}
}
if( count > ( a.size()/2 ) ){
return 1;
}
else {
return 0;
}
}
int main() {
int n;
std::cin >> n;
vector<int> a(n);
for (size_t i = 0; i < a.size(); ++i) {
std::cin >> a.at(i);
}
std::cout << get_majority_element(a) << '\n';
return 0;
}
Here are some outputs
6
1 1 1 2 3 4
0
6
1 1 1 1 2 3
1
10
512766168 717383758 5 126144732 5 573799007 5 5 5 405079772
1 ( should be 0)
Now could somebody please explain to me what's going wrong? I even tried setting vector data type to long long to prevent potential memory leaks.
As you do,
you don't need std::sort.
you need to reset count.
check should be done in outer loop
bool get_majority_element(const vector<int> &a) {
for (size_t i{}; i < a.size() ; ++i) {
int count{};
for (size_t j = i+1 ; j<a.size() ; ++j) {
if (a.at(i) == a.at(j)){
count += 1;
}
}
if (count > ( a.size()/2 )) {
return true;
}
}
return false;
}
or
bool get_majority_element(const vector<int> &a) {
for (size_t i{}; i < a.size() ; ++i) {
if (std::count(a.begin() + i, a.end(), a[i]) > a.size() / 2) {
return true;
}
}
return false;
}
Complexity: O(n²).
Once sorted, equal elements are adjacent, so you don't need to check each element:
bool get_majority_element(vector<int> &a) {
std::sort(a.begin(), a.end());
for (auto it = a.begin(); it != a.end(); /*empty*/) {
auto next = std::find_if(it, a.end(), [&](int n){ return n != *it; });
if (std::distance(it, next) > a.size() / 2) {
return true;
}
it = next;
}
return false;
}
Complexity: O(n lon n).
For info, there exist also an algorithm to do it linearly which consist to find possible candidate, and then check it.

minimizing memory use in c++

I was working on a problem in codeforces and I have no problems in the functionality of the code but the code exceeds the memory usage. Can someone explain how to improve this? How to learn about memory management in general while programming because I didn't find anything related to that. Here's my code :
Summary of the problem: You are given 6 input numbers, the first 5 numbers should be multiplied each by another integer and the summation of them after multiplication is the sixth integer in the input. You should find all the combinations of the numbers the can be multiplied by each value in the input to seek the summation. the output is basically the sum of the integers chosen for each number in the input to be multiplied by.
#include <iostream>
#include <vector>
#ifndef MAX
#define MAX 100
#endif
using namespace std;
void storeAndFilter(vector <int> &arr,int chosenNumConst, int mypasha);
void print(vector<int> &v);
int printsum(vector<int> &v);
int main(int argc, char const *argv[])
{
//array of input options
int a1, a2, a3, a4, a5, pasha;
cin >> a1 >> a2 >> a3 >> a4 >> a5 >> pasha;
//declarations of vectors
vector<int> arrStrA1;
vector<int> arrStrA2;
vector<int> arrStrA3;
vector<int> arrStrA4;
vector<int> arrStrA5;
//sorting and filtering the vectors
storeAndFilter(arrStrA1,a1,pasha);
storeAndFilter(arrStrA2,a2,pasha);
storeAndFilter(arrStrA3,a3,pasha);
storeAndFilter(arrStrA4,a4,pasha);
storeAndFilter(arrStrA5,a5,pasha);
//cout<<"All Posibilities valid (Minimized by removing values < pasha) : "<<endl;
// print (arrStrA1);
// print (arrStrA2);
// print (arrStrA3);
// print (arrStrA4);
// print (arrStrA5);
//scores vectors
vector<int> resultsA1;
vector<int> resultsA2;
vector<int> resultsA3;
vector<int> resultsA4;
vector<int> resultsA5;
int i,j,k,l,m;
for (i=0; i < (int)arrStrA1.size(); ++i)
{
for (j=0; j < (int)arrStrA2.size(); ++j)
{
for (k=0; k < (int)arrStrA3.size(); ++k)
{
for (l=0; l < (int)arrStrA4.size(); ++l)
{
for (m=0; m < (int)arrStrA5.size(); ++m)
{
if(arrStrA1.at(i)+arrStrA2.at(j)+arrStrA3.at(k)+arrStrA4.at(l)+arrStrA5.at(m)==pasha)
{
resultsA1.push_back(arrStrA1.at(i));
resultsA2.push_back(arrStrA2.at(j));
resultsA3.push_back(arrStrA3.at(k));
resultsA4.push_back(arrStrA4.at(l));
resultsA5.push_back(arrStrA5.at(m));
}
}
}
}
}
}
//divise each term by the card value
for (int i = 0; i < (int)resultsA1.size(); ++i)
{
if (a1==0)
resultsA1.at(i) /= 1;
else
resultsA1.at(i) /= a1;
}
for (int i = 0; i < (int)resultsA2.size(); ++i)
{
if (a2==0)
resultsA2.at(i) /= 1;
else
resultsA2.at(i) /= a2;
}
for (int i = 0; i < (int)resultsA3.size(); ++i)
{
if(a3==0)
resultsA3.at(i) /= 1;
else
resultsA3.at(i) /= a3;
}
for (int i = 0; i < (int)resultsA4.size(); ++i)
{
if (a4==0)
resultsA4.at(i) /= 1;
else
resultsA4.at(i) /= a4;
}
for (int i = 0; i < (int)resultsA5.size(); ++i)
{
if(a5==0)
resultsA5.at(i) /= 1;
else
resultsA5.at(i) /= a5;
}
//Uncomment to show the table list after division
// print(resultsA1);
// print(resultsA2);
// print(resultsA3);
// print(resultsA4);
// print(resultsA5);
int scra1=printsum(resultsA1);
int scra2=printsum(resultsA2);
int scra3=printsum(resultsA3);
int scra4=printsum(resultsA4);
int scra5=printsum(resultsA5);
cout << scra1 <<" "<< scra2 <<" "<< scra3 <<" "<<scra4 <<" "<< scra5 <<endl;
return 0;
}
void print(vector<int> &v)
{
int size = v.size();
cout<<"========================"<<endl;
for (int i = 0; i < size; ++i)
cout<<v.at(i)<<endl;
cout<<"========================"<<endl;
}
int printsum(vector<int> &v)
{
int sum =0;
for (int i = 0; i < (int)v.size(); ++i)
sum += v.at(i);
return sum;
}
void storeAndFilter(vector <int> &arr,int chosenNumConst, int mypasha)
{
arr.reserve(10);
int i=0;
for (; i <= MAX; ++i)
{
arr.push_back(i*chosenNumConst);
if (arr.at(i)>mypasha)
break;
}
arr.resize(i);
}
Some stuff that I thought about:
Arrays instead of Vectors maybe better
The nested for loops may be the one that is taking too much memory
But to be clear, the nested for loops doesn't make too much calculations, they find all the combinations of 5 numbers '5 loops' to sum to a specific value. Filtering before entering the loop is applied so maybe the nested loop isn't the issue.
Max memory constrain in the problem is: 256 MB
You can use much less memory by not using all those vectors. You can just write your code like this:
// make sure we handle zero properly
auto end = [&](int num){
return num == 0 ? num : pasha/num;
};
for (auto i=0, end_i = end(a1); i <= end_i; ++i)
{
for (auto j=0, end_j = end(a2); j <= end_j; ++j)
{
for (auto k=0, end_k = end(a3); k <= end_k; ++k)
{
for (auto l=0, end_l = end(a4); l <= end_l; ++l)
{
for (auto m=0, end_m = end(a5); m <= end_m; ++m)
{
if(a1*i+a2*j+a3*k+a4*l+a5*m==pasha)
{
std::cout << i << " " << j << " " << k << " " << l << " " << m << "\n";
}
}
}
}
}
}
and it outputs all the valid results. For Example for the input 0 2 3 4 5 6 it produces
0 0 2 0 0
0 1 0 1 0
0 3 0 0 0
See working example here

Filter out duplicate values in array in C++

I have a row of ten numbers for example:
5 5 6 7 5 9 4 2 2 7
Now I want a program that finds all duplicates and gives them out in the console like 3 times 5, 2 times 2, 2 times 7.
While I did code an algorithm that finds duplicates in a row of numbers I can't give them out in the console as described. My program will output:
3 times 5
2 times 5
2 times 7
2 times 2
How can I solve this problem?
#include <iostream>
using namespace std;
int main()
{
int arr[10];
int i,j;
int z = 1;
for(i = 0; i < 10; i++) {
cin >> arr[i];
}
for(i = 0; i < 10; i++){
for(j = i+1; j < 10; j++){
if(arr[i] == arr[j]){
z++;
}
}
if(z >= 2){
cout << z << " times " << arr[i] << endl;
z = 1;
}
}
return 0;
}
You can use the STL here (C++11):
int arr[10];
std::map<int, int> counters;
for (auto item : arr)
{
cin >> item;
++counters[item];
}
std::for_each(counters.begin(), counters.end(), [](const std::pair<int,int>& item)
{
if(item.second > 1) std::cout << item.second << " times " << item.first << std::endl;
});
You need to check that arr[i] is not already found before, like this for example:
if(z >= 2) {
int found_before = 0;
for(j = 0; j < i; ++j)
if(arr[i] == arr[j])
found_before = 1;
if(!found_before)
cout << z << " times " << arr[i] << endl;
z = 1;
}
which will print:
3 times 5
2 times 7
2 times 2
That way you don't print 5 again.
With your code it would print that it found 5 three times (for the first 5 in your array), and then when it would move to he second 5 in your array, it would forgot about the first 5 in your array, and report that it found 5 twice (itself and the 5th number of the array).
Why not use STL?
std::map<int, int> counter;
for (i = 0; i < 10; i++)
counter[arr[i]] ++;
for (i = 0; i < 10; i++) {
if (counter.count(arr[i]) > 0){
std::cout << counter[arr[i]] << " times "<< arr[i] << std::endl;
counter.erase(arr[i]);
}
}
std::map is a convenient tool for this job. You can easily count up occurrences of a specific number. After counting, you can print the count of each array element. With counter.erase, it's guaranteed that you won't print the same element for multiple times.
Why keeping your algorithm idea, I suggest to create sub method:
std::size_t count(const int* arr, std::size_t start, std::size_t end, int value)
{
std::size_t res = 0;
for (std::size_t i = start; i != end; ++i) {
if (arr[i] == value) {
++res;
}
}
return res;
}
then your fixed algorithm would be:
for (std::size_t i = 0; i != 10; ++i) {
if (count(arr, 0, i, arr[i]) != 0) {
continue; // Already visited
}
auto total = count(arr, i, 10, arr[i]);
if(total >= 2){
std::cout << z << " times " << arr[i] << std::endl;
}
}
An easy way is to make another array for it, especially if the numbers are not that big.
Lets say you have initialized your array like so: int nums[10] = { 5, 5, 6, 7, 5, 9, 4, 2, 2, 7 }
int result[max(nums)]; //Fill with zeroes, max(nums) is the highest number in the array
for(int i = 0; i < 10; i++) {
result[nums[i]]++;
}
for(int i = 0; i < max(nums); i++) {
if (result[i] > 1) cout << result[i];
}
Mind you this isn't optimized for memory. For larger number contents you might want to consider hashmaps.
If you don't need performance but rather compact code, then std::multiset with std::upper_bound is an alternative:
#include<set>
#include<iostream>
#include<algorithm>
int main(int a, char** b)
{
int array[] = {5, 5, 6, 7, 5, 9, 4, 2, 2, 7};
std::multiset<int> a(std::begin(array), std::end(array));
for(auto it = a.begin(); it != a.end(); it = std::upper_bound(a.begin(), a.end(), *it))
{
if(a.count(*it) > 1)
std::cout << *it << " times " << a.count(*it) << std::endl;
}
return 0;
}