Homework 3

Due Tuesday 1-Feb, at 10:00pm


To start

  1. Create a folder named ‘hw3’
  2. Download hw3.py to that folder
  3. Edit hw3.py and modify the functions as required
  4. When you have completed and fully tested hw3, submit hw3.py to Gradescope. For this hw, you may submit up to 15 times, but only your last submission counts.

Some important notes

  1. This homework is solo. You may not collaborate or discuss it with anyone outside of the course, and your options for discussing with other students currently taking the course are limited. See the academic honesty policy for more details.
  2. After you submit to Gradescope, make sure you check your score. If you aren’t sure how to do this, then ask a CA or Professor.
  3. There is no partial credit on Gradescope testcases. Your Gradescope score is your Gradescope score.
  4. Read the last bullet point again. Seriously, we won’t go back later and increase your Gradescope score for any reason. Even if you worked really hard and it was only a minor error…
  5. Do not hardcode the test cases in your solutions.
  6. The starter hw3.py file includes test functions to help you test on your own before you submit to Gradescope. When you run your file, problems will be tested in order. If you wish to temporarily bypass specific tests (say, because you have not yet completed some functions), you can comment out individual test function calls at the bottom of your file in main(). However, be sure to uncomment and test everything together before you submit! Ask a CA if you need help with this.
  7. Remember the course’s academic integrity policy. Solving the homework yourself is your best preparation for exams and quizzes; cheating or short-cutting your learning process in order to improve your homework score will actually hurt your course grade long-term.

Limitations

Do not convert numbers to strings, use string indexing or recursion this week. The autograder (or a manual CA review later) will reject your submission entirely if you do.

A Note About Style Grading

Starting with this assignment, we will be grading your code based on whether it follows the 15-112 style guide. We may deduct up to 10 points from your overall grade for style errors. We highly recommend that you try to write clean code with good style all along, rather than fixing your style issues at the end. Good style helps you code faster and with fewer bugs. It is totally worth it. In any case, style grading starts this week, so please use good style from now on!

A Note About Testing

You will notice that the skeleton file only includes testcases for some of the functions you are writing. You should write testcases for the others. (You can find some nice ways to test in the write-up below, but you will need to translate those to actual testcases.)


Problems

  1. removeOdds(L) [10 pts]
    Write the function removeOdds(L), which takes a list L and returns a new list in which any odd integer elements in L are removed. For example:
    assert(removeOdds([1, 3, 5, 4, 3, 2, 1, 7, 5]) == [4,2])
    Note that the values in the resulting list occur in the order they appear in the original list, but each occurs only once in the result.

  2. countPeaks(L) [10 pts]
    A peak element is an element that is strictly greater than its left and right neighbors, i.e., the elements that occur before and after. Given a list L of positive integer values, write the function countPeaks(L) that returns the number of peak elements. Given that the first and last elements have only one neighbor, you should assume that the elements before the first element (i.e., L[0]) and after the last element (i.e., L[-1]) are both zero. For instance, countPeaks([1,2,3,1]) should return 1 because the element at index 2 (number 3) is the only peak element: 3 is greater than its left and right neighbors (2, 1). countPeaks([3,1,4]) should return 2 because there are two peaks: 3 is a peak because it is greater than 0 (the imaginary element before L[0]) and 1 (its right neighbor); 4 is also a peak because it is greater than 1 (its left neighbor) and 0 (the imaginary element after the last index). countPeaks([1,1]) should return 0 because there are no peaks.

  3. maxProfit(prices) [15 pts]
    Write the function maxProfit(prices) which takes a list prices where prices[i] is the price of a given stock on the ith day. You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell it. The function should return the maximum profit you can be achieved from any buy-sell trade. If no profit can be achieved, the function should return 0. For example, maxProfit([7,1,5,3,6,4]) returns 5 because the best possible trade is to buy on day 1 (price = 1) and sell on day 4 (price = 6), thus the maximum profit is 6-1 = 5. Note that buying on day 1 and selling on day 0 is not allowed because you must buy before you sell. maxProfit([4,3,2,1]) should return 0 because the stock prices are declining and any buy-sell trade would generate losses.

  4. lookAndSay(a) [20 pts]
    First, read about look-and-say numbers here. Then, write the function lookAndSay(a) that takes a list of numbers and returns a list of numbers that results from "reading off" the initial list using the look-and-say method, using tuples for each (count, value) pair. For example:

    lookAndSay([]) == [] lookAndSay([1,1,1]) == [(3,1)] lookAndSay([-1,2,7]) == [(1,-1),(1,2),(1,7)] lookAndSay([3,3,8,-10,-10,-10]) == [(2,3),(1,8),(3,-10)]

    Hint: you'll want to keep track of the current number and how many times it has been seen.

  5. inverseLookAndSay(a) [20 pts]
    Write the function inverseLookAndSay(a) that does the inverse of the previous problem, so that, in general:
    inverseLookAndSay(lookAndSay(a)) == a
    Or, in particular:
    inverseLookAndSay([(2,3),(1,8),(3,-10)]) == [3,3,8,-10,-10,-10]

  6. averageWithPolicy(scores) [25 pts]

    Consider the following excerpt from a course syllabus:
    In order to reward improvement, I will replace one quiz score that is immediately followed by two higher scores. So, if you have a quiz that goes very badly, but your next two quizzes are each better than that bad quiz, I will replace that low quiz with the higher of the two scores immediately following it. If you have multiple "bad" quizzes that meet the criteria, I will replace the one that maximizes your point gain.

    Write the function averageWithPolicy(scores) which takes as an argument a list of scores and returns the average of those scores after applying this policy.

    Consider the following examples:

    assert(averageWithPolicy([42, 20, 40, 35, 50, 65]) == 47.0) assert(averageWithPolicy([25, 30, 20, 45, 40, 60, 70, 80, 90, 100]) == 59.0)

    The first example is 47 because the quiz to be replaced is the 35, and it will be replaced by a 65. That means we are finding the average of [42, 20, 40, 65, 50, 65]

    The second example is 59 because the quiz to be replaced is the 40, and it will be replaced by a 70. That means we are finding the average of [25, 30, 20, 45, 70, 60, 70, 80, 90, 100]

    Hint: You don’t actually need to find and replace anything in the list. Instead, you just need to find the largest difference among all candidates that meet the "lower before two higher" criteria. I recommend you create a helper function to do that.