Palindrome detection: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎Recursive: change code)
No edit summary
Line 31: Line 31:
This function compares the first char with the last, the second with the one previous the last, and
This function compares the first char with the last, the second with the one previous the last, and
so on. The first different pair it finds, return 0 (false); if all the pairs were equal, then return 1 (true).
so on. The first different pair it finds, return 0 (false); if all the pairs were equal, then return 1 (true).
You only need to go up to (the length) / 2 because the second half just re-checks the same stuff as the first half;
and if the length is odd, the middle doesn't need to be checked (so it's okay to do integer division by 2, which rounds down).


<c>#include <string.h>
<c>int palindrome(char *s)

int palindrome(const char *s)
{
{
int i,l;
int i,l;
for(l=0; s[l]!=0; l++) ;
l = strlen(s);
for(i=0; i<l; i++)
for(i=0; i<l/2; i++)
{
{
if ( s[i] != s[l-i-1] ) return 0;
if ( s[i] != s[l-i-1] ) return 0;
}
return 1;
}</c>
More idiomatic version:
<c>int palindrome(const char *s)
{
const char *t; /* t is a pointer that traverses backwards from the end */
for (t = s; *t != '\0'; t++) ; t--; /* set t to point to last character */
while (s < t)
{
if ( *s++ != *t-- ) return 0;
}
}
return 1;
return 1;
Line 48: Line 63:
itself a palindrome.
itself a palindrome.


<c>int palindrome_r(char *s, int b, int e)
<c>int palindrome_r(const char *s, int b, int e)
{
{
if ( e <= 1 ) return 1;
if ( e <= 1 ) return 1;
Line 58: Line 73:


<c>#include <stdio.h>
<c>#include <stdio.h>
#include <string.h>
/* testing */
/* testing */
int main()
int main()
{
{
char *t = "ingirumimusnocteetconsumimurigni";
const char *t = "ingirumimusnocteetconsumimurigni";
char *template = "sequence \"%s\" is%s palindrome\n";
const char *template = "sequence \"%s\" is%s palindrome\n";
int l;
int l = strlen(t);
for(l=0; t[l]!=0; l++) ;
printf(template,
printf(template,
t, palindrome(t) ? "" : "n't");
t, palindrome(t) ? "" : "n't");
Line 92: Line 107:


<code lang="Haskell"><pre>
<code lang="Haskell"><pre>
is_palindrome x | x == reverse x = True
is_palindrome x = x == reverse x</pre></code>
| otherwise = False</pre></code>




Line 164: Line 178:
<perl>sub palindrome
<perl>sub palindrome
{
{
my @s = split //, shift(@_);
my $s = shift;
if ( join("", @s) eq join("",reverse(@s)) ) { return 1; }
return $s eq reverse $s;
return 0;
}
}


sub palindrome_c
sub palindrome_c
{
{
my @s = split //, shift(@_);
my $s = shift;
my $l = scalar(@s);
for my $i (0 .. length($s) >> 1)
for(my $i; $i < $l; $i++)
{
{
if ( $s[$i] ne $s[$l - $i - 1] ) { return 0; }
return 0 unless substr($s, $i, 1) eq substr($s, -1-$i, 1);
}
}
return 1;
return 1;
Line 184: Line 196:
<perl>sub palindrome_r
<perl>sub palindrome_r
{
{
my @s = split//, shift(@_);
my $s = shift;
if ( length(@s) <= 1 ) { return 1; }
if (length $s <= 1) { return 1; }
elsif (substr($s, 0, 1) ne substr($s, -1, 1)) { return 0; }
my $f = pop(@s); # strip the last char
else { return palindrome_r(substr($s, 1, -1)); }
my $l = shift(@s); # strip the first char
return 0 if ( $l ne $f );
return palindrome_r(join("",@s));
}</perl>
}</perl>


Line 205: Line 215:
mtest "ingirumimusnocteetconsumimurigni", \&palindrome_c;
mtest "ingirumimusnocteetconsumimurigni", \&palindrome_c;


exit 0;</perl>
exit;</perl>




Line 224: Line 234:
if len(s) <= 1:
if len(s) <= 1:
return True
return True
elif s[0] != s[-1]:
return False
else:
else:
return is_palindrome_r(s[1:-1])</python>
if not s[0] == s[-1]:
return False
return is_palindrome_r(s[1:len(s)-1])</python>


===Testing===
===Testing===

Revision as of 20:01, 5 December 2008

Task
Palindrome detection
You are encouraged to solve this task according to the task description, using any language you may know.

Write at least one function/method (or whatever it is called in your preferred language) to check if a sequence of characters (or bytes) is a palindrome or not. The function must return a boolean value (or something that can be used as boolean value, like an integer).

It is not mandatory to write also an example code that uses the function, unless its usage could be not clear (e.g. the provided recursive C solution needs explanation on how to call the function).

It is not mandatory to handle properly encodings (see String length), i.e. it is admissible that the function does not recognize 'salàlas' as palindrome.

The function must not ignore spaces and punctuations.

An example of latin palindrome is the sentence "In girum imus nocte et consumimur igni", roughly translated as: we walk around in the night and we are burnt by the fire (of love). To do your test with it, you must make it all the same case and strip spaces.


C

Non-recursive

This function compares the first char with the last, the second with the one previous the last, and so on. The first different pair it finds, return 0 (false); if all the pairs were equal, then return 1 (true). You only need to go up to (the length) / 2 because the second half just re-checks the same stuff as the first half; and if the length is odd, the middle doesn't need to be checked (so it's okay to do integer division by 2, which rounds down).

<c>#include <string.h>

int palindrome(const char *s) {

  int i,l;
  l = strlen(s);
  for(i=0; i<l/2; i++)
  {
    if ( s[i] != s[l-i-1] ) return 0; 
  }
  return 1;

}</c> More idiomatic version: <c>int palindrome(const char *s) {

  const char *t; /* t is a pointer that traverses backwards from the end */
  for (t = s; *t != '\0'; t++) ; t--; /* set t to point to last character */
  while (s < t)
  {
    if ( *s++ != *t-- ) return 0; 
  }
  return 1;

}</c>

Recursive

A single char is surely a palindrome; a string is a palindrome if first and last char are the same and the remaining string (the string starting from the second char and ending to the char preceding the last one) is itself a palindrome.

<c>int palindrome_r(const char *s, int b, int e) {

  if ( e <= 1 ) return 1;
  if ( s[b] != s[e-1] ) return 0;
  return palindrome_r(s, b+1, e-1);

}</c>

Testing

<c>#include <stdio.h>

  1. include <string.h>

/* testing */ int main() {

  const char *t = "ingirumimusnocteetconsumimurigni";
  const char *template = "sequence \"%s\" is%s palindrome\n";
  int l = strlen(t);
  
  printf(template,
         t, palindrome(t) ? "" : "n't");
  printf(template,
         t, palindrome_r(t, 0, l) ? "" : "n't");
  return 0;

}</c>

C++

The C solutions also work in C++, but C++ allows a simpler one: <cpp>

  1. include <string>
  2. include <algorithm>

bool is_palindrome(std::string const& s) {

 return std::equal(s.begin(), s.end(), s.rbegin());

} </cpp>

Haskell

Non-recursive

A string is a palindrome if reversing it we obtain the same string.

is_palindrome x = x == reverse x


Recursive

See the C palindrome_r code for an explanation of the concept used in this solution.

is_palindrome_r x | length x <= 1 = True
                  | head x == last x = is_palindrome_r . tail. init $ x
                  | otherwise = False

Java

Non-Recursive

<java>public static boolean pali(String testMe){ StringBuilder sb = new StringBuilder(testMe); return sb.toString().equals(sb.reverse().toString()); }</java>

Recursive

<java>public static boolean rPali(String testMe){ if(testMe.length()<=1){ return true; } if(testMe.charAt(0)==testMe.charAt(testMe.length()-1)){ return rPali(testMe.substring(1, testMe.length()-1)); } return false; }</java>

MAXScript

Non-recursive

fn isPalindrome s =
(
    local reversed = ""
    for i in s.count to 1 by -1 do reversed += s[i]
    local reversed == s
)

Recursive

fn isPalindrome_r s =
(
    if s.count <= 1 then
    (
        true
    )
    else
    (
        if s[1] != s[s.count] then
        (
            return false
        )
        isPalindrome_r (substring s 2 (s.count-2))
    )
)

Testing

local p = "ingirumimusnocteetconsumimurigni"
format ("'%' is a palindrome? %\n") p (isPalindrome p)
format ("'%' is a palindrome? %\n") p (isPalindrome_r p)

Perl

Non-recursive

One solution (palindrome_c) is the same as the C non-recursive solution palindrome; while Perl palindrome sub uses the idea that a word is a palindrome if, once reverted, it looks the same as the original word (this is the definition of a palindrome).

<perl>sub palindrome {

 my $s = shift;
 return $s eq reverse $s;

}

sub palindrome_c {

 my $s = shift;
 for my $i (0 .. length($s) >> 1)
 {
    return 0 unless substr($s, $i, 1) eq substr($s, -1-$i, 1);
 }
 return 1;

}</perl>

Recursive

<perl>sub palindrome_r {

 my $s = shift;
 if (length $s <= 1) { return 1; }
 elsif (substr($s, 0, 1) ne substr($s, -1, 1)) { return 0; }
 else { return palindrome_r(substr($s, 1, -1)); }

}</perl>


Testing

<perl>sub mtest {

  my ( $t, $func ) = @_;
  printf("sequence \"%s\" is%s palindrome\n",
          $t, &$func($t) ? "" : "n't");

} mtest "ingirumimusnocteetconsumimurigni", \&palindrome; mtest "ingirumimusnocteetconsumimurigni", \&palindrome_r; mtest "ingirumimusnocteetconsumimurigni", \&palindrome_c;

exit;</perl>


Python

Non-recursive

This one uses the reversing the string technics (to revert a string Python can use the odd but right syntax string[::-1])

<python>def is_palindrome(s):

 return s == s[::-1]</python>

Recursive

<python>def is_palindrome_r(s):

 if len(s) <= 1:
   return True
 elif s[0] != s[-1]:
   return False
 else:
   return is_palindrome_r(s[1:-1])</python>

Testing

<python>p = "ingirumimusnocteetconsumimurigni" print "'" + p + "' is palindrome? ", is_palindrome(p) print "'" + p + "' is palindrome? ", is_palindrome_r(p)</python>