0

I'm trying to set up a function that checks if a word or a text is a palindrome. To do that, it splits the text so that every letter is an element of a new array, it takes rid of the white spaces and it makes the reverse array. Then it checks if every element of the two arrays, at the same positions, are equal. If not it returns false, if yes it returns true. Here the function:

function palindrome(str) {
  var low = str.toLowerCase();
  var newArray = low.split("");
  var noSpace = newArray.filter(function(val) {
    return val !== " ";
  });
  var reverse = noSpace.reverse();
  
  function check (a, b) {
    console.log(`checking '${a}' against '${b}'`);
    var partial;
    var result = 1;
    for (var i = 0; i < a.length; i++) {
      console.log(`comparing '${a[i]}' and '${b[i]}'`);
      if (a[i] !== b[i]) {
        result = 0;
      } else {
        partial = 1;
        result *= partial;
      }
    }
    return result;
  }
  
  var result = check(noSpace, reverse);
  if (result == 1) {
    return true;
  } else {
    return false;
  }
  
   
}


palindrome("r y e");

I don't know what's wrong but it seems that the function keeps on returning a true value no matter what word or text I pass to the function. What is wrong with that?

Dema
  • 199
  • 1
  • 2
  • 15
  • 1
    you may want to tag with language name you are using as well. – Marcin Orlowski Aug 18 '17 at 16:48
  • 1
    You may want to indent your code properly. To debug your code, walk through it line by line with the debugger, examining variables as you go. –  Aug 18 '17 at 16:59
  • 1
    Read the documentation for `reverse` real closely. –  Aug 18 '17 at 17:03
  • `let isPalindrome = str.replace(/\s/g, "") === str.replace(/\s/g, "").split("").reverse().join("");` – ASDFGerte Aug 18 '17 at 17:05
  • What about "Madam, I'm Adam"? –  Aug 18 '17 at 17:09
  • About forgetting `toLowerCase`, yes. About the comma and apostrophe, that is not what OP's code would recognize either, and i am not too sure what is intended to be a palindrome. Strings can contain all kinds of weird symbols and with that also all kinds of weird punctuation. The first that comes to mind is `〜`, is that punctuation or part of the sentance? Is `〜んん` a palindrome? Addition: coming from a question i read yesterday, there is a `GREEK SMALL LETTER FINAL SIGMA' (U+03C2)`, when reversing that, do you turn it to a regular sigma to represent it isn't at the end of the string anymore? – ASDFGerte Aug 18 '17 at 17:14
  • @ASDFGerte Try `"".split('').reverse().join('')`. –  Aug 18 '17 at 17:22
  • Yes, one could also write code that splits on code points, and then modifiers, zalgo text and all that comes in and the question diverges towards a billion questions about "what do you want to do?" and 100% of all answers posted will be wrong. Imho the best would be to only take ASCII and set rules for punctuation found in ASCII, that would at least mean the wanted result is clear. – ASDFGerte Aug 18 '17 at 17:25
  • @ASDFGerte Yes and no. If the issue is merely handling all Unicode characters, including supplementary plane characters, then all you need is `[...""].reverse().join('')`. –  Aug 18 '17 at 17:29
  • @torazaburo As already described above, `"ΣΣ".toLowerCase();`. Leaving ASCII will open a lot of questions about what should be a palindrome. Reversing zalgo text and modifiers is from what i can see also not handled by your example. – ASDFGerte Aug 18 '17 at 17:43

5 Answers5

3

Your issue seems to be because reverse() changes the actual array as well. So doing

var reverse = noSpace.reverse();

Will reverse noSpace and assign a reference to it on the variable reverse. That is, both arrays will be the same (reversed) array.

To bypass that, I've used .slice() to create a copy of the original array, and then called .reverse() on that new array, ridding you of any conflicts.

Here's a working snippet of what it looks like:

function palindrome(str) {
    var str_array = str.toLowerCase().split("");
    var no_space = str_array.filter(function(val) {
        return val !== " ";
    });

    // By applying '.slice()', we create a new array
    // reference which can then be reversed and assigned
    // to the 'reverse' variable
    var reverse = no_space.slice().reverse();

    function check(a, b) {
        var partial;
        var result = 1;
        for(var i=0; i < a.length; i++) {
            if(a[i] !== b[i]) {
                // We don't need to keep
                // comparing the two, it
                // already failed
                return 0;
            } else {
                // I've kept this part even though
                // I don't really know what it is
                // intended for
                partial = 1;
                result *= partial;
            }
        }
        return result;
    }
    return check(no_space, reverse) === 1;
}

console.log(palindrome("a b a"));
console.log(palindrome("r y e"));
Matheus Avellar
  • 1,507
  • 1
  • 22
  • 29
  • Looks like reverse() was the one messing up my code. slice() seems to be a good solution. I don't get the 'return check(no_space, reverse) === 1;' at the end of the palindrome function. Could you explain me that? – Dema Aug 18 '17 at 17:55
  • 1
    The `check()` function will return a value (either 0 or 1). We want the `palindrome()` function to return either `true` or `false`. In order to do that, we need the value that `check()` returns to be compared to 0 or 1 (in this case, 1). So if `check()` returns 1, we get `1 === 1` (which is `true`). If `check()` returns 0, we get `0 === 1` (which is `false`). And thus, we have `palindrome()` returning `true` or `false` depending on the return value of the `check()` function – Matheus Avellar Aug 18 '17 at 17:57
  • 1
    Alternatively, you could do `if(check(no_space,reverse)===1) { return true; } else { return false; }`. They will both work exactly the same, it's just a matter of code size – Matheus Avellar Aug 18 '17 at 18:06
1

The way you have coded for palindrome is way too complicated.

But there is one problem with your code: when you do a reverse() it changes the original array as well.

So you will need to make sure that you copy it via slice().

Also you can directly send a boolean result rather than doing a 1 and 0.

Pritam Banerjee
  • 17,953
  • 10
  • 93
  • 108
0

At result *= partial;, 1 * 1 will always equal 1

guest271314
  • 1
  • 15
  • 104
  • 177
  • 1
    But if `result` has previously been set to `0` because of a mismatch, it will remain `0`. –  Aug 18 '17 at 17:04
  • @torazaburo Yes, do you mean to convey that `.reverse()` is the issue? Why do you not post an Answer? – guest271314 Aug 18 '17 at 17:08
  • 1
    I wanted the for loop to compare all the values of the two arrays so I thought I could create a variable in which to store the results of all the comparisons. 1 is the same as the boolean true so I thought I could use that. – Dema Aug 18 '17 at 17:35
  • @Dema Why do you not use `result = 1`? – guest271314 Aug 18 '17 at 17:55
  • I wanted a variable that keeps track of the previous comparisons. If I just use result = 1 but at some point in the two arrays, two values are not the same, the function would return true anyway even if the word is not a palindrome. Is that correct? – Dema Aug 18 '17 at 18:05
  • If `result` is expected to be either `0` or `1`, what is the purpose of `*=` operator? – guest271314 Aug 18 '17 at 18:09
0

I didn't correct your code, but here is a optimized solution for you.

function palindrom(string) {
    var arr = string.split("");

    var lengthToCheck = Math.floor(arr.length / 2);
    for (var i = 0; i < lengthToCheck; i++) {
        if (arr[i] != arr[arr.length - (1 + i)]) {
            return false;
        }
    }

    return true;
}

First I split the array after every charater of the passed String. After that I get the half of the length of the array as it's enough to check just one half. With the for-loop I compare the first half with the second half. As soon as I found two characters that do not match I return false. In case the whole first half matches the second half of the array, the for-loop will be completed and after that true will be returned.

Swittmann
  • 71
  • 1
  • 12
  • 2
    S/he didn't ask for a new implementation. There are a million implementations of palindrome in the world. S/he asked why the posted code was not working. –  Aug 18 '17 at 17:07
0

What's actually happening is .reverse() reverses an array in place, it then stores a reference to that array which is not what you're calling in your check() method.

Simple fix would be to change your if statement:

if (a[i] !== b.reverse()[i])