 Welcome back to 105. Trust you all had a good reading week. So I didn't really see any questions about the midterm. So I guess we'll just do more questions unless there is something concerning we want brought up. Yep. Yeah, so there's a question of like, hey, I saw in past midterms, you know, there's like compiler error warning and I have to identify which one is which. Don't worry about differentiating which one is which. So you should be okay. So they were more pedantic for some reason. I don't know. We're not that bad. Yep. So question is if there is a question where you have to write a program, can you write a function? Yep, you can write a function, sure. Unless you might get some alarm bells if they give you like a main at the top and then an end bracket at the bottom, which probably means you should write it all in main and it's pretty small. But so if you're writing a function, you might be writing too much, but in general you can write functions. You can do whatever you want as long as you solve the problem. Yep. All right. Any other questions, comments, concerns about the midterm? It is all signed, sealed and delivered. Well, I guess we don't really have to sign it, but yeah. It is ready for you whether or not you're ready for it. So any other questions before we continue in the same style in vain as before? Everyone all studied up, everyone ready? We're gonna kill this. So in general, other strategies that you might want to take for the exam, who just owns from front to back? Probably most people. So if you haven't tried this before, I would suggest working from the back and going to the front. So typically the hardest questions are in the back. So it's good to read them first and try and solve them. And even if you can't solve them, that's okay. You have more time to think about it. Your brain is kind of a marvelous piece of biology, I guess. So while you're working on other questions, because you've read the hard one, you're gonna be subconsciously thinking about it and how to solve it. So when you go back, you might actually have a solution from it. So if you haven't tried that yet at university, I would suggest doing that. That's what I always did. Most instructors, the exam will be like easiest to hardest and you should probably try it from hardest to easiest. That way, you can get some adrenaline flowing. You can read the hard question, be like, crap, I don't know anything. And then you'll feel better as you write more, as opposed to feeling okay. And then being like, oh crap, oh no. And if you see you're running out of time, then just flip to the beginning and do the easiest questions. But I would suggest starting at the hardest one. But in terms of two questions, so yeah, again, we're just going through exam questions unless anyone has any comments, which there are a few, but redress them. And again, you can interrupt me during this. Otherwise, I will just go through the exam. So we did 2023, 2020, which I guess there's solutions for now. And we can do 2022. So we can start by doing the simple questions first. So there'll probably be questions like this, write a single C statement. Generally when the exam says write a single C statement, they actually mean like just a single like assignment statement or declaration statement or like a function call. Because technically like a for loop is a statement, but you can have statements in that. And you could argue. So it is a bit weird with the wording sometimes. So for this says write a single C statement that declares a double variable called number. So we could go ahead, we declare double number. And then we know that we want to write it equals to something and then a semicolon at the end. And yeah, you're gonna have to write C code that actually compiles. So there's a bunch of different ways to do this. Easiest way to do this question is well, we know that RAND returns an int and we know like our formula, if we want to get like a number range between A and B inclusive, it's like RAND minus B plus A minus one, or sorry, mod, whoops, I already screwed up. So it's RAND mod and then A plus B, whoops, plus one, that will give us, oh, wow, I forgot how to do this course during reading week. All right, I had one fun day and apparently I forgot everything. So that should be correct now. So to get a range between A and B, it's RAND mod B minus A plus one, and then all of that plus A. So I wrote that correctly now, hopefully, right? So for this, it says, we want a random number in the range 66.6 to 99.9. So well, we know RAND returns an int, so we might want to just make this easier on ourselves and just make the range we want to represent an integer range. So instead of doing 66.6, I can do 666 and also that's like fun, I guess, to 999. And then I can just take that range and then just divide it by 10 and then I'll get 66.6 or 99.9. So if I'm doing to do that, well, A or B minus A in this case is 333 plus one is 334. So I could do RAND mod 334. So that will give us some number back that is zero to 333. And then, well, I can just plus A, so I could just do plus A in this case is 666. And then I could essentially just take that whole thing and then I could divide by 10.0. That will go ahead, convert it to a double, all of that fun stuff. Other ways I could write this, there's more than one solution. I could do RAND mod 334 divided by 10.0 plus 66.6. Whatever you want, all means the same thing. So questions about that? So just know RAND just gives us some random integer back. All right, question two. Suppose these are variable types, write a single C statement that is equivalent but is simpler, i.e. with fewer Boolean conditions and relational operators. So we have to think back. There's De Morgan's law that says, hey, if we have something that looks like not A and B, well, that is the same thing as saying not A or not B. So I could use that to help me on my first step to make this a bit simpler. So I could say, okay, let's go ahead. Let's bring that not in and change, not the individual terms and then do an or between them. So if I do that, I would have not X is less than or equal to Y or not Y is okay. Is less than or equal to Z. So that is not that much simpler, but because I'm taking the not of this, I can just kind of convert that. So not X is less than or equal to Y, not just means it's the opposite. So the opposite of X is less than or equal to Y, is just X is greater than Y. And then I can keep the or and then I will convert this one as well. So Y less than or equal to Z is not that. It's the same as saying Y is greater than Z. So this is my final simplified one. Boulevard equals X is greater than Y or Z or Y is greater than Z. So questions about that, pretty much just says, hey, do you remember the Morgan's Law we talked about which may or may not actually be important for you. All right, good, good. All right, so, oh, so what does the following C program print? So you could probably guess you will get one of these. These are another ones that just kind of take up time, but shouldn't be too hard to do. So if it's asking what the C program prints, we have to remember that we're going to start executing this program by running main. So here we would go ahead and we're doing if a function called to Armstrong number with the value 152 is true. So I have to do this function call and get the value from it because this returns a Boolean. So first thing main is gonna do is call is Armstrong number and we're going to pass it the value 152. This function will start running. So num would get a copy of that value. So in this function, num is equal to 152. And then here it just declares a bunch of other variables. So we declare original num and then set it equal to num we got from the function which is 152. Then we also declare remainder and do not give it a value. So it's to some random value. And then we also declare result equal to zero. So after that line runs, we have seven variables in the function or why did I say seven? We have four variables in the function. So now our execution goes to the next line. Oh yeah, and there's a question that like what for the previous question, what about like other numbers between like 666.5 or other numbers in between? Don't worry about it. We don't have to do anything like that or divide it or do anything weird. As long as your numbers are in that range and they're always in that range doesn't matter for that question. So yeah, don't worry about it but yeah, you could have points in between but this is assuming that it's gonna go up by tense all the time. All right, sorry, back to this question. So now we have a while loop. So while original num does not equal zero. So currently original num is equal to 152. So that is not equal to zero. So we're going to go into this loop. So we're going to set remainder equal to original num mod 10 which what is 152 mod 10? Just two, right? Mod 10 essentially just gives you the last digit if it's all powers of two. So it's divide by 10 and then get the remainder. So our remainder is going to be two and then our result is going to be whatever the old, so plus equal means the new value of result is going to be whatever the old value of result was plus remainder times remainder times remainder. So in this case it would be two times two times two or what's that eight? So result is going to be equal to eight as long as I'm not crazy. Two times two times two, hopefully that's eight. And then it's going to set original num divide equals 10 which if I wanted to write that out it would be in the non short form it would be equal to original num just divide by 10. So that's what that does. So if I'm doing divide by 10 it's integer division AKA I'm just kind of chopping off the two. So original num is equal to 15 now. And then all these questions will say what gets printed? In this case what gets printed is result. So far and it is equal to eight. And then we would go check the condition again. Original num does not equal zero so we have to go through this loop again. So now remainder equals the current value of original num mod 10. So now remainder gets updated to wrong thing remainder gets updated to five. Then we have result plus equals the old value of results. So eight plus remainder times remainder times remainder or five to the power of three which is five to the power of three is 125. So it's going to be eight plus 125. So result gets updated to 133. Then we take original num divide equals 10. So again we just kind of chop off a digit. And then we print off result so far 133. And then we end so we would go after a print check. Hey does original num equal zero? No, okay well we're still going through this while loop. So we get a new remainder. So remainder now is just simply one. Then we have result plus equals the old value of result plus remainder times remainder times remainder or one times one times one which is just one. So we would update result to be equal to 133 plus one. So 134 and then original num divide equals 10. We update it to just simply zero. It would print, oh yeah that's the camera angle. All right so result so far equals 134. Then we would go back up. Original num is equal to zero now. So we would break out of this while loop and then return if result is the same as num. So num is 152, result is 134. So is that true or false? False, right? So it is false and let me try and fix this. Hey there I am again. All right so that is false. So our function call would return right up here. So if that's false, well then I have to go and fall through to the else. There's an else if so I have to do another function call. So I have to do it again but now num is equal to 413. So I'll skip some steps here in the interest of time and it just prints off some more garbage and it returns false as well. So then we would go to the else and then it would just print off 152 and 413 or not Armstrong numbers and that's a lot of writing. And then questions. Would one be penalized in the exam for using things that haven't been covered in lecture using binary operators like bit shift or ternary condition operator? Yeah, probably. So if you're using those, those will not help you with the exam as written. So don't worry about it. Yeah, in 2020 that would have helped with one of the questions. Don't have one of those questions. So don't worry about it. Yeah, that how many bits are in an integer thing? Yeah, that's why that question's still infamous because we haven't gone over bitwise operators. Hopefully most of you don't know what those are yet because yeah, they're fun in a psychotic way. So yeah, don't worry about it. Yeah, your exam is significantly easier than 2020. Hopefully you will not write horror stories afterwards. All right, so this says the following function is called with three distinct characters, returns the middle character. If A, B and C are passed as arguments, it returns B, rewrite this function such that it only uses one return and one if statement. So how these questions are written is if it says one if statement, you're allowed to like tack on as many else ifs and else's as you would like. So with this, you can pretty much solve this one. It will look something like, you just kind of reduce this and do like if A is less than B and B. If A is less than B and B, so if B is the middle character, you can write conditions like that and like, so you can just assume that the middle character is A and then write the whole if conditions that need to be true if the middle character is actually B. So if A is less than B and B is less than C, then that's one way B could be a middle character. Otherwise, what you might have is C is less than B and B is less than A. So that would be the other case where B is the middle character and then you could do middle equals B and then here I'll just skip some steps. You could have like an else if, write your conditions to check if the middle character is equal to C and then you just simply return the middle character for the value you created and this counts as apparently that's just one if statement. So an if with else if's tacked onto it, apparently that's one if statement. I would argue that one, but I lost that one. So if it says one if statement, just remember you can do that and here I would only have one return statement. So this is kind of like rewrite the code. All right, let's do this one because this one's fun. This one's everyone's most fun topic. Pointers, yay. So with this, what I recommend doing is what I've been doing in the lecture of like writing what is currently in memory over to the side or something like that. So here I could write, you know, what variables are in memory and then what their values are. So here I declare a variable called first and initialize its value to be one. Then I create a variable called second and then initialize its value to be two and then I create a array of four integers called data and when you write this in memory probably what's easiest to do is just to write each value independently and then just name them by like their array access. So if I have an array of four that means I would have data zero, data one, data two and data three because well arrays are always zero indexed and if I have four elements in my array, wow that camera, come on. If I have four elements that means it's zero, one, two, three, which gives me four and then it initializes them in order so it would be 10, 20, 30, 40. All right, are we okay with all the numbers so far? So we have what? We have six integers in memory and those are their values. So after this we are going to declare some pointers. So the first one is called third and since it's a pointer, it would just have like some address and currently we initialize it to the address of second. So how we could represent that is we just point to that. So we don't need to know where in memory it actually is, we just need to know that we're actually pointing to the value two and it's named second. So next we create fourth is also some address because it is a pointer and it is pointing to the address of first which is, I guess I shouldn't write over that, which is this value currently one given by the variable name first and then we create a variable called fifth. Oh and then we have to do pointer arithmetic, yay. So data, that is the array. So if we just reference it directly that is the address of the first element. So data would currently be like this if it was a pointer and then first is an integer and one is an integer. So we're just going to move that pointer that many integers. So first is equal to one. So this would be like one plus one. So we're going to eventually do data plus two. So that means if we start at data which is at element or index zero, this would be data, this is data plus one, this is data plus two. So let's hop over. So fifth is pointing currently at data at index two. Everyone okay-ish with that? Okay, so now it just does a bunch of stuff. So here first thing it does is it dereferences third. So what dereferencing does remember is just accessing the value that it is pointing to. So third is currently pointing to, here let's highlight it, it's currently pointing to two which is also the name of the variable. If we dereference it, it means we're accessing the value two and then if we do plus plus that means we're going to increment it. So through the pointer third, we're going to change this two to a three. So are we okay with that? Yep. Yeah, so the question is, if they didn't have the parentheses and it was just like this, whoops, no parentheses. So without parentheses, I'm pretty sure the dereference is going to go first. So it's going to do the same thing as the brackets. But you shouldn't have to memorize all the precedence rules. So they, hopefully we are nice and give you brackets. Otherwise it's a guess. Because yeah, otherwise you'd be like incrementing the pointer and then dereferencing it, which I guess is still valid. But yeah, we don't expect you to remember all of the precedence rules aside from like the normal bed massy ones that you should already know. And just unary operators versus binary operators always unary have higher precedence. Okay, sorry. So for the next one, so for this, so we dereference fourth, so we are accessing in this case, value one, and then we increment that. So it's one plus plus, so we're changing that one to a two. All right, next line is even more fun. So it says data second. So data second. So currently the value of second is three. So I can say that, hey, this is the same as data three equals something. So I'm changing element three in the data array. And it is equal to, so dereferencing fifth will give us the value that fifth is currently pointing to. Right now fifth is currently pointing to this. So it's currently pointing to the value 30. So this would be 30 plus first. Okay, first is just two. What the value that third is pointing to is three. So third is three. And then the value that fourth is pointing to is, let's follow fourth, is also just two. So we get data three equals to 30 plus two plus three plus two, which is this changes to 30, or not 34, 37, sorry. So this updates to 37. And then we print everything. So we print the value of first. So I'll just write it in here. It's two. Second is three. Third is going to be whatever the value that third is pointing to, which is currently three. Then the value that fourth is pointing to, which is currently two. And then the value that fifth is pointing to, which is currently 30. Right? And then after that, it goes through all the elements of an array and then prints all their values. So we would get from here, we would get 10 comma space, then 20 comma space, 30 comma space, and then 34 comma space, and then a new line. And then mercifully we're done with this question. Yeah, sorry? Yeah, it's this, right? Yeah, this is the proper solution. So any questions? Yeah. Yeah, so I just have a habit of doing this. I guess, given the marking for last, again, I wasn't teaching this course last year, but they didn't actually grade if you had a space at the end, they don't really care. So if you want, if you just wrote this, this is fine, but doesn't really get the, doesn't really test, I guess, if you're technically correct because there would be a space at the end after the last comma, but yeah, up to you. Oh, yeah, for the new lines, don't even bother. Just write it on a new line. I just wrote it there just to make sure. Yeah. Yeah, if it doesn't print them like last new line, it looks the same, right? Yeah. Yeah, so if this, given their solutions aren't really that pendantic, just don't worry about it. And then if you write it and it's wrong, they probably will grade it wrong, but if you don't write it and they don't look for it, T's grading this are humans too. So if you write neat too, and it looks correct, probably they'll mark it correct. So if you ever have to TA, you will probably fall into that trap too. Yeah, just a human thing. All right, we can probably solve this before. So yeah, now there's programming. So your exam probably looks also similar to this. There's like a few, you know, what does this code do? You outline this code, write single statements, again, probably at the front. And then there'll be a whole bunch of programming questions that you will have to write C4 as much as you can. So this, a poindrome is a word, number, or phrase, or any sequence of characters that read the same forward and backwards. Given the sequence of characters of a char type array named sequence and the size named size, complete the definition of the function isPoindrome, prototype of which is given balloon. It should return true if the sequence of characters it makes is a poindrome and false otherwise. We assume that the array has at least one element, i.e. size is at least one. So for the example, if the sequence holds, you know, the character's radar, then your function should return to true because while it should, you can kind of see how this works. So it's a poindrome. If we start from the first character and it matches the last character and then also the next character matches the second last character and then turns out for a poindrome, doesn't really matter what the middle character is, right? If it's an odd number, doesn't really matter. So this could have been a D, could have been any character, doesn't really matter. So, and we could also just reverse radar, it's the same. And that says, however, if the sequence is holding F, L, A, G, then your function should return false because gulf is not the same as flag for an array with only one element is considered a poindrome. So if it just has one element, it should be a poindrome and this one is not because well, if we look at the first character, it's an F and that is not the same as the last character. So it's immediately not a poindrome. So the way to think about this is, well, when I went through here, I kind of checked the first character, then checked it with the last character and then I just went through that until I made it to less than half of the array and if all of the match, then it is a poindrome. So, since we know the size and everything, there's lots of ways to write it. The solution given has a lot of weird things but we can probably write this a bit more simply. So, we can try, so four int i equals zero so we need to start at the first character and we don't have to go through every single element of the array, we can only, we only have to go halfway. So we can go until i is less than size divide two and then do plus plus i. So we might want to think about this array bound quick because while we know that if the size is one, then it should be considered a poindrome. So if size is one, what is size divide two? Zero, right? So that would be, i is less than zero. If i starts at zero, zero is not less than zero so we wouldn't have to do anything in this loop and if we don't have to do anything in this loop, that's probably a good thing in this case because if it's only one character, it is a poindrome. We don't even have to check what it is, doesn't matter what the value is. So we might think that we need to return if it's a poindrome or not. So in this case, we could just simply return true and then in this loop we can just check that if it's not a poindrome we can just return false. So in this case, if the size is one, then this for loop would never execute no matter whatever we put here. So nothing would happen, it would just return true because it is a poindrome. Yeah, yes. Yeah, so for the for loop remember if we like deconstructed as to how it flows, it always goes like the initialization happens. So this part and then it'll check the condition and then it'll do the body of the loop and then do the increment after that and then check the condition again. In this case, all we have to simply do is check, well, the current character. So if sequence i, so that's like the current character. Let's take the example here of radar. So for radar, size would be equal to five. So we know that if size is equal to five, well I need to check that if the array zero is equal to array at four and then if array zero is equal to array at three. So I can use that example to help me with what the indexes should be. So for the first part, I'm going to check i equals to zero and I should compare that against four. So if I want to get four, knowing the size and what i currently is, well the index I should use is just going to be the size. Anyone help? What should the index be? Yep. Yeah, size minus i minus one. So in this case, if size is equal to five, that's five minus i, which is zero. Okay, five minus zero is just five and then minus one, that gives us this. So this would be this check. So we can go through, check if, in this case, what we're looking for is if it's not a palindrome, then well, we don't have to do any additional checks, yeah. Yeah, yeah. We don't have to make it that complicated. So all we have to do here, is check if the characters are not equal. If the characters are not equal, then I can simply just return false. I don't have to check anything else. So next time through this loop in this example, i would be equal to one. So in this case, I'd be comparing i of index one to size. In this case, size is still five, five minus i. So five minus one is four, minus one is three. So my indexes check out here and then I would check if they are not equal to each other, if they're not equal to each other, then it's not a palindrome. Otherwise, I go ahead and I check the next one. In this case, size divided by two is simply, well, if we wrote it out, it'd be 2.5, but since it's integer division, it's simply equal to two. So now, trying to go through the loop again, we would get i equals to two, but two is not less than two. So that's false. So the for loop would exit and then we would just return true. We have checked every character and it is definitively not not a palindrome. So it is definitely a palindrome. So we just returned true. So we can solve it with just a few lines. All right. Any questions for that? The solution is way longer than this for some reason. Yeah, so the solution, so there's lots of different ways to do it. Like what you said, you can have two numbers and adjust them and have a high and a low and try and get them to be equal to each other and work inwards. Lots of different ways to do this. This is just the first way I thought of and it happens to not take that much code. So just so you have it. In the recording, if you want to pause just for a correct version, there it is. You can pause so you have it. All right, next question because we have eight minutes now. All right, all right, skip that one. That will take too long. All right, there's a triangle question. So you'll probably, these seem to be very common. So we did one way before the midterm. So this is the same idea. There's going to be three lines here. So we have this, there's four lines here. This, this, this, and this. So you're just going to have to come up with formulas for each of the lines, figure it out from there. The only twist for this one is it's in a big while loop. You just do this over and over again. All right, let's see if we can speed run this. So complete the definition of the function has same numbers. The prototype of which is shown below takes addresses of two arrays with unknown lengths. Each array's last element is marked with a negative number. The remaining elements contain positive integers if the exact set of integers exist in both arrays. Otherwise, the function returns false. The numbers can be in any arbitrary order in arrays A and B. There are no duplicate elements in each array. You can safely assume that there's at least one element in the array. So there is lots of ways to do this one too. So the solution will count the number of elements in the first array by like counting how many elements there are until it hits negative one, then count how many elements there are in the other array until it's a negative one. For that, whoever asked for a function before, if you do that, maybe a function helps you with that because you don't have to write two for loops, but turns out you don't actually have to count how many things are in the array. So if you are trying to do this, what you might think, this also says like unique. So basically the thought process is this for all these so you can just kind of, they're mostly designed to be like brute force. You don't have to think too hard about them and whatever solution pops into your head, hopefully it is close to being right. So the solution that pops into my head is for this, is okay, well I will go through each element of the array A and then check if I can find it in the array B. And then if I can't find the first element, then I know it's not there, I can return false, it's not there, I'm all good. Otherwise I can just keep on going through and just finding the numbers and then trying to look it up in the other array and because they are unique, I don't have to worry about duplicates or anything like that and it makes the problem a lot easier. So what I could do in here because I don't know how many elements are in each array so I can't really use a for loop but what I can do is I can use a while loop. So I could say if I wanna iterate over every element of the array A, I could just say declare in I equals zero and then I could have a while A at I does not equal negative one because if the current value is negative one, that means I'm at the end of the array and I don't want to use that character. So I could write that for my while loop and I know that I'm doing this for every element of the array and at the end I could just make sure that I don't forget to increment I each time so I'm iterating over each element of the array A. So with that, that will go ahead and iterate over every single element of the array and then I want to find the current value in the other array B. So if I'm writing this out while thinking, I can be like, okay, well, I have to iterate over every single element of B trying to look up that same value. So same idea, I would have a nested loop. I might call the index I use for array B, just J and then I could have while B of J does not equal to negative one plus plus J. And in this loop, I'm trying to look up and make sure that I can actually find the current value of A in the array B. So what I would like is if A of J is equal to B. So if that's true, I found the element, I don't have to do anything else. I know I found the matching number in the other array so I don't have to look any further and I know that I have indeed found it. So a typical technique for like looking for an element in the array and then making sure you can find it or not is just to declare some boolean called found and then you initialize it to false. This is just a trick that if you've been seen enough of these questions, you'll kind of know. So I can initialize it to false and then if I actually found a match, I can set it equal to true and then if I wanted to, I could also do break here. Turns out you don't actually need the break but no use iterating and checking other elements of B if I've already found it but turns out you don't actually need that. So you can choose to leave it out if you want and then here all I have to do is check if it's found. So if it's not found, I know that the two arrays are different so I can simply return false. Otherwise if I make it through iterating over every single element of A and looking it up and finding it in B and I find a match for everything then I'm all good and I know that they are the same so I can just return true similar to like that is palindrome thing where I go ahead and I check them all. If I can't disprove it at the end, if I check them all and I found them all then it has to be true at the end. So just so you have it real quick, here is the solution so you can like pause and read it just in case you can't read my chicken scratch writing. Again, try and write better than I do on this and like leave room between lines so you can go ahead and add variables if you need to or something like that. So yeah, so this does not explicitly check through the same size but since there's no duplicates it will handle that case as well. So if they're not the same size it means you can't find a match for everything, right? So this handles that because they're all unique. All right, any other? Well, we're out of time. So any other last last things? There's like office hours tomorrow, right? Oh wait, I guess they're not because they start when your exam starts. So yikes. All right, so I'll be on Discord. I'll probably be, yeah, I'll be on campus earlier in the morning if you want to try and swing by my office or message me on Discord or let me know and I am here to help. But good luck and just remember phone for you. We're all in this together. Thank you.