 So, we will start the video lecture recap quiz, so consider the declaration int my encode int a int b which of the following are true, so there are 4 options, please go through the options carefully and indicate all that are correct, there could be more than one correct answers. Once again the same declaration int my encode int a int b, there are 4 options, read them carefully and indicate all that are correct, there could be more than one correct options. Keeping track of the flow of control in a program with functions can be best done using which of the following access mechanisms, which of the following is stored in the called stack of a running program, could be more than one correct options, which of the following are true about activation records, indicate all correct options, which of the following are true about call by value parameter passing. So, that is the end of the quiz, so let us quickly go through a recap of the next 3 video lectures based on which the quiz that you just gave was formulated, so these are about function calls and parameter passing, we will look at recursive functions on Friday, so we just covered 3 lectures in today's class, so these are some slides already from the video lectures shown here again, so that you know the ideas are fresh in your minds, so this is an overall program structure which uses functions, so there are 2 functions here, my encode and power, if a program has functions then you have to declare the functions and then you have also got to define the functions and for each function declaration, for each function definition it is good to give preconditions and post conditions, these are all covered in the video lectures nothing new that I am talking about and you could have main function calling my encode, for those who have seen video lectures they should ring a bell, we had a main function calling my encode and then my encode was calling power, so you could have a function calling another function which in turn is calling another function, so you know one of the things that I want to sort of emphasize here is that if you go back to our Dumbo model of computing, so when a function calls another function it is like Dumbo moving from one room to another room and when we say my encode is called from the function main, Dumbo was working in the main room and then Dumbo is being asked to move to the room called my encode and do whatever operations it has to do over there and after it finishes doing the operations there it has to come back to the main room and resume operations that it has there, so it is like you can think of the analogy as in the Dumbo model Dumbo is moving from one room to another room and in each room there is some computational task for Dumbo to perform, after it finishes the task it has to come back to wherever it came from and resume whatever it was doing, so the contract view of functions basically says that in order to use a function you need not exactly know what is inside the function as long as you know the preconditions and post conditions, so the preconditions are what the function expects you to respect before you invoke the function and the post condition is what the function will guarantee if you did respect the precondition before invoking the function, so really when I am trying to call a function I could ensure that the precondition is true before the invocation and what I will be guaranteed is that the post condition is true after the invocation assuming that the function is written correctly but all this is trying to say is that you need not know what is there inside a function if the function has been written correctly you need not know the details of how the function does a computation if you know what the function is doing and what it expects you to respect before you call a function, so it is like a contract between the calling function and the caller function, the caller function says you respect the precondition I will guarantee you the post condition, the calling function as long as it respects the precondition it does not need to know how the caller function is doing what it is doing it can get back results which satisfy the post condition, so this is actually very important when you are trying to develop large programs in this course later in the course you will be doing group projects, so several of you will be working together in a group you may have written a function which your friend might be using, so even if your friend does not understand exactly what goes on inside the function as long as you have implemented it correctly presented proper preconditions post conditions your friend can still use it all your friend needs to do is to respect the precondition before invoking your function and the guarantee that it gets is the post condition, so of course the responsibility is on you the writer of the function to ensure that the post condition is respected when the precondition is satisfied, but once that is done you can forget about what is there inside the function when you are using it, so this is the contract view of functions just again from the lecture slides and here is a little animation about the flow of control, so all of you must have seen it there is our running person over there and when it comes to a function call it needs to basically go to the appropriate function like Dumbo moving from one room to another room, but then it must remember something where it has to come back, so that's this little bookkeeping information and I have sort of put that here to keep track of the fact that that person must come back here and now he goes to this different room and then he starts running over there and encounters another function and once again this is asking the person to come to this room which is for calculating power, but then we have to remember where to come back, so that is some bookkeeping information and then once again starts running here and when I have to return from here that bookkeeping information tells me where to return, so I return back from this room to that room at exactly the place where I left, the bookkeeping information told us where to come back and then once again I call the function again, again I store this bookkeeping information where to come back to, go to the room for calculating power, finish that calculation and that bookkeeping information tells me where I should come back to and then continue from there and finally when I have to return from here then I have to come back from this room to this room because that is how I went from here to here and this tells me where I should come back to, so I can come back there and resume my execution and that's how the function goes. So activation records and call stack, so basically when a function calls another function and activation record for this function is created, so going back to our Dumbo model of computation and activation record is like the infrastructure needed for Dumbo to do some calculations, so it needs some chest of drawers, it needs some you know maybe some other benches, work benches or something, so when Dumbo goes from one room to the other room, when you make a function call and Dumbo goes from one room to the other room, once it reaches the other room it must lock up the door to the first room and it must do its calculations entirely in the second room that it reached, but in order to do its calculations there it needs some infrastructure there, it needs a chest of drawers there, it also needs to know that when it has finished its calculations which previous room it should come back to and once it comes back to this previous room where should it start continuing its execution and so on, so all of this infrastructure that Dumbo needs to carry on with its computation in the second room, you can think of that as the activation record, so an activation record is basically all that the computer would need to carry on its computation inside a particular function, so whenever a function is called which is like whenever Dumbo goes from one room to the other, we make available this infrastructure, we create a fresh activation record, inside the activation record what do we have? Remember Dumbo went from one room to the other room and the door to the first room is now locked, so if it wants to do any calculations there it cannot access the drawers in the first room, so if it wants to do some calculation it has to carry those values along with it in a bag or trolley whatever from the first room to the other room, store it in the drawers in the second room and then start its calculations there, so that is basically copying of function parameter values from the collies activation record, from the collars activation record to the collies activation record, so Dumbo is carrying the values with which it is supposed to do computation from the first room to the second room and then of course the program counter must be saved, so when Dumbo is going from one room to the other room it must remember which room it should come back to and in that room what is the last thing that it did so that it can once it comes back it can resume execution from after that, so that is the program counter and then there is some other bookkeeping information as you can understand when I am going from one room to the other room and I am required to come back to that room and resume execution exactly at the same place where I left, it is good if I remember some things as I am going from one to the other one room to the other room and then this is the activation record is pushed onto the stack, why do we push this in a stack, why do we use a stack because when I return from a room when I am done with the computation in a room when I return from a function I must know what is the last room I came from and I need to go back there, so basically I need to remember who was the last one that made a function call which is the last room I came from, so I need to store things one on top of the others as the last thing is accessed first and then the next thing is accessed and so on, so this is the last and first out access mechanism which is provided by the call stack, so this is the business of activation records, it's basically the infrastructure needed by Dumbo once it goes from one room to another room to do certain computation there and what happens when it returns it's like Dumbo is returning back from that room to the previous room so it must now free up everything that it used in that room it must remove all the labels of the drawers and everything and say that now I don't need that anymore, so basically that entire infrastructure which is the activation record is popped out from the stack and now it is coming back from one room to the previous room, so if there is a result that was computed there which you want to pass back to the previous room it must be carried from the drawer there, it must be copied from the drawer there to the drawer in the first room, so that is the copying of results when you have returned result that value which is present in a drawer in the room corresponding to the called function must be copied back to the appropriate drawer in the room corresponding to the function where you are returning and then the program counter was telling where to resume execution in the previous room so Dumbo looks at that and that is how it knows where to come back to and resume execution and then the activation record is freed which means that infrastructure you say I don't need it anymore it can be used for whatever purpose, so this is the business of activation record this is how function calls are actually managed within a computer and we can resume execution at the location given by the program counter, the program counter was saved when I went from one room to the other room and then when I am coming back I will use that program counter to figure out where to resume execution, okay then we had these two paradigms of parameter passing one is called by value the other is called by reference so what is called by value, called by value in this Dumbo model is like saying you open the drawers of the first room copy the values carry them along with you go to the next room put them in some drawers there then you lock up the door and start your computation, okay so the values are actually copied the parameters that you are passing from the calling function to the called function are actually copied from the activation record of the calling function to the activation record of the called function and the formal parameters of the called function or the callee are just like drawers over there you copied the values from the drawers of one room and put them in the drawers of the other room the formal parameters of the called function are just like local variables, just like any other drawers. And there, the drawers belonging to that room. So they're not to be confused with the drawers belonging to the other room. Because once you go to the other room, you basically lock the door, and you just operate in that other room. So the drawers there will not be confused with the drawers here. But what this means is that once you do the computation in the second room, and you want to use that result of that computation, once you return to the first room, you actually have to explicitly pass that value back. So the only way that the collie can let the collars see the effects of its computation is by actually copying value from the drawer of that second room to the drawer of the first room when Dumbo returns from the second room to the first room. Is that clear? So this is called by value. Everything is copied. When you go from one room to the other room, you copy the values corresponding to the parameters from the drawers of the first room to the drawers of the second room. When you return, you copy the value corresponding to the result from the drawer of the second room to the drawer of the first room. Whereas call by reference, you know, a sort of additional enhancement on this where you're saying that you can go from the first room to the second room. But then if you passed a parameter by reference, it's like having a little window in the second room from which you can access only specific drawers in the first room. So when I pass a parameter M by reference, it's saying that well, when you come to this room where you're doing the computation corresponding to swap, you have a little window which allows you to access the drawer in the first room from where you came, the drawer corresponding to this parameter that was passed. So whenever I talk about M here, I'm really referring to A here, right? It is like a window saying that the name of this window is M, but really when I put my hand through this window and try to access a drawer, I'm actually accessing the drawer A, drawer labeled A in the first room. So, you know, call by reference is really saying that you now have some mechanism to access something in the first room. I mean, the doors are locked. You cannot go back and access all the drawers, but you have some way to access some of the drawers. And which are these drawers? These are exactly the drawers, the parameters that have been passed by reference. So that is call by reference parameter passing. So these are no longer drawers, no longer local variables in the second room. They're really windows to access drawers in the first room. So they are just references or aliases to the callers variables that were used to pass the parameters. And so as you can see that in this case, you do not need to have these two drawers named M and N in the room corresponding to SWAP because there are these two windows named M and N and when you put your hand through this window, you actually gain access to the drawers in the room named main. So good, now what we'll do is we'll start the discussion, we'll start the practice problems. So the way I'm going to do it is the first couple of problems are slightly of the easier type. So we will spend less time on that, okay? So I will show the problem, I'll explain the problem and then you will get, you know, around five minutes to solve the problem at the end of which we will collect some of the, I mean, you will discuss amongst yourselves and we'll collect some of the answers and show the answers, okay? We won't spend time on the problems. We'll try to spend some more time on the subsequent problems. So here is the first problem. So before you read that, let me just tell you all we are asking you to do is to calculate the square root of a double number, but I don't need the exact square root, I just need the integer part of the square root. So that is why this C plus plus function is called integer square root. It should take a double number and it should calculate its square root, but I don't need the exact square root, I just need the integer part of the square root. So if I give the number 5.3, the square root of 5.3 is 2. something. I don't care about that point something part. It's okay if I just get the answer 2, right? Similarly, if I call this function with 6.3, once again the square root of 6.3 is 2. something. I don't care about that something, point something part. I just need the answer 2, right? So we want to calculate the square root. That's basically the substance of this, but it's not the exact square root, it's just the integer part of the square root, okay? So now let's read the problem. So write a C plus plus function in square root that takes a non-negative double input as a parameter and it returns a double value. So really we are calculating an integer, but of course we can represent that integer as a double number also. Such that the fractional part of the result is always zero. As I said, I only care about the integer part, right? In square root of 5 should give me 2.0. In square root of 6 should also give me 2.0. In square root of 7 should give me 2.0. In square root 8 is 2.0, but in square root 9 should be 3.0. Okay? And in square root is always non-negative and this is just saying that the last line is just saying that I need the integer part of the square root. Okay? So here is a rough skeleton of how your function might look like, right? You can do some input validation here and here would be your code to compute the in square root. So once again, as I said, this is a fairly straightforward problem, nothing tricky here. So just apply your, you know, reasoning, fairly simple reasoning. I want to find what is an integer i such that i squared is less than or equal to x, but i plus one squared is greater than x. So we just need to find this out. And then you need to return this number as a double. As Professor Supratik said, you have to essentially find the square root, but you need only the integer part of it. The conditions I have, suppose everybody remembers, you get a non-negative double input parameter and you have to return a double value. But the fractional part should be zero. The last condition is important. The value that you return should be such that it should be between square root of x and square root of x plus one. So whatever be the value of x, it will be a fractional value. Suppose the value that I give to you is 4.87. What should be the answer? Somebody said 2.2. The actual square root of this value will be obviously 2. something. But the answer required is an integer number. So you have to remove the fractional part of it. And why 2? Because 2 square is less than 4.87, which is less than 2 plus 1 square. So the given number, its square root, is to be calculated, that part to be truncated. We don't need the fractional part. What will be the answer if the number given is 5.87? 5 is the square root. Square root of 5.87 with these conditions. It is still 2, because 2 square is 4 and 3 square is 9. So any value that is given between 4 and 9 will result in the answer 2, right? Please remember, less than equal to symbol here. And there is only less than on the other side. What would be the result if the value given is 16.432? 4, that is, this value is greater than equal to 4 square, but less than 5 square. So you don't need to find the exact square root, really. You need to find out that value of x, which satisfies x square less than equal to this, less than equal to x plus 1 square. That's all. All right, here we have multiple answers. Check if this will work. I start with i equal to 1. If i square is less than equal to x, and i plus 1 square is greater than x, then I do nothing but increment i. Go back, check again this condition. Increment i, go back, check again this condition. So for example, if I have been given a value 16.341, then when i is equal to 4, 4 square will be less than this and 5 square will be greater than this. So what will happen? Increment i by 1. Next time this condition will not hold. So when I come back, what happens when i is equal to 1? This will not work precisely because I have multiple conditions here. All right, what happens if I remove this? Take the same value, 16.341. i is 1. 1 square is less than 16. something. i becomes 2. 2 square is less than this. i becomes 3. 3 square is less than equal to this. i becomes 4. 4 square is less than equal to this. i becomes 5. This is not equal to this. So when you come out, the value just prior to 5 is the value to be written. Notice that I need not check the second condition at all. This may not be very easy to decipher, but you can write this in more legible and understandable code, checking both the conditions if you wish. One important thing you have to remember is there is no unique way of representing the logic that you have in mind. But to test whether the program is functioning properly or not, particularly a function, remember the contract view. What has been stated here is essentially a contract view. And if you can state the pre-conditions and post-conditions, you can be fairly certain by checking your function, whether it meets those conditions or not, that it will work. Let's go to the next question. Each is a three-dimensional space. Finds which one of them is farthest from the origin and which is the nearest to the origin. All of them are familiar with three-dimensional coordinate geometry. So basically each point has three numbers describing its position. X, Y and Z. These are floating point values generally. The distance of the point X, Y, Z from the origin is simply the positive square root of X square plus Y square plus Z square. So there is a single value. Any value has two square roots. So the positive square root is the distance between origin and this point because distance between two points is like, as you know, X1 minus X2 whole square, Y1 minus Y2 whole square. But here one of the points is 0, 0, 0. So the distance from origin is simply this. You have to write a C program to solve the above program. But use the in-square-root function designed in practice problem. So that is we want to deal with only integer coordinates. You are given X, Y, Z values for three points. So extend the problem that you just solved some time ago where you found out an integer number which is closest to the square root of a given number. So you have X, Y, Z given for three points, 0.1, 0.2, 0.3. Each one of them will have a distance. So you can say D1, D2, D3 where D1 is X1 square plus Y1 square plus Z1 square root. D2 is exactly same thing for the second point. So you might actually represent D1S as D1 square, D2S as D2 square, D3S as D3 square. Find out the integer square root and find out which is the point which is nearest to the origin. How do I define nearest to the origin? Where the distance from origin is least? You have to find out the minimum of those. And you might have two points which are equidistant from origin. Which is okay to find any one of them. And you have to identify which of the three points. So this takes some writing. You have to write a program. What you can do is you can assume that the function in square root has been written already. And let's say it has been correctly coded. So you can use in square root function and invoke it in your program. Assuming that function has been written correctly. And assuming that we are interested in only the integer coordinates of the point. So you can use in square root function and invoke it in your program. Which will take the coordinates for the three given points. Use this in square root function and print the point or its coordinates which is closest to the origin. You have to find out basically the minimum amongst those three. This problem will require full 7-10 minutes to write a program. So you better write a good program. It's a typical quiz problem. Can be solved in about 5-7 minutes. Sometimes it may take 10 minutes. Because you want to actually execute your program with some sample data that you construct yourself. And try it out. So we will say let's say 5 minutes of individual work. Because please remember you are being trained to write programs individually. Of course there is merit in discussions which we will have later. So initially please attempt this. As if you alone have to write this program. Three points are prescribed. There x, y, z coordinates have been given. You have to find out the point which is closest to the origin. For which you need to find out the square root of x square plus y square plus z square for each of the points. And the suggestion is assume that int square root function has been written properly. It returns the correct int square root. So like in the previous question like if you use the int square root function then square root of root 5 and root 6 and root 7 will be returned as 2 only. That's right. So how will we compare which is max and which is… No, so as far as the integer coordinates are concerned you will assume that all these points are at the same distance. It's like finding out the minimum of three numbers where two of them are same. And both are less than the third number. Then you don't have a unique minimum. There are two minimums. You can have three points in the three dimensional space. Each one of which is equidistant from origin. That is possible. But they are not actually equidistant. The distance is actually root 5. No, the problem is artificially framed. Because actual distance is like root 5. I agree. The problem is artificially framed which asks you to consider only the integer part of the square root. Is it okay if while comparing the max and when we take the sum of squares and while printing the distance we take the square root? No, no. See the way the problem has been framed that is what I was explaining that the problem has been framed a little bit artificially. If our actual floating point values is a fractional value as coordinates then I simply compare x square plus y square plus z square by each of the three points. And whichever is the smaller that is the point which is closest to origin. So I don't even need to compute the square root. Much less find the integer part of that square root. Okay, but the way the problem is framed that you are expected to use the function that you saw last time. Therefore it's a problem. What I would suggest is you should for the sake of practicing using a function which has been written which has been proven to be correct in the framework of the problem formulation. You should try and write the main program to do this. However, if the question is of finding out a point which is closest to origin then I suppose the universal agreement is if I simply compare the quantum of x square plus y square plus z square for each of the points and find out the minimum I will get the point which is closest to origin. Is that correct? Everybody agrees with that? So let's go to the third problem now. Are you familiar with the game of tic-tac-toe? Okay. So you want to write a C++ function that can be eventually used to play a game of tic-tac-toe. We will not use cross and takes. We will use zero and one. The point is you are not writing a program to play a tic-tac-toe game. Some of you would like to do that. You can do that later. The problem is you have to write a function which will be used in constructing a program which plays this game. So the second player wins. Let's say first player writes zero, second player writes one. Now configuration of the tic-tac-toe grid can be represented by a sequence of integers. So zero, one, zero can be represented like this. Zero, one, minus one, one, minus one. What do you think minus one represents here? It's a blank square. Nothing has been written there. This one would be represented as zero, one, minus one. So now you can represent by a sequence of nine numbers any situation in the tic-tac-toe board to begin with everything will be minus one, minus one, minus one, minus one, minus one, minus one. As a player plays, the player should prescribe the position where the player is playing and that particular position should convert from minus one to either zero or one. And at every place, every point, given a position like this, given a sequence of numbers, can you determine whether the player who has played the last move has won or not by finding out which are the three, what you can say, zeros or ones in a row. So valid configuration and numbers of zeros either equal to number of ones or more by one. Similarly, a valid configuration can have at most one winning lines of zeros or one. Is this being appreciated? Let's go back and see the whole thing again. We want to write a C++ function that can be used to play a game of tic-tac-toe using zeros and ones. So this is an example of a game being played. In this case, the second player has managed to get three ones in a column and therefore the second player wins. This could happen if a player gets three zeros or three ones in any row or any column or any diagonal. One configuration of tic-tac-toe grid is represented by a sequence of nine integers. So nine integers are given. These nine integers represent the complete tic-tac-toe configuration. So this particular configuration is represented by this sequence of nine integers. Given any sequence of nine integers in this fashion, comprising of minus ones, zeros and one, you can verify whether that sequence represents a valid tic-tac-toe configuration or not at any point in time. And what is a valid configuration? That the number of zeros either equal to number of ones or more by one. Similarly, valid configuration can have at most one winning line of zeros or one. So an example of invalid configuration. This is an invalid configuration. Somebody has already won. Player two has already won and you are actually putting one more one for him, which is incorrect. The problem is now here. So you should note down this problem very specifically. Write a c++ function t-t-t-check-config. That checks if a configuration of the game is valid one or not. Simple problem. Your function should return a boolean true if the configuration is valid. Otherwise it should return a boolean false. Remember, you are looking at a sequence of nine integers. These nine integers, each one of them has to be either minus one, zero or one. You can assume that the values that are given to the function are minus one, zero or one. But you still need to check whether the given sequence represents a valid configuration of tic-tac two or not. Coming to the end of the class, so I will have any quick questions that people want to ask. Sir, how the values will be given means A, B, C, D, E, F, G, H or... Right. So you can imagine nine variables A, B, C, D, E, F, A, B, C, D, E, F, G, H, I. So each of these nine variables is expected to be either zero or one or minus one. Sir, it is valid to win by two rows, one row and one column in one case. This is an invalid configuration. No. It can be a valid one. I can show it to you by... No, no, the point is such a configuration cannot exist in an actual tic-tac two game. Sir, it can. In one case, if we follow a sequence, we start with zero, one, zero, one, zero, one, zero, one. We fill the entire boundary and then fill a number in the middle. Then it's possible that a person wins by both the... this row and as well as by the column. Yeah, but what is the total number of ones and total number of zeros here? Five and four. Total number of ones are two more than the total number of zeros. No, no, no. This case is invalid. Yeah, that's what is being said. This case is invalid for a different reason than the fact that there are two winnings. In a different case... So what you are saying is that at most one winning line is not necessarily the condition of validity. Yes. There is one unique combination where two winning lines may be there. Yes. But only one specific combination. Yes. Or its mirror image. Yes. If we start with one, then it's mirror image. No, if we start with zero, then there is exactly one combination. Yes. Good. So our friend is apparently an expert in tic-tac-to and he has pointed out that there is a unique situation where one of the players, literally plays like a Dumbo and ensures that another player wins by having two rows at two... Sir, two conditions. Two lines. Two conditions. There are two conditions. What are the two? Diagonal. I can show it to you by coming down or... We can... So in one case you may get two lines with a plus-like appearance. Yes. In your case you may get two lines with two diagonals. Yes. Alright. Now having pointed that out, you factor that into the validity check. You have just made life of everyone far more miserable than what it was just five minutes ago. That's all. If anybody is feeling very chiseled off, you know the two people who are to be blamed. But good point that you make. I would like you to solve this problem at home. It does take a few lines of thought. Sir. Yeah. Not only two means more than two situations are possible. Means t is also there. So there are total eight possibilities of winning. Means three horizontal, three vertical and two cross. Alright. That's a long program. Let me simplify this problem by saying that examine the given configuration for non-validity based on numbers of zeros and ones. Yeah. And check whether at least one winning line exists. Yeah. That is a simpler problem. Yeah, but sir there are eight ways of winning. So we have to write eight conditions because three... That's okay. So I did mention that this problem involves some Gholagiri. Yeah. Right. Alright. Thank you.