# stringfun.py # Walker M. White (wmw2) # October 15, 2013 """A module of recursive functions on Strings.""" import string # constants to help with string import sys # Allow us to go really deep sys.setrecursionlimit(999999999) def length(s): """Returns: number of characters in s Precondition s is a string""" assert type(s) == str, str(s) + ' is not a string' # get in the habit # {s is empty} if s == '': return 0 # { s has at least one character} # return (length of s[0]) + (length of s[1:]) return 1 + length(s[1:]) def num_e(s): """Returns: number of 'e's in s Precondition s is a string""" assert type(s) == str, str(s) + ' is not a string' # get in the habit # {s is empty} if s == '': return 0 # { s has at least one character} # return (number of 'e's in s[0]) + (number of 'e's in s[1:]) #return (1 if s[0] == 'e' else 0) + num_e(s[1:]) if s[0] == 'e': first = 1 else: first = 0 return first+num_e(s[1:]) def deblank(s): """Returns: s but with blanks removed Precondition s is a string""" assert type(s) == str, str(s) + ' is not a string' # get in the habit # {s is empty} if s == '': return s if s[0] in string.whitespace: return deblank(s[1:]) return s[0] + deblank(s[1:]); def depunct(s): """Returns: s but with everything that is not a letter removed Precondition s is a string""" assert type(s) == str, `s` + ' is not a string' # get in the habit # {s is empty} if s == '': return s if not s[0] in string.letters: return depunct(s[1:]) return s[0] + depunct(s[1:]); def reverse(s): """Returns: s with its characters in reverse order Precondition s is a string""" assert type(s) == str, str(s) + ' is not a string' # get in the habit if s == '': return s # { s has at least 2 chars } return reverse(s[1:]) + s[0] def equals_ignore_case(c, d): """Returns: true if strings c and d differ only in case, if at all Precondition c, d are string""" assert type(c) == str, str(c) + ' is not a string' # get in the habit assert type(d) == str, str(d) + ' is not a string' # get in the habit return c.upper() == d.upper() def ispalindrome(s): """Returns: true if s is a palindrome There are two ways to define a palindrome: 1. s is a palindrome if it reads the same backward and forward. 2. s is a palindrome if either (1) its length is <= 1 OR (2) its first and last chars are the same and the string between them is a palindrome. Letters that differ only in case are considered to match. Precondition s is a string""" assert type(s) == str, str(s) + ' is not a string' # get in the habit # print 's is: ' + `s` if len(s) < 2: return True # { s has at least 2 characters } # return (first and last chars match) && (inner substring is pal.) return (equals_ignore_case(s[0], s[-1]) and ispalindrome(s[1:len(s)-1])) def ispalindrome2(s): """Returns: true if s is a palindrome There are two ways to define a palindrome: 1. s is a palindrome if it reads the same backward and forward. 2. s is a palindrome if either (1) its length is <= 1 OR (2) its first and last chars are the same and the string between them is a palindrome. Letters that differ only in case are considered to match. Precondition s is a string""" assert type(s) == str, str(s) + ' is not a string' # get in the habit return equals_ignore_case(s,reverse(s)) def ispalindrome_loosely(s): """Returns: true if s is a palindrome paying attention only to the letters Case and any non-letter characters are ignored. Precondition s is a string""" assert type(s) == str, str(s) + ' is not a string' # get in the habit return ispalindrome(depunct(s))