 Hey all, Mr. Gibson here with your next lesson in cryptography. Today we're going to take a look at programming the rail fence cipher in Python. So at this point, you should have learned about rail fence transposition cipher back in week one. You should have learned about conditional branching this week in week two. You should have learned about string slicing back in week one. And you should have learned already about functions, including default parameters this week in week two. So if you haven't covered any of those things, this is going to be a little bit challenging. I would encourage you to go back and review those lessons first, and then come on back when you're ready to write this function here with us today. So we're going to get started here in our Jupyter notebook. I've already created a file. I just named it rail fence. And we're going to start by defining a function at the top. So we do def to get a function started. And I'm going to just name mine rail fence. We need to think about what do we want to input to our function? And then what do we want to output from our functions? Always kind of want to think about when I start writing a function. So if I think about what do I need to actually do the rail fence cipher by hand, I need to have a message to work with. I need to have a key to work with which for the rail fence cipher is the number of rows that we're going to implement. And then I need to decide whether I'm encrypting or decrypting. When I'm done, I'm going to return out a piece of text, either plain text or cipher text, depending on what I started with. So let's take that information and turn that into some arguments of our function. So inside the parentheses for the function, I'm going to create an argument called text. So that's what I'm going to pass into this function is a string that'll go into that variable that lives inside the function that variable be local to the function rail fence. I'm going to give it an information about the number of rows. And I might want to give it some information about whether I want to in cipher or de cipher, but I'm actually going to hold off on that. We'll see why in just a minute. And when I'm done, I'm going to want to return a string. And we might want to think about how we're going to create that string based off of text and the number of rows. So those are our inputs. We only think about how we're going to use that to create our output. So let's get let's get into it here. We might want to take different approaches depending on the number of rows. We know that the algorithm in theory is pretty similar depending on what we're doing two row or three row. But in practice, we know we might want to tackle those two things differently. So the fact that you might make different decisions based off of an input value is a perfect idea for us to start using some conditional branching based off of the value of rows. So I'm going to check if rows is equal to two, I'm going to do one set of instructions. And I don't I don't know what those are yet. But I need to have something here under my if statement header. So I'm just going to make a return statement that returns to row branch. So if I run this function with the piece of text and I pass it the number two for that function to take in for rows, I'll at least see that I'm returning back the string that's in the correct branch. And then I'll do an else if rows equals three. And if it ends up in that branch for now, again, I don't know what I want to do with that. But let's just have it print a statement that confirms I've entered the correct branch. And if all else fails, if I don't do two or three for now, let's not worry about it, we've only really covered two in three row rail fence, generalizing that to be kind of an n row rail fence is a little bit tricky, not impossible. We still have enough of our programming tools under our belt yet to really do that the right way. So for now, we'll just do a catch all. If the rows isn't two or three, we'll just return number of rails not supported. And at this point, we should have a function that runs it'll work. It's not going to do what we want it to do. But it doesn't throw an error message. And let's just confirm that our branches that we've set up are working the way that we think they will. So I'm going to print whatever this function returns. I'm going to give it a sample message. So a string, I just made it made it all lower case. I'm going to choose to do row two. So when I run this, this string sample message will be passed to the argument text on our function. So anywhere inside the function, this string sample message, that string object will be assigned to the variable text. Likewise, the integer to this integer object here will be assigned to the variable rows inside this function. So when I run this, we should expect it to kind of start from top to bottom of the function. It's going to check if the value assigned to rows is equal to two. If it is, it's going to return this string back. So that means that this entire kind of highlighted region down here, this function call will return back as that string. And then it kind of decides, okay, well, what do I do next in this cell? I'm going to print what came out of that function. So I should expect the words to row branch to appear if I run the second cell, let's see if I did or if I have any error messages. May it worked. Awesome. Let's try three, make sure that works as planned. It does. And let's try something like five. Perfect. Okay, so we figured that part out. Now I need to figure out actually, how do we do the encryption? So let's go back up here into our branch of logic that has to do with when rows is equal to two, and think about how we might be able to create the correct string. This two row branch is a string, but it's not the string that actually does the rail fence cipher. So if you think about what rail fence cipher does is that it takes when we're doing two row, it takes every other letter starting at index zero and going all the way to the end. So if you think back to how we've learned how to do string slicing, that top row, which is the every other letter starting at index zero, we could write using this function or this call. Remember, when we do string slicing, it takes in three parameters or up to three parameters with the starting index, the ending index, oops, that should be a nothing. We wanted to go all the way to the end. And then we wanted to count by two. So I originally had that wrong. And in fact, that zero at the beginning is optional as well by default, if we don't provide it a first value, it will assume zero. So we've kind of clean that up. So if I were to just take this, we're not done, but this should be the top row of our zigzagging rail fence. So let's see if that works. If it does, if I change this rows number back to two, it should pull the s, the m, the l, the m, the s, the a and the e. Let's see if that works. Now why did that happen? Well, let's take a look. I never actually redefined the function, I tweak some things in this function. And I went down and tried to call that function, but I never re ran this cell to load the new version of the function into memory. It's still working with the old one. So let me try that again. I'm going to run the function cell and then run the print command. Ah, there we go. And that's, that's what we expected to see. s m l m s a e. Perfect. Now we just need to figure out how to get the bottom row. Bottom row isn't too different. Remember, bottom row is every other character all the way to the end, but not starting at index zero, but at index one. So I'm going to take this and cut it for a second to my clipboard. I don't know, try and just get the bottom row. Start at index one, go to the end, counting by two, reload that function in the memory, run the print command. And now we're getting the others, a p e e s g. And when I would really need to do is combine those two things together, one after the other. Luckily, that's what string concatenation is. So if we remember our string operations, I can take the first set of characters from this slice of this text string and concatenate them with these characters in the second string. If I run this and then run the print command again, there is a successful output from our two row rail fence. Now it's not formatted correctly, right? That's not uppercase, and it's not in blocks of five. We can fix one of those pretty easily. If we were to put a dot upper on the end of each one of these string slices, now we'll at least be working with uppercase letters. The blocking in the groups of five is a little bit trickier to get done. We'll work on that next week, but for now it's okay to just make sure things are uppercase letters. We'll be a little bit more strict on formatting from your outputs of functions later on in the course, but for this week it's fine to just make sure things are uppercase. So let's try and think about the same logic when we do a three-row rail fence. Three-row rail fence is still zigzagging. I'm going to try and see if I can recreate it here. I'm going to make a comment where we can use these hash symbols here for a comment and try to just recreate the zigzags. We got S, A, M, P, L, M, and so on. We want to think about how far apart are the characters in each row, and it looks like this first row is about four characters apart. The second row, those are all two characters apart, and the bottom row is again four characters apart. They just start at different indices. The top row starts at index zero, and then you'll count every four characters, one, two, three, four, one, two, three, four, to kind of get you that top row string. This middle row, we start at index one, and we count one, two, one, two, one, two. And in the bottom row, we start at index two, and we count every four, one, two, three, four, to get to the next character. So it's very similar to the two row, just a slightly different pattern. So using the same logic, I should be able to create a very similar return statement. I want to return starting at index zero, going to the end, counting by four this time, making sure it's all uppercase, concatenate that with starting at index one, going to the end, counting by two, and then make sure that's upper, and concatenate that with one last string slice, starting at index two, going to the end, counting by two, and making sure that's upper. If we did that correctly, and I changed this to three, we should see our same message, but now with three real real fans. Oh, I did it again. I need to rerun the cell to load it in the memory. There we go. That's looking about right. There's the SL that we predicted right here. We should have APE. There it is right there. There's our double M for the bottom row should be there somewhere. Ooh, that one doesn't seem to be showing up. Let's try and see if we can figure out why that is. I don't think I have any typos. Let's keep going here with our comment and see why that might be. We should have the last part B and then E. Oh, I'm counting by twos, not by fours. You probably already saw that. Remember, the last row should start at index two and go to the end, but I have a typo here. I have it counting every other character going by twos. It should be every four. Let's load up the function again, run the print. There we go. Okay, looking better now. And that's that right there. I wish I could say that was planned, but that's a live mistake that I made. And it's a good way to think about checking some bugs in your code. We call that a bug. It didn't necessarily throw an error, but it's not operating the way that we intended it to. And you kind of need to just go through some examples by hand, comparing what you're doing by code and making sure those two things agree. Alright, now that I've figured out that return statement, I'm going to clear out this comment. And I'm going to leave us with one thing here. We've got a really great working rail fence function. One thing we can add to this function to make it even better. And every good function should have one of these is called a doc string short for documentation string. So I left this row or this line of code right here blank after the function header, because this is where your documentation string is going to go. If you do three sets of double quotes like I've got here, anything that goes in between those, assuming it's right after the functions header, you can you can print those out to the screen if you do help rail fence. So let's just show you here for a second. This is a doc string. If I were to go down to the cell and do help rail fence, and I run that, it'll show you what the variables are in that function. So you can see what they're going to be called. And that might be helpful to knowing what you should be passing into those arguments. And then it shows everything you put inside those triple quotes. So good practices might be to include a sample that rail fence of sample message with the three should yield the output of this right here. And in a perfect world, that would be blocked in groups of five. So we're going to do that, meaning we're not done with this function, we'll come back with it in a week or so and see we can update it to give it the right output. But that's good enough for us right now. And then you can also include your arguments. And you can say this arguments are text, which is string that contains plain text or cipher text. And you've got rows, which is an integer that represents the number of rows. And now when you run that help string or help command, you can see all the information that you need to successfully run this function, you know, what the output should be for a given input. So you kind of an idea of what it's going to do. And you have the descriptor for each one of these input arguments. So you know exactly how it's going to work. One last thing we didn't talk about in this function is about whether this is in ciphering or deciphering. For rail fence, it might not make a difference, but we can think about what's a good best practice for other ciphers. For the two rail fence, it doesn't make a difference. But for three rail fence, it certainly does. You can't undo a three rail rail fence just by running it through it again. So the way that we're going to handle that in this class is we're going to create a third argument, a default argument. So we're going to give it a value to start with. And I like to think about this one is just like a flag. It's either on or it's off. So we have this in cipher argument that we're going to turn on by default. So we're going to set it equal to true in the header. And you'll see if I just did this, it doesn't break anything. Right? That's what's nice about a default argument is I don't have to give it the third or the default argument in this case. It's happy to just take the first two. If I don't give it the third one, it's going to just assume that it's true. And then what I can do now is go into my branches and create secondary branches. So I can say if in cipher, then do what I just said. Then I can say else. And then I don't know what I need to do yet, but I can say this is where the two row de cipher code will go. And now if that is set to true, it's going to do the in ciphering part of the code. And if it's not set to true, it's going to do the de ciphering part of the code once I figure that out. And we can do the same thing down here under the three row condition. I can say if in cipher, and since in cipher is in fact a Boolean that's true, that means if in cipher is said equal to true, it runs this. And then we can do else. And then I'm just going to copy and paste. This is where the three row to cipher code will go. And I think that's a good stopping point for us today. We can show you that it's working by running in cipher equals false. And change this to change this to five. So we can see all of our possible cases still run no errors. It's not actually doing what we want it to do all the time, but we have the right branches set up. So we have all of the options we're ever going to need for this function. Good to go. We've got a nice documentation string. So if we ever need help, we should probably update that to tell it what to do about the in cipher variable. So somebody using the help function could learn from that. But we're in a good we're in a good spot here. I'm going to leave filling out the rest of this function for you all to do. But that's it for tonight. Thanks for watching. We'll catch you all on the next one.