Homework 2

INSERT YOUR NAME HERE

Directions: Add work to this notebook to solve the problems below.

Be careful to name the objects you create as described in the problem. Some problems may include some tests you can run to test your code.

Before you submit your work, make sure it runs correctly without errors. Click “Kernel > Restart & Run All” to restart and run everything.

Some problems are derived from problems in these books:

  • LL: Programming for Computations - Python by Svein Linge and Hans Petter Langtangen, 2nd edition.
  • L: A Primer on Scientific Programming with Python by Hans Petter Langtangen, 2nd edition.
  • TAK: Applied Scientific Computing With Python by Peter R. Turner, Thomas Arildsen, and Kathleen Kavanagh.

Standard imports

In [ ]:
import math as m

1. Basic computations

Use the math standard library to compute the value of the expression $$\sin(\pi^2) + \sqrt[3]{1 + e^{\cos 3}}$$ as a float. Store the result in the variable some_number.

In [ ]:
 

2. Odd sublist

Write a function odd_sublist(lst) which takes as input a list lst of integers and returns a list containing only the odd integers, in the same order.

In [ ]:
 

The following assertions should not lead to errors.

In [ ]:
assert odd_sublist([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) == [1, 3, 5, 7, 9]
assert odd_sublist([1, 1, 2, 3, 5, 8, 13, 21]) == [1, 1, 3, 5, 13, 21]
assert odd_sublist([101, 1001, 10001]) == [101, 1001, 10001]
assert odd_sublist([2, 4, 8, 16, 32, 64]) == []

3. Within epsilon

Write a function within_epsilon(a, b, epsilon) which takes as input three numbers $a$, $b$, and $\epsilon$ and returns the truth value of the expression: $$|a-b|<\epsilon.$$

In [ ]:
 
In [ ]:
# Since |1 - 1.1| = 0.1 < 0.2, the following should return True:
within_epsilon(1, 1.1, 0.2)

4. Small float

In mathematics we know that if $x$ is a real number and $x>0$ then $\frac{x}{2}>0$. Show this is not true for Python floats. Store a float in the variable small_float which has the following properties:

  • small_float > 0 is True, and
  • small_float/2 == 0 is also True.

(Hint: Use the float_info package and experiment a little.)

In [ ]:
 

Both the following should return True:

In [ ]:
small_float > 0
In [ ]:
small_float/2 == 0

5. Addition errors

In mathematics we have $x + 1 - x = 1$, but this does not always hold for floats. By experimentation, find a float bad_x_value between one and two which satisfies bad_x_value + 1 - bad_x_value != 1.

Remark: It would be good to think about how far from one the expression $x + 1 - x$ can be.

In [ ]:
 

All the following boxes should print True

In [ ]:
bad_x_value > 1
In [ ]:
bad_x_value < 2
In [ ]:
bad_x_value + 1 - bad_x_value != 1

6. Ternary to int

Write a function named ternary_to_int which takes as input a string consisting only of elements of $\{0,1,2\}$ giving the ternary expansion of a positive number and produces the integer.

Hints:

  • You can tell the number of characters in a string s with the command len(s).
  • You can get the $k$-th character with s[k]. A trick to get the $j$-th character from the end is to type s[-j]. In particular the first character is always s[0] and the last character is always s[-1].
  • You can convert a string s to an integer using int(s). This works for single characters for instance.
  • You can get the substring of s not including the first character using s[1:] and the substring not including the last character using s[:-1]. These are examples of string slices, which are covered in the Python tutorial and in LL § 2.3.5. (The notion of slices works for strings, numpy arrays, lists and tuples.)
In [ ]:
 

Basic testing: Observe 102 in ternary represents $9+2 =11$. So the following call should return 11.

In [ ]:
ternary_to_int("102")

More rigorous testing: To test that your program works as expected, I copyied in the ternary function from the Number Representations notebook. This function converts an integer $n$ into a ternary string. Your function should satisfy ternary_to_int(ternary(n))==n for every positive integer n.

The following loop carries this test out for the first $n=1$ to $100$.

In [ ]:
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 [ ]:
for n in range(1,101):
    tern = ternary(n)
    out = ternary_to_int(tern)
    assert out == n, ("Error: Output of `ternary_to_int('{}')` " + \
        "should be {}, but was {}.").format(tern, n, out)

7. Base 36

If you wanted to efficiently store positive integers using only digits and lower case letters, you can write numbers in base $36$. Similar to how hexidecimal works, we'll use $0, 1, 2, \ldots, 9$ to represent place values zero through nine. Then we can use $a$ to represent a place value of ten, $b$ for eleven, up through $z$ for thirty-five.

The following function converts a place value to a character. (It makes use of the ord and chr functions for working with ascii characters in Python.)

In [ ]:
def place_value_to_character(n):
    assert type(n) == int, 'n should be an integer'
    assert n >= 0, 'n should be non-negative'
    assert n < 36, 'n should be less than 36'
    if n <= 9:
        return chr(ord('0')+n)
    else:
        return chr(ord('a')+n-10)   

Use of the function place_value_to_character is demonstrated below.

In [ ]:
place_value_to_character(15)
In [ ]:
for n in range(36):
    char = place_value_to_character(n)
    print(f'{n} -> {char}', end=', ')

Write a function to_base_36(n) which takes as input a positive integer n and returns a the base $36$ representation of $n$ as a string. For example, calling to_base_36(70) should return '1y' since $70 = 36+34$.

(Your code does not need to correctly handle values of $n \leq 0$. You should make use of the place_value_to_character function given above. Your code should be similar to the ternary function in the Number Representations notebook worked through in class.)

In [ ]:
 

Here is a simple test:

In [ ]:
s = to_base_36(70)
if s == '1y':
    print('Your code returned the correct answer.')
else:
    print('Your code returned the wrong answer.')

You can use this to encrypt messages. Here are some secret messages you should be able to decode and read:

In [ ]:
to_base_36(62912260703411)
In [ ]:
to_base_36(485761193551777857689576581216108653179423404320520214216246598371699378128)