109

That was an interview question that I was unable to answer:

How to check that a string is a palindrome using regular expressions?

p.s. There is already a question "How to check if the given string is palindrome?" and it gives a lot of answers in different languages, but no answer that uses regular expressions.

Community
  • 1
  • 1
Degvik
  • 3,050
  • 6
  • 25
  • 20
  • 1
    http://stackoverflow.com/questions/3644266/how-can-we-match-an-bn-with-java-regex can give an idea. – unknown_boundaries Mar 04 '15 at 13:38
  • 3
    For nowadays (2018) and who is looking for "the palindrome regex", see discussion about PCRE supporting [recursive patterns](https://stackoverflow.com/a/3650562/287948) at Prakhar's link, and my [*recursive regex* below, with comparisons](https://stackoverflow.com/a/48608623/287948). – Peter Krauss Feb 04 '18 at 15:27

32 Answers32

179

The answer to this question is that "it is impossible". More specifically, the interviewer is wondering if you paid attention in your computational theory class.

In your computational theory class you learned about finite state machines. A finite state machine is composed of nodes and edges. Each edge is annotated with a letter from a finite alphabet. One or more nodes are special "accepting" nodes and one node is the "start" node. As each letter is read from a given word we traverse the given edge in the machine. If we end up in an accepting state then we say that the machine "accepts" that word.

A regular expression can always be translated into an equivalent finite state machine. That is, one that accepts and rejects the same words as the regular expression (in the real world, some regexp languages allow for arbitrary functions, these don't count).

It is impossible to build a finite state machine that accepts all palindromes. The proof relies on the facts that we can easily build a string that requires an arbitrarily large number of nodes, namely the string

a^x b a^x (eg., aba, aabaa, aaabaaa, aaaabaaaa, ....)

where a^x is a repeated x times. This requires at least x nodes because, after seeing the 'b' we have to count back x times to make sure it is a palindrome.

Finally, getting back to the original question, you could tell the interviewer that you can write a regular expression that accepts all palindromes that are smaller than some finite fixed length. If there is ever a real-world application that requires identifying palindromes then it will almost certainly not include arbitrarily long ones, thus this answer would show that you can differentiate theoretical impossibilities from real-world applications. Still, the actual regexp would be quite long, much longer than equivalent 4-line program (easy exercise for the reader: write a program that identifies palindromes).

Jose M Vidal
  • 8,816
  • 6
  • 43
  • 48
  • 13
    @SteveMoser In Ruby 1.9.x, regular expressions are no longer Regular (in the Automata Theory sense) and thus things like checking for palindromes is possible. However, for the intents and purposes, palindromes cannot be checked with a _Regular_ regex (make sense?). –  Dec 03 '12 at 00:26
  • 1
    @SteveMoser There is a good writeup of Ruby's regular expression engine (`>=1.9`) [here](http://pragprog.com/magazines/2010-12/whats-new-in-ruby-) –  Dec 03 '12 at 00:49
  • @John right, so in the context of the question Jose is right and hqt is wrong. – Steve Moser Dec 03 '12 at 15:32
  • 4
    In academic terms, a regular expression has specific boundaries (defines a DFA). In reality, many regexp engines (Perl and it's relatives primarily) support backreferences which violate the academic definition (becoming NFA or even broader). So this question has different answers depending on what the questioner's frame of reference was. – jiggy Aug 21 '14 at 23:44
  • In an oral test zou shoulsd go with "formalz it is impossible", but you should point out that some regex engines allow it. – Oliver A. Oct 09 '15 at 21:30
  • In interviews I would however make sure to take care of pronunciation and spelling. – trincot Mar 29 '18 at 13:43
47

While the PCRE engine does support recursive regular expressions (see the answer by Peter Krauss), you cannot use a regex on the ICU engine (as used, for example, by Apple) to achieve this without extra code. You'll need to do something like this:

This detects any palindrome, but does require a loop (which will be required because regular expressions can't count).

$a = "teststring";
while(length $a > 1)
{
   $a =~ /(.)(.*)(.)/;
   die "Not a palindrome: $a" unless $1 eq $3;
   $a = $2;
}
print "Palindrome";
Airsource Ltd
  • 32,379
  • 13
  • 71
  • 75
  • 6
    Good answer. The question didn't ask for a single regexp that detects a palindrome straight out of the box - it simply asked for a method of detecting palindromes that makes use of regexps. Congrats on your insight to look at it this way. – Stewart Sep 21 '09 at 08:24
  • 1
    See also the simplest matching (without string manipulation) using only one regex, https://stackoverflow.com/a/48608623/287948 – Peter Krauss Feb 04 '18 at 13:41
  • Thanks @PeterKrauss. Didn't know that PCRE had recursion. Referenced your answer. – Airsource Ltd Feb 06 '18 at 12:35
36

It's not possible. Palindromes aren't defined by a regular language. (See, I DID learn something in computational theory)

Dima
  • 38,860
  • 14
  • 75
  • 115
ZCHudson
  • 510
  • 3
  • 6
  • 2
    Most regular expressions engines capture more than regular languages (net can capture matching parenthesis for example). Only standard regexes are limited to regular langs. – Santiago Palladino Oct 24 '08 at 12:45
  • The question did use the term "regular expression" though... so ZCHudson's answer is correct. – oz10 Oct 24 '08 at 15:55
  • 2
    @austirg: ZCHudson's answer is correct but incomplete. Regular expressions used in modern programming languages and regular expressions used in theoretical CS classes are different beasts. The term is just a historical heritage. See http://stackoverflow.com/questions/233243#235199 and my answer. – jfs Nov 03 '08 at 21:57
  • 3
    @J.F. Sebastian - I'd have to agree with austirg on this. When the term regular expression is used without a specific programming language mentioned than the comp sci defintion applies. Not all languages that support regexes can do this, so we shouldn't assume the one used here does. – Rontologist Nov 03 '08 at 22:11
  • @Rontologist: I see no restrictions on the choice of programming language in the question thus any language is allowed. Look at the right: what is the meaning of "regular expression" in the related questions? Are specific programming language being mentioned in any of them? – jfs Nov 03 '08 at 22:29
  • @J.F. Sebastian: They are not asking for specific languages, but none of the regex specific questions on the right are asking anything beyond the comp sci regular expressions either, so the distinction is not as important. – Rontologist Nov 03 '08 at 23:23
  • In my experience, when people post regex questions without specifying a flavor, it's usually because they don't realize there _are_ different regex flavors. – Alan Moore Mar 12 '09 at 06:07
32

With Perl regex:

/^((.)(?1)\2|.?)$/

Though, as many have pointed out, this can't be considered a regular expression if you want to be strict. Regular expressions does not support recursion.

Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
  • this doesn't work in PCRE (it doesn't match "ababa"), but it does work in Perl 5.10 – newacct Oct 02 '09 at 04:33
  • You are right. PCRE does seem treat the recursion as an atomic group, while Perl allows backtracking within it. I don't think it is possible to do this check in PCRE. – Markus Jarderot Oct 02 '09 at 21:14
  • 1
    Surprisingly, does not work for non-Latin languages, for example Armenian language. – Temujin Apr 12 '16 at 07:55
  • 6
    @Temujin It is either because unicode characters are matched as the encoded bytes (add the [`/u` modifier](http://perldoc.perl.org/perlre.html#Character-set-modifiers)), or because of combinator characters. (replace `.` with the [`\X` escape sequence](http://perldoc.perl.org/perlrebackslash.html#%5cX)). – Markus Jarderot Apr 12 '16 at 21:29
  • It didn't match like `anna`, `aa`. Modified it to [`^((\w)(?:\2*$|(?:(?1)|\w?)\2))$`](https://regex101.com/r/aABQ3g/5). Also [Casimirs Regex](https://stackoverflow.com/a/40792780/5527985) without recursion works nicely, besides not matching single characters but that's probably intended. – bobble bubble Nov 02 '19 at 14:16
  • 1
    My pattern does not work in PCRE. It does work in Perl. Your pattern fails when substrings are repeated. For example `abababa`. It is not possible to make it work with recursion for every input when using PCRE-based regex engines. Casimirs regex uses a different approach, using iteration and mutable state, and is quite fascinating. – Markus Jarderot Nov 02 '19 at 15:42
18

Here's one to detect 4-letter palindromes (e.g.: deed), for any type of character:

\(.\)\(.\)\2\1

Here's one to detect 5-letter palindromes (e.g.: radar), checking for letters only:

\([a-z]\)\([a-z]\)[a-z]\2\1

So it seems we need a different regex for each possible word length. This post on a Python mailing list includes some details as to why (Finite State Automata and pumping lemma).

FOR
  • 4,260
  • 2
  • 25
  • 36
15

Depending on how confident you are, I'd give this answer:

I wouldn't do it with a regular expression. It's not an appropriate use of regular expressions.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
14

Yes, you can do it in .Net!

(?<N>.)+.?(?<-N>\k<N>)+(?(N)(?!))

You can check it here! It's a wonderful post!

kev
  • 155,172
  • 47
  • 273
  • 272
  • 2
    The whole point of .NET flavoured Regex is that they aren't *regular* because they're not a finite state automata; they aren't really regex in the theoretical sense. – cat Jan 26 '16 at 22:45
13

StackOverflow is full of answers like "Regular expressions? nope, they don't support it. They can't support it.".

The truth is that regular expressions have nothing to do with regular grammars anymore. Modern regular expressions feature functions such as recursion and balancing groups, and the availability of their implementations is ever growing (see Ruby examples here, for instance). In my opinion, hanging onto old belief that regular expressions in our field are anything but a programming concept is just counterproductive. Instead of hating them for the word choice that is no longer the most appropriate, it is time for us to accept things and move on.

Here's a quote from Larry Wall, the creator of Perl itself:

(…) generally having to do with what we call “regular expressions”, which are only marginally related to real regular expressions. Nevertheless, the term has grown with the capabilities of our pattern matching engines, so I’m not going to try to fight linguistic necessity here. I will, however, generally call them “regexes” (or “regexen”, when I’m in an Anglo-Saxon mood).

And here's a blog post by one of PHP's core developers:

As the article was quite long, here a summary of the main points:

  • The “regular expressions” used by programmers have very little in common with the original notion of regularity in the context of formal language theory.
  • Regular expressions (at least PCRE) can match all context-free languages. As such they can also match well-formed HTML and pretty much all other programming languages.
  • Regular expressions can match at least some context-sensitive languages.
  • Matching of regular expressions is NP-complete. As such you can solve any other NP problem using regular expressions.

That being said, you can match palindromes with regexes using this:

^(?'letter'[a-z])+[a-z]?(?:\k'letter'(?'-letter'))+(?(letter)(?!))$

...which obviously has nothing to do with regular grammars.
More info here: http://www.regular-expressions.info/balancing.html

rr-
  • 14,303
  • 6
  • 45
  • 67
9

As a few have already said, there's no single regexp that'll detect a general palindrome out of the box, but if you want to detect palindromes up to a certain length, you can use something like

(.?)(.?)(.?)(.?)(.?).?\5\4\3\2\1
Stewart
  • 3,935
  • 4
  • 27
  • 36
9

You can also do it without using recursion:

\A(?:(.)(?=.*?((?(2)\1\2|\1))\z))*?.?\2\z

to allow a single character:

\A(?:(?:(.)(?=.*?((?(2)\1\2|\1))\z))*?.?\2|.)\z

Works with Perl, PCRE

demo

For Java:

\A(?:(.)(?=.*?(\1\2\z|(?<!(?=\2\z).{0,1000})\1\z)))*?.?\2\z

demo

Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
  • 1
    This is a very interesting answer to a regex question. Actually the only pattern, that [passed some of my tests](https://regex101.com/r/4mw2tF/1/tests). Thanks for this one Casimir:) – bobble bubble Nov 18 '19 at 12:02
  • 2
    @bobblebubble: Thanks for your support. As you can see, I edited this answer recently because the previous version was wrong (for three years, what a shame). – Casimir et Hippolyte Nov 21 '19 at 22:35
7

It can be done in Perl now. Using recursive reference:

if($istr =~ /^((\w)(?1)\g{-1}|\w?)$/){
    print $istr," is palindrome\n";
}

modified based on the near last part http://perldoc.perl.org/perlretut.html

CSchulz
  • 10,882
  • 11
  • 60
  • 114
Hui Liu
  • 359
  • 4
  • 11
6

In ruby you can use named capture groups. so something like this will work -

def palindrome?(string)
  $1 if string =~ /\A(?<p>| \w | (?: (?<l>\w) \g<p> \k<l+0> ))\z/x
end

try it, it works...

1.9.2p290 :017 > palindrome?("racecar")
 => "racecar" 
1.9.2p290 :018 > palindrome?("kayak")
 => "kayak" 
1.9.2p290 :019 > palindrome?("woahitworks!")
 => nil 
Taylor
  • 136
  • 1
  • 3
  • 1
    Named capture groups are not strictly regex. http://www.willamette.edu/~fruehr/LLC/lab5.html – Steve Moser Oct 22 '12 at 17:44
  • 2
    You are correct. Thats specifically why I pointed out that you would have to use named capture groups. – Taylor Oct 30 '12 at 13:56
  • 1
    Could someone by any chance explain that RE character by character for a newbie? I understand all of the following (commas separate the 'atoms') /,\A,(,|,\w,|,(,(,\w,),),),\z,/,x but I don't understand any of these ?

    ,?:,?,\g

    ,\k and I'm using rubular.com for help and it seems to understand the RE (naturally), but that doesn't help me see it, and even "For a complete Ruby regex guide, see the Pickaxe." doesn't help, for the site linked with 'Pickaxe' does not explain the atoms I am failing to understand. I know ? FOLLOWING a matches Zero or one of a, but ? preceding a character?

    – Kevin Ford The Submariner Apr 07 '13 at 18:23
  • 1
    Ah, *named capture groups*! Nice. @SteveMoser that's now a broken link, but I found [another](http://www.ruby-doc.org/core-1.9.3/Regexp.html). Thanks Taylor for mentioning them, as otherwise, I would have had no idea what was meant by ?

    and ? and ?: (non-capturing capture group) and \g

    and \k. I still can't see what ?

    | is though. Doesn't | mean "or"? I'm unable to find documentation of that usage for the pipe in REs. I'd still be delighted to see a detailed explanation for this very nice RE.

    – Kevin Ford The Submariner Apr 08 '13 at 02:10
  • @KevinFordTheSubmariner I think the `(?

    |`.. syntax just means that it's allowed to match nothing.. or the rest of the alternatives. The `(?

    ..)` syntax is just a named capturing group. It can be referenced for the exact match using `\k

    ` as opposed to a backreference to the group number. The `+0` means at the same level of recursion.

    – Scratte Mar 05 '21 at 01:27
6

Recursive Regular Expressions can do it!

So simple and self-evident algorithm to detect a string that contains a palindrome:

   (\w)(?:(?R)|\w?)\1

At rexegg.com/regex-recursion the tutorial explains how it works.


It works fine with any language, here an example adapted from the same source (link) as proof-of-concept, using PHP:

$subjects=['dont','o','oo','kook','book','paper','kayak','okonoko','aaaaa','bbbb'];
$pattern='/(\w)(?:(?R)|\w?)\1/';
foreach ($subjects as $sub) {
  echo $sub." ".str_repeat('-',15-strlen($sub))."-> ";
  if (preg_match($pattern,$sub,$m)) 
      echo $m[0].(($m[0]==$sub)? "! a palindrome!\n": "\n");
  else 
      echo "sorry, no match\n";
}

outputs

dont ------------> sorry, no match
o ---------------> sorry, no match
oo --------------> oo! a palindrome!
kook ------------> kook! a palindrome!
book ------------> oo
paper -----------> pap
kayak -----------> kayak! a palindrome!
okonoko ---------> okonoko! a palindrome!
aaaaa -----------> aaaaa! a palindrome!
bbbb ------------> bbb

Comparing

The regular expression ^((\w)(?:(?1)|\w?)\2)$ do the same job, but as yes/not instead "contains".
PS: it is using a definition where "o" is not a palimbrome, "able-elba" hyphened format is not a palindrome, but "ableelba" is. Naming it definition1.
When "o" and "able-elba" are palindrones, naming definition2.

Comparing with another "palindrome regexes",

  • ^((.)(?:(?1)|.?)\2)$ the base-regex above without \w restriction, accepting "able-elba".

  • ^((.)(?1)?\2|.)$ (@LilDevil) Use definition2 (accepts "o" and "able-elba" so differing also in the recognition of "aaaaa" and "bbbb" strings).

  • ^((.)(?1)\2|.?)$ (@Markus) not detected "kook" neither "bbbb"

  • ^((.)(?1)*\2|.?)$ (@Csaba) Use definition2.


NOTE: to compare you can add more words at $subjects and a line for each compared regex,

  if (preg_match('/^((.)(?:(?1)|.?)\2)$/',$sub)) echo " ...reg_base($sub)!\n";
  if (preg_match('/^((.)(?1)?\2|.)$/',$sub)) echo " ...reg2($sub)!\n";
  if (preg_match('/^((.)(?1)\2|.?)$/',$sub)) echo " ...reg3($sub)!\n";
  if (preg_match('/^((.)(?1)*\2|.?)$/',$sub)) echo " ...reg4($sub)!\n";
Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
  • I tried this and it seems that it matched all the palindromes: [`^((.)(?:(?1)|.?)\2|(.)\3*)$`](https://regex101.com/r/EmHGpm/3) – Hao Wu Nov 09 '20 at 06:26
5

Here's my answer to Regex Golf's 5th level (A man, a plan). It works for up to 7 characters with the browser's Regexp (I'm using Chrome 36.0.1985.143).

^(.)(.)(?:(.).?\3?)?\2\1$

Here's one for up to 9 characters

^(.)(.)(?:(.)(?:(.).?\4?)?\3?)?\2\1$

To increase the max number of characters it'd work for, you'd repeatedly replace .? with (?:(.).?\n?)?.

pbatey
  • 1,234
  • 13
  • 13
4

It's actually easier to do it with string manipulation rather than regular expressions:

bool isPalindrome(String s1)

{

    String s2 = s1.reverse;

    return s2 == s1;
}

I realize this doesn't really answer the interview question, but you could use it to show how you know a better way of doing a task, and you aren't the typical "person with a hammer, who sees every problem as a nail."

dbr
  • 165,801
  • 69
  • 278
  • 343
Dan
  • 512
  • 1
  • 4
  • 12
  • Whereas I am quite fond of this answer, I do think you'd get extra points by using BreakIterator to properly split the string up into visual characters. – Hakanai Jan 20 '14 at 05:32
4
/\A(?<a>|.|(?:(?<b>.)\g<a>\k<b+0>))\z/

it is valid for Oniguruma engine (which is used in Ruby)

took from Pragmatic Bookshelf

mpugach
  • 591
  • 5
  • 15
4

Regarding the PCRE expression (from MizardX):

/^((.)(?1)\2|.?)$/

Have you tested it? On my PHP 5.3 under Win XP Pro it fails on: aaaba Actually, I modified the expression expression slightly, to read:

/^((.)(?1)*\2|.?)$/

I think what is happening is that while the outer pair of characters are anchored, the remaining inner ones are not. This is not quite the whole answer because while it incorrectly passes on "aaaba" and "aabaacaa", it does fail correctly on "aabaaca".

I wonder whether there a fixup for this, and also, Does the Perl example (by JF Sebastian / Zsolt) pass my tests correctly?

Csaba Gabor from Vienna

3

In Perl (see also Zsolt Botykai's answer):

$re = qr/
  .                 # single letter is a palindrome
  |
  (.)               # first letter
  (??{ $re })??     # apply recursivly (not interpolated yet)
  \1                # last letter
/x;

while(<>) {
    chomp;
    say if /^$re$/; # print palindromes
}
Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
2
#!/usr/bin/perl

use strict;
use warnings;

print "Enter your string: ";
chop(my $a = scalar(<STDIN>));    
my $m = (length($a)+1)/2;
if( (length($a) % 2 != 0 ) or length($a) > 1 ) { 
  my $r; 
  foreach (0 ..($m - 2)){
    $r .= "(.)";
  }
  $r .= ".?";
  foreach ( my $i = ($m-1); $i > 0; $i-- ) { 
    $r .= "\\$i";
  } 
  if ( $a =~ /(.)(.).\2\1/ ){
    print "$a is a palindrome\n";
  }
  else {
    print "$a not a palindrome\n";
 }
exit(1);
}
print "$a not a palindrome\n";
sapam
  • 21
  • 1
2

From automata theory its impossible to match a paliandrome of any lenght ( because that requires infinite amount of memory). But IT IS POSSIBLE to match Paliandromes of Fixed Length. Say its possible to write a regex that matches all paliandromes of length <= 5 or <= 6 etc, but not >=5 etc where upper bound is unclear

Vijeenrosh P.W
  • 359
  • 1
  • 3
  • 8
2

As pointed out by ZCHudson, determine if something is a palindrome cannot be done with an usual regexp, as the set of palindrome is not a regular language.

I totally disagree with Airsource Ltd when he says that "it's not possibles" is not the kind of answer the interviewer is looking for. During my interview, I come to this kind of question when I face a good candidate, to check if he can find the right argument when we proposed to him to do something wrong. I do not want to hire someone who will try to do something the wrong way if he knows better one.

Community
  • 1
  • 1
Nicolas
  • 24,509
  • 5
  • 60
  • 66
2

something you can do with perl: http://www.perlmonks.org/?node_id=577368

Zsolt Botykai
  • 50,406
  • 14
  • 85
  • 110
  • Kindly add context to any links so your Answer is self contained, meaning the answer needs to be here in the Answer itself. See ["Provide context for links"](https://stackoverflow.com/help/how-to-answer). It would be preferable if you could answer the Question in your own words here and link only as a reference. – Scratte Mar 04 '21 at 23:24
2

In Ruby you can use \b(?'word'(?'letter'[a-z])\g'word'\k'letter+0'|[a-z])\b to match palindrome words such as a, dad, radar, racecar, and redivider. ps : this regex only matches palindrome words that are an odd number of letters long.

Let's see how this regex matches radar. The word boundary \b matches at the start of the string. The regex engine enters the capturing group "word". [a-z] matches r which is then stored in the stack for the capturing group "letter" at recursion level zero. Now the regex engine enters the first recursion of the group "word". (?'letter'[a-z]) matches and captures a at recursion level one. The regex enters the second recursion of the group "word". (?'letter'[a-z]) captures d at recursion level two. During the next two recursions, the group captures a and r at levels three and four. The fifth recursion fails because there are no characters left in the string for [a-z] to match. The regex engine must backtrack.

The regex engine must now try the second alternative inside the group "word". The second [a-z] in the regex matches the final r in the string. The engine now exits from a successful recursion, going one level back up to the third recursion.

After matching (&word) the engine reaches \k'letter+0'. The backreference fails because the regex engine has already reached the end of the subject string. So it backtracks once more. The second alternative now matches the a. The regex engine exits from the third recursion.

The regex engine has again matched (&word) and needs to attempt the backreference again. The backreference specifies +0 or the present level of recursion, which is 2. At this level, the capturing group matched d. The backreference fails because the next character in the string is r. Backtracking again, the second alternative matches d.

Now, \k'letter+0' matches the second a in the string. That's because the regex engine has arrived back at the first recursion during which the capturing group matched the first a. The regex engine exits the first recursion.

The regex engine is now back outside all recursion. That this level, the capturing group stored r. The backreference can now match the final r in the string. Since the engine is not inside any recursion any more, it proceeds with the remainder of the regex after the group. \b matches at the end of the string. The end of the regex is reached and radar is returned as the overall match.

Melih Altıntaş
  • 2,495
  • 1
  • 22
  • 35
  • This post seems to be plagiarized from https://www.regular-expressions.info/recursebackref.html under "Odd Length Palindromes in Ruby". It cannot be the other way around, because the site already existed with that wording on [September 21st 2013](http://web.archive.org/web/20130921105746/https://www.regular-expressions.info/recursebackref.html) – Scratte Mar 05 '21 at 08:41
2

here is PL/SQL code which tells whether given string is palindrome or not using regular expressions:

create or replace procedure palin_test(palin in varchar2) is
 tmp varchar2(100);
 i number := 0;
 BEGIN
 tmp := palin;
 for i in 1 .. length(palin)/2 loop
  if length(tmp) > 1 then  
    if regexp_like(tmp,'^(^.).*(\1)$') = true then 
      tmp := substr(palin,i+1,length(tmp)-2);
    else 
      dbms_output.put_line('not a palindrome');
      exit;
    end if;
  end if;  
  if i >= length(palin)/2 then 
   dbms_output.put_line('Yes ! it is a palindrome');
  end if;
 end loop;  
end palin_test;
Ruslan López
  • 4,433
  • 2
  • 26
  • 37
ankush
  • 29
  • 2
2

I would explain to the interviewer that the language consisting of palindromes is not a regular language but instead context-free.

The regular expression that would match all palindromes would be infinite. Instead I would suggest he restrict himself to either a maximum size of palindromes to accept; or if all palindromes are needed use at minimum some type of NDPA, or just use the simple string reversal/equals technique.

Flame
  • 2,166
  • 2
  • 20
  • 40
2
my $pal='malayalam';

while($pal=~/((.)(.*)\2)/){                                 #checking palindrome word
    $pal=$3;
}
if ($pal=~/^.?$/i){                                         #matches single letter or no letter
    print"palindrome\n";
}
else{
    print"not palindrome\n";
}
Stewart
  • 3,935
  • 4
  • 27
  • 36
  • 3
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Donald Duck Jan 29 '17 at 18:42
2

This regex will detect palindromes up to 22 characters ignoring spaces, tabs, commas, and quotes.

\b(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*\11?[ \t,'"]*\10|\10?)[ \t,'"]*\9|\9?)[ \t,'"]*\8|\8?)[ \t,'"]*\7|\7?)[ \t,'"]*\6|\6?)[ \t,'"]*\5|\5?)[ \t,'"]*\4|\4?)[ \t,'"]*\3|\3?)[ \t,'"]*\2|\2?))?[ \t,'"]*\1\b

Play with it here: https://regexr.com/4tmui

I wrote an explanation of how I got that here: https://medium.com/analytics-vidhya/coding-the-impossible-palindrome-detector-with-a-regular-expressions-cd76bc23b89b

Tony Tonev
  • 99
  • 5
  • So.. if someone wants to know how this works they have to click on a link? That's not how Stack Overflow is suppose to work. – Scratte Mar 05 '21 at 08:17
  • @Scratte says who? – Tyler Rinker Mar 15 '22 at 02:25
  • The [help center](https://stackoverflow.com/help/how-to-answer) and [meta](https://meta.stackoverflow.com).. It's suppose to be *the* place to get the answers. Not the place to click yet another link. – Scratte Mar 16 '22 at 13:38
2

The best you can do with regexes, before you run out of capture groups:

/(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\9\8\7\6\5\4\3\2\1/

This will match all palindromes up to 19 characters in length.

Programatcally solving for all lengths is trivial:

str == str.reverse ? true : false
Chris
  • 1,501
  • 17
  • 32
2

I don't have the rep to comment inline yet, but the regex provided by MizardX, and modified by Csaba, can be modified further to make it work in PCRE. The only failure I have found is the single-char string, but I can test for that separately.

/^((.)(?1)?\2|.)$/

If you can make it fail on any other strings, please comment.

Lil Devil
  • 663
  • 5
  • 10
0

A slight refinement of Airsource Ltd's method, in pseudocode:

WHILE string.length > 1
    IF /(.)(.*)\1/ matches string
        string = \2
    ELSE
        REJECT
ACCEPT
Stewart
  • 3,935
  • 4
  • 27
  • 36
0

\b([a-z])?([a-z])?([a-z])?\2\1\b/gi

Matches 5 letter palindromes such as refer and kayak. It does this using (non-greedy) matching of any three letters, followed by the 2nd and 1st matched letters.

Link to regex101 site using this

Josh
  • 529
  • 6
  • 21
0

In JavaScript it is done by typing

          function palindrome(str) {
  var symbol = /\W|_/g;
  str = str.replace(symbol, "").toLowerCase();
  var palindrome = str.split("").reverse("").join("");
  return (str === palindrome);
}
Erik Rybalkin
  • 1,143
  • 12
  • 21