Find a triplet that sum a given value - c++

I've been struggling with a problem where based on a given number i have to find all the triplets that sum gives the given number.
For example if the given number is 5 conditions are : (x+y+z=5 and x<=y<=z) :
Input :
5
Output :
0 0 5
0 1 4
0 2 3
1 1 3
1 2 2
I've tried to find all the solutions starting with 0 but i can't figure out how to find solutions that start with 1, 2, 3, etc
What i have so far :
int x,y,z;
void showSolutions(int c) {
z=c;
while((x<=y) && (y<=z)) {
if((x<=y&&y<=z)&&(x+y+z)==c) {
cout<<x<<" "<<y<<" "<<z;
cout<<"\n";
}
y++;
z--;
}
}
Thanks for help!

Well you can think of this recursively, let me try to point a generic method which would work for two numbers or triplets or more.
class sum
{
public:
vector<vector<int>> triplets(int k, int target)
{
vector<vector<int>> result;
vector<int> holder;
getTriplets(k, target, holder, result);
return result;
}
void getTriplets(int k, int target, vector<int>& holder, vector<vector<int>>& result)
{
if(target < 0) return;
if(k < 0) return;
if(k == 0 && target == 0)
{
result.push_back(holder);
return;
}
for(int i = 0; i <= target; ++i)
{
holder.push_back(i);
getTriplets(k-1, target - i, holder, result);
holder.pop_back();
}
}
};
You can invoke this as:
sum s;
auto res = s.triplets(3,5);
for(auto row : res)
{
for(auto col : row) cout << col << " ";
cout << endl;
}
where the first argument to triplets is the what the size of set required and the latter is the garget value. The problem here is, it will produce duplicates, 0 0 5 and 5 0 0 I will leave that for you to figure out how.
Simply add results to a temporary holder and recursively try all combinations. until you reach the target value which is 0 in our case since we are subtracting, or hit a error condition. Backtrack and pop the value and exhausting all combinations. Store the result if we hit the target.
Live Demo

#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int x,y,z;
for(z=n;z>=0;z--)
{
for(y=0;y<=z && z+y<=n;y++)
{
x=n-(y+z);
if(x<=y)
cout<<x<<y<<z<<endl;
}
}
}
for n=5,you get
005
014
113
023
122

Related

Permutations of an int array, using recursion

Exercise is as follows:
Generate every possible sequence whose elements are from the set {0,
1, 2} where 0 occurs m times, 1 occurs p times, and 2 occurs q times. The input file
contains three natural numbers separated by spaces, with a maximum value of 100. The solution must be written to the output file line by line
in lexicographic order. Each line should contain the elements of the series
separated by spaces.
If input is:
1 0 2
Output should be:
0 2 2
2 0 2
2 2 0
It's also stated, that I have to use recursion, and the input and output should be to .txt files.
So, I found a popular recursion for permutations which occurred on multiple sites (like this), but for some weird reason, it's not working properly for me..
The way I tried doing this exercise (there might be a smarter way) is by generating a vector from the input, and the using the permutation function with it. But my output is like this:
0 2 2
0 2 2
2 0 2
2 2 0
2 2 0
2 0 2
As you can see, every result appears twice, which is obviously not good..
Code is here below:
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
void input(int& m, int& p, int& q)
{
ifstream fin("input.txt");
fin >> m >> p >> q;
fin.close();
}
void fillVec(vector <int>& elements, int m, int p, int q)
{
fill_n(elements.begin() + m, p, 1); // filling the vectors with correct amount of numbers. The 0's all already there, so I only put the 1's, and the 2's in.
fill_n(elements.begin() + m + p, q, 2);
}
void print(const vector<int>& nums, ofstream& fout)
{
for (int a : nums) { fout << a << ' '; }
fout << endl;
}
void permute(vector<int>& nums, int n, ofstream& fout)
{
if (n == nums.size())
{
print(nums, fout);
}
else
{
for (int i = n; i < nums.size(); i++)
{
swap(nums[n], nums[i]);
permute(nums, n + 1, fout);
swap(nums[n], nums[i]);
}
}
}
int main()
{
int m, p, q;
input(m, p, q);
vector <int> elements(m + p + q);
fillVec(elements, m, p, q);
ofstream fout("output.txt");
permute(elements, 0, fout);
fout.close();
return 0;
}
I tried debugging, also looked at it multiple times to check that I copied the algorithm correctly, but can't find out what's the problem. It might be something pretty simple, I'm not sure..
Here's what I came up with. Each recursive step will attempt to append "0", "1", or "2" to the string being built until there's no available digits to add.
#include <iostream>
#include <string>
using namespace std;
void GeneratePermutations(int zeros, int ones, int twos, const string& leading)
{
if ((zeros <= 0) && (ones <= 0) && (twos <= 0))
{
// use "substr" to skip the leading space
if (leading.size() > 0)
{
std::cout << leading.substr(1) << endl;
}
return;
}
if (zeros > 0)
{
GeneratePermutations(zeros - 1, ones, twos, leading + " 0");
}
if (ones > 0)
{
GeneratePermutations(zeros, ones-1, twos, leading + " 1");
}
if (twos > 0)
{
GeneratePermutations(zeros, ones, twos-1, leading + " 2");
}
}
int main()
{
int zeros, ones, twos;
cin >> zeros;
cin >> ones;
cin >> twos;
GeneratePermutations(zeros, ones, twos, "");
return 0;
}
A couple of sample runs:
input : 1 0 2
output:
0 2 2
2 0 2
2 2 0
Another input: 3 1 1
output:
0 0 0 1 2
0 0 0 2 1
0 0 1 0 2
0 0 1 2 0
0 0 2 0 1
0 0 2 1 0
0 1 0 0 2
0 1 0 2 0
0 1 2 0 0
0 2 0 0 1
0 2 0 1 0
0 2 1 0 0
1 0 0 0 2
1 0 0 2 0
1 0 2 0 0
1 2 0 0 0
2 0 0 0 1
2 0 0 1 0
2 0 1 0 0
2 1 0 0 0
As you see and say yourself, you simply generate all possible permutations of the 0 2 2 array. There are 6 permutations for an array of length 3, and you correctly get them, but because there are two equal numbers, some of these permutations are equal.
However, apparently what you are required is to do generate only different permutations. Basically, this means that you need a new algorithm.
A simple solution may be to find a way to remove repeating permutations. There may be many approaches to it, starting with simply storing all the permutations and checking if you have already generated a given permutation, or storing the original array index with each number and requiring that the indices of equal number go in increasing order, etc. Or you can organize your recursion in a different way (that's what I would have done). Obviously the complexity of each approach will be different.
With std::next_permutation (which handles repetitions), a non recursive way would be:
void permute(std::vector<int>& nums, std::ostream& out)
{
assert(std::is_sorted(nums.begin(), nums.end()));
do {
print(nums, out);
} while (std::next_permutation(nums.begin(), nums.end()));
}
Demo
You can still transform above code in recursive way:
void permute(std::vector<int>& nums, std::ostream& out)
{
print(nums, out);
if (std::next_permutation(nums.begin(), nums.end())) { permute(nums, out); }
}
Demo
Your code is perfect and works as expected. The only problem is that your application is sometimes swapping the same digits, for example:
// nums = {0, 2, 2}
swap(nums[n], nums[i]); // n == 1, i == 2
// nums = {0, 2, 2}
Here you can notice that the application will swap 2 and 2, which will not make any difference.
Thus you can try something like this:
#include <iostream>
#include <vector>
#include <fstream>
// This std::vector will store all the elements that have been stored in output.txt
std::vector<std::string> output;
void input(int& m, int& p, int& q)
{
std::ifstream fin("input.txt");
fin >> m >> p >> q;
fin.close();
}
void fillVec(std::vector <int>& elements, int m, int p, int q)
{
fill_n(elements.begin() + m, p, 1); // filling the std::vectors with correct amount of numbers. The 0's all already there, so I only put the 1's, and the 2's in.
fill_n(elements.begin() + m + p, q, 2);
}
void print(const std::vector<int>& nums, std::ofstream& fout)
{
for (int a : nums) { fout << a << ' '; }
fout << std::endl;
}
void permute(std::vector<int>& nums, int n, std::ofstream& fout)
{
if (n == nums.size())
{
std::string num;
// Convert nums (int array) to num (std::string)
for (int i = 0; i < nums.size(); i++)
{
num.push_back(nums[i]);
}
// If same element found, return
for (int i = 0; i < output.size(); i++)
{
if (num == output[i]) return;
}
print(nums, fout);
// Insert element to output (std::vector)
output.push_back(num);
}
else
{
for (int i = n; i < nums.size(); i++)
{
std::swap(nums[n], nums[i]);
permute(nums, n + 1, fout);
std::swap(nums[n], nums[i]);
}
}
}
int main()
{
int m, p, q;
input(m, p, q);
std::vector <int> elements(m + p + q);
fillVec(elements, m, p, q);
std::ofstream fout("output.txt");
permute(elements, 0, fout);
fout.close();
return 0;
}
This code is the same as yours, except I've added a few checks to ensure that there are no duplicate elements. Now:
input.txt
1 0 2
output.txt (after application execution)
0 2 2
2 0 2
2 2 0
...which is desirable.
Also, consider removing the following statement:
using namespace std;
...as it's considered as bad practice.

Comparing returned vectors from recursion tree branches

Suppose I have a given sum, say sum = 4. I am also given a vector = {2,4}. There are two ways to generate the given sum from the given vector (elements may be reused).
One way is just {4} cause 4 = 4.
Second way is {2,2} cause 2 + 2 = 4.
I have to find the shortest possible combination, therefore in this particular case the answer is {4}.
Here is my approach - I go through the tree, and when on the leaf I get a 0, we hit the base case, return {} vector, and fill up the vector while traversing the tree. When I get to a node, I choose the smaller of the two (or more) vectors. This way when I reach the root node, I should get a vector of the shortest combination that can yield me the target sum.
As of yet, I do not care about time constraints as such, I know there's a lot of repetitive computing going on so I will have to memoize it once I can get the basic version correct.
I have been trying to figure why this code is not working. Any insight would be appreciated.
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
vector<int> findBestSum(int targetSum, const vector<int> &elements, vector<vector<int>> &temp) {
if (targetSum == 0)
return {};
else if (targetSum < 0)
return {-1};
else {
vector<int> small;
for (auto &i : elements) {
int remainder = targetSum - i;
vector<int> returnedVector = findBestSum(remainder, elements, temp);
if ((!returnedVector.empty() && find(returnedVector.begin(), returnedVector.end(), -1) == returnedVector.end()) || returnedVector.empty()) {
returnedVector.push_back(i);
temp.push_back(returnedVector);
}
int smallestLength = temp[0].size();
for (auto &j : temp)
if (smallestLength >= j.size())
small = j;
}
return small;
}
}
int main() {
int targetSum = 6;
const vector<int> elements{2, 3, 5}; // answer should be [3,3] however I just get a 3...
vector<vector<int>> temp;
vector<int> bestSumVector = findBestSum(targetSum, elements, temp);
for (auto i : bestSumVector)
cout << i << " ";
}
Update (14th of July, 2021):
After a few busy months I have tried to lock horns with this problem and this time my code looks like this:
#include <iostream>
#include <vector>
#include <map>
#include <numeric>
using namespace std;
bool howSum(int &targetSum, vector<int> &elementVector, vector<int> &howSumVector, vector<vector<int>> &allSums) {
static int originaltargetsum = targetSum;
if (targetSum == 0)
return true;
else if (targetSum < 0)
return false;
else {
for (auto i : elementVector) {
int remainder = targetSum - i;
bool flag = howSum(remainder, elementVector, howSumVector, allSums);
if (flag) {
howSumVector.push_back(i);
if (targetSum == originaltargetsum ||
accumulate(howSumVector.begin(), howSumVector.end(), 0) == originaltargetsum) {
allSums.push_back(howSumVector);
howSumVector.clear();
}
return true;
}
}
return false;
}
}
int main() {
int sum = 8;
vector<int> elements = {1, 4, 5};
vector<vector<int>> allSums = {};
vector<int> workingBench = {};
howSum(sum, elements, workingBench, allSums);
for (auto &i : allSums) {
for (auto &j : i) {
cout << j << " ";
}
cout << endl;
}
}
For this I have sum as 8 and elements as {1, 4, 5}.
Also I'm storing and displaying all possible solutions right now (once that is correctly done, finding shortest vector and memoization should be easy). Possible solutions in this case are:
[1, 1, 1, 1, 1, 1, 1, 1]
[4, 4]
[5, 1, 1, 1]
[4, 1, 1, 1, 1]
Currently my code only shows the first possible combination. I'm pretty sure I'm returning true and false incorrectly, please help me out here.
I took a stab at this. I do have a working solution, hopefully it is what you want:
#include <iostream>
#include <vector>
#include <algorithm>
void howSum(int targetSum, const std::vector<int> & elementVector, const std::vector<int> & howSumVector, std::vector<std::vector<int>> & allSums)
{
static int originaltargetsum = targetSum;
if (targetSum == 0)
{
allSums.push_back(howSumVector);
return;
}
else if (targetSum < 0)
{
return;
}
else
{
for (const auto i : elementVector)
{
// an element less than or equal to 0 would cause an infinite loop
if (i <= 0)
continue;
std::vector<int> newSumVector = howSumVector;
newSumVector.push_back(i);
std::vector<int> newElementVector;
std::copy_if(std::begin(elementVector), std::end(elementVector), std::back_inserter(newElementVector), [i](int element){ return element >= i; });
howSum(targetSum - i, newElementVector, newSumVector, allSums);
}
}
}
int main()
{
int sum = 8;
std::vector<int> elements = { 1, 4, 5 };
std::vector<std::vector<int>> allSums = {};
std::vector<int> workingBench = {};
howSum(sum, elements, workingBench, allSums);
for (const auto & i : allSums)
{
for (const auto & j : i)
{
std::cout << j << " ";
}
std::cout << std::endl;
}
return 0;
}
I think, in general, you were over-thinking or over-engineering the problem. Like others have mentioned, your current code is returning true too early, and nothing besides the first element/combination is tested. With recursion, it is important to take care in your return cases - really, you only want a base case or two, and otherwise you want to recur.
With the solution I have here, the main thing I have added is copying the current combination of elements for each element you need to test. That solves your main issue of not testing every combination of numbers. In addition to that, it seemed better to append to allSums when the targetSum was reached. With those changes, I was able to do away with the bool return value and simplify the code a bit. Running the code above gives these solutions:
1 1 1 1 1 1 1 1
1 1 1 1 4
1 1 1 4 1
1 1 1 5
1 1 4 1 1
1 1 5 1
1 4 1 1 1
1 5 1 1
4 1 1 1 1
4 4
5 1 1 1
This does have some duplicates (because of the order things are tested) but I felt like it is good enough since you only want the smallest solution, 4 4. To find this, you would just need to sort the allSums vector by inner vector size and then take the first entry.
I think you need to change the implementation to correctly process elements of the vector.
In your implementation it doesn't go over all vector items, just the first one.
This is one way to do it if you use vector elements as the first parameter in your function.
vector<int> findBestSum(int element, int targetSum, const vector<int>& elements,
vector<vector<int>>& temp) {
if (targetSum == 0)
return {};
else if (targetSum < 0)
return { -1 };
else {
int remainder = targetSum - element;
vector<int> returnedVector = findBestSum(element, remainder, elements, temp);
if ((!returnedVector.empty() && find(returnedVector.begin(), returnedVector.end(), -1) == returnedVector.end()) || returnedVector.empty()) {
returnedVector.push_back(element);
return returnedVector;
}
return returnedVector;
}
}
int main() {
const int targetSum = 6;
const vector<int> elements{ 2, 3, 5 }; // answer should be [3,3] however I just get a 3...
vector<vector<int>> temp;
for (auto i : elements) {
vector<int> returnedVector = findBestSum(i, targetSum, elements, temp);
if ((!returnedVector.empty() && find(returnedVector.begin(), returnedVector.end(), -1) == returnedVector.end()) || returnedVector.empty())
temp.push_back(returnedVector);
}
if (temp.size() > 0) {
vector<int> bestSum = {};
size_t small = 0;
size_t smallestLength = temp[0].size();
for (auto& j : temp)
if (smallestLength >= j.size()) {
small = j.size();
bestSum = j;
}
for (auto i : bestSum)
cout << i << " ";
}
else
cout << " sum not found" << endl;
}

Generate a pattern for i-th order partial derivative in d-dimension

I am trying to work out a finite element code, where I need to compute the partial derivatives in d dimension. In finite element the basis function N(x,y,z)=N(x)N(y)N(z), so the first order derivatives are:
N(x)'N(y)N(z) N(x)N(y)'N(z) N(x)N(y)N(z)'
second order derivatives are
N(x)''N(y)N(z) N(x)'N(y)'N(z) N(x)'N(y)N(z)' N(x)N(y)''N(z) N(x)N(y)N(z)' N(x)N(y)N(z)''
I want to have a functions with input (i,d) to tell me these patterns in the table below:
I think there must be a simple algorithm to realize this goal. Can someone gives me some help? THx
This can be solved with nested loops:
int * part_deriv(int i, int d){
int *res;
int *curr;
int num_el = fact(i+d-1) / ( fact(i) * fact(d-1) ); //fact() is the factorial function
int el_size = d*sizeof(int);
int el;
res = calloc(num_el,el_size);
curr = calloc(d,sizeof(int));
*curr = i;
memcpy(res,curr,el_size); //put the first element in the array
el = 0;
while(el<num_el){
if(*curr != 0){
for( d_idx = 1 ; d_idx<d ; d_idx++, *cur++){
*curr--; // "move" one derivative from the first variable to 'd_idx' variable
*(curr+d_idx)++;
el++;
memcpy(res+(el*el_size),curr,el_size); //put the element in the array
}
*curr--;
} else{
break; //shouldn't be reached, but added to be sure
}
}
return res;
}
I havn't completely understood how you want to output the result, so you can parse the array I output in blocks of d.
Consider the pattern for i'th derivative as base-i+1 integers. Nice sequences emerge. For example, in a two-dimensional case, they are
0
2, 1
6, 4, 2
12, 9, 6, 3
20, 16, 12, 8, 4
etc.
I realized it by recursive by calling a function.
#include <vector>
#include <iostream>
using namespace std;
void func (int d, int i, vector<int> &k, int n, int start, vector<vector<int>> &a){
if (n==i)
{
vector<int> m;
int it=0;
for(int it1=0;it1<d;++it1){
int amount=0;
while(find(k.begin(),k.end(),it)!= k.end()){
amount++;
it++;
}
m.push_back(amount);
it++;
}
a.push_back(m);
}
else{
for(int jj=start;jj<d+i-(i-n);++jj){
k[n]=jj;
func(d,i,k,n+1,jj+1, a
);
}
}
}
vector<vector<int>> test(int d, int i){
vector<int> kk(i);
vector<vector<int>> a;
func(d,i,kk,0,0, a);
return a;
}
int main(){
auto f = test(4,2);
for(auto it1=f.begin();it1!=f.end();++it1){
for(auto it2= it1->begin();it2!=it1->end();++it2)
cout<<*it2<<" ";
cout<<endl;
}
}
Here is my result for i=2,d=4:
2 0 0 0
1 1 0 0
1 0 1 0
1 0 0 1
0 2 0 0
0 1 1 0
0 1 0 1
0 0 2 0
0 0 1 1
0 0 0 2

Permutations &/ Combinations using c++

I need a different version of permutations for my code. I could able to achieve what I want but it is not generic enough. my algorithm keeps going bigger along with my requirements. But that should not be.
This is not a home work for any one, I need it for one my critical projects, wondering if any pre-defined algorithms available from boost or any other.
Below is the standard version of next_permutation using c++.
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation
int main ()
{
int myints[] = {1,2,3};
do
{
std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
} while ( std::next_permutation(myints,myints+3) );
return 0;
}
That gives below output :
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
But my requirement is :- Let's say I have 1 to 9 numbers :
1,2,3,4,5,6,7,8,9
And I need a variable length of permutations and in only ASCENDING order and with out DUPLICATES.
Let's say i need 3 digit length of permutations then i need output as below.
123
124
125
.
.
.
128
129
134 // After 129 next one should be exactly 134
135 // ascending order mandatory
136
.
.
.
148
149
156 // exactly 156 after 149, ascending order mandatory
.
.
.
489 // exactly 567 after 489, because after 3rd digit 9, 2nd digit
567 // will be increased to 49? , so there is no possibility for
. // 3rd digit, so first digit gets incremented to 5 then 6 then
. // 7, in ascending order.
.
.
.
789 // and this should be the last set I need.
My list may contain upto couple of hundred's of numbers and variable length can be 1 to up to Size of the list.
My own algorithm is working for specific variable length, and a specific size, when they both changes, i need to write huge code. so, looking for a generic one.
I am not even sure if this is called as Permutations or there is a different name available for this kind of math/logic.
Thanks in advance.
musk's
Formally, you want to generate all m-combinations of the set [0;n-1].
#include <iostream>
#include <vector>
bool first_combination (std::vector<int> &v, int m, int n)
{
if ((m < 0) || (m > n)) {
return false;
}
v.clear ();
v.resize (m);
for (int i = 0; i < m; i++) {
v[i] = i;
}
return true;
}
bool next_combination (std::vector<int> &v, int m, int n)
{
for (int i = m - 1; i >= 0; i--) {
if (v[i] + m - i < n) {
v[i]++;
for (int j = i + 1; j < m; j++) {
v[j] = v[j - 1] + 1;
}
return true;
}
}
return false;
}
void print_combination (const std::vector<int> &v)
{
for (size_t i = 0; i < v.size(); i++) {
std::cout << v[i] << ' ';
}
std::cout << '\n';
}
int main ()
{
const int m = 3;
const int n = 5;
std::vector<int> v;
if (first_combination (v, m, n)) {
do {
print_combination (v);
} while (next_combination (v, m, n));
}
}
You can use this code and the linked article as inspiration.
This task can be done with a simple iterative algorithm. Just increment the first element that can be incremented and rescale the elements before it until there is no element to be incremented.
int a[] = {0,1,2,3,4,5,6,7,8,9}; // elements: must be ascending in this case
int n = sizeof(a)/sizeof(int);
int digits = 7; // number of elements you want to choose
vector<int> indexes; // creating the first combination
for ( int i=digits-1;i>=0;--i ){
indexes.push_back(i);
}
while (1){
/// printing the current combination
for ( int i=indexes.size()-1;i>=0;--i ){
cout << a[indexes[i]] ;
} cout << endl;
///
int i = 0;
while ( i < indexes.size() && indexes[i] == n-1-i ) // finding the first element
++i; // that can be incremented
if ( i==indexes.size() ) // if no element can be incremented, we are done
break;
indexes[i]++; // increment the first element
for ( int j=0;j<i;++j ){ // rescale elements before it to first combination
indexes[j] = indexes[i]+(i-j);
}
}
Output:
0123456
0123457
0123458
0123459
0123467
0123468
0123469
0123478
0123479
0123489
0123567
0123568
0123569
0123578
0123579
0123589
0123678
0123679
0123689
0123789
0124567
0124568
0124569
0124578
0124579
0124589
0124678
0124679
0124689
0124789
0125678
0125679
0125689
0125789
0126789
0134567
0134568
0134569
0134578
0134579
0134589
0134678
0134679
0134689
0134789
0135678
0135679
0135689
0135789
0136789
0145678
0145679
0145689
0145789
0146789
0156789
0234567
0234568
0234569
0234578
0234579
0234589
0234678
0234679
0234689
0234789
0235678
0235679
0235689
0235789
0236789
0245678
0245679
0245689
0245789
0246789
0256789
0345678
0345679
0345689
0345789
0346789
0356789
0456789
1234567
1234568
1234569
1234578
1234579
1234589
1234678
1234679
1234689
1234789
1235678
1235679
1235689
1235789
1236789
1245678
1245679
1245689
1245789
1246789
1256789
1345678
1345679
1345689
1345789
1346789
1356789
1456789
2345678
2345679
2345689
2345789
2346789
2356789
2456789
3456789

C++ odd-even array, infinite answer

This program supposed to read the number of elements and a list, and split the array for even and odd numbers, and display the number of zeros in original array.
I posted a question before for the first problem I had with this program and the answers were really helpful since this is an assignment. But now I have another problem which is every time I run the program it gave me 0 'z. and it does not stop until I close the window. I think the problem is with the count function but I was not able to diagnose the problem by myself. I added:
cout<< odd_num<< " " << even_num;
after I called count function to find out what is the problem and it gave me a really big number so whatever the error is, it is coming from this function.
So please help me! I'm sure for most of you this is very basic but I just started to learn this and really appreciate it if you can help me.
Edit: I edited this code and the only problem is an extra zero as output; look at the example output at the end.
Here is the code:
int count(const int list[], int size, int & odd , int & even)
{
int zero(0);
for (int i(0); i<size ; i++)
{
if (list[i] == 0)
{
zero++;
}
if (list[i]% 2 ==0 & list[i]!=0)
{
even++;
}
else if (list[i]% 2 ==1 & list[i]!=0)
{
odd++;
}
}
return zero;
}
void split(const int list[], int size, int list_even[], int even_num, int list_odd[], int odd_num )
{
int j(0);
int k(0);
for (int i(0); i<size; i++)
{
if(list[i]%2 == 0)
{
list_even[j]= list[i];
j++;
}
else if(list[i]%2 != 0)
{
list_odd[k]= list[i];
k++;
}
}
if (j != even_num || k != odd_num)
{
cerr << "Error.";
}
}
// function to print an array
void print_list(int array[], int length)
{
for (int a=0; a<length; a++)
{
cout <<array[a]<<" ";
}
}
And here is the sample answer:
Enter number of elements: 3
Enter list:
2
30
0
Error.Even elements:
2 30 0 0
Odd elements:
There were 1 zeros in the list
Another sample is:
Enter number of elements: 3
Enter list:
2
1
5
Error.Even elements:
2 2752708
Odd elements:
1 5 2762032 2752708
There were 0 zeros in the list
You did not initialize your variables try:
int zero_num(0); // number of zeros
int even_num(0);
int odd_num(0);
Try printing them out before you start using them (before this fix) and see what they are set too. :)
Fix to your count function:
// function to copy odd and even number to seperate arrays
void split(const int list[], int size, int list_even[], int even_num, int list_odd[], int odd_num )
{
int j(0);
int k(0);
for (int i(0); i<size; i++)
{
if (list[i] == 0)
{ // zeros are not considered even in the count function
// so they should not be added here.
continue;
}
else if(list[i]%2 == 0)
{
list_even[j]= list[i];
j++;
}
else if(list[i]%2 != 0)
{
list_odd[k]= list[i];
k++;
}
}
// test that we have found the right number of even and odd numbers.
if (j != even_num || k != odd_num)
{
cerr << "Error.";
}
}
And to make sure that multiple calls to the count function does not mess up your numbers make this change:
//function to count the odd and even numbers and th enumber od zeros
int count(const int list[], int size, int & odd , int & even)
{
// reset the even and odd counts before we start.
odd=0;
even=0;
int zero(0); // variable to count zeros
for (int i(0); i<size ; i++)
{
if (list[i] == 0)
{
zero++;
}
else if (list[i]% 2 == 0 )
{
even++;
}
else if (list[i]% 2 == 1 )
{
odd++;
}
}
return zero;
}
Sample output:
Enter number of elements: 5
Enter list:
1
2
5
0
0
Even elements: 2
Odd elements: 1
5
There were 2 zeros in the list
Another sample output with zeros in begining and middle:
Enter number of elements: 5
Enter list:
0
2
0
1
7
Even elements: 2
Odd elements: 1
7
There were 2 zeros in the list
In if condition you are using & which is bit-wise operator instead of && which is Logical AND.
See:
if (list[i]% 2 ==0 & list[i]!=0)
{
even++;
}
use && instead and see if it works, else drop me a message.
[Improvement] How about to write your count function like this,
int count(const int list[], int size, int & odd , int & even)
{
int zero(0);
for (int i(0); i<size; ++i)
{
if (list[i]==0)
{
++zero;
}
else
{
if (list[i]%2==0) ++even;
else ++odd;
}
}
return zero;
}