None intro_basics1

Solutions to Sheet 1.a

In [4]:
# problem 1
def sphere_volume(r: float) -> float:
    """Returns the volume of a sphere"""
    return 4/3 * 3.14159 * r**3

sphere_volume(5)
Out[4]:
523.5983333333332
In [5]:
# problem 2
def isolate(a: int, b: int, c: int, d: int, e: int) -> None:
    """Print first two values with 5 spaces rest with one"""
    print(a, b, sep="     ", end="     ")
    print(c, d, e)

isolate(1, 2, 3, 4, 5)
1     2     3 4 5
In [6]:
# problem 3.1
def first_half(sin: str) -> None:
    half = int(len(sin)/2)  # int() removes the comma
    print(sin[:half])

first_half("12345")
12
In [7]:
# problem 3.2
def backward(sin: str) -> None:
    print(sin[::-1]) # [start:end:step]

backward("abcd")
dcba
In [ ]:
# problem 4
def list_ops() -> list[str]:
    lst = ["bear", "ant", "cat", "dog"];    print(f"1: {lst}")
    lst.append("eagle");                    print(f"2: {lst}")
    lst[2] = "fox";                         print(f"3: {lst}")
    lst.pop(1);                             print(f"4: {lst}")
    lst.reverse();                          print(f"5: {lst}")
    lst[lst.index("eagle")] = "hawk";       print(f"6: {lst}")
    lst.append("hunter");                   print(f"7: {lst}")
    return lst

list_ops()
1: ['bear', 'ant', 'cat', 'dog']
2: ['bear', 'ant', 'cat', 'dog', 'eagle']
3: ['bear', 'ant', 'fox', 'dog', 'eagle']
4: ['bear', 'fox', 'dog', 'eagle']
5: ['eagle', 'dog', 'fox', 'bear']
6: ['hawk', 'dog', 'fox', 'bear']
7: ['hawk', 'dog', 'fox', 'bear', 'hunter']
Out[ ]:
['hawk', 'dog', 'fox', 'bear', 'hunter']
In [ ]:
# problem 5
def pig_latin(word: str) -> None:
    vowels = ("a", "e", "i", "o", "u")
    if word[0].lower() in vowels:
        word = word + "hay"
        print(word)
    else:
        word = word + word[0] + "ay"
        word = word.replace(word[0], "")
        print(word)


pig_latin("aesop rock")
aesop rockhay
In [8]:
# problem 6
def palindrome() -> int:
    palindromes: list[int] = []
    for i in range(100, 1000):
        for j in range(100, 1000):
            product = i * j
            if str(product) == str(product)[::-1]: # [start:end:step]
               palindromes.append(product)
    #print(palindromes) # list of all palindromes
    return max(palindromes)


print(palindrome())
906609
In [ ]:
# problem 7 - w/ list comprehension
def alt_harmonic(n: int) -> int:
    return sum([(-1)**(i+1)/i for i in range(1, n+1)])


print(alt_harmonic(5))
0.7833333333333332
In [ ]:
# problem 7 - w/o list comprehension
def alt_harmonic_alternative(n: int) -> int:
    elements: list[int] = []
    for i in range(1, n+1):
        elements.append((-1)**(i+1)/i)
        
    return sum(elements)

        
alt_harmonic_alternative(5)
Out[ ]:
0.7833333333333332
In [ ]:
# problem 8
def list_info(lst: list[float]) -> tuple[float, float, float]:
    return min(lst), sum(lst)/len(lst), max(lst)

# alternatively

lst = [1,2,3,4]
tuple((min(lst), sum(lst)/len(lst), max(lst)))
Out[ ]:
(1, 2.5, 4)
In [ ]:
# task 9
d = {"Marco": 1, "Luca": 2, "Alex": 3}
d_inv = {item: key for key,item in d.items()}
d_inv
Out[ ]:
{1: 'Marco', 2: 'Luca', 3: 'Alex'}
In [ ]:
# problem 10
int1 = 1
int2 = int1
int1 = 3
print("int1: {}, int2: {}, equals?: {}".format(int1, int2, int1 == int2))
print("int1 id: {}, int2 id: {}, equals?: {}\n".format(
    id(int1), id(int2), id(int1) == id(int2)))

str1 = "foo"
str2 = str1
str1 = "bar"
print("str1: {}, str2: {}, equals?: {}".format(str1, str2, str1 == str2))
print("str1 id: {}, str2 id: {}, equals?: {}\n".format(
    id(str1), id(str2), id(str1) == id(str2)))

list1 = [1, 2, 3]
list2 = list1 # solve using list1.copy()
list1[0] = 10
print("list1: {}, list2: {}, equals?: {}".format(list1, list2, list1 == list2))
print("list1 id: {}, list2 id: {}, equals?: {}\n".format(
    id(list1), id(list2), id(list1) == id(list2)))

tuple1 = (1, 2, 3)
tuple2 = (1, 2, 3)
tuple1 += (1,)
print("tuple1: {}, tuple2: {}, equals?: {}".format(
    tuple1, tuple2, tuple1 == tuple2))
print("tuple1 id: {}, tuple2 id: {}, equals?: {}\n".format(
    id(tuple1), id(tuple2), id(tuple1) == id(tuple2)))

set1 = {1, 2, 3}
set2 = set1 # solve using set1.copy()
set1.pop()
print("set1: {}, set2: {}, equals?: {}".format(set1, set2, set1 == set2))
print("set1 id: {}, set2 id: {}, equals?: {}\n".format(
    id(set1), id(set2), id(set1) == id(set2)))
int1: 3, int2: 1, equals?: False
int1 id: 4388964720, int2 id: 4388964656, equals?: False

str1: bar, str2: foo, equals?: False
str1 id: 4396523312, str2 id: 4396523440, equals?: False

list1: [10, 2, 3], list2: [10, 2, 3], equals?: True
list1 id: 4584247744, list2 id: 4584247744, equals?: True

tuple1: (1, 2, 3, 1), tuple2: (1, 2, 3), equals?: False
tuple1 id: 4550627792, tuple2 id: 4428778368, equals?: False

set1: {2, 3}, set2: {2, 3}, equals?: True
set1 id: 4428894720, set2 id: 4428894720, equals?: True

In [19]:
# problem 11
# calculator.py
from math import sqrt

def my_sum(addend1: float, addend2: float) -> float:
    return addend1 + addend2

def product(factor1: float, factor2: float) -> float:
    return factor1 * factor2

# other_file.py

# from calculator.py import *
def hypotenuse(side1: float, side2: float):
    return my_sum(product(side1, side1), product(side2, side2))
    
hypotenuse(2, 3)
Out[19]:
13
In [20]:
# problem 12
import random

# example of how to generate random numbers
print(random.randrange(1, 100)) # 100 is not included
84
In [28]:
# problem 13
from collections.abc import Sequence
from itertools import chain, combinations

def calcPowerSet(lst: Sequence[int | float | str]):
    empty_set: set[int | float | str] = set()
    sets: list[set[int | float | str ]] = [empty_set]
    for i in range(1, len(lst)+1):
        for element in combinations(lst, i):
            # combinations generate combinations with the length of the second argument
            sets.append({''.join(element)}) # joins an iterable
    return sets

calcPowerSet(('1', '2', '3'))

# why not set of sets? because sets are not hashable.
Out[28]:
[set(), {'1'}, {'2'}, {'3'}, {'12'}, {'13'}, {'23'}, {'123'}]
In [31]:
from collections.abc import Iterable    

def power_set(iterable: Iterable[int | float | str]) -> chain[tuple[int | float | str, ...]]: 
    "power_set([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

list( power_set({"a","b","c"}) )
Out[31]:
[(),
 ('b',),
 ('a',),
 ('c',),
 ('b', 'a'),
 ('b', 'c'),
 ('a', 'c'),
 ('b', 'a', 'c')]
In [ ]:
# problem 14
from __future__ import annotations # because of forward reference to class Backpack

class Backpack:
    """A Backpack object class. Has a name, color, max size, and
       a list of contents.

    Attributes:
        name (str): the name of the backpack's owner.
        color (str): the color of the backpack
        max_size (int): the max size
        contents (list): the contents of the backpack.
    """

    # Problem 14: Modify __init__() and put(), and write dump().
    def __init__(self, name: str, color: str, max_size: int = 5) -> None:
        """Set the name, color, max size, and initialize
           an empty list of contents.

        Parameters:
            name (str): the name of the backpack's owner.
            color (str): the color of the backpack
            max_size(int, optional): max size of backpack

        """
        self.name = name
        self.color = color
        self.max_size = max_size
        self.contents: list[str] = []

    def put(self, item: str) -> None:
        """Add an item to the backpack's list of contents unless it is full."""
        if len(self.contents) >= self.max_size:
            print("No room!")
        else:
            self.contents.append(item)

    def take(self, item: str) -> None:
        """Remove an item from the backpack's list of contents."""
        self.contents.remove(item)

    def dump(self) -> None:
        """Remove all items from backpack."""
        self.contents.clear()

    # Magic Methods -----------------------------------------------------------

    # Problem 16: Write __eq__() and __str__().
    def __add__(self, other: Backpack):
        """Add the number of contents of each Backpack."""
        return len(self.contents) + len(other.contents)

    def __lt__(self, other: Backpack):
        """Compare two backpacks. If 'self' has fewer contents
        than 'other', return True. Otherwise, return False.
        """
        return len(self.contents) < len(other.contents)

    def __eq__(self, o: Backpack):
        q = 0
        if self.name == o.name:
            q += 1
        if self.color == o.color:
            q += 1
        if self.contents == o.contents:
            q += 1
        if q == 3:
            return True
        else:
            return False

    def __str__(self):
        return f"<<Owner:\t{self.name}\nColor:\t\t{self.color}\nSize:\t\t{len(self.contents)}\nMax Size:\t{self.max_size}\nContents:\t{self.contents}>>"            
In [ ]:
# problem 14 - test function
def test_backpack():
    test = Backpack("foo", "green", max_size=4)
    if test.name != "foo":
        print("Name is incorrect.")
    for item in ["book", "pencil case"]:
        test.put(item)
    print("Contents: ", test.contents)

    # problem 15 - test magic methods
    print(str(test))
    test2 = Backpack("foo", "green", max_size=4)
    for item in ["book", "pencil case"]:
        test2.put(item)
    print(test == test2)


test_backpack()
Contents:  ['book', 'pencil case']
<<Owner:	foo
Color:		green
Size:		2
Max Size:	4
Contents:	['book', 'pencil case']>>
True
In [45]:
# Problem 15: Write a 'Jetpack' class that inherits from the 'Backpack' class.
class Jetpack(Backpack):
    """A jetpack that inherits from backpack.

    Attributes:
    - name (str): name of owner
    - color (str): color of backpack
    - max_size (int): max size of backpack
    - fuel: current fuel of the backpack"""

    def __init__(self, name: str, color: str, max_size: int = 2, fuel: float =10):
        """Call the super class' constructor and initialize fuel

        Parameters:
        - name (str): name of owner
        - color (str): color of backpack
        - max_size (int): max size of backpack
        - fuel: current fuel of the backpack"""
        Backpack.__init__(self, name, color, max_size)
        self.fuel: float = fuel

    def fly(self, fuel_val: float) -> None:
        """Reduce the fuel amount for flying."""
        if self.fuel - fuel_val <= 0:
            print("Not enough fuel!")
        else:
            self.fuel -= fuel_val

    def dump(self) -> None:
        """Dump the contents of the backpack and fuel"""
        self.contents.clear()
        self.fuel = 0
In [ ]:
# Problem 17
# We can calculate Greek pi by sampling the space [0,1]x[0,1] and observing how
# many times the points fall within the quarter of the circle with ray 1 and
# center in (0,0). Then we can derive pi from the ratio of the area covered by
# one quarter of the circle and the area of the square [0,1]x[0,1]
# That is: (1/4 * pi * r^2)/1 = # Points within the circle / # Points in the square, 
# hence pi = \sqrt{ 4 R }