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() )
Related
I'm taking an Intro to Programming class and a good chunk of the material is drilled into our heads through myProgrammingLab. I'm having a little trouble with the concept of Recursion... It's sort of been hit or miss for me. This particular problem has me stumped. When I submit my code, it offers me
CTest1.cpp: In function 'bool isPalindrome(int*, int)':
CTest1.cpp:9: error: invalid conversion from 'int' to 'int*'
CTest1.cpp:9: error: initializing argument 1 of 'bool isPalindrome(int*, int)'"
as advice, which I can assure you is not very helpful. Lol
I think my main problem is when I get to the actual recursion. I'm aware that something's off, but.. If you could just point me in the right direction, I would very much appreciate it.
A 'array palindrome' is an array which, when its elements are reversed, remains the same (i.e., the elements of the array are same when scanned forward or backward)
Write a recursive, bool-valued function, isPalindrome, that accepts an integer -valued array , and the number of elements and returns whether the array is a palindrome.
An array is a palindrome if: the array is empty (0 elements ) or contains only one element (which therefore is the same when reversed), or the first and last elements of the array are the same, and the rest of the array (i.e., the second through next-to-last elements ) form a palindrome.
My code so far:
bool isPalindrome(int arr[], int n)
{
if (n == 0 || n == 1)
{
return true;
}
else if (arr[n-1] == isPalindrome(arr[((n-1) - n) +1 ], n))
{
return true;
}
else
{
return false;
}
}
Recursion mostly has three main components:
a stopping condition (when you reach an array size small enough to be a guaranteed palindrome (0 or 1)),
a computation step (e.g. to compare the first and last item of the array and determine whether it makes sense to continue) and
a data subset selection for the nested recursion call (e.g. an array of size n - 2, excluding the first and last characters, which we already compared and found “palindrome-worthy”).
The three components in code:
bool isPalindrome(int arr[], size_t n) {
return n < 2 || (
arr[0] == arr[n - 1] &&
isPalindrome(arr + 1, n - 2));
}
Of course you may want to test the function a bit (and do not forget to run it under valgrind as well):
#include <iostream>
int main() {
std::cout << isPalindrome((int[0]){}, 0) << std::endl;
std::cout << isPalindrome((int[1]){1}, 1) << std::endl;
std::cout << isPalindrome((int[2]){1, 1}, 2) << std::endl;
std::cout << isPalindrome((int[2]){2, 1}, 2) << std::endl;
std::cout << isPalindrome((int[2]){1, 2}, 2) << std::endl;
std::cout << isPalindrome((int[3]){1, 2, 1}, 3) << std::endl;
std::cout << isPalindrome((int[3]){2, 2, 2}, 3) << std::endl;
std::cout << isPalindrome((int[3]){2, 2, 1}, 3) << std::endl;
std::cout << isPalindrome((int[4]){1, 2, 1, 2}, 4) << std::endl;
std::cout << isPalindrome((int[4]){1, 2, 2, 1}, 4) << std::endl;
std::cout << isPalindrome((int[4]){1, 2, 3, 2}, 4) << std::endl;
std::cout << isPalindrome((int[4]){2, 3, 2, 1}, 4) << std::endl;
std::cout << isPalindrome((int[4]){1, 3, 3, 1}, 4) << std::endl;
}
As a side note, this^^^ deadly struggle with arrays suggests that a different data type would be a much better choice. For example, std::string or std::vector can be initialized way easier, should be passed by reference and, as a bonus, STL containers carry size information with them. Additionally, you can use std::string_view for substrings and std::span for “subvectors” in your recursion, without copying the container over and over on each recursion level.
Here’s an example with std::string_view and three different implementations (one with recursion and two without recursion):
#include <iostream>
#include <string_view>
bool isPalindrome1(const std::string_view s) {
return s.size() < 2 || (
s[0] == s[s.size() - 1] &&
isPalindrome1(s.substr(1, s.size() - 2)));
}
bool isPalindrome2(const std::string_view s) {
const size_t end = s.size() / 2;
for (size_t i = 0; i < end; ++i)
if (s[i] != s[s.size() - i - 1])
return false;
return true;
}
bool isPalindrome3(const std::string_view s) {
auto b = s.begin();
const auto end = b + s.size() / 2;
auto e = s.rbegin();
for (; b < end; ++b, ++e)
if (*b != *e) return false;
return true;
}
int main() {
for (auto isPalindrome : {isPalindrome1,
isPalindrome2,
isPalindrome3}) {
std::cout << isPalindrome("") << std::endl;
std::cout << isPalindrome("a") << std::endl;
std::cout << isPalindrome("ab") << std::endl;
std::cout << isPalindrome("aa") << std::endl;
std::cout << isPalindrome("abc") << std::endl;
std::cout << isPalindrome("aba") << std::endl;
std::cout << isPalindrome("baab") << std::endl;
std::cout << isPalindrome("baba") << std::endl;
}
}
isPalindrome does not accept an int as a first argument. It accepts only an array, by doing this: arr[((n-1) - n) +1] you are feeeding it an int instead if an array of ints. This ((n-1) - n) +1 will evaluate to a “position” in the array, eg: arr[0] being the first element, your case an int.
std::count returns a value and I need this value to reset to 0 for all characters in the variable 'counter' after executing the inner for loop. Goal is to count how many times a character appears. If this character appears twice in the string, add one to variable 'd'. If it appears three times, add one to variable 'e'.
Not sure what else to try or if there is potentially a better function to achieve my result.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstring>
int main() {
std::string data;
std::vector<std::string> myString;
std::vector<char> myChar;
int d = 0, e = 0;
std::ifstream inFile;
inFile.open("C:\\Users\\Administrator\\Desktop\\c++ files\\input2.txt");
if (!inFile) {
std::cout << "oops";
}
for (int i = 0; i < 1; i++) {
inFile >> data;
std::copy(data.begin(), data.end(), std::back_inserter(myChar)); //copy from string data to vector myChar via back inserter.
char counter = 'a';
for (int i = 0; i < 26; i++) {
int myCount = std::count(myChar.begin(), myChar.end(), counter);
if (myCount == 2) {
d++;
}
else if (myCount == 3) {
e++;
}
std::cout << "Counter : " << counter << " myCount : " << myCount << "\n";
counter++;
}
}
std::cout << "d is: " << d << "\n";
std::cout << "e is: " << e << "\n";
return 0;
}
input file -- https://adventofcode.com/2018/day/2
The program works correctly on first inner for loop, but second and after return values that are too high (albeit correct) for the 'myCount' variable.
std::count doesn't just give you a random value, it gives you a specific value based on the contents of the range you give it. You can't change that behaviour, not should you want to.
Instead, look at that range. Why does std::count gives values that you don't expect? They are either "too high" or they are "correct" and cannot be both; fortunately they are the latter.
This is because you repeatedly std::back_insert to the vector inside your loop. As the loop progresses, you keep counting the old characters from the last time!
If you first cleared myChar then you wouldn't have the problem. Or, ideally, bring the declaration of myChar inside the loop.
A few fixes
1) On error the program should end, not continue:
if (!inFile)
{
std::cout << "oops";
return 1;
}
2) a)myChar is accumulating all the chars of all previously read words, so it has to be cleared before use with every pass of the loop, best to move it's declaration into the block required;
b) if you're using a counter just to count but not using it, better to iterate over the data - in this case get rid of i and iterate with chars checked_char:
while (inFile >> data)
{
std::vector< char > myChar;
std::copy(data.begin(),
data.end(),
std::back_inserter(myChar)); //copy from string data to vector myChar via back inserter.
for (char checked_char = 'a'; checked_char <= 'z'; ++checked_char)
{
int myCount = std::count(myChar.begin(), myChar.end(), checked_char);
if (myCount == 2)
{
d++;
}
else if (myCount == 3)
{
e++;
}
std::cout << "Counter : " << checked_char << " myCount : " << myCount << "\n";
}
}
I am supposed to read some data (specifically string datatype) and store each element in a vector. Now I have to check if any of the different strings that were inputted match in size, and if they do I have to see if there are any matching letters. Now my question is how do I compare what's inside the vector (first the size and then the different letters). Is it possible?
Say I have
HELLO
and
HELLA
They have the same size, and 4 letters that match.
This is what I am trying to accomplish.
The code that I have does not work given my ignorance about the matter.
Thank you in advance.
vector <string> myVector;
//insert data insdide of the vector
myVector.push_back("Hello");
myVector.push_back("Hello");
myVector.push_back("Hello2");
myVector.push_back("Hello3");
myVector.push_back("Hello4");
//This is wrong
for (unsigned int i = 0; i < myVector.size(); i++) {
if (myVector[i].size == myVector[i+1].size()){
cout << "SAME SIZE" << endl;
}
}
return 0;
You just have make a simple mistake for size() function and you are trying to access the element which is not present by using i+1 for last iteration.
So just change your for loop just as below
for (unsigned int i = 1; i < myVector.size(); i++)
{
if (myVector[i].size() == myVector[i-1].size()) // .size() should be used
{
cout << "SAME SIZE" << endl;
}
}
Here's a way of writing it:
// returns true if #param s1 and #param s2 are equal in letters
bool isEqual(const string& s1, const string& s2) {
if(s1.size() != s2.size())
return false;
bool equal = false;
// iterates over all the characters in s1 and s2 and compare them
for(auto ch1 = s1.cbegin(), ch2 = s2.cbegin(); ch1 != s1.cend(),ch2!= s2.cend(); ch1++, ch2++) {
if(*ch1 == *ch2)
equal = true;
else
return false;
}
return equal;
}
// type of iter is vector<string>::const_iterator meaning it can only read the value
for (auto iter = myVector.cbegin(); iter != myVector.cend() - 1; iter++){
if(isEqual(*iter, *(iter + 1)))
std::cout << *iter << " equal " << *(iter + 1) << endl;
else
std::cout << *iter << " different " << *(iter + 1) << endl;
}
Here, I used iterators(you should write code in modern C++, avoid using subscript).
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
We have to write a gcd calculator, iteratively and recursively, and we are given a test script and my program fails 2/10 tests(gcd_iterative(1000, 48) = 1000, gcd_iterative(48, 24) = 48). so I showered my program with print statements 'and it worked. I started removing 1 statement at a time and there is 1 line where if I remove the statement it produces the wrong answer. Why does this happen and how can I fix it?
using namespace std;
#include <sstream>
#include <string>
#include <iostream>
#include <cstdlib>
int gcd_iterative(int m, int n)
{
int r;
while(r != 0)
{
r = m % n;
m = n;
n = r;
}
return m;
}
int gcd_recursive(int m, int n)
{
if(n == 0)
{
return m;
}
else
{
return gcd_recursive(n, m % n);
}
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] << " <integer m> <integer n>" << endl;
return 1;
}
istringstream iss;
iss.str(argv[1]);
int m;
if (!(iss >> m))
{
cerr << "Error: The first argument is not a valid integer." << endl;
return 1;
}
iss.clear();
iss.str(argv[2]);
int n;
if (!(iss >> n))
{
cerr << "Error: The second argument is not a valid integer." << endl;
return 1;
}
cout << "" << endl;
cout << "Iterative: gcd(" << m << ", " << n << ") = " << gcd_iterative(m, n) << endl;
cout << "Recursive: gcd(" << m << ", " << n << ") = " << gcd_recursive(m, n) << endl;
return 0;
}
the print statement is cout << "" << endl;.
The problem is in here:
int r;
while(r != 0)
{
r = m % n;
m = n;
n = r;
}
return m;
The value of r is not initialized to anything, so if the initial value is zero, the algorithm will terminate on the while loop and just return the value of m unchanged.
C++ is not required to initialize the values of stack variables to any default value or anything else, so the value in the r variable is whatever was left on the stack by the previous function call. It would seem that it just so happens that cout << endl; leaves a nonzero value in the correct stack position for r to have a nonzero value, and actually run the algorithm. (Note that if C++ did supply a default value, the default value would presumably be zero anyway, so you would still be forced to initialize).
In general, you should initialize the default values of stack variables to a safe value, rather than relying on their default values. So in this case, the fix is to set r to any nonzero value when you first declare it. E.g. int r = 1;
Side note: In C/C++ any integer value can be used as a boolean, and zero is false, so your while condition can be simplified to just while(r) rather than while(r != 0); these are completely equivalent expressions as far as the while loop is concerned.
when program's result changes like this, it is likely you forgot to initalize some variable. In your case, it looks you forgot to initialize r:
int r;
while(r != 0)
'r' will get an arbitrary value (whatever happens to be in the CPU register). It is likely that without print statements, r is zero and thus the while() loop never runs. You want to set to non-zero value explicitly.
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;
}