# CMU 15-110 Spring 2019: Principles of Computing Homework 5 (Due Tuesday 26-Mar at 8pm)

This hw is entirely solo. See the syllabus for details.
Write the function `addRowAndColSums(L)` that takes a rectangular non-empty 2d list of numbers L and non-destructively returns a new list which is the same as L, but with an extra column to the right which holds the sum of each row, and an extra row at the bottom, which holds the sum of each column. For example:
``````    L = [ [ 1, 2, 3],
[ 4, 5, 6] ]
M = [ [ 1, 2, 3, 6 ],
[ 4, 5, 6, 15 ],
[ 5, 7, 9, 21 ] ]
L = [ [ 1, 3 ] ]
M = [ [ 1, 3, 4],
[ 1, 3, 4] ]
``````

2. findWinningDice(dice1, dice2, rolls) [10 pts, autograded]
First, read the first two parts (through "Doubler Whammy") of this really interesting article about "curious dice". These dice do not have 1-6 on their sides, but other values (though still small positive integers). By carefully choosing these values, we can make dice A, B, and C such that, on a single roll, we are more likely to win with A than B, and to win with B than C, and -- amazingly -- to win with C than A. Cool.

It gets better. If we roll twice and sum the two values, then the results completely reverse! So, with two rolls, we are more likely to lose with A than B, to lose with B than C, and to lose with C than A. Truly amazing.

Here, we will use Monte Carlo techniques to verify this amazing result. In fact, we'll be a bit more general, and use Monte Carlo techniques to find the winner of any two dice for any number of rolls.

With that in mind, write the function `findWinningDice(dice1, dice2, rolls)` that takes two dice and a number of rolls, and returns the dice that is more likely to win. If they tie, return dice1.

Note that a "dice" here is actually a 1d list of the values on the sides of the dice. So the 3 dice from the top of that article are:
``````    A = [3, 3, 6, 3, 3, 3]
B = [5, 5, 5, 2, 2, 2]
C = [4, 4, 1, 4, 4, 4]
``````
To do this, use Monte Carlo techniques to determine the probability that dice1 wins given that many rolls. Then, if that result is 50% or greater, return dice1, else return dice2.

You may notice that our test function actually uses the test cases from the article, including the "Double Whammy" cases. Cool!

Note: 10**4 should be enough trials to ensure you have enough accuracy to pass the autograder.

3. Concentration! [80 pts, not autograded]
Here we will use nearly everything we have learned so far including 2d lists and the BoardGame class by writing a playable version of the game Concentration! Your game should closely match our version, which may be different from other Concentration games in some key ways.

To start, there are two videos to watch -- carefully! They are a combined 27 minutes, which is long, but we guarantee that by watching them carefully, you will spend far less time on this hw. That's the goal, at least!

With that said, here are the videos to watch (again, carefully!):
• The User Experience
• The Code + Hints

Important note: in hw4, the hints were in the code as well as the video. Here, they are all in the video. That said, we have provided headers in the code for the functions we recommend that you write.

4. Bonus/Optional: Concentration++ [up to 2.5 pts, not autograded]
As suggested at the end of the second video, for bonus you can use animation to distinguish shapes. As an example, you could have some shapes rotate clockwise and others rotate counterclockwise. You get the idea. Be clever, amaze us, make it richly engaging -- just be sure that it remains playable!

Since your submission has to match the spec, you should add a 'Bonus Mode' when the user presses 'b', and that's when the animations turn on (or off).

Also, be sure to describe your bonus feature in a comment at the top of your hw5.py file, so we are sure to give you credit for them!