a = 5  # assigninig the integer value 5 to variable 'a'
b = 2

print(a + b, a - b) # Integer addition and subtraction
print(a * b)        # Integer multiplication
print(a**b)         # 5 to the power of 2
print(a // b)       # Integer division!
print(a % b)        # modulo function
print(a / b)        # division with 'promotion' of the result to float
                    # if necessary
                    # This behaviour is different in Python2!
print(5**5460)      # 'arbitrarily accurate' integer arithmetic! 

"""
Explanation: Basic Types in Core-Python
Python has all types that you already know from other programming languages.
Notes:
- In Python, variables do not need to be declared before using them!
- Variables do not have any type but the objects they point to do!
Integer Type
End of explanation
"""


a = 5
print(type(a))   # The type of the object a variable points to
                 # can explicitely be queried!
print(type(5))    

"""
Explanation: The last example shows that Python provides aribtrary precise integer arithmetic! There is only one integer type in the Python core.
End of explanation
"""


import numpy  # 'library or module' of mathematical functions
              # and data structures.

c = 3.14159 # seen already? 
d = .1      # equal to 0.1
e = 1.2e2   # read: 1.2 times 10 to the power of 2

print(type(e))
print(c + d, c - d, d * e, c / d)
print(numpy.cos(c))  # The cosine function is defined within the numpy module
print(c%1)           # obtain fractional part of a float

print(d + 3)  # in mixed calculations, integer values are 'promoted' to float

"""
Explanation: Float Type
End of explanation
"""


# your solution here

"""
Explanation: By default Python uses Double Precision floating point numbers.
The example print(c / d) reminds us that most floating-point numbers do not have an exact representation in a computer (numerics!). See also Floating Point Arithmetic: Issues and Limitations and read especially What every computer scientist should know about Floating-Point Arithmetic if you have not yet done so!

Exercise:
Calculate the expressions: $2 + 4 \cdot 3$, $5^{5^{5}}$, $\mathrm{e}^{-1}$
and $\left({49 \atop 6}\right)=\frac{49!}{6! 43!}$
Hint: You can use the functions numpy.exp and numpy.math.factorial to obatin Eulers number and factorials respectively.
End of explanation
"""


f = False
t = True
a = 1

print(f or t)   # logical 'or'
print(f and t)  # logical 'and'
print(a == 1)   # test for equality
print(a == 2)
print(a < 5, a >= 5)

"""
Explanation: Boolean Type
Python has an explicit boolean type which can only take the values True and False. It is used to test conditions in loops and if statements.
End of explanation
"""


d = 1.0
print(d == 1.0)
print((d - 0.6) == 0.4)
print((d - 6 * 0.1) == 0.4)

# your solution here

"""
Explanation: Exercises

Write down a Python expression which evaluates to True
if $1 < x \leq 10$ and to False otherwise.
Explain the results of the following cell! Can you modify the expressions such that the results meet your expectations?
End of explanation
"""


first_name = "Thomas"
second_name = "Erben"

full_name = first_name + " " + second_name # concatenation of strings
print(full_name)

print(full_name[1], full_name[1:3])        # accessing parts of strings 
                                           # (see containers)
print(len(full_name))                      # length of string
print(full_name.upper())                   # translate all chars to uppercase

print(full_name.find("Erben"))             # find substring

"""
Explanation: String Type
The Python String type is a special case of a container which we will treat in detail in the coming weeks!
End of explanation
"""


s = "Hello Thomas"

# your solution here

"""
Explanation: Remarks:

Python fully administrates memory for you (You did not need to worry aboput memory overflows by
assigning too long strings to variables etc.)! However, it is often necessary to know how Python
does it, especially for data-intensive applications. We will talk more about this later.
Note the different ways to operate with a function on strings: len(full_name) (usual function call)
and full_name.upper() (calling a method from the String Class).

Exercise:
Give a Python command which replaces the word Hello in a string with Goodbye!
End of explanation
"""


