i already studied c++ in school and during the last days i have been doing the beginner c++ course of codecademy. On codecademy there is an exercise in which i have to identify palindrome words and return true or false. I haven't been able to resolve it so i saw the solution and it was:
#include <iostream>
// Define is_palindrome() here:
bool is_palindrome(std::string text) {
std::string reversed_text = "";
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
if (reversed_text == text) {
return true;
}
return false;
}
int main() {
std::cout << is_palindrome("madam") << "\n";
std::cout << is_palindrome("ada") << "\n";
std::cout << is_palindrome("lovelace") << "\n";
}
My only doubt is with this line:
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
i know it has to do with index values but i can't understand why it has a -1.
Could somebody explain this to me?
i thanks in advance whoever read this post. i'm sorry for my english or my poor using of stacksoverflow, i'm italian and that's my first time using this site.
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
text is basically the string that you receive as input via function. size() is function that returns the size of the string i.e text.size() so in our test cases it will return
5 for madam
3 for ada
8 for lovelace
If you think about the strings as an array with exact above size then the index range will become
0-4 for madam
0-2 for ada
0-7 for lovelace
So that's why the text.size()-1 is using as the starting index of loop. text.size() will return the actual size of string and then minus 1 to get the index of last character in string.
so behind the scene, your loop iteration will look something like below
for (int i = 4; i >= 0; i--) { //for madam
}
//aca
for (int i = 2; i >= 0; i--) {
}
//lovelace
for (int i = 7; i >= 0; i--) {
}
I hope it clear out your confusion.
Thanks,
i know it has to do with index values but i can't understand why it has a -1.
If a string is n characters long, the characters in it are indexed from 0 to n−1.
Since the loop works with characters from the end of the string to the beginning, it starts with index text.size() - 1.
However, the solution you have shown is nominally inefficient. There is no reason to make a reversed copy of the string. It suffices merely to test whether each character in the first half of the string equals the character in the reflected position:
bool is_palindrome(std::string text)
{
size_t e = text.size();
for (int i = 0; i < e/2; ++i)
if (text[i] != text[e-1-i])
return false;
return true;
}
If using a for loop to reverse the string is confusing, you could also use the reverse function
std::string reversed_text = text;
reverse(reversed_text.begin(),reversed_text.end());
which just helps flip the entire string reversed_text and can achieve the same result in a simpler way.
Related
Fairly new to coding. Trying some of the easy projects at LeetCode, and failing... Ha! I am trying to take an integer and convert it to a string so I can reverse it, then re-convert the reversed string back into a integer.
This code is throwing the "terminate after throwing and instance of 'std::invalid argument' what(): stoi" error. I've spent an hour searching google and other questions here on SO, but can't figure out why it's not working.
bool isPalindrome(int x) {
std::string backwards ="";
std::string NumString = std::to_string(x);
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
int check = std::stoi(backwards);
if (check == x) {
return true;
}
else {
return false;
}
}
EDIT: I think I figured it out. It was adding the null character to the end of the string upon first conversion, then adding it to the beginning of the string when I reversed it. Spaces can't be converted to integers.
So... I changed this line and it works:
for (int i = NumString.size() - 1; i >= 0 ; i--)
you can also reverse number without using string.
bool isPalindrome(int x) {
long long rev = 0;
int cur = x;
while( cur > 0) {
rev *= 10;
rev += cur % 10;
cur /=10;
}
return rev == x;
}
Its simpler than your answer that you edited in. YOu have
for (int i = NumString.size(); i >= 0 ; i--) {
backwards += NumString[i];
}
Imagine that Numstring has length 3 (no matter what spaces, digits,....)
So now you are efectively doing
for (int i = 3; i >= 0 ; i--) {
backwards += NumString[i];
}
So first loop goes
backwards += NumString[3];
well the indexes of things in an array of length 3 in c++ are 0,1,2. YOu are going one off the end
This is why you see loops doing
for(int i = 0; i < len; i++){}
Note the i < len not i <= len
I'm having trouble wrapping my head around this piece of code for finding out if something is a palindrome or not.
I was hoping someone could break it down for me and make it simple stupid.
I included the full code but I think the part that's baffling me, is this line
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
Thanks in advance!
#include <iostream>
// Define is_palindrome() here:
bool is_palindrome(std::string text){
std::string reversed_text = "";
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
if (reversed_text == text){
return true;
}
return false;
}
}
int main() {
std::cout << is_palindrome("madam") << "\n";
std::cout << is_palindrome("ada") << "\n";
std::cout << is_palindrome("lovelace") << "\n";
}
The code creates a string that is the reverse of the first one and compare if they are equal.
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
Simply reverses input string. It iterates input string barwards and adds chars to reversed_text char by char. If text is warchant, then reversed_text would be tnahcraw.
More C++-ish way to do this is using std::reverse:
// don't forget to include this
#include <algorithm>
bool is_palindrome(std::string text){
std::string reversed = text;
std::reverse(reversed.begin(), reversed.end());
...
This function is not "most efficient code", but it will do the job.
The code functions by inputting the reversed version of your input word and checks if the reversed version and the original version of the word are the same. As for the for loop, it works like this:
Get the position of the last character of the input word
Input that character into your reversed_text string
Continue as i decreases by 1, until the first character of the input word is inputted into the reversed_text string
This line of code reads the word from reverse direction and concatenates with the variable reversed_text.
for (int i = text.size() - 1; i >= 0; i--)
reversed_text += text[i];
For example:
if text = "HELLO" then reversed_text="OLLEH"
#include <iostream>
// Define is_palindrome() here:
bool is_palindrome(std::string text) {
std::string reversed_text = "";
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
if (reversed_text == text) {
return true;
}
return false;
}
int main() {
std::cout << is_palindrome("madam") << "\n";
std::cout << is_palindrome("ada") << "\n";
std::cout << is_palindrome("lovelace") << "\n";
}
Could someone please explain to me in great detail on how this for loop works? I would like to know how the code sequences each letter to figure out if the word is a palindrome.
To begin, we define the is_palindrome function to return a bool. Our input string is the function parameter.
Then, we reverse the text using the following for loop.
std::string reversed_text = "";
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
This code simply defines a string called reversed_string. It then reverses the input string one letter at a time (text[i] gives the i+1 letter in the input string, reversed_text += text[i] adds this letter to the string).
After that, the code is a simple if statement. It compares the original string and the reversed string. If both are the same, the function returns true. If they are not the same, the function returns false.
if (reversed_text == text) {
return true;
}
return false;
}
The ability to read code is far more important than the ability to write it, as in most of your programming life, you will read a lot more than write. More often than not, it's someone else's code. If you lack the skill, you will have a hard time working in this field.
Here's above function body commented:
// prepare a string variable to hold the reversed input
std::string reversed_text = "";
// append each character from the input to variable above, starting from the last character, effectively generating its reversed version
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
// it's a palindrome if the reversed input is the same as the input
if (reversed_text == text) {
return true;
}
// not a palindrome otherwise
return false;
First of all, I know there are many duplicates of this question but I have tried and tried and non have been able to solve my issue.
I have the following string
string s = "asdfqasdfp";
I need to loop through the string and find which sub string appears more than once. so in this case its
asdf
I have made the following code but I do not know why it doesn't work. I start from the full string and go down one at a time. I should get occurence value of 2.
int t = s.length();
for (int i = 0; i < s.length(); i++) {
string str = s.substr(0, t);
int occurence = 0;
size_t start = 0;
while ((start = s.find(str, start)) != string::npos) {
++occurence;
start += str.length();
}
if (occurence > 1) {
cout << occurence;
}
else {
--t;
}
}
EDIT: I only want the largest substring that the string contains, in this case
"asdf"
Here's a fixed version of your code, including Daniel's suggestions (thanks! Daniel's demo)
for (size_t t = s.length(); t >= 1; --t) {
for (size_t i = 0; (i + t) <= s.length(); i++) {
std::string str = s.substr(i, t);
size_t occurence = 0;
size_t start = 0;
while ((start = s.find(str, start)) != std::string::npos) {
++occurence;
start += str.length();
}
if (occurence > 1) {
std::cout << str << " " << occurence << std::endl;
return 0;
}
}
}
You need to
loop over t, and decrement it at the end of the i loop rather than inside
limit i to s.length() - t, so that there's always a t-length string to take as str
fix your substr to start at i not 0
You can also stop at the first time you find a duplicate, since this will be a largest duplicate (e.g. if there are two pairs of duplicates of length 4 it will find one of them, but it doesn't sound like you need both). You should also use size_t throughout as your integer type since that's what's used by the string functions here.
Looks ok. Do you need an << endl; to see output in your terminal?
Write a function countMatches that searches the substring in the given string and returns how many times the substring appears in the string.
I've been stuck on this awhile now (6+ hours) and would really appreciate any help I can get. I would really like to understand this better.
int countMatches(string str, string comp)
{
int small = comp.length();
int large = str.length();
int count = 0;
// If string is empty
if (small == 0 || large == 0) {
return -1;
}
// Increment i over string length
for (int i = 0; i < small; i++) {
// Output substring stored in string
for (int j = 0; j < large; j++) {
if (comp.substr(i, small) == str.substr(j, large)) {
count++;
}
}
}
cout << count << endl;
return count;
}
When I call this function from main, with countMatches("Hello", "Hello"); I get the output of 5. Which is completely wrong as it should return 1. I just want to know what I'm doing wrong here so I don't repeat the mistake and actually understand what I am doing.
I figured it out. I did not need a nested for loop because I was only comparing the secondary string to that of the string. It also removed the need to take the substring of the first string. SOOO... For those interested, it should have looked like this:
int countMatches(string str, string comp)
{
int small = comp.length();
int large = str.length();
int count = 0;
// If string is empty
if (small == 0 || large == 0) {
return -1;
}
// Increment i over string length
for (int i = 0; i < large; i++) {
// Output substring stored in string
if (comp == str.substr(i, small)) {
count++;
}
}
cout << count << endl;
return count;
}
The usual approach is to search in place:
std::string::size_type pos = 0;
int count = 0;
for (;;) {
pos = large.find(small, pos);
if (pos == std::string::npos)
break;
++count;
++pos;
}
That can be tweaked if you're not concerned about overlapping matches (i.e., looking for all occurrences of "ll" in the string "llll", the answer could be 3, which the above algorithm will give, or it could be 2, if you don't allow the next match to overlap the first. To do that, just change ++pos to pos += small.size() to resume the search after the entire preceding match.
The problem with your function is that you are checking that:
Hello is substring of Hello
ello is substring of ello
llo is substring of llo
...
of course this matches 5 times in this case.
What you really need is:
For each position i of str
check if the substring of str starting at i and of length = comp.size() is exactly comp.
The following code should do exactly that:
size_t countMatches(const string& str, const string& comp)
{
size_t count = 0;
for (int j = 0; j < str.size()-comp.size()+1; j++)
if (comp == str.substr(j, comp.size()))
count++;
return count;
}