Shortest code to determine if a string is a palindrome

42

11

A palindrome is some string that is spelled the same way both backwards and forwards. For instance, 'Eva, can I stab bats in a cave?' is a palindrome (EVACANISTAB | BATSINACAVE)

For this code golf, using the language of your choice, determine if a given string is a palindrome or not.

Edge Cases:

  • Punctuation is not counted towards palindrominess.
  • Control characters are not counted towards palindrominess.
  • Whitespace is not counted towards palindrominess.
  • Numbers are counted towards palindrominess.
  • Case in this challenge is not counted towards palindrominess.
  • There is no limit to the length of strings to evaluate, except for what is imposed by your language of choice.
  • For this challenge, limit yourself to the ASCII character set.

Technical Requirements:

  • Only method bodies are needed; additional things like method signatures, data structure declarations, etc. do not count towards the victory requirement.
  • Code must compile or interpret without compile-time errors or exceptions.
  • Code must not throw any unhandled exceptions or crash. (Almost needless to say. Almost.)
  • Code must return some value indicating palindrominess. The data type depends on the language you use (e.g. a C# user might use a bool, whereas a JavaScript user could use a var.)
  • You may not write your own interpreter that performs this task as a 'native' capability so you can 'golf' a near-winning score. (Hopefully needless to say.)

Victory Condition:

  • The shortest code in characters wins.

Current Leader: tmartin (k, 25 characters)

...Want the magic green check mark by your answer? Beat this guy's answer!

Andrew Gray

Posted 2013-04-08T18:29:49.763

Reputation: 600

1Is I/O a part of the challenge, or a function body will do? – John Dvorak – 2013-04-08T18:43:29.713

What about case? Non-ASCII and control characters? – Peter Taylor – 2013-04-08T18:52:11.590

@PeterTaylor based on the example, case should be ignored. I assume control characters are punctuation. – John Dvorak – 2013-04-08T18:53:32.353

Updated with clarifications per comments. – Andrew Gray – 2013-04-08T19:05:33.153

1The "breadcrumbs" for showing how the work is refined are available site-wide in all answers via revision history. There's no need to have a full history visible in the current version of the answer. – Peter Taylor – 2013-04-08T20:27:31.553

Could you clarify Code must not throw any unhandled exceptions or crash. please? Should there be no exceptions for any input or any valid input? – skeevey – 2013-04-08T20:56:59.063

No exceptional states for any input; the edge case descriptions should ensure that the given code is immune to any gotchas (emphasis on should.) – Andrew Gray – 2013-04-08T21:00:47.927

2 hours for code golf? Some alternatives seem shorter in the few hours since... That's a mite quick, or am I missing something? – WernerCD – 2013-04-09T03:57:24.153

1@WernerCD I'm sure the OP will change who gets the green tick when he comes back to check on the new responses. – Gareth – 2013-04-09T07:15:52.960

2Not specifying a language really trivialises this challenge for me. As seen below, interpreted languages with a focus on high order text manipulation functions always get the shortest results.

What is to stop me throwing together my own interpreter with a single function, ip(). My compete algorithm is now 'ip:i'. 4 characters. done. – Gusdor – 2013-04-09T08:11:19.863

3

@Gusdor see J and GolfScript suck all the enjoyment out of Code Golf and Language Handicap and related questions on this site's meta.

– AakashM – 2013-04-09T08:25:20.920

Gareth: You're right, I do. Gusdor: I would think 'no custom language' is an implicit rule. Of course, you bring up a fair point. WernerCD: I do keep an eye on this, but I have to sleep (I am a mere mortal.) – Andrew Gray – 2013-04-09T13:35:37.537

I was under the impression that the green tick can't be changed after a set amount of time. Different between sites? My misunderstanding? If you can change the green tick to keep current with the leader, then I stand corrected :) – WernerCD – 2013-04-19T19:23:44.247

Answers

29

K, 25

{x~|x:_x@&x in,/.Q`a`A`n}

.

k){x~|x:_x@&x in,/.Q`a`A`n}"Eva, can I stab bats in a cave?"
1b

tmartin

Posted 2013-04-08T18:29:49.763

Reputation: 3 917

Looks like a mixture of Q and k :P – skeevey – 2013-04-09T12:29:24.653

Well, I wouldn't exactly call .Q.A etc q. They're just string wrappers, there's no real k code underneath them. Now, if I said .q.inter I'd be in trouble. – tmartin – 2013-04-09T12:45:35.093

I guess it's a case of quibbling over semantics but they are defined in q.k – skeevey – 2013-04-09T12:54:20.247

Could just say Q for 31: {x~(|)x:(_)x inter(,/).Q\a`A`n}` – tmartin – 2013-04-09T13:03:09.910

i know this is very old but... you can save 1 byte with {#|:\_x@&x in,/.Q`a`A`n} , where 1 is true and 2 is false – scrawl – 2019-10-24T14:14:06.450

24

Perl, 26 char

s/_|\W//g;uc eq reverse uc

Evaluates to 1 when $_ is a palindrome, "" (one of Perl's false values) when it is not.

Sample usage:

sub palin {
    s/_|\W//g;uc eq reverse uc
}
while (<DATA>) {
    chomp;
    print "$_ => ",palin()?"yes":"no","\n";
}
__DATA__
Eva, can I stab bats in a cave?
A man, a plan, a canal. Panama!
Madam, I'm Adam Corolla.
757
Boeing 757
A man, a plan, a big shovel, a canal. Panama!
A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal >> __Panama__

output:

Eva, can I stab bats in a cave? => yes
A man, a plan, a canal. Panama! => yes
Madam, I'm Adam Corolla. => no
757 => yes
Boeing 757 => no
A man, a plan, a big shovel, a canal. Panama! => no
A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal >> __Panama__ => yes

mob

Posted 2013-04-08T18:29:49.763

Reputation: 2 506

Damn, you beat me to it. Though this won't work properly if there's a _ in the string will it? And it doesn't take any input so won't you need to use the -p option? – Gareth – 2013-04-08T22:35:50.053

\W in regexes excludes underscore. I'm afraid you'll need [^a-z\d] in your regex. I'm afraid I'm beaten anyways. – John Dvorak – 2013-04-08T22:37:14.027

3Save one with _|\W instead of [_\W]. – Howard – 2013-04-09T09:20:20.063

1

You can shorten _|\W to \Pl: http://ideone.com/0ufdaQ . Should be just the Unicode letters.

– Kobi – 2013-04-10T07:13:48.600

Actually, thinking again - \Pl would not match digits, so I guess _|\W is the best you could do. – Kobi – 2013-04-10T09:59:42.447

18

C# 82 only :)

var x=s.ToLower().Where(char.IsLetterOrDigit);return x.SequenceEqual(x.Reverse());

Couldn't resist the temptation of writing a boilerplate-free program in my favorite language.

A test is available here: http://ideone.com/8bwz7z

Cristian Lupascu

Posted 2013-04-08T18:29:49.763

Reputation: 8 369

Simple...but elegant! – Andrew Gray – 2013-04-08T20:21:22.633

@AndrewGray thank you for the comment and for the permissive Technical Requirements. C# boilerplate adds seriously to the char count, making it impractical for golf otherwise. – Cristian Lupascu – 2013-04-08T20:31:03.830

2No prob. I'm a fellow C# dev, and I like writing concise, efficient code. It's a shame there's so much boilerplate in the language... – Andrew Gray – 2013-04-08T21:13:08.907

13

GolfScript, 36 34 31 30 characters

{0"0:A[a{"@{>^}+/},{32|}%.-1%=

Similar algorithm to my previous (Javascript) solution.

0"0:A[a{"@{>^}+/ -- Optimised by Peter Taylor and Howard. My version was "/9@Z"{1$<},,2%\;. Howard donated function concatenation and Peter Taylor donated XOR for modulo-2. It's basically a generic method of comparing if the value is in a sequence of ranges.

{.96>32*-}% (11 characters) is not really an improvement over Javascript's .toUpperCase() (14 characters), especially since it mangles some weird punctuation that follows z in the ASCII table (which doesn't matter here).

as Peter Taylor's suggested, however, if we filter out alphanumerics first, we can convert to lowercase and digits just by setting one bit in each character: {32|}

.-1%= does all the palindromic heavy lifting. One part I'm not really fond of is how long it took me to find out how to reverse an array. I should have read the docs. The other two characters perform stack management and comparison.

Test: http://golfscript.apphb.com/?c=IkV2YSwgY2FuIEkgc3RhYiBiYXRzIGluIGEgY2F2ZT8iCgp7IjA6QVtheyJcez59KywsMiV9LHszMnx9JS4tMSU9


Further, if I can assume that none of the following control characters are present: (Data link escape, device control 1-4, negative acknowledge, synchronous idle, end of transmission block, cancel, end of medium) (we all agree these are all pretty obscure) or if I can treat them as uppercase versions of the digits 0-9, we can save another two characters:

GolfScript, 28 characters

{32|}%{0"0:a{"@{>^}+/},.-1%=

Test: http://golfscript.apphb.com/?c=IkV2YSwgY2FuIEkgc3RhYiBiYXRzIGluIGEgY2F2ZT8iCgp7MzJ8fSV7MCIwOmF7IkB7Pl59Ky99LC4tMSU9

John Dvorak

Posted 2013-04-08T18:29:49.763

Reputation: 9 048

2You can get rid of the clean up and save two chars: {"0:A["\{>}+,,2%}, – Howard – 2013-04-08T21:01:42.897

@Howard Thanks. I think I misunderstood + on blocks. That's a cool trick. – John Dvorak – 2013-04-08T21:08:50.547

1You can save three chars by reversing the filter and the case standardisation. You have to add a{ to the filter's list of characters to include the lower-case letters, but you can then upper-case with just {32|}%. The end result is {"0:A[a{"\{>}+,,2%},{32|}%.-1%= – Peter Taylor – 2013-04-10T23:09:06.193

There also another saving to be made on the filter. Counting modulo 2 is xor, so 0"0:A[a{"@{>^}+/ does the job. – Peter Taylor – 2013-04-11T08:13:11.943

@PeterTaylor If I don't come up with another optimisation myself soon, I probably should convert to community wiki. Thanks again :-) – John Dvorak – 2013-04-11T08:36:52.510

8

Javascript, 53 characters:

(x=x.toLowerCase().match(/[a-z\d]/g))+""==x.reverse()

is a javascript expression that evaluates to true if x is a palindrome, to false if it isn't. It assumes x is a string. If that's not guaranteed, prepend x+="",

Here's a breadcrumb: Due to how reverse() works,

(x=x.toLowerCase().match(/[a-z\d]/g))==""+x.reverse()

fails. However,

""+(x=x.toLowerCase().match(/[a-z\d]/g))==x.reverse()

is perfectly fine.

John Dvorak

Posted 2013-04-08T18:29:49.763

Reputation: 9 048

Is a char shorter with regex /[^\W_]/g – SuperPrograman – 2015-12-06T21:36:37.513

Nice tidbit on concatenating a null string! Points for good infoz! – Andrew Gray – 2013-04-08T19:35:47.163

3Hints: +"" casts to a string, + casts to a number, |0 and ~~ cast to an integer, !! casts to a boolean. – John Dvorak – 2013-04-08T19:37:28.443

7

Mathematica 54 53

One byte saved thanks to CatsAreFluffy:

PalindromeQ@StringCases[ToUpperCase@#,WordCharacter]&

For those with version 10.2 or earlier:

#==Reverse@#&@StringCases[ToUpperCase@#,WordCharacter]&

Example

PalindromeQ@StringCases[ToUpperCase@#, WordCharacter]&["Eva,can I stab bats in a cave?"]

True

DavidC

Posted 2013-04-08T18:29:49.763

Reputation: 24 524

PalindromeQ is 1 byte shorter than #==Reverse@#& – CalculatorFeline – 2016-03-18T03:27:48.273

I wondered why I had never seen it. Version 10.3! – DavidC – 2016-03-18T12:55:02.320

PalindromeQ= #==Reverse@#& – CalculatorFeline – 2016-03-18T15:39:21.887

Yes, I downloaded v. 10.4 to try it out. – DavidC – 2016-03-18T21:28:26.030

That's out? OHNO – CalculatorFeline – 2016-03-18T21:42:01.910

7

JAVA (or the most verbose language ever), 102 96 95 char

s=s.replaceAll("\\W|_","");return s.equalsIgnoreCase(new StringBuffer(s).reverse().toString());

Usage (with ungolfed code):

static boolean q(String s) {
    s=s.replaceAll("\\W|_","");
    return s.equalsIgnoreCase(new StringBuffer(s).reverse().toString());
}

public static void main(String[] args) {
    System.out.println(q("'A man, a plan, a canal - Panama!'"));
}

Shortened with the help of the commenter below

jsedano

Posted 2013-04-08T18:29:49.763

Reputation: 1 607

1While I don't know Java (I'm a C# guy, funny enough), couldn't you save 1 character by taking out the curly braces on the if? E.G.: if(s==null) return 1==0;? Or does Java enforce curlies on if statements? – Andrew Gray – 2013-04-09T14:14:11.887

3You are absolutely right, I took that out thank you!!... I haven't notice they were there, I guess I'm a Java developer that doesn't C#? – jsedano – 2013-04-09T14:17:44.947

4

>

  • Checking whether the parameter is null is a good habit, but not practiced in CodeGolf. As I can tell, nobody else did it in this question. Skip it. 2) The space between arguments helps readability, but not golfing. Remove it; 3) Instead of explicitly toLowerCase() the string use equalsIgnoreCase() later instead of equals(). This way you have to adjust the regular expression, but still 1 character shorter. http://pastebin.com/s7H84faj
  • – manatwork – 2013-04-09T14:22:34.750

    1replaceAll("[^A-Za-z0-9]","") => replaceAll("\\W","") – assylias – 2013-04-10T11:21:43.257

    Actually: replaceAll("\\W|_",""); to remove _ too => 95 characters – assylias – 2013-04-10T11:46:01.567

    I know this has been answered more than three years ago, but you can golf two more things: .toString() can be +"", and you can make it a one-lined to save another byte like this: return(s=s.replaceAll("\\W|_","")).equalsIgnoreCase(new StringBuffer(s).reverse()+""); (86 bytes) – Kevin Cruijssen – 2016-11-04T10:02:23.473

    7

    Python 2: 49 (without counting the method signature)

    def f(s):
     s=filter(str.isalnum,s.upper())
     return s==s[::-1]
    

    A complete program, with input and output can be writte in 74 characters.

    import sys
    s=filter(str.isalnum,sys.stdin.read().upper())
    print s==s[::-1]
    

    Example usage:

    $echo 'Eva,can I stab bats in a cave?' | python palindrome.py
    True 
    $ cat huge_palindrome.txt | python palindrome.py
    True
    $echo 'Able was I ere i SaW elBa' | python palindrome.py                                                                   
    True                                         
    

    (huge_palindrome.txt contains this 17,826 word palindrome)

    This solution can be adapted to python 3 adding some characters:

    Python 3: 55

    def f(s):
     s=list(filter(str.isalnum,s.upper()))
     return s==s[::-1]
    

    Bakuriu

    Posted 2013-04-08T18:29:49.763

    Reputation: 781

    sys.stdin.read is basically the same as raw_input – CalculatorFeline – 2016-03-27T15:47:55.620

    In Python 3.8 you can shorten this to 58 bytes

    – MilkyWay90 – 2019-03-16T21:55:15.973

    Also, your Python 2 & 3 solution is 61 bytes and 67 bytes, respectively. – MilkyWay90 – 2019-03-16T22:00:50.367

    @MilkyWay90 You probably missed the without counting the method signature. In 2013 it was customary to not include it. In other solution in this question in other languages they simply omitted it and assumed you have the input in an s variable. I decided to provide the complete definition but, as customary in 2013, do not include the method signature in the length – Bakuriu – 2019-03-17T16:25:15.213

    @Bakuriu Ah, I see. I've only been here a few months, so I don't know customs from 2013 – MilkyWay90 – 2019-03-17T16:33:02.787

    @Bakuriu So then my solution would be an alternative solution for 49 bytes (not counting the method singature) – MilkyWay90 – 2019-03-17T16:34:43.190

    7

    Bash: 52 48 46 characters

    s=${1,,};s=${s//[^a-z0-9]};[ $s = `rev<<<$s` ]
    

    This takes the sting to check as first parameter and sets the exit code to 0 for palindrome and 1 for not.

    Sample run:

    bash-4.2$ p() { s=${1,,};s=${s//[^a-z0-9]};[ $s = `rev<<<$s` ]; }
    
    bash-4.2$ p 'Eva, can I stab bats in a cave?'; echo $?
    0
    
    bash-4.2$ p 'A man, a plan, a canal. Panama!'; echo $?
    0
    
    bash-4.2$ p "Madam, I'm Adam Corolla."; echo $?
    1
    
    bash-4.2$ p '757'; echo $?
    0
    
    bash-4.2$ p 'Boeing 757'; echo $?
    1
    
    bash-4.2$ p 'A man, a plan, a shovel, a canal. Panama!'; echo $?
    1
    
    bash-4.2$ p 'A_man,_a_plan, a_caremer, a canal:_Panama!'; echo $?
    0
    

    manatwork

    Posted 2013-04-08T18:29:49.763

    Reputation: 17 865

    7

    R: 66

    w=grep("[a-z0-9]",strsplit(tolower(s),"")[[1]],v=T);all(w==rev(w))
    

    Usage:

    f=function(s){w=grep("[a-z0-9]",strsplit(tolower(s),"")[[1]],v=T);all(w==rev(w))}
    
    f("Eva, can I stab bats in a cave?")
    [1] TRUE
    

    plannapus

    Posted 2013-04-08T18:29:49.763

    Reputation: 8 610

    6

    k (50 48 45 38 chars)

    Suppresses all errors, returning a default of 0b (false).

    {X~|X@:&(X:_:x)in 10h$(48+!10),97+!26}
    

    Example:

    k){X~|X@:&(X:_:x)in 10h$(48+!10),97+!26} "Eva, can I stab bats in a cave?"
    1b
    

    edit: shaved three more character by avoiding intermediate variable. H/T, CS. -7: No need to suppress errors.

    skeevey

    Posted 2013-04-08T18:29:49.763

    Reputation: 4 139

    1interesting that at just 3 characters more, my code is much more readable :-) – John Dvorak – 2013-04-08T19:38:11.073

    An extra char slipped in, I have removed it. – skeevey – 2013-04-08T19:42:04.420

    6

    J, 30 characters

    */(=|.)tolower(#~'[^_\W]'rxE])
    

    Usage:

       */(=|.)tolower(#~'[^_\W]'rxE])'A man, a plan, a canal - Panama!'
    1
       */(=|.)tolower(#~'[^_\W]'rxE])'Doc, note: I dissent. A fast never prevents a fatness. I diet on cod'
    1
    

    Gareth

    Posted 2013-04-08T18:29:49.763

    Reputation: 11 678

    5

    Ruby: 43 38 characters

    s=s.upcase.tr'^A-Z0-9','';s==s.reverse
    

    Sample run:

    irb(main):001:0> p=->s{s=s.upcase.tr'^A-Z0-9','';s==s.reverse}
    => #<Proc:0x854592c@(irb):1 (lambda)>
    
    irb(main):002:0> p['Eva, can I stab bats in a cave?']
    => true
    
    irb(main):003:0> p['A man, a plan, a canal. Panama!']
    => true
    
    irb(main):004:0> p["Madam, I'm Adam Corolla."]
    => false
    
    irb(main):005:0> p['757']
    => true
    
    irb(main):006:0> p['Boeing 757']
    => false
    
    irb(main):007:0> p['A man, a plan, a shovel, a canal. Panama!']
    => false
    
    irb(main):009:0> p['A_man,_a_plan, a_caremer, a canal:_Panama!']
    => true
    

    manatwork

    Posted 2013-04-08T18:29:49.763

    Reputation: 17 865

    1You can even write s.tr!('^A-Za-z0-9','').upcase!.reverse==s – Howard – 2013-04-09T09:19:43.763

    Man, how long I combined around the use of the ! methods! You keep amazing me @Howard with your tricks. – manatwork – 2013-04-09T09:41:52.037

    Small problem though, @Howard. tr and tr! seems to behave different when they have nothing to transliterate: http://pastebin.com/4YThW2qN That makes the p['757'] test to crash with “NoMethodError: undefined method `upcase!' for nil:NilClass” error.

    – manatwork – 2013-04-09T09:53:39.510

    Oops, sorry. Didn't think about that case. – Howard – 2013-04-09T11:24:00.363

    1can be shortened further: s=s.upcase.tr('^A-Z0-9','');s==s.reverse – Cristian Lupascu – 2013-04-09T12:12:29.783

    Ouch! What a stupid miss. Thank you, @w0lf. Event better, this way the parenthesis are not necessary anymore. – manatwork – 2013-04-09T12:24:35.387

    My version is s=s.upcase.gsub /\W/,'';s==s.reverse which. is 3 chars shorter. – Hauleth – 2013-06-21T14:33:17.910

    @ŁukaszNiemier, according to my counting, that is only 2 characters shorter. And if you make it to work correctly by excluding underscores from the comparison, s=s.upcase.gsub /\W|_/,'';s==s.reverse will be 0 characters shorter. – manatwork – 2013-06-21T14:55:55.977

    5

    C++, 107 (miscounted), 100 (miscounted), 81

    string s;for(int c:t)if(isalnum(c))s+=c|32;return s==string(s.rbegin(),s.rend());
    
    • Exploits ASCII bit patterns.
    • Relies on an evil using namespace std;.
    • Uses bitwise AND and OR instead of the logical operators.
    • Uses int because it's shorter than char or auto.

      #include <string>
      using namespace std;
      
      bool IsPalindrome(const string & t) {
      string s;for(int c:t)if(isalnum(c))s+=c|32;return s==string(s.rbegin(),s.rend());
      }
      
      #include <cassert>
      
      int main() {
          assert(!IsPalindrome("gorilla"));  // simple failure
          assert( IsPalindrome("racecar"));  // simple success
          assert( IsPalindrome("Hannah"));   // case blind
          assert(!IsPalindrome("1999"));     // digit failure
          assert( IsPalindrome("2002"));     // digit success
          // Ignore spacing, punctuation, and case:
          assert( IsPalindrome(" \t09AZ/:@[`{za90"));  // boundaries
          assert( IsPalindrome("A man, a plan, a canal: Panama."));
          assert( IsPalindrome("Eva, can I stab bats in a cave?"));
          assert( IsPalindrome(""));  // empty string
          return 0;
      }
      

    Adrian McCarthy

    Posted 2013-04-08T18:29:49.763

    Reputation: 679

    4

    Lua, 56

    a=io.read"*l":lower():gsub("%W","")print(a:reverse()==a)
    

    mniip

    Posted 2013-04-08T18:29:49.763

    Reputation: 9 396

    If %W is anything like \W in regex, it also excludes characters like underscore. This is unwanted. – John Dvorak – 2013-04-08T19:35:18.857

    i checked, %w doesn't include _ (%W obviously includes it, then) – mniip – 2013-04-08T19:48:43.960

    1Only function body is needed. s=s:lower():gsub('%W','')return s:reverse()==s 46 chars – Egor Skriptunoff – 2013-04-09T00:16:54.570

    but what about function(s) – mniip – 2013-04-09T04:40:21.227

    4

    Python 3/2 59 chars:

    def pld(i):
       p=[c for c in i.lower() if c.isalnum()]
       return(p == p[::-1])
    

    Amith KK

    Posted 2013-04-08T18:29:49.763

    Reputation: 225

    4

    Haskell, 43

    Using the standard libraries Control.Monad, Control.Monad.Instances, and Data.Char:

    ap(==)reverse.map toLower.filter isAlphaNum
    

    Jon Purdy

    Posted 2013-04-08T18:29:49.763

    Reputation: 471

    I can't make this to work in ghci. import Data.Char import Control.Monad ap(==)reverse.map toLower.filter isAlphaNum neither does it with adding spaces or such, sorry I'm not too keen with Haskell :) – SlimJim – 2013-04-12T07:48:21.563

    1@SlimJim: Oops, you need Control.Monad.Instances as well. (I’m using the Reader monad instance with ap, but that instance isn’t exported by Control.Monad.) – Jon Purdy – 2013-04-12T19:11:47.727

    4

    PHP 60 characters.

    First try on codegolf.

    //thank you manatwork
    echo($x=preg_replace('/\W/','',strtolower($c)))==strrev($x); 
    

    Example:

    $c='Eva, can I stab bats in a cave?';
    echo($x=preg_replace('/\W/','',strtolower($c)))==strrev($x);
    //prints 1
    

    Carlos Goce

    Posted 2013-04-08T18:29:49.763

    Reputation: 141

    The parenthesis around the ternary operator's first operand are not needed. Actually neither the ternary operator is needed – just output true or false in your language's representation. And by avoiding the separate statement for the assignment to $x 1 more character can be shortened: echo($x=preg_replace('/\W/','',strtolower($c)))==strrev($x);. – manatwork – 2013-11-27T12:44:33.813

    3

    Python 2 64 Charecters:

    i =''.join(re.findall('[a-z0-9]+',i.lower()))
    return i==i[::-1]
    

    abhiram

    Posted 2013-04-08T18:29:49.763

    Reputation: 131

    @manatwork If you replace all the identifiers with one character identifiers you obtain a 77 characters version. No idea why abhiram posted the ungolfed version though. – Bakuriu – 2013-04-09T07:04:21.390

    @Bakuriu, never mind, I missed one statement in the question: “Only method bodies are needed”. Though lines 2 and 3 gives me only 73 characters. Regarding further length reduction, no need for raw string and the capture group, making the re.findall('[a-z0-9]+',input.lower()) part 3 characters shorter. – manatwork – 2013-04-09T07:16:14.317

    @manatwork, I edited the post and changed the variables a little. That brought it down to 66. Yes, the raw string attribute is of no use here. – abhiram – 2013-04-09T08:39:25.530

    Ok, but why you insist on the capturing group in the regular expression? Works correctly without: http://pastebin.com/JzpNRRZU

    – manatwork – 2013-04-09T08:45:01.887

    I think it caught on with me after my recent python project involving re's :) Thanks for pointing it out. – abhiram – 2013-04-09T10:18:49.013

    3

    Haskell 48

    (\x->x==reverse x).map toLower.filter isAlphaNum
    

    used like this:

    (\x->x==reverse x).map toLower.filter isAlphaNum$"Eva, can I stab bats in a cave?"
    

    SlimJim

    Posted 2013-04-08T18:29:49.763

    Reputation: 131

    3

    Smalltalk, Squeak/Pharo flavour
    116 chars using traditional formatting with tabs

    You add two methods to String:

    selffles
        ^self = self reverse
    isPalindrome
        ^(self asUppercase asDecomposedUnicode select: #isAlphaNumeric) selffles
    

    We could of course eliminate some spaces, or use shorter method names, but let's not betray the spirit of Smalltalk.

    More over, this will handle French palindromes, like in http://fr.wikipedia.org/wiki/Liste_de_palindromes_fran%C3%A7ais, not many answers in this page can.

    ['Léon a trop par rapport à Noël' isPalindrome] assert.
    

    aka.nice

    Posted 2013-04-08T18:29:49.763

    Reputation: 411

    Clever and useful answer! – Andrew Gray – 2013-04-17T18:31:43.160

    3

    Python 3 (51 char)

    and may be Python 2

    based on abhiram solution (with more agressive golfing)

    from re import findall
    
    def palindrome(i):
     i=findall('[a-z\d]',i.lower())
     return i==i[::-1]
    
    print(palindrome(input('Phrase: ')))
    

    may be shortened to 46 chars, using RE '\w'

    and variant with extremely shortened function body (27 chars)

    import re
    l=str.lower
    f=re.compile('[a-z\d]').findall
    
    def palindrome(i):i=f(l(i));return i==i[::-1]
    
    print(palindrome(input('Phrase: ')))
    

    AMK

    Posted 2013-04-08T18:29:49.763

    Reputation: 506

    2

    PHP, 26 84 80 78 62 63 bytes

    <?=strrev($s=strtolower(preg_replace("#\W#","",$argv[1])))==$s;
    

    takes input from first command line argument; prints 1 for truthy, empty string for falsy.


    I18n is a littly expansive, as there is no multibyte alternative for strrev (110 bytes; run with -r):

    preg_match_all("#.#us",$s=strtolower(preg_replace("#\W#u","",$argv[1])),$m);echo$s==join(array_reverse($m[0]);
    

    utf8_strrev blatantly stolen from the PHP manual. You might also want to take a look at this blog post.

    Titus

    Posted 2013-04-08T18:29:49.763

    Reputation: 13 814

    Come on Titus... This fails the spec. – Christoph – 2017-04-04T08:04:22.060

    1@Christoph Yeah I sometimes should fully read that. Fixed. – Titus – 2017-04-04T12:54:59.183

    Hm -R would cause problems with line breaks in the string to test wouldn't it? From the spec " -R <code> Run PHP <code> for every input line". Moreover <?=strrev($s=strtolower(preg_replace("#\W#","",$argn)))==$s;would be shorter. – Christoph – 2017-04-04T13:42:56.767

    1@Christoph Nice idea, but there is no $argn without -R. – Titus – 2017-04-04T14:06:16.373

    $argv[1]="O Genie, der Herr ehre dein Ego!"; # :D – Titus – 2017-04-05T00:24:01.977

    2

    Windows PowerShell, 56 47 45 chars

    Updated (see comments), and can remove the brackets around the regex:

    ($s=$s-replace'\W')-eq(-join$s[$s.length..0])
    

    Original (56)

    $s=$s-replace'[^\w]','';$s-eq($s[-1..-$s.length]-join'')
    

    Original Un-golfed:

    $s = "Eva, can I stab bats in a cave?"
    $s = $s -replace '[^\w]', ''
    $rev = $s[-1..-$s.length] -join ''
    $s -eq $rev
    

    goric

    Posted 2013-04-08T18:29:49.763

    Reputation: 271

    You can golf this down to 47 chars like this: ($s=$s-replace'[\W]')-eq(-join$s[$s.length..0]) – SpellingD – 2013-11-26T22:47:48.167

    @SpellingD: Nice! I'm new at code golfing, thanks for the improvement – goric – 2013-11-27T12:59:59.653

    you can remove the right parenthesis also: ($s=$s-replace'\W')-eq-join$s[$s.length..0]. – mazzy – 2018-12-10T13:47:28.247

    2

    C++, 74 bytes

    This code is actually really elegant, and easy to understand (when formatted correctly). I don't believe it's possible to get any shorter in C++, and it doesn't use any standard library functions.

    p(auto c){auto e=c;while(*e)++e;--e;while(*e==*c&e>c)--e,++c;return e<=c;}
    

    Example usage:

    p("Hello"); //Outputs 0
    p(""); //Outputs 1
    p("a"); //Outputs 1
    p("HellolleH"); //Outputs 1
    

    Nicely formatted version:

    p(auto c)
    {
        auto e=c;
        while(*e) ++e;
        --e;
        while(*e==*c & e>c)--e,++c;
        return e<=c;
    }
    

    J. Antonio Perez

    Posted 2013-04-08T18:29:49.763

    Reputation: 1 480

    1error: ISO C++ forbids declaration of ‘p’ with no type your function should have a return type. – Karl Napf – 2016-11-23T17:09:05.967

    I bet this does not ignore case, whitespace and control characters. – Titus – 2017-04-04T23:53:36.080

    You can save a character with while(*++e); instead of while(*e)++e;. But as Titus mentioned this answer is invalid. – Nick Matteo – 2017-04-25T17:04:08.770

    1

    C++14, 104 bytes

    Actually overlooked the requirement to ignore case and whitespace, so here is:

    auto f=
    [](auto s,int&n){
    auto r=s.rbegin();n=1;for(auto c:s){if(isalnum(c)){while(!isalnum(*r))r++;if((c|32)!=(*(r++)|32))n=0;}}
    }
    ;
    

    strict solution, 72 68 bytes

    -4 bytes for returning by parameter.

    As unnamed lambda, assuming input s is of type std::string and returning the result by a parameter:

    [](auto s,int&n){auto r=s.rbegin();n=1;for(auto c:s)if(c!=*r++)n=0;}
    

    Ungolfed & usage:

    #include <iostream>
    #include <string>
    
    auto f=
    [](auto s, int& n){
      auto r=s.rbegin();
      n=1;
      for(auto c:s)
        if(c!=*r++)
          n=0;
    }
    ;
    
    int main(){
    int n;
    #define p(s) f(std::string(s),n); std::cout << n << std::endl
     p("Hello");
     p("ABCCBA");
     p("ABCBA");
    }
    

    Karl Napf

    Posted 2013-04-08T18:29:49.763

    Reputation: 4 131

    1

    Python(python 2.7.6), 79 chars

    "Sorry I don't get what characters to count so I wrote the whole program"

    import re
    n=raw_input()
    n=re.sub("[^a-z]+","",n.lower())
    print n==n[::-1]
    

    This will print True if input string is palindrome else False.

    Code_link:http://ideone.com/b4NzLD

    salRoid

    Posted 2013-04-08T18:29:49.763

    Reputation: 11

    1Welcome to PPCG! It is stated in the languages specs that "Punctuation is not counted towards palindrominess" and I don't think this submission takes care of that. Unfortunately, that makes this answer invalid, but you can fix it right now – user41805 – 2017-03-31T18:12:46.637

    1

    REXX, 84 bytes

    arg n
    n=space(translate(n,,translate(n,,xrange(a,z)xrange(0,9))),0)
    say n=reverse(n)
    

    arg n reads argument into variable n, converting it to upper-case.

    xrange(a,z)xrange(0,9) concatenates the two ranges A—Z and 0—9.

    translate takes a string to process, an output translation table and an input translation table, and optionally a padding character to replace those characters not found in the output table with. Hence translate(n,,xrange(a,z)xrange(0,9)) maps the string n with an input table consisting only of alphanumerical characters and an empty output table, resulting in a string consisting only of punctuation, spaces and other non-alphanumericals (since they were not in either table). The filtered-out characters are rendered as spaces.

    translate(n,,translate(n,,xrange(a,z)xrange(0,9))) uses the above non-alphanumerics string as an input table and an empty output table, applying it to n, resulting in a string consisting only of alphanumericals, since they were not in the input or output tables. The non-alphanumerics are rendered as spaces.

    space() takes a string and a number, spacing out the words with the supplied amount of spaces between. In this case, the supplied number is 0, hence all spaces are removed.

    By this point, n has been reduced to consisting only of alphanumeric characters without any spaces.

    say n=reverse(n) prints out whether n is identical to its reversed version.

    idrougge

    Posted 2013-04-08T18:29:49.763

    Reputation: 641

    1

    Ruby, 48

    p((g=gets.upcase.gsub /[^A-Z\d]/,'')==g.reverse)
    

    Quite simple, and hastily made so not golfed too much. I shall golf it more later.

    Doorknob

    Posted 2013-04-08T18:29:49.763

    Reputation: 68 138

    1

    Dyalog APL (18 characters)

     {⍵≡⌽⍵}'\w'⎕S'\u0'⊢
    

    Search for alphanumeric characters in the right argument, and return any found upper-cased (this avoids any need for punctuation, whitespace and casing). Then just check what's returned to see if it matches the reverse.

    Example

    {⍵≡⌽⍵}'\w'⎕S'\u0'⊢'Eva, can I stab bats in a cave?'
        1
    

    James Heslip

    Posted 2013-04-08T18:29:49.763

    Reputation: 139

    This is a snippet. The (tacit) function is {⍵≡⌽⍵}'\w'⎕S'\u0' which can be named (or parenthesised) before application. Also, you can save another byte by replacing {⍵≡⌽⍵} with (⊢≡⌽). – Adám – 2017-10-25T16:28:15.573

    1

    Pylongolf2, 24 bytes

    c╨2"[^a-zA-Z]"-_╨1=~
    

    c takes the input, ╨2 to convert to lower case.
    I then push a regex onto the stack and use - to remove all non-alphabetical characters in the input.
    _ duplicates the input.
    ╨1 reverses it and = then compares them.
    ~ prints the stack in the end which prints either true or false.

    user47018

    Posted 2013-04-08T18:29:49.763

    Reputation:

    Does this ignore the punctuation, whitespace and control characters? – MickyT – 2016-03-31T19:05:10.917

    My bad, this version does not. I will fix it. – None – 2016-03-31T20:06:17.893

    Fixed the problem. – None – 2016-03-31T20:08:03.700

    1

    PowerShell, 194 190 bytes

    A recursive implementation to show how an unnamed PowerShell scriptblock can call itself.

    $P={param([string]$s)$s=($s-replace'[^a-z]').tolower();if(!$s){return $true};if($s.length-lt4){return $s[0]-eq$s[-1]};$s[0]-eq$s[-1]-and(&$MyInvocation.MyCommand.ScriptBlock $s.trim($s[0]))}
    

    ungolfed:

    $P={
    param([string]$s)
    $s=($s-replace'[^a-z]').tolower();
    if(!$s){return $true};
    if($s.length-lt4){return $s[0]-eq$s[-1]};
    $s[0]-eq$s[-1]-and(&$MyInvocation.MyCommand.ScriptBlock $s.trim($s[0]))
    }
    

    tests:

    &$P "Eva, can I stab bats in a cave?"
    &$P "Eva, can I stab cats in a cave?"
    &$P "A man, a plan, a canal. Panama!"
    &$P "A man, a plan, a big shovel, a canal. Panama!"
    &$P "Madam, I'm Adam."
    &$P "Madam, I'm Adam Corolla."
    &$P "757"
    &$P "Boeing 757"
    

    Bevo

    Posted 2013-04-08T18:29:49.763

    Reputation: 73

    Shouldn´t that be [^a-z0-9]? – Titus – 2017-04-04T23:56:47.950

    1

    05AB1E, 4 bytes (non-competing)

    Non-competing, since the language postdates the challenge. Code:

    álÂQ
    

    Explanation:

    á     # Only keep the alphabetic characters.
     l    # Lowercase the characters.
      Â   # Bifurcate, which duplicates the letters and reverses the duplicate.
       Q  # Check if they are equal.
    

    Uses the CP-1252 encoding. Try it online!.

    Adnan

    Posted 2013-04-08T18:29:49.763

    Reputation: 41 965

    Tried to run it via your link. Program output is "1" – Christopher Perry – 2017-04-05T04:57:23.500

    1

    Jelly, 10 Characters (Non-competing)

    fØBŒl
    UÇ⁼Ç
    

    Returns 1 if true, 0 if false

    Try it Online!

    X88B88

    Posted 2013-04-08T18:29:49.763

    Reputation: 91

    Does it ignore case, whitespace and control characters? A breakdown would be nice. – Titus – 2017-04-04T23:55:22.287

    The current state of Jelly allows for solving this in 7 bytes: fØBŒlŒḂ: f filter to keep ØB the set [a-zA-Z0-9] and Œl convert to lowercase, then ŒḂ test if palindrome.

    – steenbergh – 2017-04-05T08:11:05.847

    1

    Racket, 132 bytes

    Pretty embarrassing, but maybe somebody can see a way of making this shorter!

    ((λ(l[n(floor(/(length l)2))])(equal?(take l n)(take(reverse l)n)))(string->list(regexp-replace*"[^0-9a-z]"(string-downcase s)"")))
    

    Code listing with test module

    #lang racket
    
    (define/contract (palindrome? s)
      (string? . -> . boolean?)
      ((λ(l[n(floor(/(length l)2))])(equal?(take l n)(take(reverse l)n)))(string->list(regexp-replace*"[^0-9a-z]"(string-downcase s)""))))
    
    (module+ test
      (require rackunit)
      (define tests
        '(("Eva, can I stab bats in a cave?" . #t)
          ("A man, a plan, a canal. Panama!" . #t)
          ("Madam, I'm Adam Corolla." . #f)
          ("757" . #t)
          ("Boeing 757" . #f)
          ("A man, a plan, a big shovel, a canal. Panama!" . #f)
          ("A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal >> __Panama__" . #t)))
      (for ([t tests])
        (check-equal? (palindrome? (car t)) (cdr t) (~a t))))
    

    Winny

    Posted 2013-04-08T18:29:49.763

    Reputation: 1 120

    1

    APL, 78 65 Bytes

    l←⎕D,⎕UCS v+32⊣c←⎕D,⎕UCS v←64+⍳26⋄(⌽≡⊢)∊{⍵/⍨⍵∊l}¨{⍵∊c:l[c⍳⍵]⋄⍵}¨⎕
    

    I'm going to assume that the Original Poster meant limit the INPUT string to the Ascii character set.

    Zacharý

    Posted 2013-04-08T18:29:49.763

    Reputation: 5 710

    0

    JavaScript Code :: ONLY 140 characters Palindrome

    function palindrome()
    {
        var user=prompt("Enter the characters to check the palindrome");
        var split=user.split('').reverse().join(''); // ONLY this line counts 
        if(user == split)
        {
            alert("The given word is a Palindrome");
        } else
        {
            alert("The given word is not a Palindrome");
        }
    
    }
    

    palindrome();

    Praveen

    Posted 2013-04-08T18:29:49.763

    Reputation: 117

    3Erm...afraid not, the comparison is also part of checking that a string is a palindrome. – Gareth – 2013-04-09T07:14:00.690

    oh... Sorry.. Then its takes 140 characters.. – Praveen – 2013-04-09T07:16:51.167

    7The requirement says you need to ignore uppercase vs. lowercase differences and punctuation. – manatwork – 2013-04-09T07:21:12.167

    Additionally, don't worry about the method signature. We're just worried with how you solve the problem, not language-specific boilerplate. – Andrew Gray – 2013-04-09T13:15:50.687

    0

    Racket 118 bytes

    (let((l(filter(λ(x)(or(char-alphabetic? x)(char-numeric? x)))(string->list(string-upcase s)))))(equal? l(reverse l)))
    

    Ungolfed:

    (define (palindrome? s)
      (let((l(filter(λ(x)(or(char-alphabetic? x)
                            (char-numeric? x)))
                    (string->list (string-upcase s)))))
        (equal? l(reverse l))))
    

    Testing:

    (palindrome? "abc  dcB;_A")
    (palindrome? "abc;@#$zdc b  a")
    (palindrome? "1%^&234 56")
    (palindrome? "1a234 * ^ && 565432A1")
    

    Output:

    #t
    #f
    #f
    #t
    

    rnso

    Posted 2013-04-08T18:29:49.763

    Reputation: 1 635

    This is neither case insensitive and nor does it ignore punctuation, control characters and whitespace. – Titus – 2017-04-04T23:51:58.137

    Thanks for pointing out. I have corrected the code above. – rnso – 2017-04-05T02:02:03.057

    0

    AHK, 83 bytes (L7 loser)

    StringUpper,s,1
    s:=RegExReplace(s,"[\W_]")
    Loop,Parse,s
    t:=A_LoopField t
    Send % s=t
    

    Outputs 1 for palindromes and 0 for not.

    Engineer Toast

    Posted 2013-04-08T18:29:49.763

    Reputation: 5 769

    0

    C, 199 bytes

    #define R return
    #define C unsigned char
    #define F for
    s(C*a){C*b;if(a&&*a)F(b=a+strlen(a)-1;;++a,--b){F(;a<b&&!isalnum(*a);)++a;F(;a<b&&!isalnum(*b);)--b;if(a>=b)R 1;if((*a|32)-(*b|32))R 0;}R 1;}
    

    //ungolf

    v(C*a)
    { C*b;
     if(a&&*a)
       F(b=a+strlen(a)-1;;++a,--b)
               {F(;a<b&&!isalnum(*a);)++a;
                F(;a<b&&!isalnum(*b);)--b;
                if(a>=b)           R 1;
                if((*a|32)-(*b|32))R 0;
               }
     R 1;
    }
    
    #define P printf
    main()
    {C*b="Eva, can I stab bats in a cave?";
     P("%s %d\n", b, s(b));
     R 0;
    }
    

    //results

    //Eva, can I stab bats in a cave? 1
    

    RosLuP

    Posted 2013-04-08T18:29:49.763

    Reputation: 3 036

    0

    Common Lisp, 72 65 bytes

    (let((y(remove-if-not'alphanumericp(read))))(equalp(reverse y)y))
    

    -7 bytes thanks to @ceilingcat !

    Try it online!

    Renzo

    Posted 2013-04-08T18:29:49.763

    Reputation: 2 260

    0

    Retina, 31 bytes (non-competing)

    \W
    
    T`l`L
    +`^(.)(.*)\1$
    $2
    ^.?$
    

    Try it online!

    ovs

    Posted 2013-04-08T18:29:49.763

    Reputation: 21 408

    0

    QuadS, 19 bytes

    Equivalent to James Heslip's solution.

    ⍵≡⌽⍵
    \w
    \u&
    

    Try it online!

    Is…

    ⍵≡⌽⍵ the text identical to its reverse

    \w after finding all word characters

    \u& and uppercasing them

    ?

    Adám

    Posted 2013-04-08T18:29:49.763

    Reputation: 37 779