Andrew Dalke adalke at
Thu Nov 13 07:38:14 CET 2003

Hi Runic911,

You probably want this

         t = p.lower()
         t[h] == t[len(t)-1-h]

to do something.  As it is now you don't report anything.
Looking at it some more I see it has several other problems.
The code starting at 't=p.lower()' needs to be dedented a
few levels so it is outside of the 'while s != '':' loop.
Also, that should be 'if s != '':' and likely doesn't
even need to be there at all.

In addition, you could shorten it by quite a bit by using
some of this higher-level functions available in Python.
Here's some pointers.

1) get rid of puncutation in one step rather than several.

You can use the re module for that, as in

>>> s = "A man, a plan, a canal -- Panama!"
>>> import re
>>> re.sub(r'[%$!*.,:? ;()\'\"\\-]', '', s)

This is tricky, in part because the '-' must be at the end of pattern.
You could also use the translate function, as in

>>> punctuation = '%$!*.,-:? ;()\'\"\\'
>>> identity = "".join([chr(i) for i in range(256)])
>>> s.translate(identity, punctuation)

This is also tricky because you have to use an identity
translation table.  (On the other hand, done correctly this
could also convert everything to lower case.)  I would
like a function which only removed a selected set of

Or you could make your own function for it

>>> def remove_punctuation(s):
...  letters = []
...  for c in s:
...   if c not in punctuation:
...    letters.append(c)
...  return "".join(letters)
>>> remove_punctuation(s)

You could put this all into your palindrome code but
it's usually easier to understand your code if each
step does one thing.  By the way, an experienced
Python programmer might write this function as

def remove_punctuation(s):
  return "".join([c for c in s if c not in punctuation])

(since I didn't test this one, odds are good there's
a typo ;)

2) convert everything to the same case.  If you use
the regular expression way then use the lower() method,
which you know about already.

The translate function can do it like this

>>> for upper, lower in zip(string.ascii_uppercase, string.ascii_lowercase):
...  foldcase[ord(upper)] = lower
>>> foldcase = "".join(foldcase)
>>> s
'A man, a plan, a canal -- Panama!'
>>> s.translate(foldcase, punctuation)

3) instead of comparing the string to itself, make a
new string which is a reverse of the old one and compare
the strings to each other

In newer Pythons (2.3) you can use [::-1] as a way
to slice the string backwards.  Here's some examples

>>> s
'A man, a plan, a canal -- Panama!'
>>> s[::-1]
'!amanaP -- lanac a ,nalp a ,nam A'
>>> t = s.translate(foldcase, punctuation)
>>> t
>>> t[::-1]

Since t == t[::-1] you know they are palindromes.

For older Pythons you'll need to turn the string
into a list of characters, reverse the list, and turn
it back into a string, as in

>>> chars = list(s)
>>> chars
['A', ' ', 'm', 'a', 'n', ',', ' ', 'a', ' ', 'p', 'l', 'a', 'n', ',', ' ',
'a', ' ', 'c', 'a', 'n',
 'a', 'l', ' ', '-', '-', ' ', 'P', 'a', 'n', 'a', 'm', 'a', '!']
>>> chars.reverse()
>>> chars
['!', 'a', 'm', 'a', 'n', 'a', 'P', ' ', '-', '-', ' ', 'l', 'a', 'n', 'a',
'c', ' ', 'a', ' ', ',',
 'n', 'a', 'l', 'p', ' ', 'a', ' ', ',', 'n', 'a', 'm', ' ', 'A']
>>> "".join(chars)
'!amanaP -- lanac a ,nalp a ,nam A'

This should be enough information for you to make a
very nice palindrome function.

                    dalke at

More information about the Python-list mailing list