15-112 Spring 2012 Homework 5
Due Sunday, 19-Feb, at 10pm

This assignment and the accompanying autograder (except for the internal plumbing of the autograder) was written, implemented, and thoroughly tested by the 15-112 Content Production Team as part of their training.  We welcome any feedback you may have about the exercises, the autograders, or anything else regarding this assignment.


Read these instructions first!
  1. capitalizeFirstLetters
  2. foil
  3. interleave
  4. Phone Numbers
  5. Poker Hands
  6. Cipher
  7. pigLatin

  1. capitalizeFirstLetters  [5 pts]
    Write the function capitalizeFirstLetters(s) which takes a string, s, and returns the original string with the first character of every word capitalized. For example, capitalizeFirstLetters("hello, my name is john.") will return "Hello, My Name Is John."

    Note: A new word starts after one or more spaces. Non-letters are capitalized as themselves.  Punctuation does not affect the start of a new word. For example: capitalizeFirstLetters("don't do that (please)") returns "Don't Do That (please)" and not "Don'T Do That (please)" or "Don't Do That (Please)".
     
  2. foil  [5 pts]
    Write the function foil(expression) which takes a string, expression, representing a product of two expressions of the form (x + b), such as "(x + 2)(x + 3)" and returns a string containing the expanded form. In this case "x**2 + 5*x + 6".

    The variable (in this case x) can be any letter, uppercase or lowercase, and must be the same in both expressions.  The constants (2 and 3 in this case) must be positive integers less than 10.  Legal inputs will include spaces where shown in the example.
     
  3. interleave  [9 pts]
    Write the function interleave(s1, s2) that takes two strings, s1 and s2, and interleaves their characters starting with the first character in s1. For example, interleave('pto', 'yhn') would return the string "python". If one string is longer than the other, concatenate the rest of the remaining string onto the end of the new string. For example ('a#', 'cD!f2') would return the string "ac#D!f2".   Assume that both s1 and s2 will always be strings.

  4. Phone Numbers  [10 pts]
    1. keypadDigit(c) [5 pts]
      Write the function keypadDigit(c) which takes a string, c, containing a letter, and returns its corresponding number on a standard phone keypad as an integer. For example keypadDigit("A") returns 2 and keypadDigit("a") returns 2. keypadDigit("z") returns 9.
      Make your conversion according to the following:
      2 = a, b, c
      3 = d, e, f
      4 = g, h, i
      5 = j, k, l
      6 = m, n, o
      7 = p, q, r, s
      8 = t, u, v,
      9 = w, x, y, z

      You can assume keypadDigit always takes a string of length 1, and it should always return an integer 2 - 9.

    2. Note:  There are additional restrictions on this problem. You may not use conditionals or loops (if, while, for) and you may not call any helper functions. Your keypadDigit may not exceed 4 lines (not including def or commented out lines). If you are confused on how to do this, think back to the first homework, or come to office hours!

    3. phoneNumbers(text) [5 pts]
      Now using the function keypadDigit(c), write the function phoneNumbers(text) that takes a string of length 7, guaranteed to contain only letters, and returns a phone number corresponding to those letters. The function should return the phone number as a string in the format: 'XXX-XXXX'. For example: phoneNumbers('heyclam'), phoneNumbers('HeyClam'), and phoneNumbers('HEYclam') should all return "439-2526".

      Note that this function returns the numbers as a string.  If you cannot finish keypadDigit, but still want to get points for phoneNumbers, don't fret. When the private autograder runs your code, it will plug in our solution to keypadDigit if yours is not working properly.

  5. Poker Hands  [16 pts]
    Background: This problem involves 5-card hands in the game of poker, represented as strings. Hands are represented by 5 cards separated by spaces, with each card composed of two characters, the first for its rank and the second for its suit. There are 13 ranks. We use "T", "J", "Q", "K", and "A" to represent the ranks Ten, Jack, Queen, King, and Ace, and the characters "2"-"9" for ranks 2-9. There are four suits: Clubs, Diamonds, Hearts, and Spades. The first letter of each suit is used to represent the suit. For example, "JD JS TH 2D 5C" is a hand with a Jack of Diamonds, a Jack of Spades, a Ten of Hearts, a Two of Diamonds, and a Five of Clubs. You will write 4 functions that deal with these hands.

    1. isValidHand  [4 pts] This function takes a string and returns True if it follows the above specification, and False otherwise. For example, if the hand does not have exactly 5 cards, if the cards are not separated by exactly one space, or if a rank or suit is not valid, return False. You do not need to check that the 5-card hand could have come from a standard deck (so "KD KD KD KD KD" is a valid hand!).

    2. isFlush  [4 pts] This function takes a string and returns True if it is a valid hand and all of its cards have the same suit. It returns False otherwise.

    3.  
    4. isRoyalFlush  [4 pts] This function takes a string and returns True if the hand is a royal flush, and False otherwise. A royal flush has three properties: it is a valid hand, all of its cards have the same suit, and there is exactly one of each of the following ranks: Ten, Jack, Queen, King, and Ace. These cards can be in any order.
       
    5. hasPair  [4 pts] This function takes a string and returns True if it is a valid hand and that hand contains at least two cards of the same rank, and False otherwise. Note that this does not correspond exactly to the Poker hand of "one pair", since hasPair(hand) will return True for a hand with three-of-a-kind.  For example, hasPair("KD KS 7H 8C KC") returns True.

  6. Cipher [25 pts]
    Background: http://en.wikipedia.org/wiki/Substitution_cipher#Simple_substitution

    A substitution cipher is a basic method of encryption. Given a jumbled version of the alphabet, each letter in a message is replaced with the letter that is in its position in the jumbled alphabet. For example, using SQCDGYFEZBLANKJIMPURWTHVOX for a jumble means that we would replace "A" with "S", "B" with "Q", "C" with "C", and so on, turning "Hello, World!" into "Egaaj, Hjpad!" (Note that substitutions are case sensitive!) We first generate a jumbled alphabet from a string. The function alphabetHelper takes a string and returns a string of upper-case letters in the order they first appeared, and makeCipherAlphabet uses this to make an entire alphabet (by filling in the remaining letters). The function makeSubstitution takes one of these alphabets and applies the cipher, and so substitutionCipher can combine these together to take any two strings and encrypt the first using the second.

    With this in mind, write a function substitutionCipher(key, message) that takes a string, key, and a string, message, to encode. The function should use the key to create a jumble and use this jumbled cipher alphabet for substitution, then return the encoded message.

    To make this problem more approachable, we are providing more specifics on each helper function. And to make the problem more gradeable, we are requiring that you follow this design! So you should solve the problem by writing the following functions in the order given:

    1. alphabetHelper(text)  [5 pts]
      Write the function alphabetHelper(text) which takes a string, text, and returns the same string containing only unique uppercase letters. For example, alphabetHelper("Bb,Ac") returns "BAC".
       
    2. makeCipherAlphabet(key)  [5 pts]
      Write the function makeCipherAlphabet(key) which takes a string, key, and returns a string containing an uppercase, jumbled version of the alphabet starting with the string from alphabetHelper and then adding the remaining letters of the alphabet in their normal order. For example, makeCipherAlphabet("SQCDGYFEZBLANKJIMPURWTHVOX") returns "SQCDGYFEZBLANKJIMPURWTHVOX" and makeCipherAlphabet("Zebras? Zsa!") returns "ZEBRASCDFGHIJKLMNOPQTUVWXY".

    3.  
    4. makeSubstitution(message, cipherAlphabet)  [10 pts]
      Write the function makeSubstitution(message, cipherAlphabet) which takes two strings: message and cipherAlphabet. The function should use the substitution cipher described above (using cipherAlphabet for the substitution) and return an encoded version of message. For example, makeSubstitution("Hello, World!", "SQCDGYFEZBLANKJIMPURWTHVOX") should return "Egaaj, Hjpad!" (Again note that substitutions are case sensitive, and non-characters are unchanged.).

    5.  
    6. substitutionCipher(message, key)  [5 pts]
      Finally, write the function substitutionCipher(message, key) which takes two strings: message and key. The function should use makeCipherAlphabet(key) to create a cipher alphabet which is used in makeSubstitution(message, cipherAlphabet) to encode the original message (of course using the substitution cipher described above). For example, substitutionCipher("Hello, World!", "Zebras? Zsa!") should return "Daiil, Vloir!".

  7. pigLatin  [30 pts]
    Background: Pig Latin is an alteration of English. To make a word in Pig Latin, take an English word, move the leading consonants to the end, followed by " ay " (e.g. " school " -> " oolschay "). If the word begins with a vowel, or if it contains no vowels, then simply add " ay " to the end (e.g. " in " -> " inay ").

    Write a function named pigLatin which takes a string of English words and translates it into Pig Latin. The function should return the result as a string. You should treat "qu" as a single consonant, and "y" should be treated as a vowel. Words are divided by spaces, and any non-alphabetic characters (punctuation, numbers, etc.) inside a word should remain where they are. If outside of a word, they should remain outside (e.g. "hey, don‘t do that!" -> "eyhay, on‘tday oday atthay!"). If a "word" (such as "9000") contains no letters, do not add "ay" to the end. Finally, if the first letter of a word is capitalized, then the first letter of the pig latin word should be capitalized (e.g. "Professor Kosbie" -> "Ofessorpray Osbiekay"). All letters except the first will be lowercase in the input, and should be lower case in your output as in the previous example.

  8.  

    carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem