<jupyter_start><jupyter_text>Chapter 5 - Simple Functions ------------------------------- Up to this point, I have already introduced some basic "functions", such as `print()` and `int()`. In this chapter these functions will be discussed a bit more in-depth, and a few other functions will be introduced, which will be helpful in the coming chapters. In a future chapter, I will discuss how you can create your own functions. ---  Functions A function is a block of reusable code that performs some action. To get a function to do its job, you "call" it, with some appropriate parameters if the function requires them. The idea is that you do not need to have knowledge about how a function performs its action. You only need to know three things:- The name of the function- The parameters it needs (if any)- The return value of the function (if any)These will now be discussed in turn.  Function name Each function has a name. Like a variable name, a function name may consist of letters, digits, and underscores, and cannot start with a digit. Almost all standard Python functions consist only of lower case letters. Usually a function name expresses concisely what the function does.When referring to a function, it is convention to use the name, and put an opening and closing parenthesis after the name, as functions are always called in code with such parentheses.  Parameters Some functions are called with parameters ("arguments"), which may or may not be mandatory. The parameters are placed between the parentheses that follow the function name. If there are multiple parameters, you place commas between them.The parameters are the values that the user supplies to the function to work with. For instance, the `int()` function must be called with one parameter, which is the value that the function will try make an integer representation of. The `print()` function may be called with any number of parameters (even zero), which it will display, after which it will go to a new line.In general, a function cannot change parameters. For instance, look at the following code:<jupyter_code>x = 1.56
print( int( x ) )
print( x )<jupyter_output><empty_output><jupyter_text>As you can see when you run this code, the `int()` function has not changed the actual value of `x`; it only told the `print()` function what the integer value of `x` is. The reason is that, in general, parameters are "passed by value". This means that the function does not get access to the actual parameters, but it gets copies of the values of the parameters. I say "in general" because not all data types are "passed by value", but the ones I have discussed until now are. It will be a while before you get to a chapter that introduces data types that can be changed by functions when they are passed as parameters, and I will make abundantly clear how that works when it comes up.If a function gets multiple parameters, their order matters. For instance, the function `pow()` gets two parameters, and raises the first to the power of the second.<jupyter_code>base = 2
exponent = 3
print( pow( base, exponent ) )<jupyter_output><empty_output><jupyter_text>The names of the variables that are used as parameters do not matter, the first is raised to the power of the second. So the following example will give a different outcome than the first, as the same variables are given to the function in a different (rather confusing) order.<jupyter_code>base = 2
exponent = 3
print( pow( exponent, base ) ) # confusing use of variables<jupyter_output><empty_output><jupyter_text>What happens if you try to call a function with parameters that it cannot work with? For instance, what happens if I call the `int()` function with a string that does not contain an integer value, or the `pow()` function with strings instead of numbers? In general, this will lead to runtime errors in your code. For instance, both lines of the code below give a runtime error.<jupyter_code>x = pow( 3, "2" )
y = int( "two-and-a-half" )<jupyter_output><empty_output><jupyter_text>Return value A function may or may not "return" a value. If a function returns a value, that value can be used in your code. For instance, the function `int()` returns an integer representation of the parameter it gets. You can place this return value in a variable, using an assignment, or use it in a different manner, for instance immediately print it. You can even not do anything with it, though there is little reason to call the function in that case.<jupyter_code>x = 2.1
y = '3'
z = int( x )
print( z )
print( int( y ) )<jupyter_output><empty_output><jupyter_text>As you can see from the example above, you can even use function calls as parameters for a function; e.g., the second call to the `print()` function in the example gets as parameter a call to the function `int()`. In this example, the call to the `int()` function is executed before the `print()` function is called, as Python first calculates the values for all the parameters before it makes a function call. Not all functions return a value. For instance, the `print()` function does not. If you are not careful, this may lead to strange behavior of your program. For instance, examine and run the following code:<jupyter_code>print( print( "Hello, world!" ) )<jupyter_output><empty_output><jupyter_text>You can see that this code prints two lines, the first containing the text "Hello, world!", and the second containing the word "None". What is that "None" doing there? To find that out, let's examine how Python evaluates this statement.When Python first encounters this statement, it sees `print(  )`. Since `` is an argument, it starts by evaluating that. `` is actually `print(  )`. Since `` is an argument, it now evaluates that. `` is the string `"Hello, world!"`. This is not something that needs to be evaluated, so it calls `print()` with this string as argument, and "captures" the return value of `print()` because it needs it as the evaluation of ``.Here is the crux: `print()` has *no* return value, so there is nothing that Python can use for ``. For situations such as this, Python has a special value called `None`. So the first `print()` gets called with `None` as argument, and this leads to Python displaying the word "None". `None` is a special value that indicates "no value at all". If you try to print such a value, Python prints the word `None`, but is not actually printing a string that is "None". It only indicates that there was nothing to print. `None` is different from, for instance, an empty string (`""`). An empty string is still a value, namely a string of length zero. `None` is no string at all, no integer, no float, nothing. So be careful when trying to use a function call as a parameter; if the function does not actually return a value, weird things may happen.  A function is a black box Let me stress once more that you may consider a function a "black box": you do not need to know how the function works or how it is implemented. The name, parameters, and return value are all you need to know. The function might, internally, create variables and do calculations, but they do not have an effect on the rest of your code....At least, if the function is implemented well. A function that has no effect on your code is called a "pure function", and the functions that I discuss here are all "pure functions". However, sometimes functions are designed that actually do have an effect outside the function, specifically, that the user may provide parameters to that undergo a change. That may be fine, if it is intentional and well-documented. Such functions are called "modifiers". Modifiers will come up in later chapters.For now, you can just assume that any function that you use, has no effect on the rest of your code. So calling a function is safe. ---  Some basic functions At this point, I introduce some basic functions that you can use in your Python programs.  Type casting I already introduced the type casting functions, but now I have explained more details of functions, I can give a complete description.- `float()` has one parameter and returns a floating-point representation of the value of that parameter. If the parameter holds an integer, it returns the same value as a float (if you print it, you will see `.0` added). If the parameter holds a float, it returns the same value. If the parameter holds a string which can be interpreted as an integer or a float, it returns that interpretation as a float; otherwise it will give a runtime error.- `int()` has one parameter and returns an integer representation of the value of that parameter. If the parameter holds an integer, it returns the same integer. If the parameter holds a float, it returns the integer part of the float, i.e., the float value rounded down. If the parameter holds a string, and the string contains only digits, optionally with a preceding minus-sign, it returns the integer represented by those digits; otherwise it will give a runtime error.- `str()` has  one parameter and returns a string representation of the value of that parameter.**Exercise**: What will happen if you run the following code? If you do not know, try it and find out.<jupyter_code>print( 10 * int( "100,000,000" ) )<jupyter_output><empty_output><jupyter_text>**Exercise**: The code above gives a runtime error. Fix it by removing a few characters.  Calculations Basic Python functions also have limited support for calculations.- `abs()` has one numerical parameter (an integer or a float). If the value is positive, it will return the value. If the value is negative, it will return the value multiplied by `-1`.- `max()` has two or more numerical parameters, and returns the largest.- `min()` has two or more numerical parameters, and returns the smallest.- `pow()` has two numerical parameters, and returns the first to the power of the second. Optionally, it has a third numerical parameter. If that third parameter is supplied, it will return the value modulo that third parameter.- `round()` has a numerical parameter and rounds it, mathematically, to a whole number. It has an optional second parameter. The second parameter must be an integer, and if it is provided, the function will round the first parameter to the number of decimals specified by the second parameter.**Exercise**: Examine the code below and try to determine what it displays. Then run the code and see if you are correct.<jupyter_code>x = -2
y = 3
z = 1.27

print( abs( x ) )
print( max( x, y, z ) )
print( min( x, y, z ) )
print( pow( x, y ) )
print( round( z, 1 ) )<jupyter_output><empty_output><jupyter_text>`len()` `len()` is a basic function that gets one parameter, and it returns the length of that parameter. For now, the only data type which you will use `len()` for is the string. `len()` returns the length of the string, i.e., the number of characters.**Exercise**: What does the code below print? Run it and check if you are correct.<jupyter_code>print( len( 'can' ) )
print( len( 'cannot' ) )
print( len( '' ) )          # '' is an empty string, i.e., a string with no characters in it.<jupyter_output><empty_output><jupyter_text>**Exercise**: And what about the code below? Think carefully, then check the result.<jupyter_code>print( len( 'can\'t' ) )<jupyter_output><empty_output><jupyter_text>`input()` You will often want the user of a program to supply some data. You can ask the user to supply a string value by using the `input()` function. The function has one parameter, which is a string. This string is the so-called "prompt". When `input()` is called, the prompt is displayed on the screen and the user gets to enter something. The user may type anything they want, including nothing, and then press Enter to stop entering input. The return value of the function is a string which contains what the user entered, excluding that final press of the Enter key.It depends on the environment in which you use Python how exactly the user gets asked to enter input. In the notebooks, a box is displayed in which you can type something. If you run Python from the command prompt, it is done as a command line. In different editors, it is done differently; for instance, there are editors that show a pop-up box. Here is an example:<jupyter_code>text = input( "Please enter some text: " )
print( "You entered:", text )<jupyter_output><empty_output><jupyter_text>Be aware that `input()` always returns a string. Check the following code:<jupyter_code>number = input( "Please enter a number: " )
print( "Your number squared is", number * number )<jupyter_output><empty_output><jupyter_text>Regardless of what you entered, this code gives a runtime error, because since the `input()` function returns a string, `number` is a string, and you are not allowed to multiply two strings. You may resolve this by using a type casting function to turn the string result of `input()` into a numerical value, for instance:<jupyter_code>number = input( "Please enter a number: " )
number = float( number )
print( "Your number squared is", number * number )<jupyter_output><empty_output><jupyter_text>As long as the user enters a value that can be turned into a number, this code runs as intended. However, if the user enters something that cannot be turned into a number, you again get a runtime error. There are ways to resolve this issue, but I have not discussed the means to do that yet, and it will take a while before I do that. However, below I will introduce a way for you to ask the user for numbers without the code crashing if the user is trying to be a wise-ass and enters something else.Note: In the chapter "Using Notebooks" I explained that if you allow the user to enter inputs, you may get into problems if the user ignores the input box and tries to run different code. If you do not remember that, please read that chapter again.**Exercise**: Write some code that asks the user for two numbers, then shows the result when you add them, and when you multiply them.<jupyter_code># Addition and multiplication code<jupyter_output><empty_output><jupyter_text>`print()` The function `print()` takes zero or more parameters, displays them (if there are multiple, with a separating space in between each pair of them), and then "goes to the next line" (i.e., if you use two `print()` statements, the second one will display its parameters below what the first one displays).If `print()` is called without parameters, the function simply will "go to the next line". This way, you can display empty lines.You can supply `print()` with anything as a parameter, and it will do its best to print it. For now, you will only print the basic data types.`print()` can get two special parameters, called "sep" and "end". `sep` indicates what should be printed between each of the parameters, and by default is a space. You can use `sep` to turn the separating space into anything else, including an empty string. `end` indicates what `print()` should put after all the parameters have been displayed, and by default is a "new line". You can use `end` to change what `print()` does after displaying the parameters, for instance, you can ensure that `print()` does not "go to the next line".To use `sep` and `end`, you include special parameters `sep=` and/or `end=` (note: when in a code description you see something between ``, that usually means that you are not supposed to type that literally, but that you have to replace it with something of the type listed, e.g., `` means that you have to type a string in that place). For example:<jupyter_code>print( "X", "X", "X", sep="x" )
print( "X", end="" )
print( "Y", end="" )
print( "Z" )<jupyter_output><empty_output><jupyter_text>`format()` `format()` represents a rather complex functionality that is employed in a particular way. It allows you to create a formatted string, i.e., a string in which certain values appear in a specific format. To give an example, suppose I want to display a calculated float:<jupyter_code>print( 7/11 )<jupyter_output><empty_output><jupyter_text>Now I ask you to display that float with only three decimals. Until now, you would use the `round()` function (introduced above), or something like:<jupyter_code>print( round( 7/11, 3 ) )<jupyter_output><empty_output><jupyter_text>This works. However, when I put more requirements on it (for instance, "also reserve 10 positions for it, and left align the outcome in that reserved space"), it may become convoluted. Using the `format()` function, you can display the requested value in a much easier and more readable way:<jupyter_code>print( "{:.3f}".format( 7/11 ) )<jupyter_output><empty_output><jupyter_text>`format()` is a function that "works" on a string. Up until this point, I have only used functions that get parameters. However, there are functions that work only on a particular data type, and are defined in such a way that a variable of that data type has to be placed in front of the function call, with a period in between. The reason why this is, has to do with something called "object orientation", which I will discuss much later in this course. For now, just know that such functions are called "methods", and to call them, you have to place the variable of the right data type in front of them, with a period in between. The variable that is used in this way is also accessible to the method, just like its parameters are.So, the `format()` method (let's refer to it by its correct name, it is not a function but a method) is called as follows: `.format()`. It will return a new string, which is a formatted version of the string for which it is called. It can take any number of parameters, and in the process of formatting, will insert these parameter values in particular places in the resulting string.The places where `format()` inserts the parameter values in the string are indicated in the string by opening and closing curly brackets (`{` and `}`). If you only use `{}` to refer to the parameters, it will process the string from left to right, and process the parameters from left to right, inserting them in the order that they are given. For example:<jupyter_code>print( "The first three numbers are {}, {} and {}.".format( "one", "two", "three" ) )<jupyter_output><empty_output><jupyter_text>If you want to process them in a different order, you can indicate the order by putting a number between the curly brackets. The first parameter has number `0`, the second has number `1`, the third has number `2`, etcetera (if you find numbering starting with zero strange, then know that this is very common in programming languages and you will see this many more times). For example:<jupyter_code>print( "The first three numbers are (in backwards order) {2}, {1} and {0}.".format( "one", "two", "three" ) )<jupyter_output><empty_output><jupyter_text>`format()` can deal with parameters of any type, as long as they have a suitable string representation. For instance, it can deal with integers and floats, and you can mix those up with strings as you like:<jupyter_code>print( "The first three numbers are {}, {} and {}.".format( "one", 2, 3.0 ) )<jupyter_output><empty_output><jupyter_text>If you want to format the parameters in a more specific way, there are possibilities to do that, if you put a colon (`:`) in between the curly brackets, after the order number if you have one, and place some formatting instructions to the right of the colon. There are many possibilities for formatting instructions, and I will introduce only a few.First I discuss some formatting instructions for string parameters. If you want to reserve a certain number of places for a string parameter, then you can indicate that with an integer to the right side of the colon. This is called the "precision". The following code uses a precision of 7.<jupyter_code>print( "The first three numbers are {:7}, {:7} and {:7}.".format( "one", "two", "three" ) )<jupyter_output><empty_output><jupyter_text>If you do not reserve sufficient space for a parameter with the precision, `format()` will take as much space as it needs. So you cannot use the precision to, for instance, break off a string prematurely.<jupyter_code>print( "The first three numbers are {:4}, {:4} and {:4}.".format( "one", "two", "three" ) )<jupyter_output><empty_output><jupyter_text>If you use precision, you can align the parameter to the left, center, or right. You do that by placing an alignment character between the colon and the precision. Alignment characters are "``" for align right.<jupyter_code>print( "The first three numbers are {:>7}, {:^7} and {:<7}.".format( "one", "two", "three" ) )<jupyter_output><empty_output><jupyter_text>Now I will discuss some number formatting instructions. If you want a number to be interpreted as an integer, you place a "`d`" to the right side of the colon. If instead you want it to be interpreted as a float, you place an "`f`". If you want to display an integer as a float, `format()` will do the necessary conversions for you. If you want to display a float as an integer, `format()` will cause a runtime error.<jupyter_code>print( "{} divided by {} is {}".format( 1, 2, 1/2 ) )
print( "{:d} divided by {:d} is {:f}".format( 1, 2, 1/2 ) )
print( "{:f} divided by {:f} is {:f}".format( 1, 2, 1/2 ) )<jupyter_output><empty_output><jupyter_text>Just as with strings, you can use precision and alignment with numbers. You use the same instruction characters, and place them between the colon and the `d` or `f`. And just as with strings, if the precision does not provide enough places, `format()` will take extra places as needed. Note that a preceding minus-sign and the decimal period each also take a place.<jupyter_code>print( "{:5d} divided by {:5d} is {:5f}".format( 1, 2, 1/2 ) )
print( "{:<5f} divided by {:^5f} is {:>5f}".format( 1, 2, 1/2 ) )<jupyter_output><empty_output><jupyter_text>Finally, and perhaps most useful, you can indicate how many decimals you want a floating point number to be displayed with, by placing a period and an integer to the left of the `f`. `format()` will round the parameter to the requested number of decimals. Note that you can indicate zero decimals using `.0`, which will display floats as integers.<jupyter_code>print( "{:.2f} divided by {:.2f} is {:.2f}".format( 1, 2, 1/2 ) )<jupyter_output><empty_output><jupyter_text>The combination of precision, alignment, and decimals, allows you to create nice, table-like displays.<jupyter_code>s = "{:>5d} times {:>5.2f} is {:>5.2f}"
print( s.format( 1, 3.75, 1 * 3.75 ) )
print( s.format( 2, 3.75, 2 * 3.75 ) )
print( s.format( 3, 3.75, 3 * 3.75 ) )
print( s.format( 4, 3.75, 4 * 3.75 ) )
print( s.format( 5, 3.75, 5 * 3.75 ) )<jupyter_output><empty_output><jupyter_text>---  Modules Python offers some basic functions, some of which are introduced above. Besides those, Python offers a large assortment of so-called "modules", which contain many more useful functions. To use functions from a module in your program, you have to `import` the module, by write a line `import ` at the top of your code. You can then use all the functions in the module, though you have to precede the function calls with the name of the module and a period, e.g., to call the `sqrt()` function from the `math` module (which calculates the square root of a number), you call `math.sqrt()` after importing `math`.Alternatively, you can import only specific functions from a module, by stating `from  import , , , ...`. The main advantage of importing specific functions from a module in this way is that in your code, you no longer need to precede the call to a function with the module name.For example:<jupyter_code>import math

print( math.sqrt( 4 ) )<jupyter_output><empty_output><jupyter_text>is equivalent to:<jupyter_code>from math import sqrt

print( sqrt( 4 ) )<jupyter_output><empty_output><jupyter_text>If you want to rename something that you import from a module, you can do so with the keyword `as`. This might be useful when you use multiple modules that contain things with equal names.<jupyter_code>from math import sqrt as squareroot

print( squareroot( 4 ) )<jupyter_output><empty_output><jupyter_text>I will now introduce some functions from two standard modules that are often used, and some functions from a module which was developed for this course (you will learn to develop your own modules later). There are many more modules besides the ones introduced here, some of which will come up later in the course, and others which you will have to look up by yourself by the time you need them in practice. However, you may assume that for any more-or-less general problem that you want to solve, someone has made a module that makes solving that problem simple or even trivial. So, in practice, do not start coding immediately, but first investigate whether you can exploit someone else's efforts.  `math` The `math` module contains some useful mathematical functions. These functions have usually been implemented in a very efficient way, and in general they return a float. I will introduce only a few of these functions here (if you want to learn more of them, look up the `math` module in the Python reference):- `exp()` gets one numerical parameter and returns `e` to the power of that parameter. If you do not remember `e` from math class: `e` is a special value that has many interesting properties, which have applications in physics, maths, and statistics.- `log()` gets one numerical parameter and returns the natural logarithm of that parameter. The natural logarithm is the value which, when `e` is raised to the power of that value, gives the requested parameter. Just like `e`, the natural logarithm has many applications in physics, maths, and statistics.- `log10()` gets one numerical parameter and returns the base-10 logarithm of that parameter.- `sqrt()` gets one numerical parameter and returns the square root of that parameter.For example:<jupyter_code>from math import exp, log

print( "The value of e is approximately", exp( 1 ) )
e_sqr = exp( 2 )
print( "e squared is", e_sqr )
print( "which means that log(", e_sqr, ") is", log( e_sqr ) )<jupyter_output><empty_output><jupyter_text>`random` The `random` module contains functions that return pseudo-random numbers. I say "pseudo-random" and not "random", because it is impossible for digital computers to generate actual random numbers. However, for all intents and purposes you may assume that the functions in the `random` module cough up random values.- `random()` gets no parameters, and returns a random float in the range `[0,1)`, i.e., a range that includes `0.0`, but excludes `1.0`.- `randint()` gets two parameters, both integers, and the first should be smaller than or equal to the second. It returns a random integer in the range for which the two parameters are boundaries, e.g., `randint(2,5)` returns 2, 3, 4, or 5, with an equal chance for each of them.- `seed()` initializes the random number generator of Python. If you want a sequence of random numbers that are always the same for your program, start by calling `seed` with a fixed value as parameter, for instance, `0`. This can be useful for testing purposes. If you want to re-initialize the random number generator so that it starts behaving completely randomly again, call `seed()` without parameter.For example:<jupyter_code>from random import random, randint, seed

seed()
print( "A random number between 1 and 10 is", randint( 1, 10 ) )
print( "Another random number between 1 and 10 is", randint( 1, 10 ) )

seed( 0 )
print( "Three random numbers are:", random(), random(), random() )
seed( 0 )
print( "The same three numbers are:", random(), random(), random() )<jupyter_output><empty_output><jupyter_text>`pcinput` `pcinput` is a module written specifically for this course (if you do not see the file `pcinput.py` on your notebooks' home page, you should make sure to get it and upload it). It contains four functions which are helpful for getting particular kinds of input from the user. The functions are the following:- `getInteger()` gets one string parameter, the prompt, and asks the user to supply an integer using that prompt. If the user enters something that is not an integer, the user is asked to enter a new input. The function will continue asking the user for inputs until a legal integer is entered, and then it will return that value, as an integer. - `getFloat()` gets one string parameter, the prompt, and asks the user to supply a float using that prompt. If the user enters something that is not a float or an integer, the user is asked to enter a new input. The function will continue asking the user for inputs until a legal float or integer is entered, and then it will return that value, as a float.- `getString()` gets one string parameter, the prompt, and asks the user to supply a string using that prompt. Any value that the user enters is accepted. The function will return the string that was entered, with leading and trailing spaces removed.- `getLetter()` gets one string parameter, the prompt, and asks the user to supply a letter using that prompt. The user's input must be a single letter, in the range A to Z. Both capitals and lower case letters are accepted. The function returns the letter entered, converted to a capital.These functions allow you to write code that asks the user for inputs of a specific data type, and guarantee that the input will indeed be of that data type, i.e., the code does not crash if the user enters something that is unacceptable. The functions are not very nicely designed, as they display messages in English when the user enters something that is wrong (so the functions are less useful if your code is meant to support a different language). But for the purpose of this course, they work fine.**Exercise**: Run the code below, try to enter something else than an integer, and see what happens.<jupyter_code>from pcinput import getInteger

num1 = getInteger( "Please enter an integer: " )
num2 = getInteger( "Please enter another integer: " )

print( "The sum of", num1, "and", num2, "is", num1 + num2 )<jupyter_output><empty_output><jupyter_text>**Exercise**: Ask the user to supply a string. Then use that string as a prompt to ask for a float.<jupyter_code># Ask for a float using a prompt supplied by the user
from pcinput import getString, getFloat<jupyter_output><empty_output><jupyter_text>Note: I do not explain here how the functions of `pcinput` work, as they are implemented using concepts that are discussed much later in the course. You will learn, in time, how to develop such functions yourself. For now, do not worry about how they work, but just use them. This is the attitude that you should have towards most standard functions: as long as you know what they do, which parameters they need, and what they return, you do not need to spend time considering how they work.Note: If you want to use the functions from `pcinput` in programs that you develop outside the notebooks, then you must make sure that the file `pcinput.py` is available to Python. This means that it should either reside in the folder where you are writing your code, or you should place it in the Python `Lib` folder. ----------  What you learned In this chapter, you learned about:- What functions are- Function names- Function parameters- Function return values- Details of type casting with `float()`, `int()`, and `str()`- Basic calculation functions `abs()`, `max()`, `min()`, `pow()`, and `round()`- `len()`- `input()`- Details of the `print()` function- String formatting using `format()`- What modules are- The `math` module functions `exp()`, `log()`, `log10()`, and `sqrt()`- The `random` module functions `random()`, `randint()`, and `seed()`- The `pcinput` module functions `getInteger()`, `getFloat()`, `getString()`, and `getLetter()` -------  Exercises  Exercise 5.1 Ask the user to enter a string. Then print the length of that string. Use the `input()` function rather that the `getString()` function from `pcinput`, as the `getString()` function removes leading and trailing spaces.<jupyter_code># String length test.<jupyter_output><empty_output><jupyter_text>Exercise 5.2 The Pythagorean theorem states that the of a right triangle, the square of the length of the diagonal side is equal to the sum of the squares of the lengths of the other two sides (or `a**2 + b**2` equals `c**2`). Write a program that asks the user for the lengths of the two sides that meet at a right angle, then calculate the length of the third side, and display it in a nicely formatted way. You may ignore the fact that the user can enter negative or zero lengths for the sides.<jupyter_code># Pythagorean theorem.<jupyter_output><empty_output><jupyter_text>Exercise 5.3 Ask the user to enter three numbers. Then print the largest, the smallest, and their average, rounded to 2 decimals.<jupyter_code># Processing three numbers.<jupyter_output><empty_output><jupyter_text>Exercise 5.4 Calculate the value of `e` to the power of `-1`, `0`, `1`, `2`, and `3`, and display the results, with 5 decimals, in a nicely formatted manner.<jupyter_code># Some powers of `e`.<jupyter_output><empty_output><jupyter_text>Exercise 5.5 Suppose you want to generate a random integer between 1 and 10 (1 and 10 both included), but from the `random` module you only have the `random()` function available. How do you do that?<jupyter_code># Generate a random integer using only random()
from random import random<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07690700728184315, 'fraction_numerical': 0.00635669093947714, 'mean_word_length': 4.691066576086956, 'pattern_counts': {'":': 1, '<': 163, '<?xml version=': 0, '>': 166, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '40', 'dir': 'jupyter-structured-clean-dedup', 'id': '540914', 'license': 'MIT', 'n_tokens_mistral': 8773, 'n_tokens_neox': 8393, 'n_words': 5247, 'path': 'notebooks uni/PC05 - Simple Functions.ipynb', 'repo_name': 'tintin10q/RandomPythonProjects', 'size': '33508'}