I'm trying to design a program that takes an integer array as input, and then returns all combinations of values that add up to a predetermined sum. For the sake of clarity, my recursive function will return true when the total adds up to 10.
However, I also want it to return the values from the array that comprise of this total, so my definition is as follows;
If suminarray returns true, print each number from the array.
My hope was, once my base clause is reached, the recursion would unwind, and my if statements would all be evaluated, and each value would be printed from my if statement. However, all that is printed is last value from the array which made up the target total, not all the values that preceded it.
I've likely misunderstood the recursive behaviour of C++. I know how to work with recursive return calls, but logically, if the if statement can't be evaluated until the recursive function returns true or false, shouldn't they unwind, also?
#include <iostream>
bool suminarray(int *numbers, const int &size, int startPos, int total);
using namespace std;
int main()
{
int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int startPos = 0;
int total = 0;
suminarray(numbers, 10, 0, total);
return 0;
}
bool suminarray(int *numbers, const int &size, int startPos, int total)
{
if(total == 10)
{
cout << "result. " << endl;
return true;
}
else if(total > 10)
{
return false;
}
else
{
for(int i = startPos; i < size; i++)
{
cout << " loop " << i << endl;
cout << " total" << total << endl;
if(suminarray(numbers, size, i+1, total+numbers[i]) == true)
{
cout << "Uses " << numbers[i] << endl;
}
}
}
}
Edit: correction to source code.
The immediate problem (which your compiler should be warning you about), is that you have no return statement in the final else block, which causes the function to fall off the end without returning either true or false, leading to undefined behavior. If you fix that in the most obvious way:
else
{
for(int i = startPos; i < size; i++)
{
cout << " loop " << i << endl;
cout << " total" << total << endl;
if(suminarray(numbers, size, i, total+numbers[i]) == true)
{
cout << "Uses " << numbers[i] << endl;
return true;
}
}
return false;
}
your program then works, but it only prints the FIRST set of values that add up to 10 that it finds.
That immediately shows you the problem with your approach -- each function call can only return ONCE -- you can't (easily) have it both return success AND continue to try more alternatives.
As you've already guessed, the way you're imagining the recursive function unwinding is wrong.
In your example, you want to get to a total of 10, with numbers starting at 1, and ending at 9. So, first your recursive function will make the total = 1. Then it will add another 1 to that until it gets all the way down to the tenth 1. Then it will print result, then it will unwind 1 step, and print 1.
Good so far right? Well, here's where it goes off track. At this point it doesn't unwind all the way. It still stays at 9, but this time it adds a 2 to that, fails goes back until it unwinds to a sum of 8. Now it tries 2 and works this time! Printing result, then 2.
This, as i've understood, isn't what you want. What you should be doing is make something else to hold your array of answers, and not just print them.
I know how to work with recursive return calls, but logically, if the if statement can't be evaluated until the recursive function returns true or false, shouldn't they unwind, also?
This is correct. The reason you are only seeing one print statement at the end is because only one call is returning 'true'. Therefore the 'if' statement is only true once and you only see one print statement for "Uses ".
I believe your mistake is that you didn't add a return statement after your for loop. This means the return value for your function is actually undefined. Start using the -Wall flag when you compile to make sure you don't make this mistake. Here is a version where I added a "return true;" after the 'for' loop:
#include <iostream>
bool suminarray(int *numbers, const int &size, int startPos, int total);
using namespace std;
int main()
{
int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int startPos = 0;
int total = 0;
suminarray(numbers, 10, startPos, total);
return 0;
}
bool suminarray(int *numbers, const int &size, int startPos, int total)
{
if(total == 10)
{
cout << "result. " << endl;
return true;
}
else if(total > 10)
{
return false;
}
else
{
for(int i = startPos; i < size; i++)
{
cout << " loop " << i << endl;
cout << " total" << total << endl;
if(suminarray(numbers, size, i, total+numbers[i]) == true)
{
cout << "Uses " << numbers[i] << endl;
}
}
}
return true;
}
Related
I have to write a recursiive solution to the coin change problem in C++.
The problem provides a set of coins of different values and a value representing a sum to be paid.
The problem asks to provide the number of ways in which the sum can be paid given the coinages at hand.
I am stuck on this:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
long recursive(int amount, vector<long>& input_vector, long ways, vector<long>::const_iterator current) {
if (amount < 0)
return ways;
for (auto iter = current; iter != input_vector.end(); ++iter) {
cout << "amount: " << amount << ", current coin: " << *iter << '\n';
ways += recursive(amount - *iter, input_vector, 0, iter);
cout << "ways: " << ways << '\n';
}
return ways;
}
long getWays(int n, vector<long> c) {
sort(c.begin(), c.end(), greater<long>());
return recursive(n, c, 0, c.begin());
}
int main() {
int amount = 32;
vector<long> coinages = {2, 5, 6, 10};
cout << "Solution is: " << getWays(amount, coinages) << endl;
return 0;
}
The answer should be 27, but I get 0?
Even if I omit the eturn 0 at the end of the main program, I still get 0.
So I'm kind of frustrated my logic does not work here and I'm clueless about how to solve this in a different way.
If amount is 0, this is an answer, return 1 to be added to ways. If you got below 0, dead end street, return 0, nothing will be added.
if (amount == 0)
return 1;
if (amount < 0)
return 0;
I need to print an array by implementing the use of a function before the main function. So I tried the following function:
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++) {
cout << arr[i];
}
return arr;
}
I encountered two problems when implementing this into the whole code.
First, this is printing what I think is the address of the array and not the actual array. Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument? How can I account for this in my function?
Please keep in mind that I am new to C++ and coding in general. Also, this code was given to me, hence why I do not understand certain aspects of it.
This is my code so you can see what I mean:
#include <iostream>
using namespace std;
// Declare function printArr here
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++)
{cout << arr[i];}
return arr;
}
int main()
{
int arr[5] = {1, 3, 5, 7,9};
int last_num = arr[sizeof(arr)/sizeof(int)-1];
cout << "Before reversing" << endl;
cout << printArr(arr, 5) << endl;
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, 5);
return 0;
}
The declaration and implementation of printArr() is all wrong.
First, this is printing what I think is the address of the array and not the actual array.
The printArr() function itself is printing the contents of the array (well, the first 5 elements anyway), and then returning the address of the array. It is main() that is printing that address afterwards, when it passes the return value of printArr() to std::cout <<.
Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
By getting rid of the return type altogether. There is no good reason to return the array pointer at all in this example, let alone to pass that pointer to std::cout. So printArr() should be returning void, ie nothing.
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument?
Because main() is passing in the element count of the array (5) so that printArr() can know how many elements to actually print, instead of hard-coding that value in the loop. However, your declaration of printArr() does not have a 2nd parameter with which to accept that value, that is why you are getting errors.
How can I account for this in my function?
By adding a 2nd parameter in the function declaration, eg:
#include <iostream>
using namespace std;
// Declare function printArr here
void printArr(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << ' ';
}
cout << endl;
}
int main()
{
int arr[5] = {1, 3, 5, 7, 9};
const int count = sizeof(arr)/sizeof(arr[0]);
int last_num = arr[count-1];
cout << "Before reversing" << endl;
printArr(arr, count);
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, count);
return 0;
}
Live Demo
I was writing the code for the problem. Median of the stream of integers when I encountered an issue. Note that this issue is not the algorithmic but rather ambiguous behavior of the priority_queue size.
#include <bits/stdc++.h>
using namespace std;
priority_queue<double> small;
priority_queue<double, vector<double>, greater<double> > large;
void rebalance()
{
cout << "Initial size\n";
cout << "small " << small.size() << " large " << large.size() << endl;
if (small.size() - large.size()>1)
{
large.push(small.top());
small.pop();
}
else if (large.size() - small.size()>1)
{
cout << "Unexpectedly goes here\n";
cout << "garbage size difference " << large.size() - small.size() << endl;
small.push(large.top());
large.pop();
}
}
void addNum(int num) {
if (small.size() == 0 || num<small.top())
{
small.push(num);
}
else
{
large.push(num);
}
rebalance();
}
double findMedian() {
if (small.size() == large.size())
{
double ans = (small.top() + large.top()) / 2.0;
return ans;
}
else if (small.size()>large.size())
{
return (double)small.top();
}
else
{
return (double)large.top();
}
}
int main()
{
std::ios_base::sync_with_stdio(false);
int num = 5;
addNum(num);
cout << findMedian() << endl;
return 0;
}
The output for this code is
Initial size
small 1 large 0
Unexpectedly goes here
garbage size difference 18446744073709551615
fish: “./a.out” terminated by signal SIGSEGV (Address boundary error)
In the rebalance function the initial size of small is 1 and large is 0 which suggest that the loop should neither enter the if condition nor the else if condition but the loop enters the else if condition with a garbage value in size.why does this happen? Moreover I tried saving the small and large size in an integer variable and then comparing them in conditionals,which lead to acceptance of the code. Hence the algorithm handles the correctness.
What leads to this garbage value?
In
else if(large.size()-small.size()>1)
size() returns an unsigned number. A unsigned number can never be negative so if would be a negative number it wraps around to the largest number it could be and then goes backwards from there. Since large has a size of 0 and small has a size of 1 then 0 - 1 gives you 18446744073709551615. I believe what you are trying to do should be expressed as
if(small.size() < large.size())
{
small.push(large.top());
large.pop():
}
else if(large.size() < small.size())
{
large.push(small.top());
small.pop();
}
I want to find Palindrome of a word. Whats Wrong Here?
main function:
int size;
string input;
cin>>input;
size = input.length();
if(testPalindrome(input,size-1,0))
cout<<"It's Palindrome";
else
cout<<"It's not Palindrome";
And the testPalindrome function is:
bool testPalindrome (string pal , int last, int first){
if (pal[first] != pal[last])
return false;
else{
if (first<last)
testPalindrome(pal,last-1,first+1);
else
return true;
}
}
I have read this link and found the answer for determining Palindromes, but why this one is not working?
You need to return the result of the recursive call, just like when you call any other function.
If you don't, the behaviour is undefined.
I think you forgot the return statement in the function
if (first<last)
return testPalindrome(pal,last-1,first+1);
^^^^^^^
Usually the first parameter of a range specifies the lower value and the second parameter specifies either the upper value of the range that is not included in the range or the number of elements in the sequence..
And the first parameter should be declared as having constant reference type because the string itself is not changed and you will escape additional memory allocation.
The recursive function can be written like
#include <iostream>
#include <string>
bool testPalindrome(const std::string &s,
std::string::size_type i,
std::string::size_type n)
{
return n < 2 || (s[i] == s[n-1] && testPalindrome(s, i + 1, n - 2) );
}
int main()
{
std::cout << testPalindrome("abba", 0, 4) << std::endl;
std::cout << testPalindrome("aba", 0, 3) << std::endl;
std::cout << testPalindrome("aa", 0, 2) << std::endl;
std::cout << testPalindrome("a", 0, 1) << std::endl;
std::cout << testPalindrome("ab", 0, 2) << std::endl;
return 0;
}
The program output is
1
1
1
1
0
The simplest way to check whether an object of the type std::string is a palindrome is to write the expression
s == std::string( s.rbegin(), s.rend() )
I'm having a little trouble with my code. It's pretty much supposed to open two files, and compare the first twenty line of the file "StudentAnswers.txt" [inputted as a char into a char array] against a char value in (each line of another file) "CorrectAnswers.txt" in another array at the same position (index). It's like a linear search, but the same position in the arrays. Then a report should be displayed, detailing which question the student missed, the given answer, the correct answer, and if the student passed (got >= 70%) or not, like the following:
Report for Student X:
2 (A/D), 3 (C/D), 5(D/A)
This student passed the exam!
Then it should clear the SAArray, and feed the next twenty lines from StudentAnswers.txt, and start the process all over again. I guess the program has to determine the number of students from (lines of 'StudentAnswers.txt' file / 20).
I'm having trouble displaying the report, and having the array clear itself after the program. I'm guessing this can be done with a while loop and an accumulator for the number of students (to be determined by above equation).
Also, Visual Studio seems to go to "Missed __ questions for a total of ___ %", and then keep looping -858993460.
Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <algorithm>
using namespace std;
void GradeReturn(char[], char[], int, int, int);
string PassFail(float);
int main()
{
ifstream SA("StudentAnswers.txt");
ifstream CA("CorrectAnswers.txt");char CAArray[20];
char SAArray[20];
// char SA2Array[20];
bool isCorrect;
int correct;
int incorrect;
int counter;
correct = 0;incorrect = 0;
counter = 0;
cout << endl;
if (!SA.fail())
{
cout << "'StudentAnswers.txt' file opened successfully." << endl;
cout << "'CorrectAnswers.txt' file opened successfully." << endl << endl;
int a = 0;
int b = 0;
while (a < 20)
{
CA >> CAArray[a];
a++;
} // while loop to feed char into the array
while (b < 20)
{
SA >> SAArray[b];
b++;
}
} // while loop to feed char into array
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
return 0;
}
void GradeReturn(char CAArray[], char SAArray[], int correct, int incorrect, int counter)
{
float percent;
float hundred;
int student;
int catcher[20];
int writeCatcher; int starter;
int catcher_size;
student = 0;
writeCatcher = 0;
catcher_size = ((sizeof catcher) / 4);
while (counter < 20)
{
if ((CAArray[counter]) == (SAArray[counter]))
{
correct++;
cout << "Good job!" << endl;
} // correct handling
else
{
incorrect++;
cout << "You got question " << counter << " wrong." << endl;
counter >> catcher[writeCatcher];
writeCatcher++;
} // incorrect handling
counter++;
} // while loop to determine if a student got a question right or wrong
static_cast <float> (incorrect); // float conversion
cout << endl; // for cleanliness
percent = ((static_cast <float> (correct)) / 20); // percentage
hundred = percent * 100;
PassFail(percent);
if (PassFail(percent) == "pass")
{
student++;
cout << "Report for Student " << student << ":" << endl;
cout << "-----------------------------" << endl;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
starter = 0;
while (starter < (sizeof catcher)
{
if(1=1)
{
catcher_size
}
else
{
cout << "";
starter++;
}
}
}
else if (PassFail(percent) == "fail")
{
student++;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
while (starter < catcher_size)
{
if ((catcher[starter]) == -858993460)
{
starter++;
}
else
{
cout << "";
starter++;
}
}
}
return;
}
string PassFail(float percent)
{
if (percent >= 0.70) // if <pass>
{
return "pass";
}
else // if <fail>
{
return "fail";
}
cout << endl;
}
To get a loop you should keep streams open instead of closing them after reading 20 lines.
As pseudo code that would be:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
a = 0; // Reset a
}
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
You would also need to pass correct, incorrect, counter by reference so that the GradeReturn can change their value and their by do the accumulation.
Like:
void GradeReturn(char CAArray[], char SAArray[], int& correct, int& incorrect, int& counter)
Further you shouldn't rely on being able to read exactly Nx20 lines from the files every time. A file could have, e.g. 108 (5x20 + 8) lines, so you code should be able to handle the with only 8 lines. In other words, don't hard code 20 in your function like while (counter < 20). Instead pass the number of lines to be handled and do while (counter < number_to_handle).
Something like this as pseudo code:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
// ^
a = 0; // Reset a
}
}
if (a != 0)
{
// Process the rest
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
One problem you have is you're trying to compare C-style strings with the == operator. This will compare them essentially as if they were pointers to char, i.e. compare whether they point at the same location in memory, not compare the contents of the string. I urge you to look up array-decay and c-string variables to understand more.
Specifically, if (PassFail(percent) == "pass") isn't going to do what you want it to. strcomp doc, strncmp doc using std::string variables instead of c-style strings would all work, but it would be better simply to compare percent to a value, i.e. if(percent >= 0.70 directly instead of calling PassFail and comparing a string.
There are many other issues here also, you at one point call PassFail but do nothing with the return value. The only side affect of PassFail is cout << endl, if that's what you intend, it's a poor decision and hard to read way to put a newline on the console.
Try asking your compiler for more warnings, that's often helpful in finding these types of issues. -Wall -Wextra work for gcc, you may have to read your compiler manual...