[MUSIC] In this video I'm going to talk about debugging. People often don't like debugging and part of that is because it can be difficult, right. Well, [LAUGH] my response to that is then don't do it. Alright, well, that sounds silly. But my point here is that there are ways in which you can make it easier on yourself, okay. As you're writing your software, if you think about what you're doing a little bit more carefully. You follow the style guidelines. You write code thoughtfully and you test this code, as you go. You write a function, you test it. Then you write the next function, you test it. Then you start building up code based on other working code instead of building up code based on unknown code, all right? And this decreases the likelihood of bugs or, at least makes it easier to. Find the bugs that you do introduce, because you're look at small well written pieces of code, okay. Now despite your best efforts you're probably still going to have bugs in your software, okay. So you are going to have to debug, okay. Or, worse yet you might be given software of somebody else's that has bugs in it and you've gotta use and you gotta deal with it and it has bugs that you've got to find. You can't imagine how much of Joe's code I have to debug, for instance. Alright, so we have to debug. Well, debugging doesn't have to be painful. Okay, it can be interesting and fun to hunt down these bugs, alright can be little puzzles, alright. But the thing that you have to remember about debugging, the simple most important thing you need, is patience, okay? You have to be thoughtful about what you're doing, okay? You have to think about, What am I doing right now? What is the program supposed to be doing and what is it actually doing, okay? And if you bring this patience to the, to the process, and you think about what you're doing. It can actually be a relatively painless process, or at least a systematic process that allows you to get to the bug without a lot of frustration. Debugging takes several steps, right? And the first one is recognizing that a bug actually exists. So how do you do that? Well, you have to actually run your program, and you have to think about what the outputs are supposed to be. And compare them with, to the to what the outputs actually are, right? And when they don't match, well, now you know that there's a bug, okay? But if you skip this step and you only run your program once. Or you don't really thoughtfully test your program, you may never actually realize there's a bug, okay? So this is the important first step here. I'm recognizing that a bug exists. Now, once you know the bug exists that's where the debugging begins, okay? So what do I do first? Well, I need to isolate the source of the bug. I basically need to find out where the bug is, okay? And so this is, you know, an important step here where you have to think about how do I divide up my program in to smaller and smaller pieces and how do I figure out if those smaller pieces are working, okay? And, one of the key elements here is that you have to come up with these hypothesis, you have to say hey I believe this is true, okay. And instead of just saying oh I know it's true, because I looked at the code, and the code, it must be correct, right, you want to confirm this. Alright, so a lot of debugging is about confirming these hypotheses, alright, saying I know this is true, let's confirm it. Alright so I have a little function here that I know works, well, don't just say I know it works rather. Run it with a bunch of different inputs, and confirm that the outputs are exactly what you expect them to be. Then you can rule that piece of code out as having a bug, and move on to the next. All right, and you do the same thing you keep coming up with these hypothesis saying, yeah, this is what I believe to be true about this code, and then you confirm it and then you move on to the next step. And you do that again, and again, and again, and eventually you are able to isolate the source. You are able to say, heh, this function, or these, you know, ten lines of code, or whatever, this is where the bug is okay? Then you have to move on to the next step, where you sort of identify the cause of the bug. You actually figure out which line of code is really the problem, or which lines. It doesn't necessarily have to be a single line. Say hey, this is what is breaking my program. This is how it's breaking my program and understanding that, doesn't necessarily mean you know how to fix it. But at least now, you have isolated the source of the bug, you've identified what exactly is causing the bug, and then you can move on to the final stage where you actually fix the it all right? You come up with a new way of implementing the code so that you don't have the bug anymore all right? If you follow these four steps, okay, then you will end up with a more robust, better working program all right? Now these steps are easy to say, they're much harder to do. So here's a program I wrote to implement the game math dice, and it doesn't work. Okay so we've already passed step one here. We recognize that there's a bug. So let's talk about what this program actually does. Okay Math dice, I have five dice. Two are 12 sided dice, three are six sided dice. I roll the two 12 sided dice. I multiply them together. That's my target number, that's the number I'm trying to get. Then I multiply the three six sided dice, and I try to put them together to form an equation that gets me a result that is close to the target as possible. Now use the three dice, and I can use add, addition, subtraction, multiplication, division, or exponentiation in between them, alright. And I'm trying to make an equation of the form A op B op C, alright. And, you know, A and B, A op B is in parentheses here for the purposes of this game, okay. So I evaluate A op B first, and then the result there, I do that result op C. Okay? Now, let's play alright? Let's run this program. And run it, okay, so it says the target is 48, because I rolled 6 and 8 on my 2, 12 sided dice. And then my 3, 6 sided dice; I got 5, 6 and 1, and I try to make an equation that got me close. It says, six minus one, plus five, divided by five. That doesn't seem like it's right because, there are too many numbers in there right, and too many operations. So it's not of the form A op B equals C all right? So clearly, I have a problem. All right, I know I have a problem, so let's try and find it. Well, let's go down to the bottom here first to the play function. This is actually playing the game. Let's look at what it does. First it rolls two 12-sided dice as the target dice and takes their product and then it rolls three six-sided dice as the other dice that I'm trying to make the equation out of and that prints them out. Let's look at these printouts. Well, the target is 48, rolled six and an eight. Well, that seems like that's reasonable and the regular dice are five, six, and one. Well, that seems like that's reasonable too. So, I believe, that's probably okay. Now I should actually confirm that but for the sake of time in this video, okay, I'm going to skip that step. But you should go off and confirm that, that's working correctly. Next, I make a bunch of equations here, out of the dice. All right, so I have a set of ops plus, minus, times, divided by, and power. And the dice and I make the equation. So first, well I know this is correct, right? But let's print them out. Print equations. Okay, so, let's run this game again. Okay I printed the equations and if you are following along yourself, this just goes and goes and oh my goodness, I got a lot of equations here. okay. Here's the first mistake you might make, okay, trying to debug this, now, when I have this many equations is going to take forever, okay. I'm not going to, I can't really see, are these right, I have no idea, okay. Well, yeah, I can kind of tell right off the bat 4 plus 4 plus 3 plus 3 equals 14, well, that has four dice in it and I only have three dice so, yeah, this is probably wrong. But, the first thing I want do is, you know, sort of cut things down, okay? And I also don't like this randomness okay? This randomness is going to make it so that it does a different thing every time. So, I'm going to actually change this here, to the following, alright. My target dice, are always going to be, three and six. My targetval is still the product of my targetdice and my dice themselves are going to be in a one, three, four, okay. Let's do that. I can at least repeat this again and again and again, and I have the same inputs, right? There’s also a lot of different operations here. Let’s cut this down as well. Let’s copy this. Comment it out. Paste it in here and just cut this down into addition and subtraction. Okay, now hopefully things are a little bit more manageable. Alright, I can see I've only got pluses here. Oh my goodness, I still have lots of equations. Alright, well let's have fewer dice, see if that changes anything. Okay, yes, now I have many fewer equations, all right, So, now I've cut things down. I've got repeatable behaviors here that inputs are always going to be the same. I have fewer equations that I need to deal with, all right. So, I have some more hope here of figuring out what's gong on, all right. Well this print out that I've go here is not all that useful. Let's print the length of the equations, how many there are and for equations in equations. Print tqn, all right. Hopefully this now, okay, much more readable, much easier to understand. I have eight equations all right and just for fun you know, let's put this back. Okay, oh my goodness. I have 48, 48 kind of manageable. 8 much more manageable. Alright, and if I had all the operations in there well, that number would be even bigger, okay? So this is the first sort of thing I would want you to do. I want you to start thinking about making your program a little bit more trackable while I'm trying to debug it. Alright, I know the equations are to big so let's see if i can figure out why. Let's go up here to make equations. Alright here we are making our equations, and first of all we generate all the permutations of the dice and then we generate all the sequences of operations that we have. Alright, well, let's look at that. So what are all the permutations of these dice? Print dice orders. Okay. One three three one. All that seems reasonable, right? Okay. If I have the dice one and three, all the possible orderings of that is one and three, three and one. All right, fine. Now, let's print ops orders. Okay, so, now I'm trying to get all the sequences of the operations. And remember I cut this down to plus and minus to make my life a little bit easier. Let's see that, alright. We have plus plus, plus minus, minus plus and minus, minus. Well that seems right, doesn't it? Except it doesn't, okay? If I only have 2 dice, I only need 1 operator. That seems if I had 3 dice, so let's, let's go down here and put 3 dice back in. Stay confirm. Some hypothesis that is, is always giving me one too many. Okay. And let's scroll back up and yes. I am getting plus, plus, plus, plus, plus, minus. So, it is enumerating all the possibilities, all the sequences that I can get with plus and minus but it's not the right size. Okay? So, I'll put this back to one and three. Kay, run that again. All right. Okay. So, that suggests that general sequences is broken, so let's go up here in general sequences, and let's look what happens here, Kay? Well, I look through this and, do you see the bug? [LAUGH] Maybe, maybe not. All right, but basically what's happening here is that I now immediately see this. And you may not. You may need to put print statements in here. But again, for the sake of time, I'm going to jump to it. I have a plus one in here that shouldn't be there. [LAUGH] All right? Let's run this now. Okay, now we get plus and minus. This seems Okay? I have the single operator. Okay. The only way of doing it, if whether I have plus or minuses, I can either adjust plus or adjust minus. Okay. Well, now I have got a complete, like error, down here. okay. Well that's because I wrote this silly string equation, where I am going to print out the equations. In such a way that it only works if my equation is a certain size. Okay. This is also a bug, right? I should fix this. Okay? But let's ignore it for now, all right? Instead let's go back to three dice and see if everything has been fixed. Okay, so now my target looks right, my dice look right. I got all the permutations, the sequences of operators are okay. I now have 24 combinations. When I look at these equations they look reasonable, all right? And the result now though says the closest equation is 1 plus 3 plus 5 equals 9. And let's look in the results here, 1 plus 3 plus 5 equals 9. Is that the best I can do? Well, yeah, it seems like it. So we actually walked through a systematic process there to find that bug. So I put things back now and let's see if everything works, okay? Alright. Now our target is 5. We've got the Dice: 3, 6, and 6. And 6 divided by 6 is 1 times 3 is 3. Is that the best I can do? Well, could be. Alright. Here's 42. Now, here I'm not so convinced. That the closest I can get to 42, with 5, 5 and 6, is 1.6. That's clearly not true. I could do 5 plus 5 times 6, all right? That's 60. That's much closer than 1.6. All right? Perhaps you can find something else. Okay so, I don't think it's working yet, right? My equations look okay now though. So I think that I am making an equation and it's printing out nicely 5 + 5 divided by 6 = 1.667, I think it's valued incorrectly. So what's left here, right? Find closest, all right. Well, again, let's do the same thing, all right. Let's make things consistent so I. Don't have randomness going on here. Six, seven, and let's make the dice almost, five, five, six. Let's run that again just to confirm that I'm going to get the same thing. I am. Alright, so let's look at this find closest function. Alright, here we are. Find closest. Now we want to be systematic here. We, I, I know this works, right? I wrote it. Clearly, but let’s confirm how it works. Right? So, you can see what it does. It, you know, sets the closest to B, infinity and then it tries to find things that are closer. So let’s print out what happens here. Let’s print the equation. Every time we find something that’s closer, let’s print it. Okay, 16, 31. No we're that close, we're down at 19 ha, and then we went up to 60, then down, all right, clearly this is not working, right. It's not getting closer and closer and closer to 42, right. I shall only swap something in if it's actually closer to 42, not just bouncing up and down, all right. So, clearly something's wrong here, all right. So, let's, let's print out some more, let's. Trying to figure out what's actually happening so let's print each time the equation. What's print you know the current closest. Alright and let's print the difference which is the abs target minus equation minus 1. Alright. And let's print to blank line each time. Alright. Let's run through this. Okay, I've got a lot of information here now. Let's go back up. Alright. My equation gives me 16 and the closest is infinity. The difference is 26. All right. Okay. I've got another equation. I got four out of the closest currently is 16 which is the last time we saw the difference is 38 all right. 16, 16, 16 so when do we leave 16, here we go. 16 we go to 31, right because 31 was bigger, or closer to 42, rather. Okay, now, here's the problem. Right, right here. Okay, our closest was 31. We see 19, which has a difference of 23, and we take it. Why are we taking 19? That is definitely further away, hmm. So let's look at what's happening here. Oh, I see. Alright, I did not actually put difference of it from the current closest. Okay? All right. That was my [UNKNOWN] All right. And let's run this. And, what is my result? My closest equation now gets me to 35. 35 seems like it's a lot closer to 42. So, I now have a lot more confidence that this is actually working. Let's run it a few times. Alright 35. Now I can probably put back the other random selection and let's see if there are any other problems. Ok, trying to get to 10. I got exactly 10. That seems clearly right. Trying to get a 9. I got exactly 9. I think I might have it working now. So hopefully watching me debug this program helped a little bit in understanding the kinds of processes that you might go through, to successfully debug a program right? Remember the first step is understanding that there actually is a bug, okay? So you do have to run and test your program, and think about the output is it right or not? Okay the second one is isolating the source of the bug and I sort of showed. Hopefully by example. A little bit of how you might go about isolating the source of the bug, okay? You want to take the pieces of your program. You don't want to try and figure it out, from the big giant part of your program. Where you have big giant outputs. You want to narrow down the inputs and the outputs, so they're much smaller. So that you can deal with them. You can look at them, and understand what's going on. Then you want to look at smaller and smaller pieces of your program. Then you want to confirm the truth. You know that it works, you wrote it, but you need to confirm that, okay. Because often it doesn't, right. That's why there's a bug, okay. So you can see that I printed some things out, I sort of looked at what I expected. And I found out things were not the way that I expected them, and that helped me isolate the problem. Okay? Once I've done that, I now can identify. And you know, that's a little bit harder for you to see inside my head, but looking at the code, I can say, oh, yeah, this is the line of code that's actually broken and here's how you fix it. Now the bugs that were in here were relatively simple. Your bugs might be this simple, they might not, okay? But the process remains the same, right? Recognize there's a bug, isolate the source of the problem, identify what the actual problem is, and then fix it.