 So, we will start with a quick review of the quiz paper, although time is very short given the remaining lectures. So, I will go fairly quickly over it, you can look at the solution and see if there are bugs or other ambiguities or problem. So, the first question was about passing by reference and what happens if there is aliasing among the variables involved in a function argument. So, main things that someone has implemented a reverse function which will work for any input and output arguments and. So, it passes in VEC and also passes in VEC as the output argument thinking that VEC will be updated correctly in place to become the reverse of the original VEC, but in the first case both of them have aliasing problems the first implementation as in VEC and out VEC and reverse assumes that there are different vectors, but main does not satisfy that contract main actually passes references to VEC the same vector as the two arguments and that results in a bit of a problem. So, what happens is in VEC is 0, 1, 2, 3, 4 and in this case both in VEC and out VEC are references to the same vector. Now, if you study the code what the code is doing the first thing that happens is out VEC is resized to in VEC size and because out VEC and in VEC are the same that has no effect at all. It just preserves the original size of the array not vector nothing else changes. Now, the mess starts which is VX equal to 0 to in VEC dot size. So, VX is going across like this the implementation thing it is thinks it is doing the right thing if in VEC and out VEC are different which is out VEC of VN minus 1 minus VX. So, that is in the beginning VN minus 1 minus VX is assigned to in VEC of VX, but because it is the same array after the first iteration this becomes a 0 copied from there after the second iteration this becomes a 1 after the third iteration this becomes a 2 it is copied from itself and then what happens I keep going and this 1 is now copied from there to remain 1 this 0 is actually cancelled out and copied from here to become a 0. So, that is what will happen because of running the first implementation of reverse it is not actually reversing anything. Now, how about the second atom that is also bugged yes, yes, but what the compiler is going to look at is whether you are trying to modify in VEC or not. As far as the compiler is concerned it does not know how this function will be called as long as you are syntactically not trying to change in VEC in the body of the function the compiler is fine. So, that is the first implementation which would work if in VEC and out VEC were different, but will fail if they are the same. Similarly, the second implementation does the following it assumes that out VEC is empty to start with that may or may not be a good assumption while you are writing your code. So, now in VEC is again 0 1 2 3 4 and out VEC is alias to the same. So, out VEC is actually not empty when it comes in which is itself a bug or you know misunderstanding between the caller and the callee and then what does this implementation do it looks at the incoming vector from the last position downward and appends it to the outgoing vector. So, what is going to happen is that I look at the 4 and I will append the 4 to the same array actually they are the same and then I look at 3 I will append 3 2 1 0. So, your final state of both in VEC and out VEC which are the same VEC will be 0 1 2 3 4 4 3 2 4. So, none of the 2 implementations actually correctly implement vector reversing under the special condition that the same VEC is passed as the 2 arguments. So, what would be a safe implementation that you actually use a temporary and then do something with it. If you reset if you resize out VEC to 0 then the in VEC will be lost and both of them would be empty which is also a bug. So, if you want your function library functions to work irrespective of what assumptions callers make you have to code it in a very general way all right. So, that is question 1 the only thing you required there is to understand the meaning of ampersand and that aliasing is happening those are the 2 things we tested. So, aliasing we already discussed in class. So, I was hoping that several people would get this. The second question is mathematically queued there is not much programming to do there, but it is nice. So, so far we talked about binary encodings where you look at a decimal number and you just transcribe it to a different radix base 2 and that is how it is stored in the computer. But there is no inherent reason why the computer has to actually store assign a decimal number to its corresponding binary number all we need is a bunch of bit patterns as long as we can distinguish between 2 numbers and do arithmetic on them correctly who cares. So, in particular if you thought about how binary codes work it is very clear that it has a simple recursive structure. So, the 0 bit binary code see with p bits the number of code words you get is 2 to the power p. So, with 0 bits p equal to 0 you get 1 code word which has 0 bits. So, you can think of it as an empty sequence. Now, with p equal to 1 etcetera you get 2 code words 2 to the power 1. So, 1 is 0 and the other is 1 I will drop the brackets from now on. Now, what do you do for p equal to 2 you say well the first bit can be 0 or 1 for each of those first bit there can be 2 second bits and that is how I get my 4 code words. So, extending that one more step what happens with 3 bit codes. So, again all I need to do is to stick out 0 and 1 like that and then copy those 0 0 0 1 1 0 1 1 and again another copy and I fill in the 1s those are 3 bit code words. So, instead of doing it this way in case of the gray code. So, this is b 3 the gray code g 3 for example says I am again going to produce the first half of code words with 0 prefixes the second half of code words with 0 suffix 1 prefixes, but whatever be the ordering of 2 bit code words here the ordering here will be reversed it is reflected. So, in particular for the p equal to 1 case it is the same here what will happen for the gray codes is 0 0 1 1, but 0 1 1 0. So, this code word is reflected here. So, similarly if I take those code words and write out 0 0 0 1 1 1 1 0 I have to reflect it. So, I say 1 0 1 1 0 1 0 0 0 0 and gray codes have this beautiful property that as you go from one code word to the next exactly 1 bit change. In fact, even when you roll back from the last one to the first one which is not the case with standard binary code because as you can see from 0 1 1 2 1 0 0 all 3 bits change from 1 1 1 2 0 0 0 again all 3 bits change. So, there are many transitions where multiple bits are changing. So, why are gray codes so useful? So, for example, you have this robot arm and there is a motor with a shaft which is positioned at some place right the computer is to read where the arm is to decide how to move it. So, because this is the property of 1 bit change even holds as you circle around you could think of gray codes on a circle. If you have 3 bits you could think of it as a disk with 8 sectors and the 3 bits are like that. So, let us say 0 0 0 and then the second code is 0 0 1 0 1 1 0 1 0 and so on. The benefit of this is what happens is the motor shaft is connected to a disk like this and then there are optical or mechanical sensors which are reading either there are metal foils connected to ground or there are dark and light patches on a disk. Either case optical or mechanical sensor is reading those 3 bits to decide at what angle the disk is therefore, at what angle the arm is. So, what happens is as the disk spins past at the junction between 2 different sectors if multiple bits change mechanically or you know optically they will never really change at the same time. So, at the transition point the sensor may get a weird reading of some other angle position and that might throw off the controller thinking of the arm has suddenly moved to some weird angle. Whereas in gray code that will never happen because exactly 1 bit will change position. You do not want multiple bits to change as you cross sectors because the multiple bits will not change exactly at the same instead at least as sensed by the computer. Some bits will change faster than others because of the electronics limitations of electronics limitations of sensing the light or the switch position and therefore. So, for example, in the binary code suppose you are making a transition from this to this and this bit changes first. So, the first code word you get is 1 1 1 which is suddenly a jump to that position. So, there is a transient electrical phenomena which gives you a weird code that can never happen in this because only 1 bit changes at a time. So, that is why gray codes are very useful for analog to digital conversions and sensing positions of arms and motors and so on. So, anyway the question was more about you know how to calculate gray code. So, to give you the second answer first that is actually a quite a give away clue. So, if I take the binary code and shift it right by 1 I am going to get this I am going to get 0s for the first 2 guys 1 for the next 2 and then 2 for the next 2 and 3 for the last. If I shift it 1 position to the right. So, this is n this is n divided by 2 assuming unsigned. And now if you stare at this it is very clear that this is the XOR of those 2 that is the XOR of those 2. So, it is all XOR. So, in fact gray code is equal to n XOR n divided by 2 or n shift right by 1 for unsigned those are identical. Yes. If you did that is fine. So, remember that n is already provided to you in binary format in the standard you know radix 2 number format. This is also a binary number if you want you can write it out in bits. Sorry n is an n is an integer unsigned integer you need unsigned so that the shifting and so is g. And then what I did I looked at the last bit 0 and what I did I did it not and then I compared it with if it is functionally the equivalent function will get full marks that is all. You do not need to recognize it as an XOR as long as your logic is correct that is fine. So, now the real question is the first one which is suppose you did not know this trick how do you complete the recursive routine for finding the gray code given an n without doing beta arithmetic. So, the recursive function does not do beta arithmetic it is just an exercise in recognizing recursion when you see it and here is the logic. So, if you stare at the table it should be relatively clear if you are relaxed and caffeinated sufficiently. So, what is the deal I am going to give you I am going to point you to a particular row the function of n is to point you to a particular row and then I have to find the columns in the g matrix. So, if I have not recalculated g and stored it which is the that is not the point. So, n is either in the first half or n is in the second half and that is very clear from the sample codes that given. So, remember that total of 2 to the power p minus 1 plus 2 to the power p minus 1 for total of 2 to the power p rows and if n is in the first half then the first bit is 0 if any in the second half the first bit is 1 and that is basically the clear initial logic of the recursive routine. So, first of all if p is equal to 0 then there is nothing to push it is an empty sequence. So, just return the first blank is just return if n is less than 2 to the power p minus 1. So, 0 through 2 to the power p minus 1 minus 1 then we push back a 0 otherwise we push back a 1 or true false and true and then the recursion is what is the interesting part. So, the important thing is that if n is here then push back 0 here you push back 1, but the important thing is that going in I do not reflect and here I have to reflect. Now, this is not entirely correct the first time around this is correct, but when I enter the recursion I have to use the reflect sum. So, anything you are doing here you are supposed to insert the opposite thing there. So, in fact you have to push back 1 of the 12 check reflect and not reflect which order does it come. So, in one case you push back reflect in the other case you push back not reflect and then the rest is fairly clear there is only one more thing left to explain which is in case n is going in there then as I have already decided this and I am diving into the smaller table I have to subtract 2 to the power p minus 1 from n. Now, it turns out that if you you can solve the second part in two ways either is to one is to just eyeball it and recognize that x r is going on the other is to actually translate this logic into the shift and the x r right. So, subtracting 2 to the power p minus 1 from n has a correspondence to shifting the original number. Yeah. Sir, if you do it to implement the reflect when you reflect there it will never implement that that code over there n. Effectively that is what is happening if you decided to change the recursive code so that you would still do it correctly you will get full mark. Sir, if I were to implement that then how it is whether false n or that will decide. But see this is you do not even need recursion here where is the recursion here you only shift right n once and that you are done right whereas this is a failure way of doing it. Sir, it is an idea in a similar way that I did it big way. So, it gave me 0 and 1 output give me 0 and 1. Yeah. So, if I were to implement that code. Our final policy is if it works you get full marks we do not really care how. In fact even if you take this code and mess it up a little bit so that your answer is correct will give full marks. So, the only thing we are looking for is the recursive structure which is correct that is all. Yeah. Sir, if you are saying C minus 1 and 1 should be not reflect or it will always be 1. That is yeah that is a good point you can you can check it out. So, see if you can find a bug that is actually a good point it may be not reflect just like the upper one. So, if you find this wrong post return model find a correct solution this is not final yet we are still pulling around. So, the third question was not supposed to be difficult, but the language was probably not too well constructed for you. So, there are these three courses and there are four hours to prepare for it hours can only be partitioned integrally between the courses. So, English French and German you can allocate each of them anything between 0 and 4 hours total hours is 4. And here is a table of if you study that subject for so many hours what is the probability of failing it. So, if you do not study at all you will fail English with the probability of 0.8, but if you study English for 4 hours you will only fail with probability of 0.6. Now the first thing that is immediately clear from the table is in this particular example that the probability of passing increases as you study. This is not always true in real life, but at least here it is monotonically in decreasing the failure probability is decreasing. So, clearly you want to use up all your 4 hours studying and not doing something else, but the question is how to allocate and it is not obvious. So, corresponding to this p table which is the probability of failure table we put up a dynamic programming table which is called f. So, f x t is the best or minimum probability of failing courses number t and to the right larger if you have x hours remaining or available for those courses. So, the small trickery here to see if you have understood dynamic programming is that the solution is no longer built up from the 0 side to the larger side it is actually the opposite in one dimension. So, here is t course is 0 1 2 here is x the hours 0 1 2 3 4 in this particular example. If you actually use symbols and if the input array is m by m this is this that is fine you will get full marks for that, but the important thing is that as you have defined f. So, f at any x t if you have 2 hours left to allocate to courses 1 and beyond then what is the minimum probability of failing both of them. And therefore, it is kind of we start from this and then you work our way left. So, if I had. So, if I only care about course 2 in the world and I have 0 hours to study then it is clear about my failure probability that is already given by p. So, clearly as I have argued that there is no point wasting time you want to use up all of it because the more you study the lower your failure probability is becoming. So, if the only course in the world were course 2 and you had 2 hours you would spend the 2 hours in course 2 because your probability of passing in course 2 is going up, but from this column onwards things become nontrivial and the quantity of finally interested in this quantity. If I have 4 hours and I allocate it nicely what is the minimum probability of passing at least 1 of them. So, I want to minimize the probability of failing all of them f is failing courses at t or to the right and to the right given a x hours allocated for the courses to the right of me. Just go you do not have to find anything. So, one thing you need is the expression for filling up the intermediate cells here. So, what the way you are going to do this is you are going to range k between 0 and 4. So, positioned at t which is to the left of 2 at some column t I am going to say I am going to allocate k hours to the t of course and then anything that remains to t plus 1 onwards. So, remember f is the probability of failing everything at t and to the right I want to minimize it. So, I fail to graduate if I fail all 3 courses. So, I work up the solution from the right to the left. So, f x t gives me the best or smallest probability of failing everything all courses at t and to the right. So, at the course t I can allocate anything suppose I have x hours in hand. So, let us say this is in particular my x and this is the specific t I am at and I am asking if I had 3 hours in hand and I have to only take care of courses 1 and 2. Then how am I going to best allocate time. So, that the probability of passing failing both of them is minimized only to pass one of them remember. So, the way I do that is since I have 3 hours in hand k this number k can range between 0 and 3 and I will allocate anything between 0 and 3 hours to course 1 itself. And the remaining time x minus k to course 2 and beyond there is nothing beyond but t equal to the probability of failing is just the piece there is nothing left. So, now this formula is fairly clear the best or minimum probability of failing everything at t and beyond given x hours that is f x t is say all these options of f x t and spending k hours on course t or all those options you want to minimize the probability of failing the t th course with k hours times the best probability of failing the t first course onward to the end given x minus k hours. So, we discuss something very similar to this subset sum. So, if I have to make up a sum of a if I use a n then a n is subtracted from a and the remaining guys have to make up a total of a minus a n very similar it just goes in the opposite index order, but that is very minor difference you can even quote this other way if you want. So, this is the final cell of interest to you if I had 4 hours how do I minimize the probability of failing all the course. So, it is a slight departure in that you know the examples we had always had to answer in the lower right corner this one has the example that way and your computation will proceed in a way front to the left it is not a step you just fill in all the you can fill the column in any order it does not matter, but you have to fill the columns one by one starting from the right and coming to the left. So, the recurrence is the trickiest part you invest something in the current column you keep the rest for the right multiply the two probabilities because failure probabilities are independent and once you get the recurrence the C plus plus code is very very trivial. We will decide depending on the class performance if you got the logic of the recurrence wrong, but you implemented the C plus plus code right we might give you most of the marks for the C plus plus implementation only. So, you might not hold the mistake in the earlier part against you in the later part probably you should ok. So, that is the exam, but does yeah. Well, if you chose it implicit fine I do not know we are trying to give away one of the three marks yeah. So, these just turning that recurrence into a code and that is pretty easy fill up the last column then fill up the. So, by the way if you do the calculation this is the final matrix you see your probability of failing all three courses given 4 hours is about 0.29 that both first entry. So, that is the f matrix you get eventually and the code to create that f matrix is just a few lines actually nothing particularly interesting after the declaration it is all very simple. So, what do we have here? So, the fail probabilities are given in that p and you read that from C n and then the matrix f has the same size of the fail probabilities then you initialize the last column which is x comma size 2 minus 1 for x between 0 and size 1. And then the recursion loop goes down the x's, but it goes to the left on the t's. So, t's from size 2 minus 2 this is size 2 minus 1. So, from size 2 minus 2 downward minus minus t you have to create a best variable to get the minimum which is initially max double or plus infinity or whatever. And then you calculate for each k between 0 and x inclusive and then you assign f to the best value and that is it. So, the code is pretty simple if you made a small mistake in the recurrence and you transcribe that into the code we would not cut marks for the code. Dynamic programming is a historical name which says that instead of the computing recursive values of a function again and again like in Fibonacci or in string edit distance calculation make up a matrix where the elements will give you values of the recursive function. So, in some cases they do in some cases they do not for string edit distance of Fibonacci they do not for this problem it does not it is equal to the size of the input which you have to store anywhere. But yes there could be recursive program which you cannot easily turn into a dynamic program there are such things. So, if you already need to store the minimum of those. That is right. Yeah. So, next we come to this event simulation. Now today I do not want to go into the intricacies of the event simulation logic that we will find in the code I have already posted. Today we will study the more software engineering aspects of it how we are coding it up not so much how it works. So, the broad logic without looking at the code in detail is that we have this two main structures one is the actual queue where customers are queued up and what we really put in this I mean a very natural choice for a data structure for the queue is a list because as you have seen you can add things to the end of the list you can pull out things from the front of the list all in constant time. So, we want a list of something and call it a queue list of what. So, it could be one of the primitive types like integer double we do not know it is actually much better. So, as a site comment much of the intellectual content of this course has already been important to you. You know how to deal with indices you know how to sort you know how to search you know how to hopefully do a bit of dynamic programming. So, about 80 percent 90 percent of that is over the important things that will cover in the remaining part of the course is not so much the art of algorithm just that, but how do you keep your cool and actually get through thousands to tens of thousands lines of code by good programming practices. What does C plus plus give you to structure your thoughts better to keep related data in similarly named things how to divide up units of computation naturally into methods and functions that we have seen a little bit of already. I have got a lot better if you could write functions. I will continue on that and so much of the remaining two weeks half of it at least we are going to spend on how to structure your code. So, that it reads easier you can write it more quickly and cleanly. So, instead of saying that a customer is an integer and then having five different arrays storing the name of the customer and you know when they landed up when they left we are going to have something called a decoder or a structure or a struct. So, customer will be such a new type that we will create and we will see how to do that. So, our queue is a list of customers. The customer in the front of the queue it is slightly grayed out there is a customer who is being served at any time if there is a customer there the customer is being served. Now, this structure or the struct for each customer we want to hold a few things in real life you might even hold the customer's name and date of birth who knows, but in the bank for example, the customer gets a ticket number. Now, the ticket number is perhaps local to that days transaction every day there is a new ticket roll coming out of the ticket machine, but once the teller gets the customer's customer number then a lot of other fields about the customer can be extracted from the banks computers. So, maybe this customer structure does not hold the customer's entire life history, but for the purpose of the queuing management you at least want to hold the ticket number. So, ticket number is there. Now, what is the ticket number? It is probably an int is fine you probably do not expect to serve 2 billion customers in a day. So, it is perfectly fine to use a integer. Then you want to record this arrival time start service time and end service time that gives you the customer's experience in the system. Well, again as far as the simulation is concerned whether there is loud music playing or what is too stuffy we cannot model that so far. So, these may be doubles arrival time start service time and end service time. Now, we could of course declare 3 lists 1 of a ticket number 1 for arrival time 1 of service time 1 for end service time. But that is cumbersome. They logically belong in one record and if I define 3 different lists doing that then my push back and pop front operation would have to be done thrice over for every customer it looks cumbersome. You forget about one statement the whole logic fails. So, it is always dangerous and it is ugly. So, that is why we create structs in C plus and then we need that event queue which I would not be dealing with much today anymore that is the mapping from a time to an action. But again here you might have said that the time is a double and an action is a suitably coded integer or an enum. But it is better to write it using word which the program reader will instantly understand. So, when you say multi-map time action events that is much more meaningful than if you say multi-map double int events. So, because someone reading the code will instantly understand that this multi-map is keyed on time and what it accesses is some kind of an action. Let us now go look at what action is and what time is fine. So, that is how we will start out on this next study of type structures and then classes.