Principles of Computing

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 46

Math Notes

Sunday, June 28, 2015

4:02 PM

The class pages linked below cover a selected set of math topics associated with the course. For
students whose math background may be in need of supplement, we have also included links to related
material from two sections of the Khan Academy: Algebra 2 (specifically functions and their graphs,
polynomial and rational functions, exponential and logarithmic functions) and Pre-calculus (specifically
probability and combinatorics as well as series, sequences and induction).
Overall - Entering math expressions in homework
Week 1 - Functions - supplemental material at the Khan Academy
Week 2 - Grid representations
Week 3 - Basic probability - supplemental material at the Khan Academy
Week 3 - Expected value - supplemental material at the Khan Academy
Week 4 - Enumeration
Week 4 - Permutations and combinations - supplemental material at the Khan Academy
Week 5 - Arithmetic sums - supplemental material at the Khan Academy
Week 5 - Logarithms and exponentials - supplemental material at the Khan Academy
Week 5 - Growth rates of functions - supplemental material at the Khan Academy
From <https://class.coursera.org/principlescomputing1-003/wiki/video_notes>

Principles of Computing Page 1

Math Expressions for Homework


Sunday, June 28, 2015

4:03 PM

For some homework questions, you will be asked to enter a math expression (instead of a number) as
the answer to a problem. Coursera's quiz system can recognize and symbolically processes math
expressions created using a combination of standard mathematical constants and functions as well as
unknown variables. For example, you can enter the math expression (1+x)2 as the text (1 + x) ^ 2. The
power of Coursera's system is that it will automatically check whether the expression you entered is
equivalent to the answer entered by the instructor, even if the two answers are in different forms. For
example, the expression 1 + 2 * x + x ^ 2 will be recognized as equivalent to (1+x)2 while 1 + x + x ^ 2 will be
recognized as being different.
This guide outlines the basics of entering mathematical expression in the form that Coursera
expects. Remember that you can use the "Preview answer" button to check whether you have properly
formatted your answer according to Coursera's specifications. Listed below the mathematical functions
and constants that Coursera's system recognizes:
abs
Principles of Computing Page 2

abs
arg (returns phase in radians of a complex number)
ceiling
conjugate
deg (converts radians to degrees)
exp
floor
gcd (2 arguments only; otherwise you must type it as "gcd((a, b, c, d))" or "gcd([a, b, c, d])" e.g. a list/tuple)
im (get imaginary part of a number)
lcm (2 arguments only; otherwise you must type it as "gcd((a, b, c, d))" or "gcd([a, b, c, d])" e.g. a list/tuple)
ln
log (also base e, same as ln)
max
min
mod
rad (converts degrees to radians)
re (get real part of a number)
root (2-argument, where root(a, 2) is equivalent to sqrt(a))
sqrt
sign (returns -1 if negative, 0 if zero, 1 if positive)
Trigonometric functions: acos, acosh, acot, acoth, asin, asinh, atan, atan2 (2 -argument arctangent), atanh,
cos, cosh, cot, coth, sin, sinh, tan, tanh
Other functions: erf, binomial
There are also a few built-in constants, some of which are capitalized:

Catalan (Catalan's constant)


E (note uppercase)
EulerGamma (Euler-Mascheroni constant)
GoldenRatio
I (sqrt(-1) - note uppercase)
J (sqrt(-1), same as I)
nan
oo (infinity)
pi
zoo (complex infinity)
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=math_expressions>

Principles of Computing Page 3

Functions
Sunday, June 28, 2015

4:05 PM

One of the main goals of this class is to start you along the path to understanding the behavior of the
Python code that you will write. In particular, we are interested in understanding how long your
program takes to run in terms of the size of the input provide to the program. The key mathematical
Principles of Computing Page 4

program takes to run in terms of the size of the input provide to the program. The key mathematical
concept that we will use to model the running time of a program is the function. As our first Practice
Activity, we will review some basic definitions and properties of functions that you should have learned
in high school Algebra.

Mathematical functions
A mathematical function is a mapping from a set of inputs to a set of outputs with the property that
each input corresponds to exactly one output. The standard mathematical definition of a function has
the form

f(p1,p2,...,pn)=body
where f is the name of the function, p1,p2,...,pn is a sequence of parameters for the function, and body is
an expression involving the parameters p1,p2,...,pn. Supplying values v1,v2,...,vn for the
parameters p1,p2,...,pn, we can call the function via an expression of the form f(v1,v2,...,vn). To evaluate
this expression, we substitute the values vi for the variables pi in expression body and then compute the
value of the resulting expression.
For example, consider the function that takes a number and returns the square of the number.
Mathematically, this function would have the form square(num)=num2. The function
call square(5) would substitute 5 for num and return the value 52=25.

Python functions
One nice feature of Python is that function definitions and calls have a form that is very similar to the
mathematical form described above. If we temporarily ignore our style guidelines, the square function
defined above would be expressed in Python as
def square(num):
return num ** 2

A function call in Python is almost identical to a function call in mathematical form. To compute the
square of 5 in Python, we would simply use the expression square(5). You should already be comfortable
writing simple function definitions in Python if you intend to take this class.

Polynomial functions
The most important type of functions that we will consider in the class are polynomial functions.
A polynomial is an expression consisting of variables and coefficients, that involves only the operations
of addition, subtraction, multiplication, and non-negative integer exponents. A function is a polynomial
function if the body of the function is an polynomial whose variables corresponds to the parameters of
the function. For example, the function

f(x,y)=xyxy+1
is a polynomial function in two variables x and y. A polynomial in one variable is referred to as
a univariate polynomial. A univariate polynomial in the variable xcan be written in the form

cnxn+cn1xn1+...+c0
where the coefficients c0,c1,...,cn are numbers. In this form, the integer n is the degree of the polynomial. A
function of one parameter x is a linear function in x if its body is a univariate polynomial of degree at most
one in x. Likewise, such a function is a quadratic function in x if the body of the function is a univariate
polynomial of degree at most two in x. As an example, note that function square defined above is a
quadratic function in num. Similar terminology involving cubic, quartic, quintic, etc. applies is the degree of
the degree of polynomial corresponding to the body of the function is 3,4,5..., respectively.

Other important functions


We will consider several other types of important functions in this class. A rational function is a function
whose body is the ratio of two polynomials (i.e; both the numerator and denominator are polynomials).
For example, the function

f(x)=x21+x
is a rational function in x since its body is the ratio of the polynomials x2 and 1+x. Another common class of
functions is the exponential functions of the form f(x)=cx where c is a number. A related class of function is
the logarithmic functions. The logarithm of a number is the exponent to which another fixed value, the base,
must be raised to produce that number. Logarithmic functions are typically written in the
form g(y)=logc(y) where c is the base of the logarithm. For example, log2(32) is 5 since 25=32.
If the notion of the logarithm is new to you, a simple method for understanding the behavior of
the log function is to note that it is the inverse of a corresponding exponential function. Two
functions f and g are inverses if they satisfy the equation g(f(x))=x. For exponentials and logarithms, these
functions satisfy logc(cx)=x. We will discuss exponentials and logarithms more later in the class.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=functions>

Principles of Computing Page 5

Grid Representations
Sunday, June 28, 2015

4:06 PM

Mathematically, a grid is a partition of a 2D region into a disjoint collection of cells. Typically, these cells
are all a single simple shape such as a square, triangle or hexagon. Several mini-projects, including 2048,
Zombie Apocalypse, and the Fifteen puzzle, involve rectangular grids of squares. Grids are useful in
many computational applications because they provide a convenient way to partition a geometric
region in a way that can be easily modeled as a 2D data structure.
Indexing rectangular grids
For now, we focus on rectangular grids that are composed entirely of squares. Mathematically, such a grid
has a height grid_height and a width grid_width, measured in terms of individual squares. The standard
terminology when referring to the size of such a grid is to specify height first, followed by width. For example,
a three-by-four grid is three squares high and four squares wide.
When working with such grids, we will index individual squares in the grid in the same manner that entries in
a matrix are indexed, top to bottom then left to right. In particular, a square is indexed by its row i and its
column j in the grid where the row index i lies in the range 0,1,...,height1 and the column index j lies in
the range 0,1,...,width1. This program produces a diagram in CodeSkulptor that illustrates this indexing
scheme.
When compared to canvas coordinates, this matrix-based indexing scheme transposes the horizontal and
vertical dimensions. For example, note that the coordinates given to draw_polygon in the diagram-plotting
program linked above order the column index first and the row index second when generating vertices of
each square drawn in the grid. For now, you don't need to worry about this issue since the GUIs that we
provide for each mini-project handle this transposition without any effort on your part.
Modeling rectangular grids in Python

Given a square, we can store the index associated with a square as the tuple (row,col) in Python. Then, we
can represent some relevant property of that square as the entry cells[row][col] in the 2D list cells. Note the
expression cells[row] returns a 1D list corresponding to a row of the grid. We can initialize this 2D list via the
code fragment:
cells = [ [... for col in range(grid_width)] for row in range(grid_height)]

Note that if row or col are not used in the expression ..., Pylint will warn that these variables are unused.
To avoid this warning, you can rename these variables to dummy_row and dummy_col to alert Pylint that

Principles of Computing Page 6

To avoid this warning, you can rename these variables to dummy_row and dummy_col to alert Pylint that
these variables are intentionally unused. This renaming will suppress the warning.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=grids>

Principles of Computing Page 7

Basic Probability
Sunday, June 28, 2015

4:06 PM

Probability is a branch of mathematics associated with the analysis of random phenomena. In Computer
Science, probability can arise in several ways: as part of the mathematics involved in analyzing a random
process or as part of a computational approach to solving a particular problem. For this class, our main
application of probability will be in analyzing and building programs associated with simple games.
However, don't view this application as limiting. Probabilistic methods arise in applications like scientific
computation, cryptography, and robotics.
Since many of you may have had limited exposure to probability, we review some basic terminology
associated with probability theory to begin. A trial (or an experiment) is any procedure that can be infinitely
repeated and has a well-defined set of possible outcomes, known as the sample space. If the sample space is
finite, each outcome can be assigned a number between zero and one that corresponds to the likelihood of
that particular outcome occurring. This number is the probability associated with the outcome. Since every
trial always results in exactly one outcome from the sample space, the sum of the probabilities associated
with the outcomes is always exactly one.
A simple example of a trial is a single roll of a fair six-sided die. The outcomes of this trial are the values on six
sides of the die {1,2,3,4,5,6}. Since the die is fair, the probabilities associated with these six outcomes are
all equal so the probability of each outcome is exactly 16. More generally, the probabilities associated with
outcomes of a trial are said to be uniformly distributed if these probabilities all have equal value.
An event is a set of outcomes of a trial (a subset of the sample space). For a single six-sided die, a simple
example of an event would be that the resulting roll is even. The probability of an event is the sum of the
probabilities associated with its set of outcomes. For example, rolling an even number with a six-sided die
corresponds to an event with three outcomes {2,4,6}, each with probability 1/6. Therefore, the probability of
that event is 1/6+1/6+1/6=12.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=probability>

Principles of Computing Page 8

Expected Value
Sunday, June 28, 2015

4:07 PM

In some computer science departments, one third of the students in a department have a GPA of 2.0,
one third have a GPA of 3.0, and one third have a GPA of 4.0. Suppose that we choose a student at
random from this department. What do you expect the students GPA to be? The answer is 3.0, since the
mean, or average, GPA is (2.0 + 3.0 + 4.0)/3 = 3.0. This value (the mean) is also called the expected value
(that is, we say that the expected GPA of a student in this CS department is 3.0).
At the same university, but in the biology department, half of the students have a GPA of 3.0 and the other
half have a GPA of 4.0. What is the expected GPA of a biology student in this university? The answer is (3.0+
4.0)/2=3.5. In other words, if we choose a biology student at random from this university, we expect the
student's GPA to be 3.5. Notice that the expected value in this case does not make sense as we understand
the term "expect," since no student in our case has a GPA of 3.5. The interpretation of the expected value
here is the mean, or average, GPA.
Let's now turn back to an example involving dice. What is the expected outcome of a single roll of a fair sixsided die? The answer is (1+2+3+4+5+6)/6=3.5. Of course, 3.5 has a probability of 0 being the outcome of
this trial. But, again, the interpretation of the expected value here is that 3.5 is the average of the values we
get if we had rolled this die an infinite number of times.
Notice that in the three examples above we divided by 3, 2, and 6, respectively. The reason for this is in these
three cases, the values 13, 12, and 16 are the probabilities of the relevant outcomes, respectively. That is, the
probability of each possible outcome in the fair die trial is 16. So, we can rewrite the formula for the expected
value as 161+162+163+164+165+166=3.5.

More generally, if the possible outcomes of a trial have value x1,x2,,xk and their probabilities
are p1,p2,,pk, respectively, then the expected value of this trial is ki=1pixi. As an example, consider the
case where we roll two fair six-sided dice and consider their sum as possible outcomes of the trial. In this
case, the set of possible outcomes is {2,3,4,5,6,7,8,9,10,11,12}. To compute the expect value of this sum,
we need to determine the probability of each of these outcomes.
In this case, there are 36 possible rolls if the values of the pair of dice are treated as an ordered tuple. There
is one possible tuple (1,1) that yields a sum of two so p2=136. Likewise, there are two possible
tuples (1,2) and (2,1) that yield a sum of three so p3=236=118. Continuing this analysis, pi=136(6abs(7
i)). Applying our formula for expected value, we arrive at the expression:
1362+2363+3364+4365+5366+6367+5368+4369+33610+23611+13612=7.

Principles of Computing Page 9

From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=expected_value>

Principles of Computing Page 10

Enumeration
Sunday, June 28, 2015

4:11 PM

All sequences of outcomes


Given a set of outcomes, a standard problem in combinatorics is to enumerate all possible sequences of
outcomes formed by repeatedly choosing an outcome from the set. For this class page, we will restrict
our attention to the case where repeated outcomes are allowed. This problem typically arises when one
is analyzing the probabilities associated with a sequence of trials.
As a starting point, let's consider the question of how many sequences of length n are possible if the set of
outcomes has size m. This question can be answered using a simple counting argument. There are m choices
for the first element in the sequence. Since repetitions are allowed, there are also m choices for the second
item and so on. In general, the number of sequences of length n is

Principles of Computing Page 11

mmm...m=mn.
This program computes the set of all possible sequences of outcomes of a specified length using the
function gen_all_sequences. (The program also includes a function gen_sorted_sequences which we will discuss
later.) Note that these functions represent sequences as tuples since the members of a set must be
immutable.

Sorted sequences of outcomes


In some applications, the ordering of the outcomes in each sequence is unimportant. For example, in
most dice games (including Yahtzee), the two sequences of rolls (4,3,2,1,2) and (1,2,2,3,4) each
represent the same hand. In cases such as these, it may make sense to treat these two sequences as
being equivalent to improve the performance of your program.
A standard technique for accomplishing this goal is to group all sequences of outcomes that have the same
number of instances of each outcome (but in different orders) in a single cluster and then choose a single
representative sequence for this cluster. One simple choice for this representative is to take the sequence in
which the outcomes appear in sorted (ascending) order. In the dice example in the previous paragraph, the
sorted sequence (1,2,2,3,4) would be the representative sequence for all sequences that contain one 1,
two 2's, one 3, and one 4. Your Yahtzee mini-project will use this idea and represent Yahtzee hands as a
sorted tuple of die values to avoid having multiple representations for the same Yahtzee hand.
While building a function that directly generates these sorted sequences is possible, we note that a simpler
approach is to generate all possible sequences, sort each individual sequence, and add them into a new set.
Insertion into the set will automatically eliminate the duplicate sequences that arise from sorting. The
function gen_sorted_sequences generates the set of all sorted sequences using this method. Note that this is a
substantially smaller subset of the set of sequences produced by gen_all_sequences. (For those that are
interested, this set has size
(n+m1)!n!(m1)!.)

Applications to probability
In many applications in probability, we are interested in enumerating the sequences of outcomes
associated with a sequence of trials. For this class, we restrict our attention to the situation in which
each trial is independent; that is the outcome of the trial does not affect the probabilities associated with
the outcomes of other trials. For a sequence of independent trials, the probability of a particular
sequence of outcomes is the product of the probabilities associated with each individual outcome.
A simple example of an independent sequence of trials would be rolling a pair of dice. In this case, the roll of
the first die would have six outcomes {1,2,3,4,5,6} and the roll of the second die would have six
outcomes {1,2,3,4,5,6}. Joining an outcome from the first roll with an outcome from the second roll yields
a set of all 36 possible sequences of outcomes,

{(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(2,1),...,(6,3),(6,4),(6,5),(6,6)}
Since we considered all sequences (not just sorted sequences), the probability associated with each sequence
of outcomes is the same (136).

In this setting, we can now discuss events that correspond to a subset of this set of sequences. For the case of
two dice, a typical question might be: what is the probability that sum of the dice is exactly 7? Since each of
the 36 possible sequences of outcomes has a probability of 136 and six of these
outcomes {(1,6),(2,5),(3,4),(4,3),(5,2),(6,1)} correspond to an event where the sum is 7, the probability
that the sum of two dice is 7 is exactly 636=16. Note the sequences (2,5) and (5,2) must be treated as
distinct sequences for this analysis.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=enumeration>

Principles of Computing Page 12

Permutations and Combinations


Sunday, June 28, 2015

4:14 PM

In some cases where a sequence of trials is conducted, we would like to preclude having the same
outcome occur twice. For example, consider the case of a lottery in which ping-pong balls are drawn one
at a time from a lottery machine. Once the first ball is drawn, it is set aside and that ball cannot be
redrawn later in the drawing process. In cases like this one, we are often interested in the number of
possible sequences associated with this process.
This question is a well-studied one and two mathematical tools are available to help in the analysis. Both of
these tools rely on a mathematical function that you may be familiar with. The factorial of a non-negative
integer m (denoted m!) is the product of the numbers 123...(m1)m. For example, 4!=1234
=24. To simplify various formula involving factorials, 0! is defined to be 1. The factorial function can be
accessed in Python using themath module. For example,
import math
print math.factorial(6)

prints 720 in the console.

Permutations
Given a set of outcomes, a sequence of outcomes of length n with no repetition is a permutation of
size n of this set. For our lottery example, if the set of outcomes is {1,2,3,...,59}, the ordered
sequence (34,12,27,56,58) is a permutation of length five. Observe that the
sequence (23,11,23,3,47) would not be a permutation since the outcome 23 is repeated. Also, note
that the permutation (34,12,27,56,58) is distinct from the permutation (56,12,27,34,58)since the
ordering of the elements in the permutation matters.
Principles of Computing Page 13

ordering of the elements in the permutation matters.


A common question when working with permutations is "How many permutations of length n are possible
given a set of outcomes of size m?" Computing the answer requires a little counting. In generating the
ordered sequence associated with the permutation, there are m choices for the first element, m1 choices
for the second element, and so on, with mn+1 choices for the nth element. Thus, in total, there are

m(m1)...(mn+1)
possible permutations. This product can be conveniently written as m!(mn)! since all of the terms in products
in the numerator and denominator that are less than mn cancel out leaving the desired product.

Combinations
As was the case when repetition was allowed, the order of the resulting sequence may not matter in
some applications. The standard technique for handling this situation is to group all sequences that
correspond to the same set of outcomes in a single cluster. (Note we can use a set here instead of a
sorted sequence since repetition is not allowed.) The sets of outcomes associated with each cluster is
a combination of this set. For example, most lotteries require only that your set of numbers match those
drawn during the lottery to win. The order in which the numbers are drawn is irrelevant. In this case, the
sets {34,12,27,56,58}and {56,12,27,34,58} represent the same combination of lottery numbers.
The number of combinations of size n associated with a set of outcomes of size m also has a simple formula
in terms of factorials. As noted previously, there are m!(mn)! permutations of length n. These permutations
can be grouped into clusters where all of the permutations in a single cluster involve the same outcomes, but
in different orders. Note that in this model, each cluster corresponds to a combination. Since there
are n! possible ordered sequences of outcomes in each cluster, the total number of possible combinations
is m!(mn)!n! which is often written mathematically as (mn).
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=permutations>

Principles of Computing Page 14

Arithmetic Sums
Sunday, June 28, 2015

4:16 PM

In counting the number of steps executed during the evaluation of loops or nested sequence of loops,
various arithmetic sums will sometimes arise. Here is a quick overview of the notation for arithmetic
sums and closed form solutions for some common sums.
Notation
An arithmetic sum is the operation of adding a sequence of numbers. If we index the numbers in the
sequence by the subscript i, the arithmetic sum can be expressed mathematically in the form

i=0nai=a0+a1+a2+an.
Note that, as opposed to Python, both the lower bound (zero) and the upper bound (n) are also included in
the sum.
Common arithmetic sums and their solutions

Closed form expressions for almost all of the various arithmetic sums that you will encounter during this class
are listed below. It's not particularly important to memorize these expressions, just be aware that they exists
so you know that you can look them up when necessary.

i=0n1=1+1+...+1=n+1
The sum of a constant expression is a linear polynomial in n.
i=0nn=n+n+n+...+n=(n+1)n
The sum of a linear expression in n is a quadratic polynomial in n.
i=0ni=0+1+2+...+n=12(n+1)n
This sum is known as a triangular sum. The sum of a linear expression in i is also a quadratic polynomial in n.
i=0n2i=20+21+22+...+2n=2n+11
This sum is known as a geometric sum. In most cases, the sum of a sequence of exponential expressions is
Principles of Computing Page 15

This sum is known as a geometric sum. In most cases, the sum of a sequence of exponential expressions is
again exponential.

i=0ni=0+1+2+...+n=n+111
Note that this relation holds as long as 1. If 0<<1and the sum is infinite, i.e; n=, the sum reduces
to 11.
i=1n1i=1+12+13+...+1nlog(n)+
This sum is called a harmonic sum and has only an approximate solution (indicated by the symbol ).
Here, is a small constant
See this page for more information on logarithms (log(n)) and exponentials (exp(n)).
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=arithmetic_sums>

Principles of Computing Page 16

Logarithms and Exponentials


Sunday, June 28, 2015

4:17 PM

During this class, we will use two mathematical functions with which you should be familiar. The first
function is the natural exponential exp(n)=en where e isEuler's constant 2.71828... The second
function log(n) takes the natural logarithm of n with respect to the base e. These two functions
are inverses of each other in the following sense:
If exp(n)=m, then log(m)=n. Conversely, if log(m)=n, then exp(n)=m.
In some situations, we may wish to work with different base such as base 2 or base 10. In this case, the base
of the logarithm is typically indicated as a subscript to the log function. For example, the
functions 2n and log2(n) are the examples of the exponential and logarithm function taken base 2.

When working with exponentials and logarithms, we will often make use of two properties. The product of
two exponentials is an exponential of the sum of the exponents while the logarithm of a product is the sum
of logarithms of the product's multiplicands.

exp(n+m)=exp(n)exp(m)
log(n m)=log(n)+log(m)

Log/Log plotting
To illustrate the usefulness of logarithms, let us consider of the problem of determining whether a set of
data points (xi,yi) lies on some polynomial function y=axn. This problem will sometimes crop up when
we are trying to estimate the running time of a code fragment where each value of the xi is the size of
the input to the code fragment and each value of the yi is an estimate of the running time of the code
(such as the number of statements executed).
Simply plotting the data points doesn't always help resolve this question since the constants a and n are
unknown. Moreover, the range and scale of the plot can easily influence how "curved" the plot is. However, if
we take the logarithm of both sides of this equation, the polynomial equation reduces to a linear equation
in log(x) and log(y).
Principles of Computing Page 17

in log(x) and log(y).

log(y)=log(axn)
log(y)=log(a)+nlog(x)
If the data points (xi,yi) lie on y=axn, then they must satisfy the equation

log(yi)=log(a)+nlog(xi)
where log(a) and n are constants. This observation suggests a strategy for determining whether the data
points lie close to a polynomial function. Plot the data points (log(xi),log(yi)) and check whether these data
points lie near a straight line. If they do, the original data points (xi,yi) lie near a polynomial function.
Moreover, the degree of this polynomial is simply the slope of this line.
Many plotting packages support this kind of analysis by offering a log/log plotting option. Under this option,
the axes are labelled with the various values of the xand y. However, these labels and the plotted data are
positioned at the locations log(x) and log(y). For example, plots with axes labeled 1,10,100,1000,...are
usually log/log plots.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=log_and_exp>

Principles of Computing Page 18

Growth Rates of Functions


Sunday, June 28, 2015

4:18 PM

Principles of Computing Page 19

As part of this class, we will model the growth rates of certain quantities associated with a program,
such as the number of statements in its execution trace, its running time, or the size of its computed
output. In these cases, our goal will be to determine a function f(n) that models the growth of this
quantity as a function of the input size n to the program. As part of the analysis, we will often wish to
compare the growth rate of this function to various known functions to better understand the behavior
of the program.
Given two function f(n) and g(n), these functions grow at the same rate if the ratio f(n)g(n) approaches some
fixed constant as n grows large. If this ratio approaches zero as n grows large, f(n) grows more
slowly than g(n). On the other hand, if this ratio approaches infinity, f(n) grows faster than g(n). For this
class, we won't focus too much effort on doing a formal mathematical analysis of growth rates. Instead, we
will learn a few simple mathematical rules for comparing the growth rates of various functions and rely on
techniques such as plotting when these rules aren't sufficient for our analysis.
Note that in our comparison of functions, we consider functions that are constant multiples of each other to
be "equivalent". This choice reflects the fact that we are more concerned with the growth in the size of a
quantity than the actual value of the quantity. For example, the running time of a program may depend on
many factors such as the power of computer's processor, the speed of its operating system, and the
performance of any environment that runs the computation (like a web browser). However, if the running
time of a program grows at an exponential rate, the processing power of even the fastest computers will be
quickly overwhelmed.

Techniques for comparing growth rates


In practice, comparing the growth rates of the functions that we will encounter in this class is relatively
easy. Here are some simple rules that you should remember:
Two polynomial functions f(n) and g(n) grow at the same rate if they have the same degree. Lower degree
terms in these functions have no effect on the relative growth rates.
If the degree of a polynomial function f(n) is higher than the degree of g(n), f(n) grows faster than g(n).
Conversely, if the degree of f(n) is lower, f(n) grows slower than g(n).
The function log(n) grows faster than the constant function 1 and slower than the linear function n. The

Principles of Computing Page 20

The function log(n) grows faster than the constant function 1 and slower than the linear function n. The
function nlog(n) grows faster than n and slower than n2.
Any exponential function n with >1 grows faster than any polynomial function. The factorial
function n! grows faster than n and, consequently, faster than any polynomial function.
One simple visual technique for comparing the growth rates of pairs of functions is to plot f(n)g(n) for a
reasonable range of values for n. Examining the resulting plots usually provides some insight into the relative
growth rates of the functions being compared. For example, the three plots created by this program illustrate
the situation when f(n) is 0.1n3+20n while g(n) are the functions n3, 20n2, and 0.1n4, respectively. Note
that the leftmost plot tends toward a positive constant value (a horizontal line), the middle plot increases
continuously and has no upper bound, and the right plot converges towards zero. These plots reflect the fact
that two cubics grow at the same rate, a cubic grows faster than a quadratic, and a cubic grows slower than a
quartic.

An example from ball physics


Games like Pong involve a ball bouncing around a closed domain. One interesting generalization of this
situation is to allow several balls that bounce off of each other as well as the walls of the domain.
This CodeSkulptor program allows the user to click in the canvas to spawn new balls, and displays the
frame rate (number of draws per second) of the resulting simulation. As the number of balls increases,
the time taken to compute all ball/ball collisions during each physics update in the simulation increases
and the frame rate of the simulation begins to slow.
Since each one of the n balls is tested for collision against every other ball during the physics update, the
total number of ball/ball collisions is approximately 12n2. (The factor of 12 arises because each pair of balls is
tested for collision only once.) The left plot below shows an estimate of the time taken to compute all 12n2 of
these collisions during a single update. Observe that this function has a parabolic shape and appears to be
growing quadratically. (All times are computed on an ancient desktop so don't worry about the absolute
scale.) The right plot shows the ratio of the running times and the function n2. Observe that the plot is
trending towards a positive constant which confirms our analysis that the running time for this update
method is growing quadratically.

Principles of Computing Page 21

One method for accelerating this physics update is to divide the canvas into a grid whose cells are roughly the
size of the balls. Before computing ball/ball collisions during a physics update, each ball is assigned to the cell
that contains the center of the ball. Since the size of the grid cells are the diameter of the ball, a maximum of
four balls can be assigned to any one cell. Then, during the collision phase, a ball is tested against only those
balls in its own cell and its eight spatially-adjacent neighbors. This limits the total number of balls that needs
to be tested for collision to be less than or equal to 49=36 balls. Overall, a maximum of 36n total collision
tests are done during each update.
This CodeSkulptor program implements this alternative algorithm for performing physics updates. The left
plot below shows the time per update plotted as a function of the number of balls. Observe that the running
time for each update appears to grow linearly as a function of the number of balls. The right plot shows the
ratio of the running times and the function n. Observe that the plot is trending towards a positive constant
which confirms our analysis that the running time for this update method is growing linearly.

This example illustrates the importance of algorithms and our analysis of their efficiency. At first glance, our
original method seemed simple and efficient. However, we note that the added complexity of our improved
collision method is well worth the effort since the enhanced speed of the update method allows us to add
many more balls to our simulation.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=fun_growth>

Principles of Computing Page 22

Coding Notes
Sunday, June 28, 2015

4:22 PM

This page contains like to a collection of class pages relating to coding issues for the class. Please spend
a few minutes browsing these links so you are aware of this information when necessary.

Python pages:
Guidelines for coding style (IMPORTANT)
Python development environments
A guide to Pylint errors
A guide to Python errors
Python knowledge required for the class
Building tests for your Python programs
Importing custom modules in Python
Using default arguments in Python
Mini-project descriptions and OwlTests:
Week 1 - 2048 (merge) - OwlTest
Week 2 - 2048 (full) - OwlTest
Week 3 - Tic-Tac-Toe (Monte Carlo) - Owltest
Week 4 - Yahtzee - Owltest
Week 5 - Cookie Clicker - OwlTest
From <https://class.coursera.org/principlescomputing1-003/wiki/helpful_pages>

Principles of Computing Page 23

Coding Style Guidelines


Sunday, June 28, 2015

4:22 PM

Principles of Computing Page 24

Principles of Computing Page 25

In this class, we will expect you to follow our coding style conventions. These conventions will largely be
enforced by the use of Pylint. Pylint is a source code bug and quality checker for the Python programming
language. The machine-graders for this class will use a customized version of Pylint to check the style of your
code. Pylint errors that violate of the style guidelines will result in deductions from the score of your miniproject. An explanation of common Pylint errors can be found here.
Here are some of the style guidelines that we will follow in this class. As you interact with Pylint, you will get
more exposure to these guidelines.

Documentation
Documentation strings ("docstrings") are an integral part of the Python language. They need to be in the
following places:

At the top of each file describing the purpose of the module.


Below each class definition describing the purpose of the class.
Below each function definition describing the purpose of the function.
Docstrings describe what is being done in a module, class, method, or function, not how it is being done.
Except in rare cases where the how is part of the contract (i.e., binary search, so you know it runs in
time log(n)). A docstring for a function should explain the arguments, what the function does, and what the
function returns. This sample file demonstrates the use of docstrings. Note that the __init__ methods of
classes generally do not have docstrings because their purpose is obvious: to initialize the object. You may
want to have one, though, to describe the arguments.
These docstrings are treated specially in Python, as they allow the system to automatically give you
documentation for modules, classes, functions, and methods. At the command prompt, you can type help(...),
and it will return the docstring for whatever the argument you passed to help is. (Note that CodeSkulptor
does not provide a command prompt, so you cannot use help in CodeSkulptor.)

Comments
Comments should describe how a section of code is accomplishing something. You should not comment
obvious code. Instead, you should document complex code and/or design decisions. Comments and
docstrings are not interchangeable. Comments start with the "#" character. While you will see some Python
programmers do this, you should not comment your code by putting a multi-line string in the middle of your
program. That is not actually a comment, rather it is just a string in the middle of your program!
A good example:
# This is a block comment
# that spans multiple lines
# explaining the following code.
val = some complicated expression

A bad example:
"""
Somebody told me that a multiline
string is a block comment.

It's not.
"""
val = some complicated expression

Note that docstrings are multi-line strings, but they do not violate this convention because docstrings and
comments are different and serve different purposes in a program.

Global variables
Global variables should never be used in this class. Avoiding their use is good programming practice in any
language. While programmers will sometimes break this rule, you should not break this rule in this class.

There is one exception to this rule: you may have global constants. Because the Python language does not
actually support constants, by convention, Python programmers use global variables with names that are in
all capital letters for constants. When you see a variable with a name in all capital letters, you should always
assume that it is a constant and you should never change it. Again, such global constants are the only global
variables that will be allowed in this class.

Principles of Computing Page 26

Indentation
Each indentation level should be indented by 4 spaces. As Python requires indentation to be consistent,
it is important not to mix tabs and spaces. You should never use tabs for indentation. Instead, all
indentation levels should be 4 spaces. Note that CodeSkulptor automatically converts all tab indents into
4 spaces.

Names
All variable, function, class, and method names must be at least 3 characters. The first character of a name
should follow these conventions:

Variable names should always start with a lower case letter. (Except for variables that represent constants,
which should use all upper case letters.)
Function and method names should always start with a lower case letter.
Class names should always start with an upper case letter.
Further, we will follow the common Python convention that variable, function, and method names should
not have any capital letters in them. You can separate words in a name with an underscore character, as
follows: some_variable_name. Similarly, class names should not contain underscores, and instead use
capitalization to separate words, as follows: SomeClassName.
As previously noted, constants should be in all capital letters, such as: THIS_IS_A_CONSTANT. Note that this
means that your class names must have at least one lower case letter in them, to distinguish them from
constants.
By convention in Python, you can "violate" the above rules and start a name with an underscore, _, to
indicate that the name is private and should not be accessed outside of the context in which it is defined. In
this case, the rest of the name after the underscore should follow the rules given above. This will arise mainly
when you define instance fields in classes, as these style guidelines insist that such fields be private
(discussed next).

Class and Instance Fields


Class and instance fields should never be accessed directly from outside the class. You should therefore
always start your field names with an underscore. Even if you don't, you still should not access them from
outside of the class.
You will often see public fields in Python programs (and in programs of other languages). This is not a good
habit to get into. Instead, all fields should always be private. If there is good reason to make the data in the
field accessible outside the class, you should create a method to do so. By convention in other languages,
these methods are usually named get_field, where field is the name of the field. You should follow this
convention.
Note that this is not common in Python. Rather, public fields or properties are used. However, we are trying
to teach principles that transcend a particular programming language. All languages support writing so-called
"getter" methods, whereas many do not support properties. There is nothing wrong with Python properties,
it is just a different syntax for using methods. However, the use of public fields is not good practice in any
programming language, whether the language allows it or not.
You should avoid the use of class fields, which are declared in the scope of the class itself and are common to
all instances of the class. Instead, you should use instance fields (defined as attributes of self). These will be
unique to each instance of the class.

Scope
You should not use names that knowingly duplicate other names in an outer scope. This would make the
name in the outer scope impossible to access. In particular, you should never use names that are the same as
existing Python built-in functions. For example, if you were to name one of your local variablesmax inside of a
function, you would then not be able to call max() from within that function.

Arguments and local variables


While there is not necessarily a maximum number of arguments a function can take or a maximum number
of local variables you can have, too many arguments or variables lead to unnecessarily complex and
unreadable programs. Pylint will enforce maximum numbers of arguments, variables, methods, etc. If you
run into limits that Pylint complains about, you should restructure your program to break it into smaller
pieces. This will result in more readable and maintainable code.
Further, you should not have function arguments or local variables declared that are never used, except in
rare circumstances. Sometimes, you do need to have a variable that you never use. A common case is in a
loop that just needs to execute a certain number of times:
for num in range(42):
# do something 42 times

In this case, you should name the variable with the dummy_ prefix. This indicates clearly to you, others, and
Pylint that the variable is intentionally unused.
Principles of Computing Page 27

Pylint that the variable is intentionally unused.


for dummy_num in range(42):
# do something 42 times

From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=style_guidelines>

Principles of Computing Page 28

Python Development Environments


Sunday, June 28, 2015

4:26 PM

In this class, the instructors will consistently use the CodeSkulptor Python environment. All of the examples,
exercises, and assignments will use CodeSkulptor. If you already took our previous course, An Introduction to
Interactive Programming in Python (IIPP), you should be familiar with this tool. If not, you can watch these
introductory videos from that class to learn more about it:

CodeSkulptor
Saving in CodeSkulptor
CodeSkulptor will work for all of the assignments in this class. We strongly advocate that you use
CodeSkulptor throughout the class, as that ensures that you are working in the same environment as the
instructors and everyone else. All of the assignments and exercises were developed and tested within
CodeSkulptor. However, it is not a strict requirement that you use CodeSkulptor for this class. The class uses
Python 2 (most importantly, the machine grader runs Python 2), so whatever environment you choose must
support Python 2. The following video from IIPP briefly discusses moving beyond CodeSkulptor:
Beyond CodeSkulptor
If you want to explore other Python development environments, we suggest you post in the Python
subforum and discuss alternatives with your classmates.
Note: There are some caveats with using alternate environments:
1. Due to the high volume of help requests, if you choose to use the Code Clinic, the staff will only be able to
help you with code configured to run in CodeSkulptor and submitted as a CodeSkulptor URL. This restriction
is critical since it allows us to reliably and efficiently access your code when helping you.
2. You will need to download any files that are provided with each assignment to your computer and figure out
where to locate them so that your development environment can find them (more below).

Principles of Computing Page 29

where to locate them so that your development environment can find them (more below).
3. The machine grader only supports a limited subset of Python modules. You will need to restrict yourself to
those modules in order to work with the grader. The grader supports all modules that CodeSkulptor supports.
In many of the template files, we will import some provided code, i.e., import poc_provided. To access this code,
you simply need to go to the corresponding CodeSkulptor URL (by adding a hash tag, the imported file name,
and the ".py" extension): http://www.codeskulptor.org/#poc_provided.py (note that this is just an example
of how to construct the URL and that file does not exist). Once you have copied all of the provided files onto
your machine (with the same names that we gave them), then you should be able to develop your code on
your local machine. However, you will need to make sure you locate those files where your environment can
find them.
Note:The machine grader currently has two restrictions. First, the machine grader only supports the upload
of a single file. So, even though most development environments make it easy to break your program up into
multiple files, you must keep all of the code you write for an assignment in one file for this class. While this is
not necessarily the best programming practice, it is necessary for us to deal with the complexities of a large
online class like this. Second, the machine grader only supports the following Python
libraries: random, time, math, re, collections.defaultdict, and collections.Counter. Again, this has to do with the
complexities of providing a machine grader for a large online class like this. These modules are sufficient to
complete all of the assignments in this class and CodeSkulptor also supports all of these modules.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=pythonides>

Principles of Computing Page 30

Guide to Pylint Errors


Sunday, June 28, 2015

4:27 PM

Pylint is a source code bug and quality checker for the Python programming language. The machinegraders for this class will use a customized version of Pylint to check the style of your code. Pylint errors
due to violations of the style guidelines will result in deductions from the final score for your miniproject.
If you would like to experiment with Pylint, you are welcome to use this Owltest page to submit programs
directly to Pylint for style checking. Here are explanations of some common warning message that Pylint will
display.

Missing docstring for program: Pylint warns you if your program does not begin with a docstring (which
violate the style guidelines). This programgenerates the warning "[line 1] Missing docstring". Adding a docstring
at the top of the program will remedy this error.
Non-compliant variables names: Pylint warns you if your variable names do not conform to the style
guidelines. In particular, all variable names should consist of three or more lower case letters or underscores.
For example, this program will generate the warning "Invalid name "n" (should match [a-z_][a-z0-9_]{2,30}$)" which
signals that the parameter name n does not meet the style guidelines. Renaming n to number in
the program avoids the warning.
Use of global variables: Pylint warns you if you are using global variables (which violate the style guidelines).
Since global constants are allowed, Pylint will warn you that they should be named using all capital letters.
For example, this program generates the warning " Invalid name "canvas_width" (should match (([A-Z_][A-Z0-9

Principles of Computing Page 31

For example, this program generates the warning " Invalid name "canvas_width" (should match (([A-Z_][A-Z0-9
_]*)|(__.*__))$)". Capitalizing the names of the two global constants yields a program free of warnings.
Missing docstring for a function or class definition: Pylint will warn you if your function or class definition
does not contain a docstring (which violate the style guidelines). For example, this program generates the
warning "[line 5] Missing docstring". Adding a docstring to the function definition yields aprogram that avoids
this warning.
Code refactoring warnings: Pylint analyzes your code and check for long, complex blocks of code. If the
complexity of these blocks exceeds Pylint's built-in limits, Pylint will issue a warning asking you to refactor
(rewrite) your code in smaller pieces using several functions or methods. For example, thisprogram generates
the warning "Too many return statements (10/6)". In this case, rewriting this program to use the remainder
operator avoids the warning.
Redefining built-in function names: Pylint warns you if you attempt to redefine the name of a built-in Python
function. For example, this program will generate the warning "Redefining built-in 'format'" that signals that you
are trying to redefine the built-in format function in Python. Renaming formatto template in the program avoids
the warning. (Yes, we did this in the template for Stopwatch for IIPP. We also write bad code sometimes.)
Unused variables: Pylint warns you if a variable in your code is unused (which may indicate a problem in your
code). A common situation where this issues arises is when using list comprehensions to create lists with
constant values. This example will cause Pylint to report the error "[line 10] Unused variable 'index'". Renaming
the variable with the prefix dummy_... will inform Pylint that this variable is intentionally being used as a
dummy variable. This programwill pass Pylint's style check.
Access to a protected member: Pylint warns you if you attempt to access a class field outside the class
definition. This example will cause Pylint to report the error "[line 16] Access to a protected member _name of a
client class". (Pylint also gives a refactoring warning about having no public methods for the class.) Adding the
method get_name (and a second public method) yields this program that will pass Pylint's style check.
Invalid name for class field: Pylint warns you if you fail to use a leading underscore on class fields to indicate
that they are private. This example will cause Pylint to report the error "[line 12] Invalid name "name" (should
match _[a-z0-9_]{3,30}$) function "Widget.__init__", line 12" . Adding a leading underscore to the field name yields
this program that will pass Pylint's style check.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=pylint_errors>

Principles of Computing Page 32

Guide to Python Errors


Sunday, June 28, 2015

4:29 PM

Principles of Computing Page 33

This is an attempt to translate Python errors into English created by Emily Wachtel. It is by no means
complete or comprehensive, but we've added it here as a resource.
So what do all these errors mean?
Principles of Computing Page 34

So what do all these errors mean?

SyntaxError: "I don't recognize what you just wrote as Python code."
'Syntax' refers to the rules that dictate how you're allowed to write down a coding language. For example,
the rule that states that youmay not begin a variable name with a digit is part of the syntax of Python. A
SyntaxError will pop up if you violate any of Python's syntax rules. This could be forgetting to close a
parenthesis or quote, mistakes in indentation, forgetting colons after function headers, etc. Note that syntax
errors can be tricky - sometimes the real error is actually before or after the line that the error is reported on.
When you go hunting for syntax errors, try looking at the entire block of code that surrounds the line where
the error appears.
Example 1: Syntax Error: bad input ('
') - http://www.codeskulptor.org/#user29_RBAM7aLLFF_10.py
Example 2: Syntax Error: bad token('"') - http://www.codeskulptor.org/#user29_9vki2pLzHk_1.py
Example 3a: Syntax Error: bad input('print') - http://www.codeskulptor.org/#user29_p7riICJqyf_1.py
Example 3b: Syntax Error: 'return' outside function - http://www.codeskulptor.org/#user29_UWijfk8YnI_0.py
Example 4: Syntax Error: can't assign to literal - http://www.codeskulptor.org/#user29_GAQb6gQq0Y_2.py
Example 5: Indendation Error: unindent does not match any outer
indentation - http://www.codeskulptor.org/#user29_DM85TuO1tN5P1fJ.py
-------------------------------------------------------------------------------------------------------------------------------------------------------------------NameError: "What in the world is X?"
A NameError is triggered when Codeskulptor doesn't recognize the variable, function name, etc. that you're
referring to. A NameError is Codeskulptor's way of saying "I've never heard of that before!" Common causes
of this are misspellings or forgetting to declare variables entirely.
Example 1: NameError: name 'some_variable_name' is not defined - http://www.codeskulptor.org/#user29
_rvErPx9lFA_7.py
Example 2: NameError: name 'some_function_name' is not defined - http://www.codeskulptor.org/#user29
_DSrwc3QXrb_1.py
-------------------------------------------------------------------------------------------------------------------------------------------------------------------TypeError: "You're trying to use some of those things in a way that wasn't intended."
This error can come up when you're trying to do perform an operation on something, but the operation and
the thing just don't go together. One example is trying to multiply a dictionary and an integer - it just won't
work. A helpful tool in debugging type errors is the Python type() function. Adding print statements like "print
type(my_variable)" will help you figure out what's going wrong.
Example 1: TypeError: cannot concatenate 'str' and 'int' objects (or any other data
type): http://www.codeskulptor.org/#user29_O8c065gLl1_11.py
Example 2: TypeError: function_name() takes exactly x arguments (y given) - http://www.codeskulptor.org/
#user29_Xd5fyxBt6K_0.py
Example 3: TypeError: 'int' object is not iterable (could be a different data
type) - http://www.codeskulptor.org/#user29_Vd3ft6yTVH_0.py
Example 4: TypeError: 'int' object is not callable (could be a different data
type) - http://www.codeskulptor.org/#user29_BRRaiVlwpD_0.py
Example 5: TypeError: handler must be a function - http://www.codeskulptor.org/#user29_5JQUSZ4lDP_1.py
-------------------------------------------------------------------------------------------------------------------------------------------------------------------AttributeError: "That object doesn't know how do to what you asked it to do"
In OOP, objects have "attributes" - things that they're aware of, and/or know how to do. In terms of Python,
attributes are an objects properties and the methods defined by its class. An AttributeError will be thrown
when you ask an object to do something or access something that isn't in its class definition.
Example 1: Attribute Error: '[Object X] has no attribute [attribute Y] - http://www.codeskulptor.org/#user29
_JWjKm5ZQV4_6.py
Example 2: Same as Example 1, but with an explicit class definition - http://www.codeskulptor.org/#user29
_Qvjnv5BNTg_0.py
-------------------------------------------------------------------------------------------------------------------------------------------------------------------IndexError: "That list/dictionary/tuple (etc.) doesn't have that many items in it."
An IndexError happens when you try to access an index that doesn't actually exist. It's like telling someone to
take 13 eggs out of a 12-egg carton - it won't work, because there are only 12 spaces. Printing out your index
values, along with len(the_list_in_question) will help you in debugging these errors. Important to note:
negative indices *are* possible in Python! See the video lecture on lists for more information.

Principles of Computing Page 35

negative indices *are* possible in Python! See the video lecture on lists for more information.
Example 1: IndexError: list index out of range - http://www.codeskulptor.org/#user29_eget014sAQ_9.py
-------------------------------------------------------------------------------------------------------------------------------------------------------------------TokenError: "You probably forgot to close a bracket." *
Very simply, tokens are things that stand for other things - sort of like variables, except they're used at a
more structural level. Some examples of tokens are EOF (End Of File) and EOL (End Of Line). These are the
two most common ones you will come across in Python, but they are used everywhere in programming. The
TokenErrors that you will see in this course are usually solved by remembering to close your brackets. See the
example for a more in-depth explanation of why this is.
Example 1: TokenError: EOF in multi-line statement - http://www.codeskulptor.org/#user29_TwsBlWnsiG_
3.py
*Not actually what it means - but a more detailed explanation is more appropriate for other courses, and this
is the most common cause of TokenErrors in this class.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------ValueError: "There's something wrong with the value of one of those arguments (but the type is ok)."
A ValueError is raised when a function receives an argument that looks ok on the surface (e.g., it receives a
character, and it was looking for a character), but the value of that argument is unexpected (e.g., the function
was only built to handle digits, and it received a letter 'a'). This type of error can be solved by checking the
documentation for whatever function you're trying to use,
and making sure that whatever you put inside the parentheses, the function was built to handle it.
Example 1: ValueError: invalid literal for int() with base 10: ' ' - http://www.codeskulptor.org/#user29
_v7yqnKyAPa_2.py
IndentationError: "Your code blocks aren't all indented to the proper levels."
This is a type of Syntax Error. See Syntax Errors, example # 5.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------Miscellaneous section - these errors are either self-explanatory or not common in the level of programming
done in IIPP
OverflowError - caused by trying to store, for example, a long inside an int. A long has too many bytes to fit
inside the int data type
ZeroDivisionError - you guessed it - you're trying to divide by zero somewhere
ImportError - caused by trying to import a module that doesn't exist. Check your spelling.
JavaScript section - these are not Python errors. They are related to your browser, not your code.
HierarchyError - Internet Explorer is not supported by CodeSkulptor. Use Chrome or Firefox.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=python_errors>

Principles of Computing Page 36

Required Python Knowledge


Sunday, June 28, 2015

4:33 PM

In this class, we will assume a basic knowledge of Python consistent with having taken our previous
course, In Introduction to Interactive Programming in Python. Although we'll be using Python 2, starting
with a knowledge of Python 3 is fine. The only two differences from Python 3 that you will probably
notice in Python 2 are printing (print "Hello world" instead of print("Hello world")) and integer division (11 /
4 is 2 instead of 2.75).

Basic elements of Python


Below is a list of the data types in Python with which you should be familiar.
Primitive data types - integers (int), floating point numbers (float), strings (str), Booleans (bool),
Built-in composite data types - lists (list), tuples (tuple), dictionaries (dict), sets (set),
User-defined data types - objects created via a class definition.
You should also be familiar with creating various types expressions (arithmetic, Boolean, and string)
using both built-in constants and variables and capable of effectively using statements of the following
types:
Simple statements - assignment statements (=), print statements (print), return statements (return), import
statements (import), global statements (global), pass statements (pass),
Compound statement - conditional statements (if, elif, else), function definitions (def), for loops (for), while
loops (while), class definitions (class).
You should also have some basic familiarity with objected-oriented programming. This knowledge need
not be particularly deep. However, we will assume an understanding sufficient to create modest-sized
object-oriented programs with one to three classes. Note that you do not need to be familiar
with simplegui or any other Python GUI module to take this class.

Assessing your knowledge of Python


To determine whether your knowledge of Python is sufficient to succeed in this class, we suggest that
you perform two assessments. First, work Homework 1. This homework is designed to test your basic
knowledge of Python as described above. Since this homework is primarily concerned with language
syntax, we also suggest that you attempt the practice mini-project for week 1, Solitaire Mancala, to
assess your ability to write short programs. This practice mini-project requires you to implement nine
methods for a SolitaireMancala class. Eight of the methods should require at most 3-4 lines of Python.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=python_knowledge>

Principles of Computing Page 37

Building Tests for your Python Program


Sunday, June 28, 2015

4:34 PM

Informal testing using testing templates


In this class, we will emphasize the importance of testing your programs. In IIPP, we provided some simple
informal testing templates that consisted of a collection of test data coupled with several calls to a function
or method. Both the expected output and the computed output from these calls were printed to the console.
For example, this testing template from IIPP helped students determine whether their format function for
their Stopwatch mini-project was implemented correctly. Typically, using this template requires users to
paste their code into the template and manually compare the computed vs. expected results in the console.
In situations where the user is not particularly experienced with testing, this manual approach can be
beneficial to the programmer.

Improved testing with the poc_simpletest module


As our programs grow more complicated, manual comparison of test results can become tedious and errorprone. To facilitate testing in this class, we have built a small Python module called simpletest that automates
the creation and reporting of testing results. The source for this module is available here. The module
consists of a single class TestSuite that includes three methods:

__init__(self) which creates an empty TestSuite object.


run_test(self, computed, expected, message = "") runs a test comparing computed to expected. If they differ, an error
message with header message is printed to the console.
report_results(self) reports a summary of the result of running the various tests in the test suite.

An example
Using poc_simpletest, it's possible to create fairly complete test suites for your programs. This test suite is
designed to test this format function for the stopwatch project. Note that the test suite is imported into the
solution file in line 5 and run in line 21. Inside the test suite, the test code is encapsulated inside a single test
function run_suite() that includes the function being tested as a parameter. This design allows us to import the
test suite using a single importstatement and then run the test suite using a single call to run_suite(). One can
turn off testing by simply commenting out the call to run_suite(). (For information on how importing works,

Principles of Computing Page 38

turn off testing by simply commenting out the call to run_suite(). (For information on how importing works,
please this page.)

Unit testing using the unittest module


Python supports quite sophisticated testing using the unittest module described here. We will leave
exploration of the substantial capabilities of unittest for later.
From <https://class.coursera.org/principlescomputing1-003/wiki/=view?page=testing_methodogy>

Principles of Computing Page 39

Importing custom modules in Python


Sunday, June 28, 2015

4:35 PM

In this class, we will store provided code, test suites, and GUI code in separate files (which are referred
to as modules in Python) to keep the size of your programs tractable. You have already seen examples of
built-in modules such as math and random whose implementations are hidden from you. In this page, we
will show you how you can create and import Python modules of your own creation. Storing various
parts of your code in separate modules is a simple way to organize the components of your program.

Principles of Computing Page 40

parts of your code in separate modules is a simple way to organize the components of your program.
In Python, the import statement allows you to reference and execute code stored in a separate module.
Import statements have the syntax
import my_code as important_module

On the desktop, Python looks for the file "my_code.py" in the directory where your program is saved
and loads that file. At that point, the user can reference variables, functions, and classes defined in the
file by adding the prefix important_module. to the names of the variables/functions/classes defined in the
module. (Note that if you omit the "as important_module" part of the import statement, you should use
the prefix "my_code" when referencing entities defined in the module.)

Importing custom modules in CodeSkulptor


In CodeSkulptor you do not have access to your local file system. However, you do have access to files
stored in Google Storage as CodeSkulptor URLs. Just as on the desktop, you can import a cloud-saved file
using the portion of the URL after the "#". For example, the filehttp://www.codeskulptor.org/#user34_
3ou1Va0MGe2QRm5.py contains a single function print_something() whose body prints the message "This
print is in the imported code" to the console. You import this file into another CodeSkulptor file via the
statement
import user34_3ou1Va0MGe2QRm5 as important_module

Note the name used in the import statement matches the part of the CodeSkulptor URL after the "#" for
the file above. (Remember to omit the ".py" extension just as is done in desktop Python.) This
program imports the file above and prints out a message generated by the imported code by
callingimportant_module.print_something().

Common types of imports in this class


In this class, we will use imports in three main ways:
To provide auxiliary code/classes that you will use in implementing your mini-projects. The import
statements for these cases will typically have the form
import poc_helper_stuff as provided

where the name "poc_helper_stuff" corresponds to the file with the URL "http://www.codeskulptor.org/
#poc_helper_stuff.py" that we have manually created on Google Storage. (Note that this particular file
doesn't exist.)
To import test suite code into your mini-project for testing. These imports will typically consist of two
statements: one that imports the module containing your test suite and a second that runs your test suite.
For example, you can import and run the test suite for Solitaire Mancala via the code
import poc_mancala_testsuite
poc_mancala_testsuite.run_suite(SolitaireMancala)

In this example, the function run_suite in the file http://www.codeskulptor.org/


#poc_mancala_testsuite.py takes the class SolitaireMancala defined in your program and uses it to
create SolitaireMancala objects for use in the test suite. Note that you import a test suite of your own creation
using the "userXX_XXXXX" part of the CodeSkulptor URL via the statement import userXX_XXXXX as
poc_mancala_testsuite.
To import a GUI that can be used to visualize your program in action. Again, these imports will typically
consist of two statements; one that imports the module containing the GUI and a second that runs the GUI
using an instance of the class defined in your mini-project. For example, you can import and run the GUI for
Solitaire Mancala using the statements
import poc_mancala_gui
poc_mancala_gui.run_gui(SolitaireMancala())

In this case, note that the function run_gui in http://www.codeskulptor.org/#poc_mancala_gui.py takes an


instance of the SolitaireMancala class and uses it in the GUI.
From <https://class.coursera.org/principlescomputing1-003/wiki/=view?page=imports>

Principles of Computing Page 41

Default Arguments in Python


Sunday, June 28, 2015

4:36 PM

The way Python handles default arguments is not intuitive and is often confusing to students. This issue
because especially important when others (say a machine grader) are calling functions with default
arguments that you have written. The key thing to understand is that the default argument is evaluated
onlyonce, when the function is defined. The same object is then used whenever the default argument is
needed.
Consider for example, the following program:
def mystery(item, sequence=[1, 2, 3]):
sequence.append(item)
return sequence
print mystery(4)
print mystery(5)

You would probably expect this program to produce the following:


[1, 2, 3, 4]
[1, 2, 3, 5]

However, it does not. Try it: http://www.codeskulptor.org/#examples_defargs.py.


What is happening? The list [1, 2, 3] is evaluated once and stored with the function mystery. Whenever you
call mystery with only one argument, that same object is assigned to the sequence parameter. The first time the
function is called, the behavior is as expected. However, the list is mutated, so it is no longer[1, 2, 3]. The
second time the function is called with only one argument, that mutated object is assigned to
the sequence parameter. So, in the above code, it is [1, 2, 3, 4] when mystery is called the second time. So, the
result of the second call is [1, 2, 3, 4, 5], not [1, 2, 3, 5] as you might expect.
What should you do? Basically, it is a very bad idea to use mutable objects as default arguments. So, you
should avoid doing so. Only use immutable default arguments and you will not run into this problem.
From <https://class.coursera.org/principlescomputing1-003/wiki/=view?page=defargs>

Principles of Computing Page 42

Mini Projects
Sunday, June 28, 2015

5:51 PM

Principles of Computing Page 43

2048 (Merge)
Sunday, June 28, 2015

5:51 PM

Principles of Computing Page 44

Overview
2048 is a simple grid-based numbers game. The rules of the game are described here.
In the first two assignments, we will implement a version of the 2048 game. Although the original game is
played on a 44 grid, your version should be able to have an arbitrary height and width. In this first
assignment, we will focus on only one aspect of the game: merging tiles.
We have provided the following template that contains the basic code that you will need to implement the
merge function. The signature (name and parameters) of the functions in this file must remain unchanged,
but you may add any additional functions or other code that you need to.

Coding Style
In this class, you will be asked to strictly follow a set of coding style guidelines. Good programmers not only
get their code to work, but they also write it in a way that enables others to easily read and understand their
code. Please read the style guidelines carefully and get into the habit of following them right from the start.

Testing Your Code


As always, testing is a critical part of the process of building your mini -project. Remember you should be
testing your code as you write it. Don't try to implement everything and then test, You will have lots of errors
that all interact in strange ways that make your program very hard to debug.
Throughout this course, we will be using a machine grader (OwlTest) to help you assess your code. You can
submit your code to this Owltest page. The OwlTest page has a pale yellow background and does not submit
your project to Coursera. OwlTest is just meant to allow you to test your mini -project automatically. Note
that trying to debug your mini-project using the tests in OwlTest can be very tedious since they are slow and
give limited feedback. Instead, we strongly suggest that you first test your program using your own tests. To
get you started, there are some tests for this project given at the end of the description.
Remember that OwlTest uses Pylint to check that you have followed the coding style guidelines for this class.
Deviations from these style guidelines will result in deductions from your final score. Please read the
feedback from Pylint closely. If you have questions, feel free to consult this page and the class forums.
When you are ready to submit your code to be graded formally, submit your code to the CourseraTest page

Principles of Computing Page 45

When you are ready to submit your code to be graded formally, submit your code to the CourseraTest page
for this mini-project that is linked on the main assignment page. Note that the CourseraTest page looks
similar to the OwlTest page, but they are not the same! The CourseraTest page has a whitebackground and
does submit your grade to Coursera.

Merge
For this assignment, you will implement a function merge(line) that models the process of merging all of the
tile values in a single row or column. This function takes the list line as a parameter and returns a new list with
the tile values from line slid towards the front of the list and merged. Note that you should return a new list
and you should not modify the input list. This is one of the more challenging parts of implementing the game.
In this function, you are always sliding the values in the list towards the front of the list (the list position with
index 0). You will make sure you order the entries in line appropriately when you call this function later in the
next assignment. Empty grid squares with no displayed value will be assigned a value of zero in our
representation.
For example, if a row of the board started as follows:

And you slide the tiles left, the row would become:

Note that the two leftmost tiles merged to become a 4 and the third 2 just slides over next to the 4.
A given tile can only merge once on any given turn, although many pairs of tiles could merge on a single turn.
For the above example, the input to the merge function would be the list [2, 0, 2, 2]. The function should then
produce the output [4, 2, 0, 0]. We suggest you begin to implement this function as follows:
1. Start with a result list that contains the same number of 0's as the length of the line argument.
2. Iterate over the line input looking for non-zero entries. For each non-zero entry, put the value into the next
available entry of the result list (starting at position 0).
Notice if you only follow this process, you would end up with the result [2, 2, 2, 0].
Now you should think through what you should add to your function in order to merge tiles. Keep in mind,
however, that any tile should only be merged once and that these merges should happen in order from
lowest index to highest index. For instance, on the input [2, 0, 2, 4], the result should be [4, 4, 0, 0],not [8, 0, 0, 0].
Note that there are many ways to implement the merge function. The objective of this project is for you to
use what you've learned in our previous classes to implement a complex function. You have already learned
all of the Python required to implement merge, so the challenge is to think carefully about what the function
does and how to best accomplish that.
Here is one basic strategy to implement the merge function:
3. Iterate over the input and create an output list that has all of the non-zero tiles slid over to the beginning of
the list with the appropriate number of zeroes at the end of the list.
4. Iterate over the list created in the previous step and create another new list in which pairs of tiles in the first
list are replaced with a tile of twice the value and a zero tile.
5. Repeat step one using the list created in step two to slide the tiles to the beginning of the list again.
This is not the most efficient way of implementing merge. While it is fine to implement it in this way, we
challenge you to think of other ways of doing it that do not require creating so many lists. Ultimately, how
you approach the problem is up to you.
As you work on your merge function, here are some simple tests you should try:

[2, 0, 2, 4] should return [4, 4, 0, 0]


[0, 0, 2, 2] should return [4, 0, 0, 0]
[2, 2, 0, 0] should return [4, 0, 0, 0]
[2, 2, 2, 2, 2] should return [4, 4, 2, 0, 0]
[8, 16, 16, 8] should return [8, 32, 8, 0]

These tests are by no means exhaustive and are just meant to get you started.
From <https://class.coursera.org/principlescomputing1-003/wiki/view?page=2048_(Merge)>

Principles of Computing Page 46

You might also like