Introduction to Programming for Business Analytics - Exercise 3: Control Flow
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 22 | |
Author | ||
License | CC Attribution 4.0 International: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/63717 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Producer |
Content Metadata
Subject Area | ||
Genre | ||
Keywords |
00:00
Computer animation
10:26
Computer animation
19:46
Computer animation
29:07
Computer animation
38:27
Computer animation
47:47
Computer animation
57:07
Computer animation
01:06:27
Computer animation
01:15:47
Computer animation
01:25:07
Computer animation
01:34:27
Computer animation
Transcript: English(auto-generated)
00:00
Hi, and welcome to the third exercise video for the class introduction to programming for business analytics. This week is about control flow and different ways to control the flow in Julia program.
00:25
You might have the feeling that the tasks of this exercise are much more difficult than the tasks in previous exercises, and that's completely normal because control flow structures are notoriously difficult to understand, but don't worry about it because if you keep practicing
00:45
over the semester, then it will feel very simple to you by the end of the semester. And as always, please try to solve the exercise tasks yourself before you watch the portion of the video where I explain the solution for the exercise task.
01:04
With that said, let's get started. The first task is about logical operators. And it says give three examples for a bool expression which involves a logical operator. We have learned about three logical operators in the lecture, so why don't we provide one
01:27
expression with each of the logical operators, and the logical operators are the NOT operator, which is expressed with the exclamation mark, then the AND operator, which is expressed with the two ampersands, and then the OR operator, which is expressed with the two vertical bars,
01:47
also called pipes. And to finish our three Boolean expressions, we need to provide arguments for the operators. In case of the NOT operator in the first cell, we need only one Boolean expression.
02:05
For instance, we can just provide a Boolean literal. In this case, the literal is true, and we hand this to the NOT operator, and then it evaluates to false. And for the other operators, these are binary operators, so we need two literals.
02:24
And we know that the true operator only evaluates to true if both of the arguments are also true. So let's do that.
02:42
There we go. And we know that the false operator evaluates to true if one, at least one of the arguments is true. So there we go. Of course, if you did provide different Boolean expressions, that's completely fine, as long
03:02
as each of them involved one of these three logical operators. Off to task two, which says complete the truth table. Let me first copy the table so we can always see what I have added so far.
03:32
Okay.
03:50
You know from the lecture that in the truth table, we always put the value which the expression in the top line evaluates to when the variables inside of the expression take the values which
04:08
are given in the first columns of the truth table. So in the cell I just highlighted, we have to put the value, the expression p and q evaluates
04:21
to if both p and q are true. So in this case, it's the value true. And the next two cells are the result of the end operator.
04:42
If one operand is true and one operand is false, we know that the end operator only evaluates to true if both of the operands are true. So both of the other cells are going to be false.
05:12
Now off to the or column. We know that the or operator evaluates to true if at least one of the operands is true.
05:21
So in the first three lines, rows of the table, one of the operands is true. Sometimes it's p, sometimes it's q. And so in the first three lines, the result will be true.
05:53
And in the last row, both p and q are false. So the or operator now evaluates to false.
06:12
In the next column, we have the expression not p, which is always exactly the opposite
06:21
of p. And p is true in the first two rows. So the result of not p is false then.
06:41
And in the last row, the value of p is false. So not p evaluates to the value true. Now for the last column. The Boolean expression on top may seem a little difficult to understand at first, but it's
07:04
actually quite simple. We can look at it in a hierarchical way. So on the uppermost hierarchy level, we have the not operator expressed by the two pipes.
07:22
And then to the left and right side of that, we have two expressions which involve the and operator. And in the first and expression, this one is going to be true if p is true and q is
07:46
false because it's negated and in no other case. And the second and expression is going to be true if p is false because it's negated and q is true, right?
08:02
Because if p is false, then not p is going to evaluate to true. And if q is true, then q just the expression q is also as the value true. So the entire expression in parentheses here is going to evaluate to true as well. And in all other cases, it's going to evaluate to false.
08:21
So we basically now have the results of these two expressions. And we know that the or expression is going to evaluate to true if either the left side or the right hand side or both are evaluating to true.
08:40
So if either p is true and q is false, or p is false and q is true, then the entire expression is going to evaluate to true. And in all other cases, it's going to evaluate to, to false.
09:01
So what we have, what we have here is essentially the logical way of saying p equals p not equals q. Right? So if p equals q, if both are false, or both are true, then the expression is going to evaluate to false. And if p does not equal true, then the expression is going to evaluate to true.
09:26
So and this is also known as the exclusive or in logic. Exclusive or also often said as x or. Okay. With that in mind, we can just immediately put the correct values on through the table.
09:43
So the first, in the first row of the table, both p and q are equal. So the result of the expression is false. And in the next two rows, the values of p and q are not equal.
10:07
So the result of the expression is true.
10:26
And in the last row of the table, p and q are again equal. So the result of the expression is again false. And with that, we're done with task two.
10:41
Task three is called translating logical expressions to FLs branches. And first, we define two variables A and B. To each of these, we assign a bool value. And then the task description says now the following two Julia code cells are semantically equivalent.
11:01
This means that they will print the same result in the same circumstances. So what this means is that this code I've highlighted just now, this code prints the same the same result as this code.
11:22
If the circumstances are the same, and by circumstances, we mean the the values which are assigned to A and B before this code is executed. So if A in this case is true, then this expression here, this expression not A will evaluate
11:47
to false, the opposite of A, and then this will be printed so the result will be false. And the second cell does exactly the same only with an if-else expression.
12:02
The if-else expression effectively implements the not operator. So if A is true, then the control flow will enter the first branch of the expression, sorry, of the of the code state snippet. And so line two here, and in line two, we just print false.
12:26
And then in this case, the the control flow will continue after the entire if-else expression. So there is nothing left there. So the code execution will just end at that point.
12:41
And if A is false, then the first part of the if-else branch will be skipped. And the control flow will immediately go to the second branch, which just prints true. So this way, we can see that if A is true, we print false, if A is false, we print true.
13:03
So it's exactly the same as the not operator up here. Yeah, now the task says use nested if-else branches to make the next code cell semantically equivalent to the code print line A and B. Okay, let's do that. Let's use nested if-else branches for that.
13:22
We can just start with if A. And now we know that in the case that A is true, so in the in the case we're implementing right now, in the case that A is true, the result of our entire and expression will now depend on B, right?
13:43
Because if B is now also true, then we have to print true because A because true and true evaluates to true. And if B is false, we have to print false because A sorry, true and false evaluates to false, right?
14:01
So we need another if branch here, which checks the value of B. And now in the third line, we have the case that A and B are both true. So we print the result of true and true, which is just true.
14:24
And now in this case, in the else case of the if statement, we are in the case where A is still true, but B is now false, right? Because the control flow will skip the first part of the branch if B is false and go here
14:40
where the cursor is currently. And this is why we can just print the result of true and false now, which is false. Now this is all the different cases we can have in the first part of the outer if branch.
15:05
And in the second part of the outer if branch, A is now false. And if A is false, the result of the expression A and B does not depend on B anymore.
15:21
It's completely irrelevant if whether B is true or false. Because A is already false. That's why the entire expression will also be false. So we can just print false here. And with that, we're done. And we have implemented a code cell equivalent to a print line A and B with just if else
15:45
branches. The next part of the task gives us this code cell which already contains if else branches and we should now provide a a cell that uses logical operators to make this code cell
16:04
right here equivalent to this if else branch. So let's see what happens here. If A is true, then no matter what B is, we print false. And if A is false, then we enter this part of the code.
16:24
And if B is true now, so this is the case where A is false and B is true, we print false. And if B is also false, so this is the case where A is false and B is also false, we print true.
16:41
This is essentially the opposite of a or statement, right? So in an or expression, if A is true, we would have true as the result. But in this case, we print false. And if A is false, if we take the expression A and B, then we would have print true as
17:08
the result of A or B. But in this case, we have exactly the opposite of that. In the remaining case where A is false and also B is false, we print true, which is again
17:22
the opposite of what we would get if we had A or B. And obviously with logic, the opposite is just a negation, which is why the answer to the question is to negate the or expression A or B.
17:47
And if you have trouble to follow what I just said, I would encourage you to write down a truth table of the entire thing. So start with a table which contains two columns, A and B, and then all the different combinations.
18:05
So A true and B false, A true and B true, A false and B false, and A false and B true. And then add more columns, which indicate parts of the if-else branch that is given.
18:30
And then you will find that this is the answer to the question because you will have a column which is exactly equivalent to the column you get for this expression here.
18:46
So the next part of the task gives us the XOR expression that we've seen earlier in the task which contained the truth table.
19:03
So it prints true if A is true and B is false. And it also prints true if A is false and B is true. And in all other cases, so if A and B are equal, then it prints false.
19:26
So we can again do this with nested if-else branches. So let's start with if A. And now in the case where A is true, the result of our evaluation
19:43
now depends on the value of B, right? So we add another if branch, if B. And now we are in the case where A is true and B is also true, so we print false. And in the case where A is true and B is false, which is the case in line six now, we just
20:07
print true. And with that, we're done with the first half of the outer if-else branch.
20:22
Sorry, I forgot the end keyword here. Hope I didn't forget that in the last tasks. No, looks good. Okay. And now for the second half of the outer if-else branch, we are in the case where A is false.
20:44
So now again, the result of the expression depends on the value of B. So we need another if-else branch for B. And in the case where B is true and also A is false, again, they are not equal. So the xor expression evaluates to true.
21:06
And in the case where B is false and A is also false, the exclusive or expression evaluates to false.
21:21
And with that, we're done with task three. Task four says, in your internship at an IT consulting company, you are asked to write Julia code for a simple parking meter. The parking meter accepts one coin and prints out a ticket indicating the time until which
21:43
the ticket is valid. A 50 cent coin buys 15 minutes of parking, a one euro coin buys 45 minutes and a two euro coin buys two hours. The part of the code you have to write is provided with three variables. The variable coin indicates the coin which was put into the machine, either the string
22:04
euro symbol 0.5, or the string euro symbol one or the string euro symbol two. And the hour variable contains the hour at which the coin was put in. Finally, the minute variable contains the minute at which the coin was put in.
22:21
Write Julia code which prints out the text that should be on the ticket. For example, for the values that are given in this cell, your code should print this message. Okay, and you may have noticed that this part of the message is actually quite simple to print because all we have to do is to print out the values of these variables basically
22:43
with some text in between. So let's get started. We just call the function print and the first thing we want to print is the value of the variable coin and the words entered at now the value of the variable hour and the value
23:03
of the variable minute full stop and then it says ticket valid until and this is where the more difficult part of the task begins because now we have to calculate this time. And to do this, we have to first calculate the number of minutes that are bought by the
23:27
coin that was put into the machine. And then we somehow have to add this to this time. Okay, let's get started by calculating the number of minutes bought by the coin.
23:41
We can do this by assigning different values to a variable that we can call minutes bought. Okay, so there are three cases. And the first case is the variable coin is equal to the string zero symbol 0.5.
24:01
And in this case, we want to assign 15 minutes to the variable minutes bought because this is the number of minutes bought by a 50 cent coin. And in the other case, where coin is equal to one euro, we want to assign the value 45
24:23
minutes. And in the last case, we know that the variable coin has the value euro symbol two. So we can just assign 120 minutes. Okay, now we have to add minutes bought to, to the time that is in the variables our minute.
24:49
And we can get start by just adding minute to minutes bought. This can be basically our first try for the end minute.
25:04
And the end minute is basically what we want to print here. So this should be this should be five. And right now, let's see what we get. Okay, we get the value 65.
25:23
No surprise, because 50 plus 15 is obviously 65. So this makes us notice that if the number of minutes is over the number of minutes in one hour, we have to adjust the value.
25:47
And we can do this by using this modulus operator, which is the percent simple in Julia and in many other programming languages as well. And if we just evaluate this expression 65, modulus 60, it gives us five, which is exactly
26:07
the value that should remain in the variable and minute. So we can just we can just calculate and minute modulus 60, and reassign this to the variable
26:27
and a minute. And then we get the value five here. Okay, now, another thing we have to compute is the end hour. So what this is, this is the hour that we have to print here.
26:42
And this should be zero in the end. And we can get started by just adding the number of hours that is in this sum to the variable our right because if there is if if the coin buys two hours, for example, we
27:04
want to add two to this variable our and then this is our end our Okay, how do we calculate how many hours are in this sum? To do this, we can use something that most of you probably learned in primary school,
27:20
which is division with a remainder. And we already use the modular operator, which gives us the remainder of the division, right, if we divide 65 by 60, the remainder is five. And to get the result of the division, instead of the remainder, we can use this operator
27:40
here in Julia, and this gives us one. So this is exactly the number of hours that we want to add to our variable our. So let's do this. We divide this by 60 and add it to the variable our.
28:03
Let's see what our output currently looks like. Okay, so it says the ticket is valid until 24, colon five, which is sort of true, but
28:23
not quite how we expect to read a time. So obviously, if this number here, the end our the value of the end our variable is larger than 23. We have to subtract 24 from it to to make it zero again to make it start again from
28:45
from zero. So we can just use another if else statement for that. So if an hour is greater than 23, and our minus equals to 24.
29:03
And that's it. Okay, and this gives us 05. So that's exactly the values that we want to print. But the thing we're missing now is the leading zeros. And to add the leading zeros, we can create string variables, which we can call and our
29:27
prefix maybe, because we prefix it to the hour and minute prefix because we prefix that to the minute. And we have to assign to these variables before we can use them in the string.
29:43
And in the most simple case, we just we just print the empty string, right, printing, printing, printing the empty string changes nothing. And now we have to think about the cases in which we want to add a leading zero. And that is when there's only one digit.
30:03
And the numbers that have only one digit are the numbers which are smaller than 10. So we can use an if else statement to check for that if the end hour is less than 10. We give an hour prefix of zero.
30:23
And in the other case, we use an empty hour prefix, the same for the minute, if the end minute is less than 10, we use a minute prefix of the string zero.
30:42
And in the else case, we just use this empty minute prefix. And with that, we are done, we have exactly the output that was given as an example. Now let's see if it also works with different values for the variables.
31:01
What if we enter a two hour coin instead, then the output is the ticket is valid until 150. Okay, that seems to work pretty well. Let's try with a different time maybe. Okay, one Euro entered at 8.30, ticket valid until 09.15.
31:30
Okay, that looks pretty good. So yeah, we can also notice that in this, in this time that we print here, we also missed
31:46
the, missed the leading zeros. So we can, we can do this, this minute prefix and hour prefix thing, we can do this again for the first part of the output.
32:03
So now we just use the variables hour and minute, oops, and we use, we can just use these variables again. Okay, let's see what this gives us.
32:33
Okay, yes, now we have the leading zero also here. And if we change this to this, for example, then it should also look good.
32:44
Yep, ticket valid until 08.48. We have the leading zeros. That looks very fine. Okay, with that, we're done with task four. Task five asks us to translate between for loops and while loops. And the task starts with an example with a simple for loop that just prints the numbers
33:05
from one to 10, and then a slightly less simple while loop that does exactly the same. Okay, now we are asked to provide a while loop such that this code cell which I've just
33:22
selected is equal semantically equivalent to the code that's provided here. So let's first look at the code. It creates a variable called countdown to which it assigns the value 10. And then while countdown is larger or equal than one, it prints the current value of countdown
33:47
and then it subtracts one from countdown. So this will, as the variable already says, print the number 10 first and then count down basically to two down until countdown is not larger or equal than one anymore.
34:06
So basically, it will count down to zero, and it will print the numbers in between. So we can do this with a for loop. Yeah, and in the for loop header, we always have to create a variable basically, let's
34:26
call it countdown to be consistent with the while loop, but for semantically equivalence, the name of the variable does not matter. So it could be anything. And then the for loop header continues always with the in keyword.
34:42
And then comes the iterable sequence, right. And now we want an iterable sequence that starts at 10 and goes down to one because this is all the numbers we want to print. And we can, we can do this with a range expression just by typing 10, then the colon, which creates
35:10
the range expression. Then we type minus one, which is the step in the range expression, and then the last value of the range expression one, okay.
35:25
And the for loop ends with the end keyword. And in the body of the for loop, we now put the print line of the call to the print line function. And as the as the argument to the print line function, we provide the variable countdown.
35:42
Let's see what this gives us. And there we go. It prints the numbers 10 down to one just as we wanted. And the second part of the task gives us this example here. In Robert McCloskey's book make way for ducklings, the names of the ducklings are not going to
36:05
read all of those. The following program traverses the string JKLM NOPQ to create the names and display each one in a new line. Okay, that's, that's that it creates all the names.
36:22
And now we should do the same thing, but using a while loop, okay. With a while loop, we always need the keyword while right, then a condition.
36:43
And then we need the end keyword. And in the body of our while loop, that we know so much, we have to print and when the body we have to print, basically the suffix prefixed with prefix and or letter, let's
37:11
call it letter, as we do in the for loop. And we should hand this as an argument to the print length function, right.
37:21
Okay. And now we have to think about how we obtain the value of the variable letter. And the first iteration of our while loop, the letter should be equal to J, then to K, then to L, then to M, and so on.
37:41
And we can do this with a, with an indexing variable, right, if we, if we index into the string prefixes with one, then this will give us this will give us the letter J.
38:03
If we index with two, it will give us the letter K, if we index with three, it will give us the letter L, and so on. So this index should be one in the first iteration, two in the next iteration, and so on. Up until the last index, which is the length of the of the string prefixes.
38:30
And so we have to we have to initialize the index variable with one because that's the first index we want. And then in our loop body, we can now define the variable letter, which is the just the
38:50
the bracket operator called on prefixes with the value of the variable index. And then it will print it will print the name of the of the duckling that we want.
39:05
And we also have to increment the index, which is nothing else, but we have to add one to the index because in the first iteration, we want one right to get jack, then the second iteration, we want to to get keg and so on.
39:25
And yeah, the only thing now we have to we still have to do is to complete the condition. And for the condition, we have to we have to basically stop after all the names of the
39:42
ducklings have been printed. So we could basically just check if if the last time that has been printed is quack, and then we would we would be done. But that would be a little complicated, much easier is to just check if the index variable is equal to the last to the last element of a sorry to the last index that exists into
40:08
the string prefixes. And this is the same as saying that index. What I just said is that index should be the last element, and this would be the same as
40:22
index equals the length of the string, but we are in a while loop. So we, we basically have to invert this. So while the index is smaller than the last existing index, we want the while loop to continue right.
40:41
And let's see with what this does. Okay, it creates all of the names, but it stops before the last name. And we can fix this, I believe if we put less than or equal here instead of less than.
41:03
Let's try this. Yes, it works. Perfect. All the names are being printed. And we're done with this task. Task six is about the equivalence between for loops and while loops. And the question the task asks is, are for loops and while loops semantically equivalent?
41:26
In other words, can every for loop be converted into a semantically equivalent while loop and vice versa? If your answer is yes, justify your answer. If your answer is no, give a counter example.
41:41
Okay. The answer is yes. For loops and while loops are equivalent. And to to justify this, we basically have to think about the both of the cases separately, right? So we have to first justify why for loops are equivalent to while loops.
42:03
And then we can justify why while loops are also equivalent to for loops. Please just keep in mind that this is not the same. If for loops could be equivalent to while loops, and not vice versa, and this would
42:20
just be an implication and the implication is not the same as a by implication. The by implication is what the task asks. So that for loops are equivalent to while loops and while loops equivalent to for loops. Yes. So let's create a code cell to start the demonstration.
42:52
So every for loop has the following has the following structure. We have the keyword for then some variable name, the keyword in then an interval sequence.
43:12
And then we have some body and then the end keyword. And in the body, we can use the variable name, right this this variable which is called name.
43:29
We can use this in the body. So we can essentially say that body can be any function which receives name as its as its argument.
43:42
And sequence sequence could also basically be a function which we call once and it gives us back the iterable sequence. In practice this this could be a function that returns a string or also in place of the function call we could we could just have the string but it's the same.
44:01
So let's just say we have here some expression that returns the iterable sequence, express this as the function call to the function sequence. Then we have here the body which we express as the function body and to which we supply the argument name. Okay, and now let's think about how we can provide an equivalent while loop.
44:27
And it's actually quite simple. So the first thing that happens when the for loop is evaluated by Julia, or rather executed by Julia, I should say, is the call to the function sequence.
44:46
And this is basically like creating a variable to which we assign the value of the return value of the function sequence. And after that, Julia goes through every element in the sequence and supplies it to the function
45:05
body in order. And we can do this with a while loop. And we do it like we did in task five with the with the duckling names.
45:20
We can create an index variable, which we can call one. And then we iterate until index is until index is larger than the last index of the sequence. So we iterate while index is smaller than or equal to the length of the sequence not
45:44
to index sorry, to the sequence. And in every iteration of the while loop, we now execute the body function to which we provide the argument name and name is nothing else than the the index element of
46:07
the sequence. So yeah, like this, right, if sequence is a string, it would be the character at the
46:23
position. And if sorry, if sequence is a string, it would be the character at the position. If sequence is an array, it would be the element at the position. And if sequence is a range, it would be the number at this position. Okay, and now we just put the end keyword.
46:40
And with that, we're done. So this these two are really semantically equivalent. You can try it with every with any sequence and anybody. And these two loops will will do the same. So I think this serves as justification for the first part of the question. Can every for loop be converted into a semantically equivalent while loop?
47:04
This is how you would do it. And now for the second part of the question, can every while loop be converted into a semantically equivalent for loop. And here we have to use a little trick. But let's first let's first look at the the generic structure of a while loop.
47:25
So a while loop starts with the keyword while, then it has some condition, which is basically like a function and every in every iteration the function is called and if it returns true,
47:41
then the while loop is entered and if it returns false, then the while loop is skipped. And inside of the while loop, we again have some body. Yeah that's it. That's the generic form of a while loop. So now we have to think about how we can how we can express this using a for loop.
48:05
And with the for loop, we have kind of a problem because the for loop doesn't iterate using a sequence. Sorry, it doesn't iterate using a condition instead iterates using a sequence, right?
48:23
So how can we have it that the for loop continues as long as the function condition returns condition returns true and stops when the function condition returns false? Well, what we can do is we can create a sequence which has one element in the case where condition
48:53
returns where condition returns true when it's first called, and which contains no elements
49:03
in the case where condition returns false when it's first called. So this way we can we can do the first iteration of the while loop, right? So we can say if condition, we put an array that has some sorry, a vector that has some
49:25
elements. And in the other case, where condition returns false, we put an empty sequence. So this is already this is already equivalent to the first iteration of the while loop,
49:43
right? So the first iteration of the while loop, we call the condition if it's true, we enter and execute the body. If it's false, we skip. So this is exactly the same. If condition returns true, our sequence is an element, which means that the follow will be entered and the function body will be called.
50:02
And if condition returns false, then the sequence would have no elements. And this means that the loop will not be entered, not be entered, and the function body will not be called. But obviously, our while loop here can have more than can have more than one iteration.
50:24
And one way to to realize this in the follow is to append elements to the sequence as long as the function condition keeps returning true. So we have another if statement if branch in the in the loop.
50:42
And if condition returns true, we want to append something to the sequence, we can do this by calling the push function. So we push one into the sequence. That's it, condition returns false, we just do nothing. And now, we have implemented a for loop, which is semantically equivalent to a while loop
51:07
with the help of some if and else branches. And with the help of a sequence, which doesn't exist in the while loop, but yes, it's equivalent. It does basically the same.
51:22
Right, so we can conclude that there is a way to convert a for loop into a semantically equivalent while loop. There's also a way to convert a while loop into a semantically equivalent for loop. So we can answer the question in the task. And our answer is yes.
51:42
But obviously, this isn't really this isn't really useful in our everyday life. It's nice to know that we can do this. But when we solve actual programming problems, we shouldn't think about this too much. We should just choose the loop for a while loop, which suits our problem, and which helps
52:08
us to express the code in the most concise way. Task seven asks us to write some Julia code that implements the Sieve of Eratosthenes
52:24
algorithm and uses it to find all the prime numbers that are smaller than the variable the value of the variable n. And as an example value, 100 is given here.
52:43
And the the task description says that we should start our implementation by creating a vector of bool values one for every number between one and n. Okay, let's let's just do it.
53:02
And I will call our our vector of bool values, I will call this marks. Because the the description of the algorithm speaks of marks. And let's just begin by making marks an empty vector.
53:21
Now we can use a loop to iterate over all the numbers between one and n, which we express using this range expression. And for all of these, we push something into our vector marks. And the task description says at first every element of the vector is true.
53:45
So we just push the value true into it. Let's see what this gives us. It gives us an 100 element vector, which is just a bunch of true Boolean values.
54:02
And the task description says after that use a loop to go through all numbers between two and n. All right, simple. We just use a for loop, which goes to the numbers between two and n. That's it.
54:20
This is our loop. We can we can look at what it does by just putting a println statement and yeah, it just prints all the numbers starting from two up until 100. All right. And now the the description and the task goes on and says inside use another loop for marking
54:46
numbers in step three. So this is step three of the algorithm. To mark a number as not prime, change its entry in your vector to false. All right.
55:02
Step three in the algorithm is that we should mark as not prime all numbers that are an integer multiple of the current number and the current number. The current number is is i in this case, right?
55:23
Sorry, i in this case. Yeah, and now let's let's use a loop to do to do this. And the loop should go through all numbers that are integer multiple of the current number.
55:42
And we can actually express this with another range, the range would start at the first integer multiple. The first integer multiple of any number is obviously two times the number. So that would be e i times two. And the range then increments with i and it and it ends at the last of all numbers that
56:15
we can mark. So this would be n then.
56:21
Inside of the loop, we should mark as not prime the number and the task description says that to mark a number as not prime, we should change its entry in our vector to false. So this just means that we change the entry of j here in our vector, we change this to
56:42
false. Alright, and this is done. But we haven't, we haven't implemented the entire algorithm yet, because what wasn't described here is steps one and two of the algorithm.
57:01
And step one of the algorithm is to skip the current number if it has already been marked as not prime. And we can skip the number by wrapping the entire body of the loop with an if branch
57:21
if branch like like this, I will indent the lines to make it more clear. And this should be skipped now this this these three lines should be skipped. If the current number has already been marked as not prime, and we mark a number as not
57:42
prime by changing its entry in our vector to false. So this this should only be executed if marks at the element i is true, right? Because if marks at the element i is false, then we should skip it. So this is exactly what we expressed with this if branch.
58:05
And then the second step of the algorithm is the current number is a prime, print it out. Okay. And we can do this by just calling print line of i. And now it should print all the prime numbers.
58:21
Let's see if it works. Yes. And if I'm not mistaken, this is all the prime numbers that are smaller than 100. And we could also increase n to be larger than 100. And it would give even more prime numbers. So yes, that's, that's task seven done.
58:43
In task eight, we will now implement the gradient descent algorithm. And gradient descent is an algorithm which can find a minimum local minimum of a differentiable function. And the task description says the algorithm is widely used in industry and research.
59:04
And in fact, gradient descent is the algorithm that is currently used in a very important branch of artificial intelligence. The branch is called deep learning. And in deep learning, we use gradient descent to train our artificial neural networks.
59:21
And these artificial neural networks can then be used to detect the content of an image, for example. So yeah, truly a very important algorithm here, gradient descent, but obviously, it's a little complicated to optimize or minimize a artificial neural network, which is why
59:44
we start with this simple function, x to the power four plus x to the power of two minus five x and has a global minimum at at around 0.924. But this global minimum is exactly what we
01:00:00
what we want to find now by implementing gradient descent. Okay, and how does the algorithm work? Well, you can have a look at this figure and it shows our function f. This is shown in blue and the figure shows three different tangents of the
01:00:23
function. So the first tangent is at minus five here. And what the algorithm basically does is, it basically looks at the tangent of the current best guess of the local minimum of the function and then it minimizes
01:00:49
the tangent, not the function, it minimizes the tangent in a small interval around the current best guess. And the minimum of this tangent is then
01:01:01
chosen as the next best guess of the function's minimum. And this is done iteratively in a loop until the tangent is perpendicular to the x-axis, which is the same as to say the gradient at the point at the position is zero. And then we found the minimum. Alright, so if we start here, the algorithm will basically
01:01:25
go down the tangent to somewhere around here and will it will again go down the tangent to somewhere around here, down the tangent, down the tangent, down the tangent, and so on all the way until we have found the minimum. Okay. And the
01:01:42
description of the algorithm is a little bit more precise given in the task, I will not read this right now, you can read it at home. And the first part of the of the work we have to do is to implement FSE Julia function. And we can actually just, we can just copy and paste it from the from the markdown code
01:02:07
because markdown syntax and Julia syntax are, in this case, incidentally, the same. And voila, we have implemented a Julia function. Now, we can do almost the
01:02:23
same for the functions derivative. But we can't name a Julia function f prime and the mathematical notation. Sorry, f prime. So we have to choose another name for our function. Let's just use f prime written in text. Okay, the first two
01:02:48
parts are done now. And now we have to implement the stopping criterion of the algorithm. I just said that the idea behind the stopping criteria is to is to stop when the derivative at the current best guess becomes zero. But as as every
01:03:09
numeric algorithm gradient descent is always somewhat imprecise. So if we just type f prime at x star equals equals zero, then it won't work because there
01:03:21
will be some inaccuracy in the calculations. So this is why we use this tolerance value. And the task says, your function that we define now should be called should stop. So let's just start with that should stop. To define a
01:03:41
function, we always use these parentheses, right, which act as delimiters for our argument list, and the function should have two parameters x star and tolerance. And a call to the function should evaluate to true if the
01:04:03
absolute value of f prime of x star is smaller than tolerance, otherwise false. Okay, we can just express this using the numerical comparison operator small less than. So the absolute value, we can calculate this using the function apps,
01:04:22
then we call our function f prime. And we put in the x star. And now if this is smaller than tolerance, so just less than tolerance, then the entire expression will evaluate to true. So the function will also evaluate to true. And if it's
01:04:47
larger or equal, then it will evaluate to false. So the function should stop will also evaluate to false. Okay, so this is the stopping criterion done. Now we define variables for the constant values in the algorithm. Nothing more simple
01:05:04
than that. Alpha 0.001, the tolerance 0.0001. And the maximum number of iterations 10,000. So maximum iterations equals 10,000. Okay, so these
01:05:29
values, they are also often called hyper parameters. And you can also choose different hyper parameters. And you in fact, if you change f, you would have to
01:05:41
choose different hyper parameters probably, because with gradient descent, it's very often necessary to tune these hyper parameters to the function you want to minimize. But the hyper parameters that are given in the task description, they are appropriate already for the function that's also given in the task
01:06:00
description. Okay, and now the the main part of implementing the algorithm is to first define variables for the two non constant values of the algorithm x star. And we should choose a minus five as our initial guess here. And the next
01:06:25
non constant value is the iteration counter. So let's let's call this current iteration. And then we use a while loop to implement the three steps of the algorithm as described above. So while then some condition and then
01:06:47
somebody and then the keyword end. And the condition is now just our stopping criterion or the maximum number of iterations. So this is just a completely
01:07:01
given in the task description. Step one, check if the stopping criterion is met, or the maximum number of iterations is reached. If so, the algorithm is done. And if the algorithm is done, we skip our while loop. So we just check if the stopping criterion is met, which we can do by calling the function shows
01:07:24
stop, we have to negate the we have to negate the functions result because the while loop should continue as long as we should not stop, which is why we negate the result. And to shut stuff, we provide the current best guess right x star, and
01:07:46
then our constant tolerance value. So this is this is our way to check if the stopping criterion is met. And then the task description also says, check if the maximum number of iterations is reached. So this means that we, we compare, we
01:08:08
compare the current iteration to the maximum iteration. And as long as the current iteration is smaller than the maximum iterations, we want to continue
01:08:26
with the execution of the algorithm. And we will stop if the stopping criterion is met, or the maximum number of iterations is exceeded. And stopping if either of
01:08:44
those is, is true means that we should continue while both of these are false, right. So we put the operator and here, which, which will make the while loop
01:09:01
continue while should stop returns false. And current duration is smaller than maximum iterations. Okay, now for the other steps of the algorithm. First step is to replace x star with this term here. So replacing x star is just assigning a
01:09:24
new value to it. So like this, and we will replace it with x star minus alpha times f prime of x star. So x star minus alpha times f prime of x star. All
01:09:57
right, this is this is the step two of the algorithm. And step three is to
01:10:03
update the counter for the number of iterations and go back to step one. So we just update the counter. The counter is here called current iteration. We just add one to that because we now enter the new iteration. And then it's back to step one. And this just means that we are now at the end of the body
01:10:24
of our while loop. So the iteration is so the execution continues at the head of the while loop by again, checking the condition which is step one in the description of the algorithm. Alright, so with that we have now used a while loop
01:10:42
to implement the three steps of the algorithm as described above. Then the task description says furthermore include a call to print line in the loops body which prints a message that indicates the current iteration and the current value of x star. Okay, let's do this. Let's include a print line call.
01:11:05
And we can just say current iteration and x star. Now we have we have that
01:11:24
done. And after the algorithm has terminated print the minimum that has been found. So another call to print line which says minimum found x equals
01:11:43
both x equals x star. And then the minimum is at the is at the position f of x star, right? So this is also done. And then the task description says check
01:12:11
if your implementations result is correct by comparing it to the given minimum. Okay, so let's execute this now. Hope it works. Right. Let's see. Let's
01:12:22
see what it does. So we have now many lines of output. And we can see that the algorithm has run for 1254 iterations. And that in the last iteration, x star
01:12:46
was 0.9237 approximately. And 0.9237 we can now compare this to the to the minimum that was given, which was given at 0.924. And yeah, this is this is
01:13:06
approximately the same. So we have apparently implemented the algorithm correctly. With that, we're done with the gradient descent task. Task nine is
01:13:20
called fundraising and says, suppose you come up with a new product idea, and would like to start your own business as a student, you need some investors to financially support your project. When you share your ambitions with your colleagues and friends, some of them are ready to invest, you write down potential investors and their investment in the following table. And
01:13:42
the column your preference indicates how much you like the respective investor with six being the highest preference and one being the lowest preference. All right, and the first task is to represent the table in the form of three Julia vectors, one vector of strings and two vectors of numbers. Okay, so our first vector should be maybe should be called investor and
01:14:08
should contain all the strings now, right? So all the all the names of the investors. So first is Unis startup fund. Then we have the entrepreneur club,
01:14:25
and then the sports club. Continuing with the call, sorry, colleagues from work. After that our rich grandma and a random neighbor. Okay, so this
01:14:55
is the this is the first column, which we just represented. And then the next
01:15:01
column we can represent now as a vector of numbers. So this would be potential investment. Let's keep it short and just say investment here. First line is 11,000. Then we have 4000. Zero again, zero and 10,000. And then 2500. And the
01:15:27
last column preference is again just a vector of numbers. 265341. Okay, I made a typo. 341. Okay, but that should, that should do it. Yeah, we have represented
01:15:46
the table in the form of three Julia does. All right. Now, how much money have you raised so far in total? Write Julia code to find the answer. So this is actually quite simple. We only have to iterate over this vector, vector
01:16:02
investment and add all the amounts. So yeah, let's do it in the for loop. For I in investment, we add the amount to something, maybe we can create a
01:16:21
variable called total first, which we initialize with a zero, right? Zero is the, it's the neutral element of addition. So yeah, the the, if we would have no element in our in our sequence investment, then the sum of the empty sequence should be the sum of an empty sequence should be zero, right? So that's
01:16:46
this is how we would initialize our variable. And then in every iteration of the loop, we add I to the to the total. And then at the end, we should print the
01:17:03
result, which is 27,500, which we have raised so far in total. All right, next task. Now you want to decide which investments you should accept. You want to avoid to talk to those investors again, who said they would not invest
01:17:23
any money. Using Julia create copies of your three arrays. Yeah, this should be vectors, three vectors, which do not include those entries for which the column investments contains a zero. While you create the filtered vectors,
01:17:47
print each row in the filtered table. For example, the first line of your output should be investor equals only startup fund investment equals 11,000. And preference equals two. All right. Let's get started. We should create
01:18:04
copies of your of our three vectors. So let's just let's just copy and paste them down here to make the copies. And we, we can start our copied vectors,
01:18:27
we can again start them with being initialized as the empty vector. And because we we want to copy them, not replace them, we should give the
01:18:41
variables different names. And let's go with with filtered investor filtered is just all the investors that invest more than zero euros. Investment filtered is all the investments that are larger than zero. And preferences the preferences of
01:19:01
those investments. So how much we prefer them. All right. Now we have to, to use some loop to, to iterate over our table here, right. So the first iteration of the loop, we want to look at the first row, second iteration of the loop, we
01:19:22
want to look at the second row, and so on. And in every iteration, we want to check now is the investment in the in the current row is this zero. In this case, we want to discard the row. And if the if the investment is larger than
01:19:42
zero, we want to keep the row. Okay, so let's use a loop to iterate over every index in our table. And we can do this with a range. And the range will
01:20:02
obviously start at one because that's the first index and the last index would be the length of our table. And to determine this, we could use the length of any of these arrays, I would just go with the first one. Length of in oops, we length length of investor here. Okay. Let's, let's see if this works. Let's
01:20:28
just print out. Let's just print out every row to just to see if it works. So the first item would be investor i, then we would have investment i. And then we
01:20:47
would have preference i. And now this should just, this should just print the table. Yeah, it's not very pretty. But it works. Yes, it prints all the six, all
01:21:02
the six rows of the table. Okay, perfect. But we don't just want to print them, we want to filter them first, right? We only want to keep those who have invested more than zero euros or which which is to say that they want to invest anything
01:21:22
at all. So we can do this with an if branch. If investment at the index i is larger than zero, this is the only case we will do something. And this effectively means that we discard all the investments which are zero. Let's
01:21:47
try again. And yeah, we can see that the two investments which are zero, so sports club and colleagues from work do not appear in the output anymore. So they have effectively been filtered out. But the tasks description was to create the
01:22:03
copies of the arrays which are filtered. So it's not sufficient to just print the result, we also have to, we also have to put it into the copied arrays. So let's do that. We use three push statements. In the first we push into investment
01:22:27
filtered. Second, we push into investment filter. And the third we push into preference filter. Okay, and obviously we push the current investor to the first
01:22:44
array, the current investment into the array of investments and the current preference into the array of preferences. All right, let's also make
01:23:07
the output confirm to the format that was given in the task description. So this would be investor equals this, investment equals
01:23:24
this and preference equals this. Yeah, I am I'm missing a quotation mark here and
01:23:45
now a parenthesis but this should do it. Very nice. And with that we have completed the second part of task nine. And now for the last part it it says you
01:24:06
know that you need no more than 25,000 euros at the beginning. You want to keep the number of investors minimal as long as you reach that threshold. At the same
01:24:23
time you want to accept investments which you prefer the most first. Which investments should you accept? Write Julia code to find the answer. Print the group of investors one per line and the sum of their investments in the last
01:24:41
line. And then it also gives us a hint. You can use the function sortPerm which links to the official Julia documentation here. You can use the function sortPerm and an array and and array slicing to sort one array according to the items of another array. Again this should all be vector here
01:25:03
but you know that that a vector is just a special case just a special case of an array in Julia so you you should get used to us saying vector in place of
01:25:23
array because really a vector is an array but not the other way around. Okay and let's let's see what happens here. So we have this vector called keys three one two and we have this vector called strings sorry this vector of strings
01:25:43
called values which contains the values B C and A. And now we we do this here we first we call the function sortPerm by providing keys as the argument and then we we slice the vector values with the result of this function call here. And
01:26:07
this gives us the vector values sorted according to the keys in the in the vector keys. So we can see that when we sort keys the result would obviously be
01:26:22
one two three. And the result of the third line is now that the first element of of the result is the element which is at the position in values where the smallest element of keys is. This is why C is now at in the front because the one
01:26:48
is at the second place in keys so the item that is in the second place in keys goes to the first place in the result. And now the two is in this in the third
01:27:01
place in keys so the item which is in the third place in values takes the second place in the result and which is why A is in the second place and so on. Okay and now the key insight for this task is that we can use this this pattern to sort our table according to the preferences. And let's see what
01:27:26
happens if we do. So let's create a sortPerm according to our preferences. This preference is not defined but let me find it on our called it preference.
01:27:49
Okay yeah okay this is our sortPerm and now let's sort our three vectors according to this sortPerm. So the first vector was called investor filtered,
01:28:07
then investment filtered, then preference filtered. Okay yeah we don't we can't filter we can't sort by preference we have to sort by preference filtered of course. And let's let's call these investors sorted now and also
01:28:31
investment sorted and preference sorted and to obtain them we just take investor
01:28:45
filtered and we sort it according to the sortPermutation which then sorts it according to the preferences. All right the same with the investments and also
01:29:06
with the preferences. Let's see what this looks like. So we see that the first
01:29:21
element is now the random neighbor. The random neighbor was the item with the largest sorry with the smallest preference in the table and the second item is uni startup fund which has the preference two in the table and so on. All until the up until the Entrepreneur Club which had the largest preference in
01:29:46
our input table. All right so what we want to do is to accept investments with the highest preference first and then going to the lower preferences but we
01:30:02
will stop as soon as we have 25,000 euros of investments. So let's let's create a variable we call funds and we and we use this variable to keep track of the investments we have accepted. And we can now use a loop to accept
01:30:28
investments and every iteration of the loop we will accept one investment right and we will continue doing this as long as we have accepted less than 25,000
01:30:42
euros. So we can express this by typing funds is less than 25,000 and in the body of the loop we now have to invent to accept an investment and we don't want to accept any investment no we don't want to accept the best available
01:31:03
investment right the best available best okay and the best available
01:31:20
investment is the the last investment sorry it's the investment with the highest preference which we have not yet accepted so we also need to keep track of the investments we have accepted so far so we could do this by
01:31:46
creating a variable we can call current investment and at first we want to accept the investment with the highest preference this comes last in our sorted
01:32:00
vector of investors so we will start with the length of this vector as our first index and accepting an investment just means that we add is that we added
01:32:24
to our funds right so in the in the list investment sorted we would choose the the item at the current index and then we have to decrease the index you
01:32:53
could also do this with a for loop by the way let's see what the task description also says which investment should you accept right Julia code to
01:33:01
find the answer print the group of investors will not one per line at the sum of the investments in the last line okay so what we also have to do is to print the investor we accepting an investment from so let's just print accepting invest man from and then our investor so this would be investor
01:33:25
sorted at the current index okay and II if I wrote print itself print line should be print line of course accepting investment from entrepreneur club rich
01:33:44
grandma uni startup fund this looks about right what we forgot is to print the sum of the investments in the last line so let's do that accepted investments of in total so yeah we've now accepted 25,000 euros which is
01:34:12
what we wanted to do and what we ended up not using was this array so we can just delete that and yes with that we're done with task 9 as always if any
01:34:29
questions remain about the tasks in this exercise then please ask us on moodle or write us an email and in any case see you next time and have a nice day
Recommendations
Series of 22 media