# Codeforces - problem: (A) Mike and palindrome

While on SO someone posted this question and I gave it a quick try. My solution passed all the testcases.

Link to the problem: Problem: (A) Mike and palindrome

Question:

Mike has a string s consisting of only lowercase English letters. He wants to change exactly one character from the string so that the resulting one is a palindrome.

A palindrome is a string that reads the same backward as forward, for example strings "z", "aaa", "aba", "abccba" are palindromes, but strings "codeforces", "reality", "ab" are not.

Input

The first and single line contains string s (1 ≤ |s| ≤ 15).

Output

Print "YES" (without quotes) if Mike can change exactly one character so that the resulting string is palindrome or "NO" (without quotes) otherwise.

Examples

input: abccaa output: YES

input: abbcca output: NO

input: abcda output: YES

### CODE

#include <string>
#include <iostream>

int main(){
std::string str;
std::cin >> str;
int i{0}, j{str.length() - 1}, cnt{0};

// Check from both the ends if characters are equal.
while(i < j){
if (str[i]!= str[j]) ++cnt;

++i;
--j;
}

// If there's one mismatch.
if ( cnt == 1 ) std::cout << "YES";
// Odd length string with 0 mismatches e.g: abcba, can change middle char.
else if ( cnt == 0 && str.length()&1 ) std::cout << "YES";
else std::cout << "NO";
}


Formatting: Don't be so stingy with the indentation, give your code some room to breathe!

Validating input: You should check if std::cin was successful.

It is always good if you can split out complexities into functions. Your main function does it all, read input, calc result, and write the output. I would suggest you created a separate function to determine if the string is a palindrome:

bool isPalindromeWithOneChange(const std::string& str) {
// ...
// ...
return cnt == 1 || (cnt == 0 && length % 2);
}


And change main to the following:

int main() {
std::string str;
std::cin >> str;
if (std::cin.fail() || std::cin.bad()) {
std::cerr << "Input failure";
return 1;
}
if (isPalindromeWithOneChange(str))
std::cout << "YES";
else
std::cout << "NO";
}


Note that the underlying data type for array indexes and length is size_t.

This is just personal preferences, but I find the following easier to read with the decleration on seperate lines:

const std::size_t length = str.length();
std::size_t i = 0;
std::size_t j = length - 1;
std::size_t cnt = 0;


With the decleration of length you can replace this line:

else if ( cnt == 0 && str.length()&1 ) std::cout << "YES";


With the following

else if ( cnt == 0 && length % 2) std::cout << "YES";


You can break out of the while loop as soon as cnt is larger than one.

Final nitpicking / brain farts

Whether you use length & 1 or length % 2 is entirely up to you but one thing you lose with & 1 is the intention. You should write what you want your code to do and rely on the compiler to handle it correctly.

• Any decent compiler will generate exactly the same code for & 1 and % 2 if optimizations are turned on, at least if it can see that length is an unsigned number. Oct 18 '21 at 15:27
• @upkajdt Thank you for the review. length&1 is a force of habit. Oct 18 '21 at 16:24
• @upkajdt Do you know why the formatting does not work correctly in the last paragraph? Apparently, If you put a newline after <br> it should work Oct 18 '21 at 16:26
• @Ch3steR, thanks, that fixed it. I would suggest you have a look at codegolf.stackexchange.com if you like these sorts of challenges.
– jdt
Oct 18 '21 at 16:47
• BTW: Nearly always, prefer std::string_view over std::string const& for parameter-type. The exception is if you might need zero-termination, or called code expects that exact type. Oct 18 '21 at 16:50