-4

I have the following program which returns true (1) or false (0) depending on whether the array passed as a parameter is a palindrome or a concatenation of two arrays, both of which are palindromes as well:

#include <iostream>
using namespace std;

bool palindrome(int arr[], int n)
{
    int flag = 0;
    int counter = 0;

    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] == arr[j]) {
                counter++;
                if (counter == (n/2))
                   flag = 1;
            }
        }
    }

    if (flag != 1)
        return false;
    else
        return true;
}

int main()
{
    int arr[] = { 1, 2, 3, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);

    cout << palindrome(arr, n) <<endl;
    return 0;
}

If I use a single palindrome like 1, 2, 3, 2, 1 or 1, 2, 3, 3, 2, 1 I'm getting true and it's working the way it should. If my array however is a concatenated it's not always working properly. For example, if I use 1, 2, 3, 2, 1, 5, 6, 6, 5, I will get true (1) as a result. But with 1, 2, 3, 2, 1, 5, 6, 7, 6, 5 I get false (0) although both parts of the array are palindromes. Or with 1, 2, 3, 3, 1, 5, 6, 6, 5 I get true (1) although the first part doesn't contain a palindrome.

How to make my program display correct result every time and detect if both parts of the array are palindromes? Any help is appreciated.

rsm
  • 3
  • 2
  • 2
    This question's code/phrasing suggests that it came from one of many countless coding challenge/puzzle scam sites. They take advantage of people who want to learn C++ by offering arcane coding puzzles and promising that you don't really need to study and learn C++ with a good textbook for many years, just do a bunch of meaningless coding puzzles. Everyone eventually realizes that they got scammed; these pointless coding puzzles are a waste of time, and there's nothing to be learned from them. But only after spending a lot of time doing them, with nothing to show for it. – Sam Varshavchik Aug 12 '23 at 21:54
  • 1
    *How to make my program display correct result every time* -- That is done by you using the [debugger](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) to see where the program diverges from your plan. When you wrote the program, you had a plan on paper to solve the problem. You shouldn't have written a single line of code if you knew up front your plan was flawed. – PaulMcKenzie Aug 12 '23 at 22:08

2 Answers2

1

The main problem in your code is in the palindrome checking approach. Currently, you are looking for pairs of equal elements within the array and counting how many pairs you find. This is not an accurate way to determine whether an array is a palindrome or a concatenation of two palindromes.

Here's a solution you can try:

#include <iostream>
using namespace std;

bool isPalindrome(int arr[], int start, int end) {
    while (start < end) {
        if (arr[start] != arr[end]) {
            return false;
        }
        start++;
        end--;
    }
    return true;
}

bool checkConcatenatedPalindrome(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        if (isPalindrome(arr, 0, i) && isPalindrome(arr, i + 1, n - 1)) {
            return true;
        }
    }
    return false;
}

bool isAnyPalindrome(int arr[], int n) {
    return isPalindrome(arr, 0, n - 1) || 
checkConcatenatedPalindrome(arr, n);
}

int main() {
    int arr[] = { 1, 2, 3, 2, 1, 5, 6, 7, 6, 5 };
    int n = sizeof(arr) / sizeof(arr[0]);

    cout << isAnyPalindrome(arr, n) << endl;
    return 0;
}

In this code, I have defined a function 'isPalindrome' which checks if a subarray is a palindrome. The 'checkConcatenatedPalindrome' function iterates through the array and checks all possible combinations of two subparts to see if both are palindromes. If it finds a pair that satisfies this condition, it returns true.

This code should be able to handle both palindromes and concatenations of palindromes correctly.

  • Note that `checkConcatenatedPalindrome()` only works for an array with concatenated palindromes, but does not work for an array that is a single palindrome. So the caller would have to do something like `isPalindrome(arr, 0, n-1) || checkConcatenatedPalindrome(arr, n)` to get a proper result. You might want to add a 3rd function to handle that – Remy Lebeau Aug 12 '23 at 22:23
  • You are right, thank you! – Davide Giannulli Aug 12 '23 at 22:26
  • `sizeof(arr) / sizeof(arr[0])` might now (C++17) be replaced by [`std::size(arr)`](https://en.cppreference.com/w/cpp/iterator/size) – Jarod42 Aug 13 '23 at 00:29
1

Your palindrome() function is implemented all wrong, it is not actually checking for a palindrome at all. It is using 2 loops to check if consecutive elements are equal, when it should instead be using 1 loop to check if the 1st and last elements are equal, then if the 2nd and 2nd-to-last elements are equal, and so on until the middle of the array is reached.

Try something more like this instead:

#include <iostream>
using namespace std;

bool palindrome(const int arr[], int n)
{
    if (n < 1)
        return false;

    int middle = n / 2; --n;
    for (int i = 0; i < middle; ++i) {
        if (arr[i] != arr[n-i]) {
            return false;
        }
    }

    return true;
}

template<size_t N>
bool palindrome(const int (&arr)[N])
{
    return palindrome(arr, N);
}

int main()
{
    int arr1[] = { 1, 2, 3, 2, 1 };
    cout << palindrome(arr1) << endl;
    // true

    int arr2[] = { 1, 2, 3, 3, 2, 1 };
    cout << palindrome(arr2) << endl;
    // true

    int arr3[] = { 1, 2, 3, 2, 1, 5, 6, 6, 5 };
    cout << palindrome(arr3) << endl;
    // false

    int arr4[] = { 1, 2, 3, 2, 1, 5, 6, 7, 6, 5 };
    cout << palindrome(arr4) << endl;
    // false

    int arr5[] = { 1, 2, 3, 3, 1, 5, 6, 6, 5 };
    cout << palindrome(arr5) << endl;
    // false

    return 0;
}

Online Demo

Note that when testing a concatenated array for palindromes, you need to know the lengths of each sub-array. That requires extra logic to figure out how long each sub-array is, if the caller doesn't pass in that info. In the case of your 3rd and 5th examples, the sub-arrays are different lengths, so it is not a simple matter of just dividing the whole array in half.

Try something like this:

#include <iostream>
using namespace std;

bool isPalindrome(const int arr[], int n)
{
    if (n < 1)
        return false;

    int middle = n / 2; --n;
    for (int i = 0; i < middle; ++i) {
        if (arr[i] != arr[n-i]) {
            return false;
        }
    }

    return true;
}

bool isSinglePalindromeOrConcatentedPalindromes(const int arr[], int n)
{
    if (isPalindrome(arr, n))
        return true;

    int m = n - 1;
    for(int i = 1; i < m; ++i)
    {
        if (isPalindrome(arr, i) && isPalindrome(arr+i, n-i))
            return true;
    }

    return false;
}

template<size_t N>
bool isSinglePalindromeOrConcatentedPalindromes(const int (&arr)[N])
{
    return isSinglePalindromeOrConcatentedPalindromes(arr, N);
}

int main()
{
    int arr1[] = { 1, 2, 3, 2, 1 };
    cout << isSinglePalindromeOrConcatentedPalindromes(arr1) << endl;
    // true

    int arr2[] = { 1, 2, 3, 3, 2, 1 };
    cout << isSinglePalindromeOrConcatentedPalindromes(arr2) << endl;
    // true

    int arr3[] = { 1, 2, 3, 2, 1, 5, 6, 6, 5 };
    cout << isSinglePalindromeOrConcatentedPalindromes(arr3) << endl;
    // true

    int arr4[] = { 1, 2, 3, 2, 1, 5, 6, 7, 6, 5 };
    cout << isSinglePalindromeOrConcatentedPalindromes(arr4) << endl;
    // true

    int arr5[] = { 1, 2, 3, 3, 1, 5, 6, 6, 5 };
    cout << isSinglePalindromeOrConcatentedPalindromes(arr5) << endl;
    // false

    return 0;
}

Online Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • C-array by reference, nice. I like how it cleans up the calls in main, but I'd probably use a `std::array` at that point. – sweenish Aug 13 '23 at 00:11