Longest palindromic substrings: Difference between revisions
Content added Content deleted
m (→{{header|Python}}: Added a functionally composed Python draft.) |
|||
Line 297: | Line 297: | ||
printf(1,"%s: %v\n",{s,longest_palindromes_raku(piStr)})</lang> |
printf(1,"%s: %v\n",{s,longest_palindromes_raku(piStr)})</lang> |
||
=={{header|Python}}== |
|||
Defines maximal expansions of any two or three character |
|||
palindromic nuclei in the string. |
|||
(This version ignores case but allows non-alphanumerics). |
|||
<lang python>'''Longest palindromic substrings''' |
|||
# longestPalindrome :: String -> ([String], Int) |
|||
def longestPalindromes(s): |
|||
'''All palindromes of the maximal length |
|||
drawn from a case-flattened copy of |
|||
the given string, tupled with the |
|||
maximal length. |
|||
Non-alphanumerics are included here. |
|||
''' |
|||
k = s.lower() |
|||
palindromes = [ |
|||
palExpansion(k)(ab) for ab |
|||
in palindromicNuclei(k) |
|||
] |
|||
maxLength = max([ |
|||
len(x) for x in palindromes |
|||
]) if palindromes else 1 |
|||
return ( |
|||
list(filter( |
|||
lambda x: maxLength == len(x), |
|||
palindromes |
|||
) if 1 < maxLength else list(s)), |
|||
maxLength |
|||
) |
|||
# palindromicNuclei :: String -> [(Int, Int)] |
|||
def palindromicNuclei(s): |
|||
'''Ranges of all the 2 or 3 character |
|||
palindromic nuclei in s. |
|||
''' |
|||
cs = list(s) |
|||
return [ |
|||
# Two-character nuclei. |
|||
(i, 1 + i) for (i, (a, b)) |
|||
in enumerate(zip(cs, cs[1:])) |
|||
if a == b |
|||
] + [ |
|||
# Three-character nuclei. |
|||
(i, 2 + i) for (i, (a, b, c)) |
|||
in enumerate(zip(cs, cs[1:], cs[2:])) |
|||
if a == c |
|||
] |
|||
# palExpansion :: String -> (Int, Int) -> String |
|||
def palExpansion(s): |
|||
'''Full expansion of the palindromic |
|||
nucleus with the given range in s. |
|||
''' |
|||
iEnd = len(s) - 1 |
|||
def p(ij): |
|||
i, j = ij |
|||
return 0 == i or iEnd == j or s[i-1] != s[j+1] |
|||
def expansion(ij): |
|||
i, j = ij |
|||
return (i - 1, 1 + j) |
|||
def go(ij): |
|||
ab = until(p)(expansion)(ij) |
|||
return s[ab[0]:ab[1] + 1] |
|||
return go |
|||
# ------------------------- TEST ------------------------- |
|||
# main :: IO () |
|||
def main(): |
|||
'''Longest palindromic substrings''' |
|||
print( |
|||
fTable(main.__doc__ + ':\n')(repr)(repr)( |
|||
longestPalindromes |
|||
)([ |
|||
'three old rotators', |
|||
'never reverse', |
|||
'stable was I ere I saw elbatrosses', |
|||
'abracadabra', |
|||
]) |
|||
) |
|||
# ----------------------- GENERIC ------------------------ |
|||
# until :: (a -> Bool) -> (a -> a) -> a -> a |
|||
def until(p): |
|||
'''The result of repeatedly applying f until p holds. |
|||
The initial seed value is x. |
|||
''' |
|||
def go(f): |
|||
def g(x): |
|||
v = x |
|||
while not p(v): |
|||
v = f(v) |
|||
return v |
|||
return g |
|||
return go |
|||
# ---------------------- FORMATTING ---------------------- |
|||
# fTable :: String -> (a -> String) -> |
|||
# (b -> String) -> (a -> b) -> [a] -> String |
|||
def fTable(s): |
|||
'''Heading -> x display function -> fx display function -> |
|||
f -> xs -> tabular string. |
|||
''' |
|||
def gox(xShow): |
|||
def gofx(fxShow): |
|||
def gof(f): |
|||
def goxs(xs): |
|||
ys = [xShow(x) for x in xs] |
|||
w = max(map(len, ys)) |
|||
def arrowed(x, y): |
|||
return y.rjust(w, ' ') + ' -> ' + ( |
|||
fxShow(f(x)) |
|||
) |
|||
return s + '\n' + '\n'.join( |
|||
map(arrowed, xs, ys) |
|||
) |
|||
return goxs |
|||
return gof |
|||
return gofx |
|||
return gox |
|||
# MAIN --- |
|||
if __name__ == '__main__': |
|||
main()</lang> |
|||
{{Out}} |
|||
<pre>Longest palindromic substrings: |
|||
'three old rotators' -> (['rotator'], 7) |
|||
'never reverse' -> (['ever reve'], 9) |
|||
'stable was I ere I saw elbatrosses' -> (['table was i ere i saw elbat'], 27) |
|||
'abracadabra' -> (['aca', 'ada'], 3)</pre> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |