Palindrome detection: Difference between revisions

From Rosetta Code
Content added Content deleted
m (<lang>)
Line 28: Line 28:


=={{header|Ada}}==
=={{header|Ada}}==
<code ada>
<lang ada>
function Palindrome (Text : String) return Boolean is
function Palindrome (Text : String) return Boolean is
begin
begin
Line 38: Line 38:
return True;
return True;
end Palindrome;
end Palindrome;
</code>
</lang>
=={{header|C}}==
=={{header|C}}==


Line 48: Line 48:
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).
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).


<code c>#include <string.h>
<lang c>#include <string.h>


int palindrome(const char *s)
int palindrome(const char *s)
Line 59: Line 59:
}
}
return 1;
return 1;
}
}</code>
</lang>
More idiomatic version:
More idiomatic version:
<code c>int palindrome(const char *s)
<lang c>int palindrome(const char *s)
{
{
const char *t; /* t is a pointer that traverses backwards from the end */
const char *t; /* t is a pointer that traverses backwards from the end */
Line 70: Line 71:
}
}
return 1;
return 1;
}
}</code>
</lang>


===Recursive===
===Recursive===
Line 77: Line 79:
itself a palindrome.
itself a palindrome.


<lang c>
<code c>int palindrome_r(const char *s, int b, int e)
int palindrome_r(const char *s, int b, int e)
{
{
if ( e <= 1 ) return 1;
if ( e <= 1 ) return 1;
if ( s[b] != s[e-1] ) return 0;
if ( s[b] != s[e-1] ) return 0;
return palindrome_r(s, b+1, e-1);
return palindrome_r(s, b+1, e-1);
}
}</code>
</lang>


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


<code c>#include <stdio.h>
<lang c>#include <stdio.h>
#include <string.h>
#include <string.h>
/* testing */
/* testing */
Line 100: Line 104:
t, palindrome_r(t, 0, l) ? "" : "n't");
t, palindrome_r(t, 0, l) ? "" : "n't");
return 0;
return 0;
}
}</code>
</lang>


=={{header|C++}}==
=={{header|C++}}==
The C solutions also work in C++, but C++ allows a simpler one:
The C solutions also work in C++, but C++ allows a simpler one:
<code cpp>
<lang cpp>
#include <string>
#include <string>
#include <algorithm>
#include <algorithm>
Line 112: Line 117:
return std::equal(s.begin(), s.end(), s.rbegin());
return std::equal(s.begin(), s.end(), s.rbegin());
}
}
</code>
</lang>


=={{header|Forth}}==
=={{header|Forth}}==
Line 132: Line 137:
A string is a palindrome if reversing it we obtain the same string.
A string is a palindrome if reversing it we obtain the same string.


<code haskell>
<lang haskell>
is_palindrome x = x == reverse x</code>
is_palindrome x = x == reverse x
</lang>




Line 140: Line 146:
See the C palindrome_r code for an explanation of the concept used in this solution.
See the C palindrome_r code for an explanation of the concept used in this solution.


<code haskell>
<lang haskell>
is_palindrome_r x | length x <= 1 = True
is_palindrome_r x | length x <= 1 = True
| head x == last x = is_palindrome_r . tail. init $ x
| head x == last x = is_palindrome_r . tail. init $ x
| otherwise = False</code>
| otherwise = False
</lang>


=={{header|J}}==
=={{header|J}}==
Line 168: Line 175:
=={{header|Java}}==
=={{header|Java}}==
===Non-Recursive===
===Non-Recursive===
<lang java>
<code java>public static boolean pali(String testMe){
public static boolean pali(String testMe){
StringBuilder sb = new StringBuilder(testMe);
StringBuilder sb = new StringBuilder(testMe);
return sb.toString().equalsIgnoreCase(sb.reverse().toString());
return sb.toString().equalsIgnoreCase(sb.reverse().toString());
}
}</code>
</lang>
===Recursive===
===Recursive===
<lang java>
<code java>public static boolean rPali(String testMe){
public static boolean rPali(String testMe){
if(testMe.length()<=1){
if(testMe.length()<=1){
return true;
return true;
Line 181: Line 191:
}
}
return rPali(testMe.substring(1, testMe.length()-1));
return rPali(testMe.substring(1, testMe.length()-1));
}
}</code>
</lang>


=={{header|Logo}}==
=={{header|Logo}}==
Line 223: Line 234:


=={{header|Modula-3}}==
=={{header|Modula-3}}==
<code modula3>
<lang modula3>
MODULE Palindrome;
MODULE Palindrome;


Line 239: Line 250:
END isPalindrome;
END isPalindrome;
END Palindrome.
END Palindrome.
</code>
</lang>


=={{header|OCaml}}==
=={{header|OCaml}}==


<code ocaml>let is_palindrome str =
<lang ocaml>let is_palindrome str =
let last = String.length str - 1 in
let last = String.length str - 1 in
try
try
Line 252: Line 263:
(true)
(true)
with Exit ->
with Exit ->
(false)</code>
(false)
</lang>


and here a function to remove the white spaces in the string:
and here a function to remove the white spaces in the string:


<code ocaml>let rem_space str =
<lang ocaml>let rem_space str =
let len = String.length str in
let len = String.length str in
let res = String.create len in
let res = String.create len in
Line 269: Line 281:
aux (i+1) (j+1)
aux (i+1) (j+1)
in
in
aux 0 0</code>
aux 0 0
</lang>


and to make the test case insensitive, just use the function <code>String.lowercase</code>.
and to make the test case insensitive, just use the function <code>String.lowercase</code>.
Line 281: Line 294:
the same as the original word (this is the definition of a palindrome).
the same as the original word (this is the definition of a palindrome).


<code perl>sub palindrome
<lang perl>sub palindrome
{
{
my $s = shift;
my $s = shift;
Line 295: Line 308:
}
}
return 1;
return 1;
}
}</code>
</lang>


===Recursive===
===Recursive===


<code perl>sub palindrome_r
<lang perl>sub palindrome_r
{
{
my $s = shift;
my $s = shift;
Line 305: Line 319:
elsif (substr($s, 0, 1) ne substr($s, -1, 1)) { return 0; }
elsif (substr($s, 0, 1) ne substr($s, -1, 1)) { return 0; }
else { return palindrome_r(substr($s, 1, -1)); }
else { return palindrome_r(substr($s, 1, -1)); }
}
}</code>
</lang>




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


<code perl>sub mtest
<lang perl>sub mtest
{
{
my ( $t, $func ) = @_;
my ( $t, $func ) = @_;
Line 320: Line 335:
mtest "ingirumimusnocteetconsumimurigni", \&palindrome_c;
mtest "ingirumimusnocteetconsumimurigni", \&palindrome_c;


exit;</code>
exit;
</lang>


=={{header|Python}}==
=={{header|Python}}==
Line 330: Line 346:
but right syntax <tt>string[::-1]</tt>)
but right syntax <tt>string[::-1]</tt>)


<code python>def is_palindrome(s):
<lang python>def is_palindrome(s):
return s == s[::-1]</code>
return s == s[::-1]
</lang>


===Recursive===
===Recursive===


<code python>def is_palindrome_r(s):
<lang python>def is_palindrome_r(s):
if len(s) <= 1:
if len(s) <= 1:
return True
return True
Line 341: Line 358:
return False
return False
else:
else:
return is_palindrome_r(s[1:-1])</code>
return is_palindrome_r(s[1:-1])
</lang>


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


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


=={{header|Ruby}}==
=={{header|Ruby}}==
Line 354: Line 373:
===Non-recursive===
===Non-recursive===


<code ruby>def is_palindrome(s)
<lang ruby>def is_palindrome(s)
s == s.reverse
s == s.reverse
end</code>
end
</lang>


===Recursive===
===Recursive===


<code ruby>def is_palindrome_r(s)
<lang ruby>def is_palindrome_r(s)
if s.length <= 1
if s.length <= 1
true
true
Line 368: Line 388:
is_palindrome_r(s[1..-2])
is_palindrome_r(s[1..-2])
end
end
end</code>
end
</lang>


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


<lang ruby>
<code ruby>p = "ingirumimusnocteetconsumimurigni"
p = "ingirumimusnocteetconsumimurigni"
print "'" + p + "' is palindrome? ", is_palindrome(p), "\n"
print "'" + p + "' is palindrome? ", is_palindrome(p), "\n"
print "'" + p + "' is palindrome? ", is_palindrome_r(p), "\n"</code>
print "'" + p + "' is palindrome? ", is_palindrome_r(p), "\n"
</lang>

Revision as of 14:34, 31 January 2009

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. The compliance to the aforementioned, strict or not, requirements completes the task.


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.

It might be useful for this task to know how to reverse a string.

Ada

<lang ada> function Palindrome (Text : String) return Boolean is begin

  for Offset in 0..Text'Length / 2 - 1 loop
     if Text (Text'First + Offset) /= Text (Text'Last - Offset) then
        return False;
     end if;
  end loop;
  return True;

end Palindrome; </lang>

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).

<lang 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;

} </lang> More idiomatic version: <lang 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;

} </lang>

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.

<lang 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);

} </lang>

Testing

<lang 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;

} </lang>

C++

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

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

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

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

} </lang>

Forth

: palindrome? ( caddr len -- ? )
  1- bounds
  begin  2dup >
  while  over c@ over c@ =
  while  1+ swap 1- swap
  repeat 2drop false
  else   2drop true
  then ;

Haskell

Non-recursive

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

<lang haskell> is_palindrome x = x == reverse x </lang>


Recursive

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

<lang haskell> is_palindrome_r x | length x <= 1 = True

                 | head x == last x = is_palindrome_r . tail. init $ x
                 | otherwise = False

</lang>

J

Non-recursive

Reverse and match method

rmP=: -: |.

example

   rmP ;;: tolower 'In girum imus nocte et consumimur igni'
1

Recursive

tacit and explicit verbs:

sPt=:0:`($:@(}.@}:))@.({.={:)`1:@.(1>:#)

sPx=: 3 : 0
 if. 1>:#y do. 1 return. end.
 if. ({.={:)y do. sPx }.}:y else. 0 end.
)

Java

Non-Recursive

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

Recursive

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

to palindrome? :w
  output equal? :w reverse :w
end

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)

Modula-3

<lang modula3> MODULE Palindrome;

IMPORT Text;

PROCEDURE isPalindrome(string: TEXT): BOOLEAN =

 VAR len := Text.Length(string);
 BEGIN
   FOR i := 0 TO len DIV 2 - 1 DO
     IF Text.GetChar(string, i) # Text.GetChar(string, (len - i - 1)) THEN
       RETURN FALSE;
     END;
   END;
   RETURN TRUE;
 END isPalindrome;

END Palindrome. </lang>

OCaml

<lang ocaml>let is_palindrome str =

 let last = String.length str - 1 in
 try
   for i = 0 to last / 2 do
     let j = last - i in
     if str.[i] <> str.[j] then raise Exit
   done;
   (true)
 with Exit ->
   (false)

</lang>

and here a function to remove the white spaces in the string:

<lang ocaml>let rem_space str =

 let len = String.length str in
 let res = String.create len in
 let rec aux i j =
   if i >= len
   then (String.sub res 0 j)
   else match str.[i] with
   | ' ' | '\n' | '\t' | '\r' ->
       aux (i+1) (j)
   | _ ->
       res.[j] <- str.[i];
       aux (i+1) (j+1)
 in
 aux 0 0

</lang>

and to make the test case insensitive, just use the function String.lowercase.

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).

<lang 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;

} </lang>

Recursive

<lang 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)); }

} </lang>


Testing

<lang 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; </lang>

Python

Non-recursive

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

<lang python>def is_palindrome(s):

 return s == s[::-1]

</lang>

Recursive

<lang 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])

</lang>

Testing

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

Ruby

Non-recursive

<lang ruby>def is_palindrome(s)

 s == s.reverse

end </lang>

Recursive

<lang ruby>def is_palindrome_r(s)

 if s.length <= 1
   true
 elsif s[0] != s[-1]
   false
 else
   is_palindrome_r(s[1..-2])
 end

end </lang>

Testing

<lang ruby> p = "ingirumimusnocteetconsumimurigni" print "'" + p + "' is palindrome? ", is_palindrome(p), "\n" print "'" + p + "' is palindrome? ", is_palindrome_r(p), "\n" </lang>