<?xml version="1.0" encoding="windows-1252"?>
<node id="382882" title="Re^2: Finding longest palindrome from a string" created="2004-08-13 22:09:05" updated="2005-07-25 19:49:09">
<type id="11">
note</type>
<author id="114691">
Aristotle</author>
<data>
<field name="doctext">
&lt;p&gt;And here's the proof (sorry it's so wide).&lt;/p&gt;

&lt;readmore&gt;
&lt;table border="1" cellspacing="0" cellpadding="3"&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt; &lt;td&gt;Rate&lt;/td&gt; &lt;td&gt;bgreenlee&lt;/td&gt; &lt;td&gt;japhy2&lt;/td&gt; &lt;td&gt;japhy&lt;/td&gt; &lt;td&gt;ccn2&lt;/td&gt; &lt;td&gt;ccn&lt;/td&gt; &lt;td&gt;jasper&lt;/td&gt; &lt;td&gt;deibyz&lt;/td&gt; &lt;td&gt;murugu&lt;/td&gt; &lt;td&gt;clive&lt;/td&gt; &lt;td&gt;buu&lt;/td&gt; &lt;td&gt;jdporter&lt;/td&gt; &lt;td&gt;aristotle&lt;/td&gt; &lt;td&gt;limbic_region&lt;/td&gt; &lt;td&gt;elgon&lt;/td&gt; &lt;td&gt;browseruk&lt;/td&gt; &lt;td&gt;aristotle2&lt;/td&gt; &lt;td&gt;random_walk&lt;/td&gt; &lt;td&gt;tune&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;bgreenlee&lt;/td&gt; &lt;td&gt;1.59/s&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-44%&lt;/td&gt; &lt;td&gt;-44%&lt;/td&gt; &lt;td&gt;-49%&lt;/td&gt; &lt;td&gt;-49%&lt;/td&gt; &lt;td&gt;-50%&lt;/td&gt; &lt;td&gt;-90%&lt;/td&gt; &lt;td&gt;-90%&lt;/td&gt; &lt;td&gt;-91%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-98%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;japhy2&lt;/td&gt; &lt;td&gt;2.82/s&lt;/td&gt; &lt;td&gt;77%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-1%&lt;/td&gt; &lt;td&gt;-10%&lt;/td&gt; &lt;td&gt;-10%&lt;/td&gt; &lt;td&gt;-11%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-84%&lt;/td&gt; &lt;td&gt;-94%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-98%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;japhy&lt;/td&gt; &lt;td&gt;2.85/s&lt;/td&gt; &lt;td&gt;79%&lt;/td&gt; &lt;td&gt;1%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-9%&lt;/td&gt; &lt;td&gt;-9%&lt;/td&gt; &lt;td&gt;-10%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-84%&lt;/td&gt; &lt;td&gt;-94%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-98%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;ccn2&lt;/td&gt; &lt;td&gt;3.14/s&lt;/td&gt; &lt;td&gt;97%&lt;/td&gt; &lt;td&gt;11%&lt;/td&gt; &lt;td&gt;10%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;0%&lt;/td&gt; &lt;td&gt;-1%&lt;/td&gt; &lt;td&gt;-80%&lt;/td&gt; &lt;td&gt;-80%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-94%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-98%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;ccn&lt;/td&gt; &lt;td&gt;3.14/s&lt;/td&gt; &lt;td&gt;97%&lt;/td&gt; &lt;td&gt;11%&lt;/td&gt; &lt;td&gt;10%&lt;/td&gt; &lt;td&gt;0%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-1%&lt;/td&gt; &lt;td&gt;-80%&lt;/td&gt; &lt;td&gt;-80%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-94%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-98%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;jasper&lt;/td&gt; &lt;td&gt;3.16/s&lt;/td&gt; &lt;td&gt;99%&lt;/td&gt; &lt;td&gt;12%&lt;/td&gt; &lt;td&gt;11%&lt;/td&gt; &lt;td&gt;1%&lt;/td&gt; &lt;td&gt;1%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-80%&lt;/td&gt; &lt;td&gt;-80%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-94%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-98%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;del&gt;deibyz&lt;/del&gt;&lt;/td&gt; &lt;td&gt;15.6/s&lt;/td&gt; &lt;td&gt;880%&lt;/td&gt; &lt;td&gt;453%&lt;/td&gt; &lt;td&gt;448%&lt;/td&gt; &lt;td&gt;396%&lt;/td&gt; &lt;td&gt;396%&lt;/td&gt; &lt;td&gt;393%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-1%&lt;/td&gt; &lt;td&gt;-10%&lt;/td&gt; &lt;td&gt;-68%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-91%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;del&gt;murugu&lt;/del&gt;&lt;/td&gt; &lt;td&gt;15.8/s&lt;/td&gt; &lt;td&gt;891%&lt;/td&gt; &lt;td&gt;459%&lt;/td&gt; &lt;td&gt;454%&lt;/td&gt; &lt;td&gt;402%&lt;/td&gt; &lt;td&gt;402%&lt;/td&gt; &lt;td&gt;398%&lt;/td&gt; &lt;td&gt;1%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-9%&lt;/td&gt; &lt;td&gt;-68%&lt;/td&gt; &lt;td&gt;-82%&lt;/td&gt; &lt;td&gt;-91%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;clive&lt;/td&gt; &lt;td&gt;17.3/s&lt;/td&gt; &lt;td&gt;984%&lt;/td&gt; &lt;td&gt;512%&lt;/td&gt; &lt;td&gt;506%&lt;/td&gt; &lt;td&gt;449%&lt;/td&gt; &lt;td&gt;449%&lt;/td&gt; &lt;td&gt;446%&lt;/td&gt; &lt;td&gt;11%&lt;/td&gt; &lt;td&gt;9%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-65%&lt;/td&gt; &lt;td&gt;-81%&lt;/td&gt; &lt;td&gt;-90%&lt;/td&gt; &lt;td&gt;-95%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-96%&lt;/td&gt; &lt;td&gt;-97%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;buu&lt;/td&gt; &lt;td&gt;49.1/s&lt;/td&gt; &lt;td&gt;2981%&lt;/td&gt; &lt;td&gt;1639%&lt;/td&gt; &lt;td&gt;1623%&lt;/td&gt; &lt;td&gt;1460%&lt;/td&gt; &lt;td&gt;1460%&lt;/td&gt; &lt;td&gt;1450%&lt;/td&gt; &lt;td&gt;214%&lt;/td&gt; &lt;td&gt;211%&lt;/td&gt; &lt;td&gt;184%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-45%&lt;/td&gt; &lt;td&gt;-72%&lt;/td&gt; &lt;td&gt;-87%&lt;/td&gt; &lt;td&gt;-89%&lt;/td&gt; &lt;td&gt;-90%&lt;/td&gt; &lt;td&gt;-91%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;jdporter&lt;/td&gt; &lt;td&gt;89.1/s&lt;/td&gt; &lt;td&gt;5493%&lt;/td&gt; &lt;td&gt;3057%&lt;/td&gt; &lt;td&gt;3027%&lt;/td&gt; &lt;td&gt;2732%&lt;/td&gt; &lt;td&gt;2732%&lt;/td&gt; &lt;td&gt;2714%&lt;/td&gt; &lt;td&gt;471%&lt;/td&gt; &lt;td&gt;465%&lt;/td&gt; &lt;td&gt;416%&lt;/td&gt; &lt;td&gt;82%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-50%&lt;/td&gt; &lt;td&gt;-76%&lt;/td&gt; &lt;td&gt;-80%&lt;/td&gt; &lt;td&gt;-81%&lt;/td&gt; &lt;td&gt;-83%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;aristotle&lt;/td&gt; &lt;td&gt;178/s&lt;/td&gt; &lt;td&gt;11060%&lt;/td&gt; &lt;td&gt;6199%&lt;/td&gt; &lt;td&gt;6139%&lt;/td&gt; &lt;td&gt;5551%&lt;/td&gt; &lt;td&gt;5551%&lt;/td&gt; &lt;td&gt;5516%&lt;/td&gt; &lt;td&gt;1039%&lt;/td&gt; &lt;td&gt;1027%&lt;/td&gt; &lt;td&gt;929%&lt;/td&gt; &lt;td&gt;262%&lt;/td&gt; &lt;td&gt;100%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-51%&lt;/td&gt; &lt;td&gt;-60%&lt;/td&gt; &lt;td&gt;-63%&lt;/td&gt; &lt;td&gt;-67%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;del&gt;limbic_region&lt;/del&gt;&lt;/td&gt; &lt;td&gt;364/s&lt;/td&gt; &lt;td&gt;22756%&lt;/td&gt; &lt;td&gt;12800%&lt;/td&gt; &lt;td&gt;12679%&lt;/td&gt; &lt;td&gt;11474%&lt;/td&gt; &lt;td&gt;11474%&lt;/td&gt; &lt;td&gt;11401%&lt;/td&gt; &lt;td&gt;2232%&lt;/td&gt; &lt;td&gt;2207%&lt;/td&gt; &lt;td&gt;2008%&lt;/td&gt; &lt;td&gt;642%&lt;/td&gt; &lt;td&gt;309%&lt;/td&gt; &lt;td&gt;105%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-19%&lt;/td&gt; &lt;td&gt;-24%&lt;/td&gt; &lt;td&gt;-32%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;del&gt;elgon&lt;/del&gt;&lt;/td&gt; &lt;td&gt;448/s&lt;/td&gt; &lt;td&gt;28063%&lt;/td&gt; &lt;td&gt;15795%&lt;/td&gt; &lt;td&gt;15646%&lt;/td&gt; &lt;td&gt;14161%&lt;/td&gt; &lt;td&gt;14161%&lt;/td&gt; &lt;td&gt;14071%&lt;/td&gt; &lt;td&gt;2774%&lt;/td&gt; &lt;td&gt;2743%&lt;/td&gt; &lt;td&gt;2498%&lt;/td&gt; &lt;td&gt;814%&lt;/td&gt; &lt;td&gt;404%&lt;/td&gt; &lt;td&gt;152%&lt;/td&gt; &lt;td&gt;23%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-7%&lt;/td&gt; &lt;td&gt;-16%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;del&gt;browseruk&lt;/del&gt;&lt;/td&gt; &lt;td&gt;481/s&lt;/td&gt; &lt;td&gt;30111%&lt;/td&gt; &lt;td&gt;16951%&lt;/td&gt; &lt;td&gt;16791%&lt;/td&gt; &lt;td&gt;15198%&lt;/td&gt; &lt;td&gt;15198%&lt;/td&gt; &lt;td&gt;15102%&lt;/td&gt; &lt;td&gt;2983%&lt;/td&gt; &lt;td&gt;2950%&lt;/td&gt; &lt;td&gt;2687%&lt;/td&gt; &lt;td&gt;881%&lt;/td&gt; &lt;td&gt;440%&lt;/td&gt; &lt;td&gt;171%&lt;/td&gt; &lt;td&gt;32%&lt;/td&gt; &lt;td&gt;7%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-10%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;aristotle2&lt;/td&gt; &lt;td&gt;532/s&lt;/td&gt; &lt;td&gt;33288%&lt;/td&gt; &lt;td&gt;18744%&lt;/td&gt; &lt;td&gt;18567%&lt;/td&gt; &lt;td&gt;16807%&lt;/td&gt; &lt;td&gt;16807%&lt;/td&gt; &lt;td&gt;16701%&lt;/td&gt; &lt;td&gt;3307%&lt;/td&gt; &lt;td&gt;3271%&lt;/td&gt; &lt;td&gt;2980%&lt;/td&gt; &lt;td&gt;984%&lt;/td&gt; &lt;td&gt;497%&lt;/td&gt; &lt;td&gt;199%&lt;/td&gt; &lt;td&gt;46%&lt;/td&gt; &lt;td&gt;19%&lt;/td&gt; &lt;td&gt;11%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-98%&lt;/td&gt; &lt;td&gt;-99%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;del&gt;random_walk&lt;/del&gt;&lt;/td&gt; &lt;td&gt;35318/s&lt;/td&gt; &lt;td&gt;2217869%&lt;/td&gt; &lt;td&gt;1251726%&lt;/td&gt; &lt;td&gt;1239954%&lt;/td&gt; &lt;td&gt;1123012%&lt;/td&gt; &lt;td&gt;1123012%&lt;/td&gt; &lt;td&gt;1115948%&lt;/td&gt; &lt;td&gt;226223%&lt;/td&gt; &lt;td&gt;223816%&lt;/td&gt; &lt;td&gt;204478%&lt;/td&gt; &lt;td&gt;71886%&lt;/td&gt; &lt;td&gt;39555%&lt;/td&gt; &lt;td&gt;19774%&lt;/td&gt; &lt;td&gt;9604%&lt;/td&gt; &lt;td&gt;7775%&lt;/td&gt; &lt;td&gt;7242%&lt;/td&gt; &lt;td&gt;6543%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt; &lt;td&gt;-31%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;del&gt;tune&lt;/del&gt;&lt;/td&gt; &lt;td&gt;51210/s&lt;/td&gt; &lt;td&gt;3215868%&lt;/td&gt; &lt;td&gt;1814999%&lt;/td&gt; &lt;td&gt;1797929%&lt;/td&gt; &lt;td&gt;1628368%&lt;/td&gt; &lt;td&gt;1628368%&lt;/td&gt; &lt;td&gt;1618126%&lt;/td&gt; &lt;td&gt;328060%&lt;/td&gt; &lt;td&gt;324569%&lt;/td&gt; &lt;td&gt;296530%&lt;/td&gt; &lt;td&gt;104276%&lt;/td&gt; &lt;td&gt;57399%&lt;/td&gt; &lt;td&gt;28717%&lt;/td&gt; &lt;td&gt;13971%&lt;/td&gt; &lt;td&gt;11319%&lt;/td&gt; &lt;td&gt;10545%&lt;/td&gt; &lt;td&gt;9532%&lt;/td&gt; &lt;td&gt;45%&lt;/td&gt; &lt;td&gt;--&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/readmore&gt;

&lt;p&gt;Note that I had to disqualify some entries for failing the tests.&lt;/p&gt;

&lt;p&gt;The full benchmark I ran follows. Note that some entries required slight modifications in order to compile with strictures and run without warnings. I paid careful attention to keep the semantics intact, but if I disqualified your entry, please check my copy of your code for potential breakage.&lt;/p&gt;

&lt;readmore&gt;
&lt;code&gt;
use strict;
use warnings;
use Benchmark qw( cmpthese );
use Test::More qw( no_plan );
use CGI qw/ :html /;

my %contestant = (
	aristotle =&gt; sub {
		my $str = shift;
		my $rts = reverse $str;

		my $palindrome = '';
		for my $rotate_count ( 0 .. length( $str ) - 1 ) {
			my $mask = $str ^ $rts;

			# to distinguish adjacent palindromes
			substr $mask, $rotate_count, 0, "\1";

			while ( $mask =~ /\0{3,}/g ) {
				my $len = $+[0] - $-[0];
				next if $len &lt;= length $palindrome;
				my $offs = $-[0];
				--$offs if $offs &gt; $rotate_count;    # compensate for marker
				$palindrome = substr $str, $offs, $len;
			}

			substr $rts, 0, 0, chop $rts;
		}

		return $palindrome;
	},

	aristotle2 =&gt; sub {
		my $str = shift;
		my $rts = reverse $str;

		my $palindrome = '';
		my $minlen     = 3;
		for my $rotate_count ( 0 .. length( $str ) - 1 ) {
			my $mask = $str ^ $rts;

			# to distinguish adjacent palindromes
			substr $mask, $rotate_count, 0, "\1";

			while ( $mask =~ /\0{$minlen,}/g ) {
				my $offs = $-[0];
				--$offs if $offs &gt; $rotate_count;    # compensate for marker
				$palindrome = substr $str, $offs, $+[0] - $-[0];
				$minlen = 1 + length $palindrome;
			}

			substr $rts, 0, 0, chop $rts;
		}

		return $palindrome;
	},

	buu =&gt; sub {
		my @p;
		my $arg = shift;
		my $p = '';

		while ( $arg =~ /((.).?\2)/g ) {
			my $m = $1;
			while ( $arg =~ /((.)$m\2)/ ) {
				$m = $1;
			}
			if ( length( $m ) &gt; length( $p ) ) {
				$p = $m;
			}
		}

		return $p;
	},

	ccn =&gt; sub {
		local $_ = shift;
		my @n;
		for ( my $i = 0 ; $i &lt; length ; pos = $i++ ) {
			$n[ length $&amp; ] = $&amp; if /\G(.+).?(??{reverse  $1})/;
		}
		return @n ? $n[-1] : '';
	},

	ccn2 =&gt; sub {
		local $_ = shift;
		my $s = '';
		for ( my $i = 0 ; $i &lt; length ; pos = $i++ ) {
			$s = $&amp;
				if /\G(.+).?(??{reverse  $1})/
				and length( $s ) &lt; length( $&amp; );
		}
		return $s;
	},

	tune =&gt; sub {
		my $l = '';
		map { $l = $_ if ( $_ eq reverse $_ ) &amp;&amp; ( length $l &lt; length $_ ) }
			split /\s+/, $_[0];
		return $l;
	},

	random_walk =&gt; sub {
		my ( $left, $right, $pal, $i ) = ( "", "", "", 1 );
		my $test = join " ", @ARGV;
		for ( ; $i &lt; ( ( length $test ) / 2 ) + 2 ; $i++ ) {
			$left .= "(.)";
			$right = "(\\$i)" . $right;
			if ( $test =~ /$left.?$right/ ) { $pal = $&amp;; next }
			return $pal;
		}
	},

	clive =&gt; sub {
		my $rev = reverse $_[0];

		my $len = 0;
		my $d;
		for ( 0 .. length( $_[0] ) - 1 ) {
			my $c = join '',
				map { substr( $rev, $_, 1 ) eq substr( $_[0], $_, 1 ) ? 1 : 0 }
				0 .. length( $_[0] ) - 1;
			my $match =
				( sort { length( $a ) &lt;=&gt; length( $b ) } $c =~ /(1+)/g )[-1];
			$match &gt; $len and $len = $match and $d = $c;
			$rev = substr( $rev, 1 ) . substr( $rev, 0, 1 );
		}
		$d =~ s/(.*)($len).*/substr($_[0],length($1),length($len))/e;
		return $d;
	},

	murugu =&gt; sub {
		my $x    = shift;
		my $prev = 0;
		my $max;
		while ( $x =~ /(([a-z0-9]+)[a-z0-9]?(??{reverse $2}))/gi ) {
			$max = $1 if ( length( $1 ) &gt; $prev );
			$prev = length $max;
		}
		$max;
	},

	jasper =&gt; sub {
		$_ = pop;
		s/\s//sg;
		my @a;
		do {
			push @a, $1 if /((.*).?(??{reverse$2}))/i;
		} while s/.//;
		( sort { length( $b ) &lt;=&gt; length $a } @a )[0];
	},

	deibyz =&gt; sub {
		my $match = '';
		while ( /.*?(.+)(.?)((??{reverse$1})).*?/g ) {
			$match = $1 . $2 . $3 if length( $1 . $2 . $3 ) &gt; length( $match );
		}
		$match;
	},

	limbic_region =&gt; sub {
		my %lookup;
		my ( $index, $record ) = ( -1, 0 );
		push @{ $lookup{ substr( $_[0], $_, 1 ) } }, $_
			for 0 .. ( length $_[0] ) - 1;

		LETTER: for my $letter ( keys %lookup ) {
			my $last = $#{ $lookup{ $letter } };
			for my $start ( 0 .. $last - 1 ) {
				for my $end ( reverse( $start + 1 .. $last ) ) {
					my $pos    = $lookup{ $letter }[$start];
					my $length = $lookup{ $letter }[$end] - $pos + 1;
					next LETTER if $length &lt;= $record;
					my $palindrome = substr( $_[0], $pos, $length );

					if ( $palindrome eq reverse $palindrome ) {
						( $index, $record ) = ( $pos, $length );
						last;
					}
				}
			}
		}
		return substr( $_[0], $index, $record );
	},

	bgreenlee =&gt; sub {
		my $str     = shift;
		my $longest = '';
		while ( $str =~ /(?=(.*)(.?)((??{reverse $1})))/g ) {
			$longest = "$1$2$3" if length( "$1$2$3" ) &gt; length( $longest );
		}
		return $longest;
	},

	browseruk =&gt; sub {
		my $string = shift;
		my @pals;
		while ( $string =~ m[(.) (?=( (?:\1) | (?:.\1) ) ) ]gx ) {
			my ( $left, $right ) = ( $-[0], $+[-1] );

			while ( $left
				and $right &lt; length( $string )
				and substr( $string, $left, 1 ) eq substr( $string, $right, 1 )
				)
			{
				$left--;
				$right++;
			}
			my $pal = substr( $string, $left, $right - $left );

			if ( !@pals or length( $pals[-1] ) &lt; length( $pal ) ) {
				@pals = $pal;
			}
			else {
				push @pals, $pal unless @pals;
			}
		}
		return wantarray ? $pals[0] : @pals;
	},

	jdporter =&gt; sub {
		local $_ = shift;
		my $pal;
		for my $i ( 0 .. length( $_ ) ) {
			last if defined( $pal ) &amp;&amp; length( $_ ) - $i &lt; length( $pal );
			my $j = rindex $_, substr( $_, $i, 1 );
			while ( $j &gt; $i ) {
				my $s = substr $_, $i, $j - $i + 1;
				if ( $s eq reverse $s )    # it's a palindrome
				{                          # but is it the longest yet found?
					$pal = $s
						unless defined $pal &amp;&amp; length( $pal ) &gt; length( $s );
				}
				$j--;
				$j = rindex $_, substr( $_, $i, 1 ), $j;
			}
		}
		$pal;
	},

	elgon =&gt; sub {
		use POSIX qw(ceil);
		my $string = shift;
		my %char_hash = map { $_ =&gt; 1 } split //, $string;
		foreach my $key ( keys %char_hash ) {
			my @appearances;
			for ( my $i = 0 ; $i &lt; length( $string ) ; $i++ ) {
				push( @appearances, $i ) if substr( $string, $i, 1 ) eq $key;
			}
			foreach my $start ( @appearances ) {
				foreach my $finish ( reverse @appearances ) {
					next if $start &gt;= $finish;
					my $half_length = ceil( ( $finish - $start + 1 ) / 2 );
					return
						substr( $string, ( $start ), ( $finish - $start + 1 ) )
						if substr( $string, $start, $half_length ) eq
						reverse substr( $string, ( $finish - $half_length + 1 ),
						$half_length );
				}
			}
		}
		return "FAILED!";
	},

	japhy =&gt; sub {
our$P="";pop=~m{(.+).?(??{reverse$1})
(?{length$P&lt;length$&amp;and$P=$&amp;})^}xs;$P
	},

	japhy2 =&gt; sub {
our@P="";pop=~m{(.+).?(??{reverse$
1})(?{$P[length$&amp;]=$&amp;})^}xs;$P[-1]
	},
);

my @input = (
	'2710327103701371111111111111111111611111111111111111111116602611111111'
	. '1111111111111111111111111111111111111111111611111111111111111',
	'abcdefghijklmnopqrstuvwxyz12345678987654321zyxwvutsrqponmlkjihgfedcba',
	'ababcbabcdcbabcdedcbabcdefedcbabcdefgfedcbababcbabcdcbabcdedcbabcdefedcbabcdefgfedcba',
	'abcdedcbabcdefgfedcbabcdefghijklmnonmlkjihgfedcbabcdefghijklkjihgfedcbabcdefghijklmnoponmlkjihgfedcba',
);

my @correct = (
	'61111111111111111111111111111111111111111111111111116',
	'abcdefghijklmnopqrstuvwxyz12345678987654321zyxwvutsrqponmlkjihgfedcba',
	'edcbabcdefedcbabcde',
	'onmlkjihgfedcbabcdefghijklkjihgfedcbabcdefghijklmno',
);

for my $user ( sort keys %contestant ) {
	my @result = map $contestant{ $user }-&gt;( $_ ), @{[ @input ]};
	for( 0 .. $#input ) {
		is $result[ $_ ], $correct[ $_ ], "$user test $_";
	}
}

print "\nRunning benchmark\n";

my $result = cmpthese( 0, { map +( $_ =&gt; do {
	my $user = $_;
	sub { $contestant{ $user }-&gt;( $_ ) for @{[ @input ]} };
} ), keys %contestant }, "none" );

print map Tr( td( $_ ) )."\n", @$result;
&lt;/code&gt;
&lt;/readmore&gt;

&lt;div class="pmsig pmsig-114691"&gt;
&lt;p align="right"&gt;&lt;em&gt;Makeshifts last the longest.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;</field>
<field name="root_node">
382567</field>
<field name="parent_node">
382881</field>
</data>
</node>
