 Okay, here we go. So this is about the use of an array. It is more like a philosophical question. It has multiple answers. There is which is the more appropriate scenario for use of an array in a program. This formulation of the question is not related to C++ implementation. This is the standard mathematical notation that you would use while describing an array. So an array A for example is simply described as A equal to the set of values. So there are a total of 6 values, 5, 9, 12, 34, 56, 43. Since this is a conventional mathematical notation, the different elements of an array are represented using indexes 1, 2, 3, 4, 5, 6, etc. To clarify this, it is stated that A1 is equal to 5. So what is the sum of A2 plus A4 plus A6? Very straightforward. Everybody has done this simple sum. Which of the following properties are true for arrays? Again, this relates of course to C++. Comment on the properties of arrays which hold for arrays. Choose appropriate answer for arrays in C++. We must declare its name and size and when we declare the size, the size could be a floating point number. Just two simple statements made. These all relate to array declarations and array handling. This is definitely a C++ question. An array A of size 5 is defined with initial values 2, 5, 6, 3, 2. What will be the value corresponding to A of this expression? A simple question, if you have seen the lectures, you should be able to answer it very quickly. So here is a core segment, practically lifted straight from a lecture. So those of you who have seen the lecture know exactly what is happening here. It presumes that marks is an array of type int which is defined earlier. You can also presume that the value of n is less than or at most equal to the size of the array. So if this core segment is run, what does A represent? Standard deviation, average, sum or none of these. In practice, when you write programs involving arrays, the lectures advise that you should take certain precautions. Some of those are listed here. Whether anyone or more are valid or none of them hold for handling array. So there are the four choices here. All right. So here we start the session with a very brief recap. We are going to solve some problems. Increasingly, we will be moving towards writing programs. As Mr. Supratik and I have been mentioning, today you will have to write core segments and therefore listen to these things attentively. The first of course is merely a very quick 15 second glance at some of the points related to arrays that were mentioned in the class before we start. So all of you recall from the lecture that if you have an array, it's a hundred integer elements, then each element will be allocated four consecutive bytes because int is four bytes. Concecutive elements are allocated, memory locations are allocated to different elements of the array. The way the array is declared is like this. You write a size and absolute number inside square brackets, the name and define the type of the array. Every element of the array is accessed by an index. So if you want to find out the sum of n numbers, n marks rather, then you declare this marks array, start with sum equal to zero. The array has n elements. So you read n. So basically saying it's like our CS11, there are 600 students, but not all or 573 students who may give the quiz. So the exact number of students who give the quiz need to be entered here. This is another iteration. This presupposes that marks have been read into the array. No, it is reading error. So as soon as it reads this, it adds the element of that marks to sum and at the end you output this sum. Okay. Now, if my intention in life was to find the sum of n marks, do I need an array? Yes or no? If I only want to find sum, I don't need an array at all. I can just read a mark, add it to sum, discard it. In fact, I don't need so many locations. I need exactly one location, just a value to be read. Obviously arrays are to be used when I have to do something more with these values after finding sum. For example, not just the average, but I have to find standard deviation. A program was discussed in the lecture. If I have to find out standard deviation, I need all individual elements and also the average which must have been pre-computed before I go to calculate the standard deviation. So therefore I need to retain this value. In general, there will be many occasions when you will be required to retain and use these values again and again and again in algorithm. Notice that this is the preferred way we have indicated. You can actually set up a for loop in myriads of different ways. Every individual can decide one's own way. But this is something which has come to be an acceptable more or less conventional practice in C++ that you start the index with zero. You end the index to be just less than n because the array goes up to n minus one and you increment the array by one. Count++ is also a perfectly acceptable practice because you are incrementing that count by one. In the classes, in the lectures, you have seen different ways of handling indexes. During the discussion on the iterative solutions, you have seen multiple things that can be stuck inside the single false statement. Now those are very nice things to know and those are very good things to use when you want to do multiplicity of things. However, as a practice when you are handling an array and you are just scanning all the elements of an array, whether it is a one-dimensional array or two-dimensional array, the best thing is to set up the simplest loop without any complicated computations inserted inside the false specification. So in English, you should read this slide, execute the loop over all elements of the array. That is the purpose, nothing else. This is the first practice problem. So see it carefully. This is a new term that is being introduced. Erastrozen is, this is a very old algorithm, by the way, to find out all prime numbers up to some n. So what you do is you list all natural numbers. You of course, omit one because one divides everything technically. So one is a factor of everything. But you start with two, two to n. Now what you want to do is you want to reduce this long list of all integers, chop off those numbers which have any previous number factor. So four is a multiple of two, you have to chop it off. Six is a multiple of two, you have to chop it off. So you keep removing elements of these natural numbers. Once you have done this for two, you take the next number, which is still remaining there, which is not yet chopped off, which is three because three does not have two as a fact. So now you take three and scan the remaining elements if they are powers of three, that is multiples of three. And if they are multiples of three, you chop them off. What will be the next element remaining in that list? Two is over, three is over. Will four be there? No. Four would have been chopped off when you looked at two. So five will be there. Now you look at the remaining elements, chop off all those elements which are multiples of five. You keep doing this, you will end up with only those elements which are all prime number. So this is a very simple algorithm. Now what is the equivalent of chopping off? If you are supposed to do it on paper, you may simply cross a number. But you will start with all these numbers, all these natural numbers in an array. So what is the equivalent of chopping it off in an array? Chop, chop. What do you see? C plus plus. I don't want this number. Okay? He has a solution which says whenever any number is found to be a multiple of any previous number, replace that number with minus one. But now when you examine, you will have to keep checking whether first that number is minus one or not. Because you will be still scanning the entire array. You don't know which particular position a number has gone. The second possibility is that actually when I remove a number, I physically remove it. Meaning I upgrade all the subsequent numbers up by one position. If I have 100 numbers left and let's say four is removed. So I push five to the fourth position, I mean the position of four, six to position of five and so on. And my array becomes smaller. The third possibility is to use an external flag. Keep this array as is. But have another array and integer array which has only let's say zero, which means all numbers have not yet marked. And some other number, which means that number is marked. That approach is taken in this practice problem to tell you how while dealing with arrays you quite often have to deal with one array and based on the judgment that you arrive at by examining some element of that array, you do something on the element of this other array. These are things which are frequently required. So therefore that approach has been taken in this practice problem. There are multiple approaches possible, of course, to implement this. So to recap again, we know that prime numbers are number which are only divisible by one in itself. We don't bother about one. We don't bother about itself, but we bother about any other number less than that. If it divides it, then we forget. So we use this back to solve the problem. So here is the algorithm. We start with a list of consecutive integers, two to n. We assume that all elements are unmarked. That means all are currently, technically, they are all prospective candidates of being prime numbers. Now we mark the lowest unmarked element p and remove all multiples of the p in the list. The lowest unmarked element has to be a prime number because if it is not a prime number, it should have been marked in the previous iteration. You're starting with the first number as two, two each prime and that will be the lowest unmarked number when you start with this algorithm. So when you kickstart this statement is correct and you can show easily by induction that this statement will remain valid if the following procedure is executed. So mark the lowest unmarked element and remove all multiples of p in the list except p itself. Repeat steps two and three until all elements are marked. So keep doing this for the first number two, then the next number three, then the next number which will not be four because four would have been marked, next number five and so on. So here is an algorithm that is given for you to program structure that is given for you. This is an explanation. All elements left in the list are prime which are numbers less than n. So let's say n is equal to 14. You start with this list two, three, four, five, six, seven, eight, fourteen and when you complete the execution of the C++ program that you are going to now write, you should have the output list as two, three, five, seven, eleven, thirty. The output list does not mean that these will be the elements physically remaining in the array. We said we'll not disturb the array elements but we'll mark them. So these are the elements which will be output which would have been unmarked at the end of the algorithm. Fairly simple straightforward algorithm but we would like you to write the C++ program in a particular way. You can write multiple variations as someone suggested you could use replace a number by minus one. That's also an easy way of solving the problem but in this particular case you solve it like this. The step by step execution of this algorithm just as an explanation for some because some of you because you have to set up an iteration. So iteratively you start by looking at two. Now after outer iteration which you will set for examining all elements inside each iteration you'll have to conduct another iteration to scan the remaining elements of the array from this point onwards and examine whether any one of them is a multiple. So if you start with two remove four, six, eight, ten, twelve and fourteen. The effective new list now is two, three, five, seven, nine, eleven, thirty. Now you again mark three and remove nine. Then in the new list is this. Now you mark five you will also mark it. After you mark five there is nothing to be removed. After you mark seven nothing to be removed all of these will remain. So marking is equivalent of doing something, recording it. Putting minus one was his suggestion. Putting a separate array is the suggestion that the people who wrote this algorithm have taken. So here is the code line. The outline says I declared an array called removed 100. This array is a special array. This is not the list of numbers. This is something like a set of flags. It could have been a Boolean array as well because I just need to know whether true or false. But the person has chosen to use an int array. The array will contain zero if a corresponding number in another array is not removed and it will contain one if the corresponding number is removed. So that means if there is a list of hundred numbers which I need to examine there should be hundred elements in the removed array as well. And there should be one one on two correspondence. The fifth element of that main list should correspond to the fifth element here as far as the flagging is concerned. The way you are supposed to write is you write a code snippet which will mark all elements with zero. Which elements? The elements of array removed. This is the flag array. How could you have achieved it more simply? Will it assign five to all the elements of array? All elements will become five. Then why? If I say zero, all elements should become zero. So don't make assumptions. The best way it is if you are not sure of what C++ does or if you think that a feature is compiler dependent feature, which means it is not guaranteed to run exactly identically on different compilers on different machines, do the Golagiri yourself in your program. That is what this program says. This is an extremely simple code that you have to write. The second one is if i is not removed, then remove all multiples of i less than hundred except i. You will wonder that if this is the removed list and there has to be a list of actual numbers. This contains, by the way, all zeros initially, so you have to fill this up. You would expect an actual list to contain what is what you are going to examine, right? Some of them are going to be removed. For example, this is going to be removed. This is going to be removed, etc. Where is the array? There is nothing called list. There is nothing there. The point is you don't require an explicit list of integer numbers because you can use the association between index of this array and the corresponding number. So if you are looking at four, effectively you are looking at the value of i, some index i. For int i equal to two, two hundred, two less than hundred. So please note that you are not going to examine this element, this element at all because it does not exist. It is meaningless. Now, when you are examining i equal to two and you are going to mark this element, then you are removing all other elements which are multiples of two by simply changing the value of i and marking the ith element of this removed array, you don't require any other array. After all, you want to remember which particular integer number you don't want to look at subsequent. This single array is more than sufficient. So look at how the problem has been transformed. The problem stated you start with a list of integers and then mark them. That's what you would do on paper. The problem has been transformed into a removed list. And what does removed list contain? It contains zero if it is not removed and one it is removed. So this list will contain all zeroes initially and start containing someones. Where is the list? The list is hypothetical. The list is A in your mind and in the algorithm the list is equal to the index of this array. As the index varies, you are looking at that number. So when you vary i, i is not only index to this array. i is also the natural number which you are examining. Finally, using the array of removed. Now you know the array contains only zeroes and ones, nothing else. But using this array and of course some conditional if you have to set up a separate iteration to go over the entire array. But the third course snippet says you have to write output all primes less than one. All right. Let us quickly look at instead of having discussions on the solutions that you have found out, four people have offered for their solutions to be seen. So let us together analyze these. So just look at the first snippet. This is solution by Schloecker. This one is straightforward. Everybody agrees. This is correct. So almost a trivial thing. You have to set up an iteration for some index equal to zero to less than 100 and put that jth element to zero. Look at the second snippet. I had this outer iteration statement in i equal to two i less than 100 i plus plus already included. So your snippet actually starts from here. By the way, this is serious because in your quiz examinations and in your test examinations and your problem in the lab, the project submissions of the papers of the program submission. If you are required to write a snippet and submit it as a dot CPP file, you have to write only this. For example, if for snippet two, you write for int equal to i equal to two in our auto grader. This for int i equal to two is already there. Now that will get added to this and there will be chaos in the auto grading. So when you are said write code snippet two, it means you have to write the code which will exactly you cannot write whatever is already pre-written. Just remember this from an exam point of here. Of course, it is correct because it explains the context, but just remember. So the second code snippets look at every i value of i. At this juncture, i is being treated as a number. It's not an index of n. You have to examine all numbers from two to 100 less than 100. So i is that number. Now you examine what she has done is to mark numbers two, three, four, five, six, whether they are removed or not. She assumes that the marking starts with zero element, zero, one, two, eight. So you have to remove this and go back. So complicate your logic. I'm not sure if the rest of the logic will be correct then. The output statement also you have to do that. I can find a fault in your final solution. If removed i equal equal zero for your outputting l plus two, clever girl. All right. So do you do you now see the logic? You have an iteration for every number i that you take. You have to examine all the numbers k from i plus one to less than 100 and examine whether k is divisible by the starting number i. So you just examine k modulo i. If k modulo i is equal to zero, it means k is divided by i. If it is, then k must be marked out because k is no more a prime. So removed k minus two equal to one, that is because she has a lag of two in the removed array. It's a slightly complex. So this solution will work. There is another solution by Nikhil. This is code snippet two. I'm not discussing code snippet one because it is trivially understood by everyone. Please note that the outer iteration is already set in the problem. Like to remind you this for int i equal to two i less than 100 i plus plus is already set up here. So your code snippet has to assume that you have some value of i at this point. If the ith element itself has been removed, then you simply say continue. That means I don't want to do anything with this i. I just go back and take the next element. But if i is not removed, then all multiples of i have to be removed amongst the subsequent numbers. So that is where this iteration is set for j equal to i plus one to n. And if j modulo i is zero, then jth element, I mean jth value is marked as removed. This will also work correctly. There is another one by Chaitanya. Again I'm not discussing code snippet one. So what he does is he examines if the value of i has not been removed. That means removed i is zero, which means i has not been removed. So i has to be considered. But look at the optimization he is trying here. He is not examining from j equal to two to less than n. The point being that if I am examining a certain value i, then i multiplied by something less than n is sufficient. I need not examine the remaining value. If up to that range I have not found any multiple. I will not find any other multiple later. Values of j, where i into j is less than n, only needs to be examined. I don't need to examine remaining values of it. This clever optimization reduces the number of inner iterations to be executed. Thereby reduces the amount of work without sacrificing the correctness of the algorithm. Any number which is a multiple. Now here is a problem there. I multiplied by jth element is removed. So I multiplied by two, I multiplied by three, I multiplied by four, I multiplied by five. So instead of actually looking at every number and dividing by i, he is reciting sort of multiplication table of i. And any value which is in the multiplication table is being removed. You agree that i into j is nothing but a multiplication table. And every j is actually therefore of such kind has to be removed. Here is another one by Aniket. He is not optimizing on the number of elements examined. But what is he doing is that if the ith element is not removed in that, that means i is a valid number to be considered, he's starting j equal to two into i. What is the justification Aniket of starting j equal to two into i? So he's saying that all numbers below two into i would have been taken care of. They would have been either eliminated in the previous iterations or their primes. So he's also doing the multiplication table implementation in a different way. He has to examine all multiples of i. He's actually not examining anything at all. He is like in our younger days in hindi we used to say And every time he finds a multiple he just hatches that index and sets it to minor. So all of you have got different ways of solving the problem but you could also sort it in a straight forward way. Examine all values for j greater than i up to n. Find out whether each value of j is a multiple of i by finding out the modulo remainder and setting the value appropriately but some of these algorithms are slightly more efficient. Here is another problem. We may not have much time to have discussions on this problem. We'll continue these discussions even tomorrow but i would like to discuss this problem today. Everybody is familiar with q. All of you are familiar with q for the bus or something. Well the kind of disorderly queues that you see at bus stops is not what i'm trying to describe here. Here is an orderly queue where a new person coming in always joins the end of the queue and does not join a friend who is standing somewhere in between. When a bus comes only the head of the person at the head of the queue only enters and people don't crowd in the last man does not get in. So c plus plus queues naturally behave in a far better manner than most human being behave. But this is the queue we are discussing. We want to simulate a queue. A queue can be simulated by using an array. The head of the queue could be the starting point of the array. The tail of the queue could be the other end of the array. Since we can directly access any element you can access the top element as well as the last element. First element as well as the last element. So n queue and d queue are two operations defined here. We'll also discuss a deck later. The n queue is actually joining the queue. It's an insertion operation that inserts the given new element which has come at the end of the queue. And correspondingly d queue is a deletion operation which takes out the element at the start of the queue. Now here we are going to simulate a queue by actually inserting and deleting elements. Insertion is very simple. If there is a place at the end of the array you insert whatever was the last element you have to somehow remember it. And that plus next element you insert the new fellow. Easy. But to d queue to let a fellow go and catch a bus you have to physically remove the fellow. So physically removing means you have to shift all the remaining elements up by one place. Okay? That is how you could simulate. So here are some examples. If you have an array initially the queue is empty. So the array elements have nothing. Mr. 4 joins the queue. So that is the first element. Now Mr. 5 joins the queue. So now the elements are 4 and 5 because 5 gets added at the last element. 6 joins the queue, 6 gets added at the last element. If you just say d queue, please note that d queue function has no parameter. By implication the first element or 0th element has to be removed. So 0th element is removed and the array queue looks now as 5 and 6 only. Another 8 joins the queue is like this. 9 joins the queue is like this. If there is a d queue, d queue operation is like that. So this is the question one. Consider the queue 4 6 7 8 9 10. This is the queue. You can actually define an array and initialize that array to these values. If you put six values in brushes then exactly first six elements 0th, 1st, 2nd, 3rd, 4th and 5th will be initialized independent of the size of your array. So that is your queue. In fact you can call that array as queue. Now you have to perform the following operations the queue. So what is being written here is a main program with semicolons missing. You define that array and you simply say n queue 11, n queue 13, d queue, d queue, d queue, n queue 12. Obviously you should have to write two functions. One function which is n queue. Another function which is d queue. Please note that if you pass arrays in functions they are always passed by reference not by value. And this is the second question. I will come back to the first question so keep it here so you can start writing it. Second question is what is the minimum number of operations needed to remove 12 out of the queue. You have n queue 12. Now when you say how many operations required to remove 12 means if you have to d queue 12 how many operations you will have to undo. How many shift operations, comparison operations etc. So please note this question down. Have you noted this? I would expect you to actually write down these two functions at home today because tomorrow we'll have some discussion session and additional problems when we meet. Thank you so much.