Programming notes

This is a notebook that was created in class on February 11, 2020. The goal was to review some basic programming in Python to be sure your background was strong enough to complete Homework 2.

Tuples:

In [1]:
(1, 2, 3)

Lists:

In [2]:
[1, 2, 3]

For ... in ...:

In [3]:
for x in ["cat", "dog", 53]:
    print(2*x)
    y = "x is {}".format(x)
    print(y)

Range:

Ranges represent a list of consecutive values.

In [4]:
range(5)

You can convert a range to a list.

In [5]:
list(range(5))

Some information about range can be discovered by evaluating range?.

In [6]:
range?
list(range(3, 10))
In [7]:
list(range(1, 11, 2))
Out[7]:
[1, 3, 5, 7, 9]
In [8]:
list(range(11, 0, -2))
Out[8]:
[11, 9, 7, 5, 3, 1]
In [9]:
for i in range(11, 0, -2):
    print(i)
11
9
7
5
3
1

Summing the elements in a tuple, list or range:

In [10]:
sum(range(11, 0, -2))
Out[10]:
36

While and break

Here we compute the sums $$\sum_{i=1}^N i$$ for increasing values of $N$ until the first time the sum exceeds 1000.

In [11]:
i = 1
total = 0
while True:
    total = total + i
    print("total = {} when i = {}".format(total, i))
    if total > 1000:
        break
    i = i + 1
total = 1 when i = 1
total = 3 when i = 2
total = 6 when i = 3
total = 10 when i = 4
total = 15 when i = 5
total = 21 when i = 6
total = 28 when i = 7
total = 36 when i = 8
total = 45 when i = 9
total = 55 when i = 10
total = 66 when i = 11
total = 78 when i = 12
total = 91 when i = 13
total = 105 when i = 14
total = 120 when i = 15
total = 136 when i = 16
total = 153 when i = 17
total = 171 when i = 18
total = 190 when i = 19
total = 210 when i = 20
total = 231 when i = 21
total = 253 when i = 22
total = 276 when i = 23
total = 300 when i = 24
total = 325 when i = 25
total = 351 when i = 26
total = 378 when i = 27
total = 406 when i = 28
total = 435 when i = 29
total = 465 when i = 30
total = 496 when i = 31
total = 528 when i = 32
total = 561 when i = 33
total = 595 when i = 34
total = 630 when i = 35
total = 666 when i = 36
total = 703 when i = 37
total = 741 when i = 38
total = 780 when i = 39
total = 820 when i = 40
total = 861 when i = 41
total = 903 when i = 42
total = 946 when i = 43
total = 990 when i = 44
total = 1035 when i = 45

Random numbers:

In [12]:
import random
In [13]:
random.randint?

Print a random sequence of twenty zeros or ones.

In [14]:
for i in range(20):
    print(random.randint(0, 1))
0
1
0
0
1
1
0
1
1
0
0
0
1
0
0
1
1
0
1
1

Print a random sequence of twenty coin flips:

In [15]:
for i in range(20):
    x = random.randint(0, 1)
    if x == 0:
        coin = "Heads"
    if x == 1:
        coin = "Tails"
    print(coin)
Heads
Heads
Tails
Heads
Tails
Heads
Heads
Heads
Tails
Tails
Heads
Tails
Heads
Heads
Tails
Heads
Heads
Heads
Heads
Heads
In [16]:
def flip(n):
    """Flip a coin n times, and print the results."""
    for i in range(n):
        x = random.randint(0, 1)
        if x == 0:
            coin = "Heads"
        if x == 1:
            coin = "Tails"
        print(coin)
In [17]:
flip(5)
Heads
Tails
Heads
Tails
Heads
In [18]:
flip?

Ternary

In [19]:
def ternary(n):
    # Below we peform sanity checks on the input.
    assert type(n) == int, 'n must be an integer'
    assert n>0, 'n must be a positive integer.'

    rep = '' # This will store the ternary representation.
    while n != 0:
        trit = n % 3
        rep = str(trit) + rep # add the new trit on the left.
        n = n // 3 # Update the value of n.
    return rep
In [20]:
ternary(10)
Out[20]:
'101'

Working with strings:

In [21]:
s = "My dog's name is Sugar."

Iterating through the characters in a string:

In [22]:
for c in s:
    print(c, end="-")
M-y- -d-o-g-'-s- -n-a-m-e- -i-s- -S-u-g-a-r-.-

The length of a string:

In [23]:
len(s)
Out[23]:
23

The first character:

In [24]:
s[0]
Out[24]:
'M'

The second:

In [25]:
s[1]
Out[25]:
'y'

The 23rd character:

In [26]:
s[22]
Out[26]:
'.'

There is no 24th character in s.

In [27]:
s[23]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-27-82823ef8b99e> in <module>()
----> 1 s[23]

IndexError: string index out of range

Another way to iterate through the characters in a string:

In [28]:
for i in range(len(s)):
    c = s[i]
    print(c, end="-")
M-y- -d-o-g-'-s- -n-a-m-e- -i-s- -S-u-g-a-r-.-

Iterating through backwards:

In [29]:
for i in range(len(s)-1, -1, -1):
    c = s[i]
    print(c, end="-")
.-r-a-g-u-S- -s-i- -e-m-a-n- -s-'-g-o-d- -y-M-

Converting a string to a number:

In [30]:
int("0")
Out[30]:
0
In [31]:
int("23")
Out[31]:
23

Substrings:

Recall what s is:

In [32]:
s
Out[32]:
"My dog's name is Sugar."

The capital S appears at index 17, and the r appears at index 21:

In [33]:
print(s[17])
print(s[21])
S
r

To get the substring Sugar you can type:

In [34]:
s[17:22]
Out[34]:
'Sugar'

This is called a "slice." The meaning of numbers is similar to the range function. We are extracting the substring beginning in index 17 up index 22 (excluded).

You can also use a step size of 2 if you wanted:

In [35]:
s[17:22:2]
Out[35]:
'Sgr'

Interval Arithmetic

Load the interval arithmetic package.

In [36]:
from mpmath import iv

Use 3 bits of precision:

In [37]:
iv.prec = 3

This will find an interval with endpoints using 3 bits of precision that contains 1.3.

In [38]:
iv.mpf("1.3")
Out[38]:
mpi('1.25', '1.5')

The value None is returned if the truth of a comparison can not be decided from the intervals.

In [39]:
print(iv.mpf("1.3") < iv.mpf("1.4"))
None

Normally you would get true or false:

In [40]:
print(iv.mpf("1.3") < iv.mpf("2.1"))
True

Assume $x \neq y$. If you want to decide if $x < y$, you can repeat a comparisson at higher and higher precision until you get a definitive answer.

In [41]:
x = "1.3"
y = "1.4"
prec = 1
while True:
    iv.prec = prec
    value = (iv.mpf(x) < iv.mpf(y))
    print("At {} of bits of precision, the comparisson returned {}.".format(prec, value))
    if value == True or value == False:
        # The comparison worked
        break
    prec = prec + 1
print("The comparison is {}.".format(value))
At 1 of bits of precision, the comparisson returned None.
At 2 of bits of precision, the comparisson returned None.
At 3 of bits of precision, the comparisson returned None.
At 4 of bits of precision, the comparisson returned None.
At 5 of bits of precision, the comparisson returned True.
The comparison is True.
In [42]:
x = iv.pi
x
Out[42]:
mpi('3.125', '3.25')

x.delta gives the width of the interval (as an interval).

In [43]:
x.delta
Out[43]:
mpi('0.125', '0.125')

Print out the interval to two significant digits:

In [44]:
iv.nstr(x,2)
Out[44]:
'[3.1, 3.3]'

To three, and store the value in x.

In [45]:
x = iv.nstr(x,3)
x
Out[45]:
'[3.13, 3.25]'

We can use a substring to pull out the first number.

In [46]:
x[1:5]
Out[46]:
'3.13'

Here is a fancier way of extracting the first number from the string. If s is a string, you can type s.split? to find out what split does. Play around with it!

In [47]:
x.split("[")[1].split(",")[0]
Out[47]:
'3.13'