String Slicing

  1. s[1:6]
  2. s[:2] or s[0:2]
  3. s[6:9]
  4. s[6:] or s[6:10]
  5. s[6] or s[6:7]
  6. s[:] or s[0:10] (or just s)

String Searching

              
def defront(s):
    if len(s) >= 2:
        return s[2:]
    return s

def x_end(s):
    found = s.find('x')
    if found != -1:
        return s[found:]
    return ''

def pre_colon(s):
    colon = s.find(':')
    if colon != -1:
        return s[:colon]
    return s

def at_word(s):
    at1 = s.find('@')
    if at1 != -1:
        at2 = s.find('@', at1 + 1)
        if at2 != -1:
            return s[at1 + 1:at2]
    return ''


              
          

String Construction

          
            
def only_one_first_char_new(s):
	"""This function builds up a new string adding all characters in the input string except those that are
	the same as the first char
	
	>>> only_one_first_char_new('abba abba abba')
	'abb bb bb'

	>>> only_one_first_char_new('Stanford')
	'Stanford'

	>>> only_one_first_char_new('')
	''
		"""
	
	#handle empty string as input 
	if s == "":
		return ""

	first_char = s[0]
	output = first_char
	for i in range(1, len(s)):
		if(s[i] != first_char):
			output += s[i]

	return output

def only_one_first_char_keep(s):
	"""This function removes all occurences of the first character except the first char itself and 
	returns the udpated string

	>>> only_one_first_char_keep('abba abba abba')
	'abb bb bb'

	>>> only_one_first_char_keep('Stanford')
	'Stanford'

	>>> only_one_first_char_keep('')
	''

	>>> only_one_first_char_keep('aaaaa')
	'a'
	"""

	if s == "":
		return ""

	#remove all occurrences of the first charcater with the empty string 
	first_char = s[0]
	s = s.replace(first_char, "")

	#add the first character back to the front of the string and return it
	return first_char + s



def make_gerund(s):
	"""This function adds 'ing' to the end of the given string s and returns this new word. If the given world already 
	ends in 'ing' the function adds an 'ly' to the end of s instead before returning.
	>>> make_gerund('ringing')
	'ringly'
	>>> make_gerund('run')
	'runing'
	>>> make_gerund('')
	'ing'
	>>> make_gerund('ing')
	'ly'
	"""


	#if it already ends in ing, add an 'ly' instead 
	if len(s) >= 3 and s[len(s)-3:] == 'ing':
		s = s[0:len(s)-3] + 'ly'
	else:
		s = s + 'ing'

	return s



def put_in_middle(outer, inner):
	"""This function inserts the string inner into the middle of the string outer and returns this new value
	>>> put_in_middle('Absolutely', 'freaking')
	'Absolfreakingutely'

	>>> put_in_middle('ss', 'mile')
	'smiles'

	>>> put_in_middle('hit', 'obb')
	'hobbit'
		"""

	middle = len(outer) // 2
	return outer[0:middle] + inner + outer[middle:]

          
        

Word Puzzles

          
def is_palindrome(word):
    """
    Returns whether or not word is a palindrome, i.e., the same read forwards
    or backwards.

    Arguments:
        word -- The word to check

    >>> is_palindrome('CIVIC')
    True
    >>> is_palindrome('ROTATOR')
    True
    >>> is_palindrome('PYTHON')
    False
    >>> is_palindrome('PROGRAMMING')
    False
    >>> is_palindrome('')
    True
    """

    for i in range(len(word)):
        if word[i] != word[len(word)-i-1]:
            # One of the letters doesn't match its pair at the end of the word
            return False

    return True


def is_tridrome(word):
    """
    Returns whether or not word is a tridrome, i.e., the first three letters
    are the same as the last three letters.

    Arguments:
        word -- The word to check

    >>> is_tridrome('ENTERTAINMENT')
    True
    >>> is_tridrome('UNDERGROUND')
    True
    >>> is_tridrome('DEFENESTRATION')
    False
    >>> is_tridrome('PYTHON')
    False
    >>> is_tridrome('')
    False
    """

    """
    We need to check that
    1. the word is at least six letters, and
    2. the first three letters of the word are the same as the last three 
       letters.

    To check the first condition, we check if
        len(word) >= 6

    For the second condition, we can extract the first three letters of the 
    word with word[:3] and the last three with word[-3:]. If negative indexing
    isn't comfortable, the last three letters of the word can also be sliced
    with word[len(word)-3:]!

    In Python, we can combine these two conditions using the `and` keyword,
    which short-circuits (i.e., if the first condition is false, it doesn't
    check the second condition).

    This leads to the rather nice one-line solution:
    """
    return len(word) >= 6 and word[:3] == word[-3:]


ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def is_peaceful(word):
    """
    Returns whether a word is peaceful, i.e., whether its letters appear in
    sorted order.

    Arguments:
        word -- The word to check
    >>> is_peaceful('ABORT')
    True
    >>> is_peaceful('FIRST')
    True
    >>> is_peaceful('')
    True
    >>> is_peaceful('PYTHON')
    False
    >>> is_peaceful('CHOCOLATE')
    False
    """

    """
    Python provides a really nice `sorted` function that can sort collections.
    It returns a list, and you can turn a list into a string by joining together
    its elements with a string:
        ''.join(lst)

    We can, therefore, get a nice one-line solution with:
    """
    # return word == ''.join(sorted(word))

    """
    Or, you might prefer the iterative solution, using string comparisons to 
    check if a character is >= the next character (Python lets you compare 
    strings alphabetically!):
    """
    # for i in range(len(word) - 1): # don't check the last letter
    #     if word[i] >= word[i+1]:
    #         return False
    # return True

    """
    And finally, we can use a creative application of the `.find` function to 
    obtain a character's position in the alphabet:
    """
    for i in range(len(word) - 1): # don't check the last letter
        """
        We search for the character in ALPHABET. 
        """
        curr_letter_index = ALPHABET.find(word[i])
        next_letter_index = ALPHABET.find(word[i+1])
        if curr_letter_index >= next_letter_index:
            return False
    return True


def is_stacatto(word):
    """
    Returns whether a word is a stacatto word, i.e., whether the letters in
    even positions are vowels.

    Arguments:
        word -- The word to check

    >>> is_stacatto('AUTOMATIC')
    True
    >>> is_stacatto('POPULATE')
    True
    >>> is_stacatto('')
    True
    >>> is_stacatto('PYTHON')
    False
    >>> is_stacatto('SPAGHETTI')
    False
    """
    VOWELS = 'AEIOUY'

    for i in range(len(word)):
        if i % 2 == 1:
            even_letter = word[i]
            if not even_letter in VOWELS:
                return False # we've found an even letter that isn't a vowel,
                             # so we can return immediately.

    return True


def count_palindromes(filename):
    """
    Return the number of palindromes in the file
    """
    count = 0
    with open(filename, 'r') as f:
        for line in f:
            word = line.strip().upper()
            if is_palindrome(word):
                count += 1
    return count


def count_tridromes(filename):
    """
    Return the number of tridromes in the file
    """
    count = 0
    with open(filename, 'r') as f:
        for line in f:
            word = line.strip().upper()
            if is_tridrome(word):
                count += 1
    return count


def count_peaceful(filename):
    """
    Return the number of peaceful words in the file
    """
    count = 0
    with open(filename, 'r') as f:
        for line in f:
            word = line.strip().upper()
            if is_peaceful(word):
                count += 1
    return count


def count_stacatto(filename):
    """
    Return the number of stacatto words in the file
    """
    count = 0
    with open(filename, 'r') as f:
        for line in f:
            word = line.strip().upper()
            if is_stacatto(word):
                count += 1
    return count
          
        

CoHome Delivery

          
def contains_email(line):
    """
    This function checks to see if an email address is present in a given line of a message. 
    It checks for the '@' symbol. If one is present, it checks that it is part of an email address, 
    meaning it must have at least one character before and after it. If an email address is found,
    the function returns True and it returns False otherwise. 
    """
    at_location = line.find('@')
    if at_location == -1:
        return False

    if line[at_location - 1] == ' ' or line[at_location + 1] == ' ':
        return False

    return True

def contains_phone_number(line):
    """
    This function searches a given line of a message for a 10 digit sequence of numbers to check if a phone
    number is present. If a phone number is present, it returns True and it returns False otherwise. 
    """
    for idx in range(len(line)):
        if line[idx].isdigit():
            possible_phone_number = line[idx:idx + 10]
            if len(possible_phone_number) == 10 and possible_phone_number.isdigit():
                return True 
        
    return False

def is_message_valid(filename):
    """
    This function searches a file for an email address or phone number using the helper methods defined above. 
    If the file contains a phone number or email address, it is considered invalid and the function should 
    return False. If it contains neither a phone number or email address, the message is valid and should 
    return True.
    >>> is_message_valid('100284.txt')
    True
    >>> is_message_valid('100282.txt')
    True
    >>> is_message_valid('100280.txt')
    False
    """
    with open(filename, 'r') as f:
        for line in f:
            if contains_email(line):
                return False 
            if contains_phone_number(line):
                return False 
    
    return True
          
        

Download a solution PyCharm project here.