 I think it's time. Are we ready? I have to tell you something funny before we get into this talk, though. I decided it would be cool to have my five-year-old daughter do the illustrations and the pictures for this talk. So about halfway through it, I realized that I'm giving her all these weird requirements and making her do all these things to fit my talk. So I think I have actually become that interviewer that we all hate. It might be a problem. So take the rest of this talk with an appropriate grain of salt, I guess. But we're going to talk about coding interviews today and how to pass coding interviews and what they are, that kind of thing. And the reason I wanted to do this talk is basically this tweet right here. This is where I got the name from the talk, by the way. And it's true, right? It's true, it's sadly true. And I feel like that what we do in interviews and what we do in our day jobs, there's a bit of a disconnect there. And we don't spend enough time talking about the interviewing side. So let's talk about the interviewing side. These are the coding interviews I'm familiar with that are in wide practice. You can have take-home problems where they give you some challenge that you work on with or without a time limit. Technical interviews where you work with one of their employees often involve some kind of pairing, but it's probably not like normal pairing like you do on the job. Mostly it's them watching you struggle to figure out some problem or something like that, maybe providing a little bit of insight or questioning. There's the whiteboard interview where you're programming on a whiteboard or in a Google Doc or something like that. And then there's, I've seen auditions where people have you do some real work on their application either on your own or with help and then they judge you based on that. So I work at NoRid Inc. And as part of my job, I do grade take-homes, I do technical interviews. So I see a lot of what doesn't work. And I think I have some tips that I can give to help you get past those problems. And it's kind of in my interest to do so, right? Like if our director of engineering comes to me and says, let's hire eight new people this year, if I could find a bunch of good programmers, say like in May, then I could take a few months off from interviewing, right? So that would be just great. And okay, this talk comes with caveats for sure. First of all, you know, there's no guarantees. I am gonna tell you the major mistakes to avoid. And I'm gonna try and raise your chances in your interviews, but it's well known that the mood of your interviewer, their level of training they've had, these are all things that are out of our control. So it's definitely a numbers game. I'm sorry about that. I wish it wasn't, but it is. And that's something we can't fix from this talk. I'm also not gonna judge the various interviewing practices. I think there's things our industry does well. I think there's things, plenty of things our industry does not do well. That's a great conversation to have, but that's not this conversation. There was a really good talk yesterday called Hiring People with Science. If you didn't catch that talk, you should probably watch the video. It gets into some of this, and it was really good. Also, I am not familiar with every kind of interview out there. For example, the whiteboard interview, I've never taken or given one, so I won't have much to offer there aside from general tips. And finally, if you do everything I tell you to do in this talk, it's gonna take a lot of time and your spouse and family are probably not gonna be that happy with you, so it's up to you to apply the appropriate filter of how much you should do here and for your needs. Okay, can't be out to side. Let's talk about what you can do. The worst thing you could do is show up to the interview and then start trying to pass the interview, right? You need to do some things to get ready to help you swing the odds in your favor. And the first one is to study. Interview questions are pulled from a well-known subset of computer problems. So if you are more familiar with those kinds of things, you're going to do better in the interview. And it may not be stuff that you are using every day in your job. So if that's the case, it's really important that you kind of load this back into your brain. These are some of the concepts I think are the most useful. I've cross-checked this list with a couple of different sources. They all pretty closely agree and I've kind of put my own interpretation on it. I've kind of arranged it so that the most important stuff is at the top and to the left. So if you kind of work your way this way as you have time, I think it's probably the most helpful. But these are things that you need to know. And it's not that I think you will be asked to implement a binary search directly, but sometimes just being familiar with these concepts can help you in some ways in an interview. And we'll talk about that. So I stuck big O notation in the upper left, which might seem a little bit surprising, but I think it's more important than people give it credit for. This is a tool for understanding how long your code's going to run or how much memory it's going to eat up in the upper bound. And I would say that I think it can actually help you solve problems easier. We'll get into that in just a second, but take a look at these lines. These are different common complexities for algorithms. And it's a big difference if you're on that green line that slowly climbs up, whereas if you're on that orange curve, which is almost a straight right to the top, right? That's a big difference. And understanding the difference between these can be very powerful. So I think big O notation kind of gets a bad rap. I think we think of it as a formal tool that only matters when we're documenting something or things like that. But I don't think that's the case. I really do believe it's useful even in programming and maybe even more especially in interviews style programming. So let's take a quick big O notation quiz. Let's see if you remember how much you remember. So I'm gonna give you a few seconds. Think in your head of what you think the complexity of this code is, and then I'll show you the answer. Okay, gotta guess. This one is big O of N. It's a linear algorithm, right? The two important bits are right here. We scan over the data the entire set twice, summing once and multiplying the second time. That would be two N, but in big O notation we drop constants and non-dominant terms. So it's just N, right, it's linear. How about this one? This is the classic recursive algorithm of the Fibonacci sequence. Give you a few seconds. This one is big O two to the N. And I wanted to show this one because if you run into recursive algorithms there's a formula you can use to figure it out. So this line right here is the important one. It's however many branches there are and then however raised to the power of the depth you have to go down. So in this case we're making two recursive calls. One with I minus two and one with I minus one. And we have to go down however many steps in the sequence based on the parameter that's passed in. So that's a formula for figuring out recursive algorithms. Okay, this one's more complicated. So super bonus points if you get this one. All right, anybody think they know it? I'm sorry. N log N. That's kind of part of it. This one is big O, B log B plus A log B. Which seems horribly complicated, right? But it's not quite as challenging as it looks I think if you break it down. So this is the sort right here. Ruby uses a hybrid sort and like most good sorts it's B log B or N log N. So that's the first term of the answer. And then the second term of the answer comes from these two lines. We're scanning over A and for each element in A we're doing a binary search on B. So they're dependent work. You have to multiply them together. So that's where the A log B comes from. The sort is independent from that. So we added on. And don't feel bad if you don't know these or you didn't get these. I took a big O quiz when I was preparing for this talk. I'm like, I wonder how well I would do. Yeah, I miss plenty of them. So it's not like everybody gets these right all the time but studying them will give you some advantages. I'm gonna try and make the case for that now. So let's do this. This is a classic interviewing problem. I pulled it from a list of interviewing problems. It says given two sorted arrays find the elements in common the arrays are the same length and each has all distinct elements. So the most obvious solution to me is something like this where you would scan over one of the sets and for each item in the set you would see if it's in the other set. This one is, I believe, big O N squared, I guess, because as you're running over the set you can potentially have to run over the other set to the entire set for every item, right? So this is the brute force approach and, but just looking at the problem and knowing what I know, I know that the sets are sorted, I know they're distinct, I know they're the same size. If I use all of that knowledge then I'm guessing there's a linear solution, right? I suspect that's the best I can do that I can walk through the set one time and know what items are shared. I can try to figure that out on my own and that might look something like this. This is kind of the way I just described it where I can scan over one set and collect the answers. Meanwhile, I can keep a pointer into the other set and I can bump it along whenever I pass a certain size because then I know I won't have to consider those anymore. But this is hard for me to think about and I don't know if I got it right. I think it's linear but I'm not entirely sure. Anyways, it's complicated, right? But if you're familiar with things like bigger notation and how we measure complexity, there's easier ways to get to a similar solution. So we could do something like this. Why don't we just run through the set, one of the sets and load it into a hash. And then let's run through the other set and check it against that hash. We made two passes but they're both linear, right? So we're still at the linear algorithm and we added a hash insertion check but that's constant time, right, on a hash. So it's a non-dominate term and we end up dropping it anyway. So this is a linear solution and it's much easier for me to think through this one and realize it. So that's my argument that this can be a tool to find easier solutions to problems. Ruby can help you as you're playing with these things. Many tests include some assertions that will give you inputs and then measure the time your code takes to run and fit it to a curve to see which category it falls in. This code's a little small and I apologize for that. You're not missing much though. This is the recursive algorithm I showed you earlier for the Fibonacci sequence. This one is pretty much the same thing except it's inside a default block for Ruby hash which gives us memoization, right? Once a value's been calculated it'll be in the hash and it's just cached. And then this is the dynamic programming version. So if memoization is coming at the problem from the top down with caching, then dynamic programming is coming at it from the bottom up and building up to the correct answer you want, right? Just three different ways to calculate the same thing. So then we can test these with Minitest using Minitest benchmark. You get these assertions and you can say I expect this algorithm to be exponential. The problem is this algorithm is so bad it quickly overwhelms Ruby. And so I had to change the inputs down to a set that would keep it something that can execute in a reasonable amount of time. And in this case I really had to chop the inputs down so maybe not a lot of data points which is kind of bad. But that's kind of a bit of feedback too. If your algorithm overwhelms Ruby quickly it's probably not a great algorithm, right? So that you can kind of still use that as a guideline. This is the memoized version. It's linear, still a little bit more than Ruby could handle but they only had to trim the range. It's tiny bit I knocked off the highest category, that's it. And then the dynamic programming version Ruby could handle just fine. Which kind of surprised me. The hash version is happening mostly in C you would think I expected that one to do better but it didn't. So these are some tools you can use to play around with algorithms and find what they are. Let's look at a different problem. This is not a coding problem, it's a brain teaser. It says you have nine balls, eight are the same weight and one is heavier. You're given a balance which tells you only whether the left side or right side is heavier. Find the heavy ball in just two uses of the scale. I'll give you a couple of seconds to think about this and see if you can come up with the solution. Does anybody think they know how to do this one? Ideas. My daughter illustrated this one for us. So if we put three balls on the left side and three balls on the right side and leave three balls on the table, if the left side's heavier it's in that set, if the right side's heavier it's in that set, if they're even it's on the table. Either way we've narrowed it down to a set then we can do the exact same thing with one ball each and find the heavy ball, right? This is part of what I was saying when being familiar with certain concepts can help you get to answers to interviewing problems. So this problem I think you are more likely to figure out if you've played with things like binary search or merge sort, this is kind of similar to those principles, right? And dividing them out into categories and managing those categories individually. So that's what I meant by just being familiar with the concept even if you don't specifically have to implement that algorithm. No matter what you need to practice these kinds of problems, I wish there was a better way but there's not. My favorite site for doing the practice is exorcism.io. The problems are fairly good sized, they're pretty consistent and while you solve them you can participate in the feedback mechanism on the site so help improve your code at the same time. You need to get to where you can solve exorcism style problems in under an hour, right? If you have a technical interview that's an hour and a half maybe you're not gonna be coding the entire time so really you gotta be solving these problems in under an hour. You can also use my older site rubyquiz.com. There's more problems there but they're less consistent so you gotta kind of take it with a grain of salt. Exorcism is probably more useful. If you really wanna go all in, this book is over 600 pages of programming interview problems. It's got explanations, general advice, it gives you lead-ins to the problems, discusses the answers. This is the deep dive right here. If you go through this book and get to where you're familiar with the problems in it you're pretty much ready for anything I think. So if you wanna go that far. Another thing I would recommend that's not about solving problems specifically, you need to have some open source. You wanna be able to send it to them or get it to them in your cover letter is a great place to put it when you're applying but it doesn't have to be a big gem. A small gem is fine. In fact I prefer it when I go to look into your open source if I don't have to read through thousands of lines of code to figure out what's going on. So having even a hundred line gem is great. Focus on things like having a great read me, clean code with small methods, tests, documentation, the kind of stuff you do in your day to day job hopefully. And that's what's great, right? Is that they get to see you as you are in your day to day job, right? Which is something they don't necessarily get out of some of the things in the normal interview process. So this can help. Okay, that's enough for preparing. What about when we actually get to the interview? These are the things you should do while you're there actually taking the challenge. So first of all let's talk goals. Your main goal is not to be seen as a bad hire. We have lots of information that tells us that good hires are good, but bad hires are really bad, right? It's not just the performance of the bad hire itself. They drag down the performance of other employees. So it's like a multiplier, right? It's bad. So companies are optimizing for avoiding bad hires, which is good news actually. It means if you can avoid making major mistakes, you look a lot better than a lot of other people. So really you wanna try to just avoid making major mistakes. That should be your primary goal, okay? And I'm gonna give you some tips for things you can do to do this. Number one, you have to read carefully. You must understand the problem you are trying to solve or you are not going to solve it well, right? This is pretty straightforward. If you're being given the problem verbally, you have to ask clarifying questions until you really have your head around it. There's two reasons for that. One, you have to understand the problem. We've already talked about that. But two, if you are taking the problem from someone else, then your goal is to get that person on your side. And it begins with this conversation, right? Specking out the problem, understanding what you're trying to do. That's what you're trying to accomplish here. And a lot of people make this mistake. It's a basic mistake. When I interviewed at No Red Ink, a very nice guy, Michael Glass, who interviewed me, gave me a problem to reimplement set time out in Ruby. And the very first thing I did, I was like, oh yes, set time out in Ruby. I know what we're talking about. And I just cracked open a text editor and started writing a test about how I was gonna test the different threads going on. And Michael's all, no, no. In JavaScript, there's no threads. There's just this one stream of execution. I want you to do it like that. Oh yeah, that. So everybody makes this mistake. You have to understand the problem. It'll save you. Following directions, this is important. Lots of people don't do this. It's a little bit shocking. Here, I'll give you a pop quiz. Let's play a game. If the problem says, you should use git, should you use git? Yes or no? Yes, this is a good idea, right? If they said that, then they have some reason for it. Something they're trying to get out of it. Like, maybe they're looking at how you structure your commits, how big they are or not. Perhaps they're checking the amount of time it took you between commits. They can see that. But anyways, they have some reason for telling you that and you should do it. Here's another one, a little bit trickier. If the problem says, no one has ever solved this using Rails, should you use Rails? Yes or no? No. Why did not everybody say no? Were you thinking in your head, yeah, but I could be the one? Right, is that where you were thinking? You're not gonna be the one. I'm sorry to break it to you. And you don't need to be. Why tie one of your hands behind your back? Why make it harder? Why don't you try to just solve the problem well? That's easier, right? So don't do it, don't do that. Stop and think. As programmers we are just, we'll jump right in, we'll start coding, it'll come to us, we can always refactor, right? Yeah, okay, but if you're on a time limit, you gotta use your time well, right? And using five minutes to make a plan so that you use the rest of your time better, we'll pay you back, right? It's okay to build a plan. It doesn't mean you're doing waterfall development. If you build a simple plan, okay? It's okay. In fact, I feel like this is important enough that we need another hilarious tweet. So here you go, right? Okay. When you're doing this thinking, you have to think out loud. And this is tough for some people and I really feel for you. I know that some people struggle with this. Loudmouths like me, we have no problem with this. We can't stop talking. But some people do struggle with this. If you do, you need to practice. In front of a mirror, you can have you and your friends interview each other. You can do it with a spouse, significant other, whatever. Until you get the hang of it, you must externalize that internal monologue. I interview multiple people that get to a part and they start thinking and they just stop. They stop talking. And I try to be respectful of it. I give them a little time and then I'll ask a question like, can you tell me what you're considering? And I've actually had people say to me, hang on, I just got to figure this out. And I'm like, yeah, I know. And I got to figure out whether or not I want to hire you based on what you're figuring out. Right? So we have to know what that is. We have to be able to understand it. When you're doing this, work in magic words. There's some great magic words that help. My first thought is whatever. After that, it almost doesn't matter. I don't care if your first thought's a terrible idea, right? It was your first thought. And then I get to watch you walk through the process and see if it's good or bad, right? I'm considering the trade-offs. I love hearing this one. Hopefully you know by now that all of programming is trade-offs and you're always weighing one thing versus the other thing. If you tell me you're considering the trade-offs and then you make a choice that I wouldn't have made, I won't hold that against you. I know that you know that there were trade-offs involved and for whatever reason, your experience told you this path was better. That's fine by me. If you're considering it, I'm good. I might circle back to this. All programmers write code they don't like. Hopefully you know that too. And we write things and we're like, I'm not totally satisfied with that. Maybe I'll come back when I have a better idea. It's great to hear that, that you know that, that you're aware of that, that you'd love to improve it. But right now you're gonna get on with solving the problem. These three magic words are the most important. I don't know. Say it. Apparently this is very hard for people to say. Very hard. If I can't make you say I don't know in an interview, it's a huge black mark against you as far as I'm concerned. It's, think about the one thing you know really, really well. Maybe better than anybody. Maybe it's Ruby programming. Maybe it's Golf. Maybe it's Pin in your Warhammer 40 game managers. I don't care. One thing you know really well. Think about how much it annoys you to listen to other people talk about that thing when they clearly don't know what you know, right? That is you in every other subject, okay? There's a lot of things we don't know. You need to get comfortable with admitting that, right? Like there's no reason not to say that. There are things your interviewer doesn't know, right? You just say, I don't know. It's not that hard to say I don't know. Yeah, right, I don't know. Okay, I wish I didn't have to have this slide in there, but we interviewed a candidate who was doing a CSS recreation of a page on our site that happened to include a woman model and they were making sexist comments about the woman model as they worked. Please don't do that in an interview on the job ever. Just don't, right? We wanna know that you have a personality, a sense of humor, that would be great, but please keep it appropriate. If you are a five-year-old deciding which dessert you're going to have is the hardest decision of all, if you're given an interview problem, there's a hard part in the middle, the core of the problem. It's a search, a sort, an algorithm, a thing that does the work, transformation of data, the interesting bit. That's the part they want to see you do. Start there, do that first. This is the most common mistake I see people make in solving problems. They read the problem and they think, oh yeah, I know what they want me to do. I know what they want me to solve. They start building this elaborate object tree, doing all this setup work, data import, beautiful UI, whoops, time's up, that's what they submit. They didn't do the problem, they didn't get to the thing. If you run out of time, you wanna know you did the thing, right? The important bit. You can always say, oh, I didn't get to the data import, but that's like two lines of CSV code or whatever. But you want to have worked on the interesting part. So start there. Also, while you're doing that really interesting part, because you're faking out input and you're hard coding decisions from the UI, go ahead and just make it a test case. It's the same thing. It doesn't cost you any extra time. You can test the success case, you can test a couple of edge cases, and here's the killer secret. No one does this. No one. So this is a massive advantage, and it doesn't cost you any extra time. You don't need to test the whole thing. When you get to the data import in the UI, whatever, drop the testing, that's fine. But when you're doing that core bit at the beginning, test it. You will look amazing. No one does this. It's a great secret, I promise. Avoid dependencies, right? Unless the problem specifically says you're working with something, the interview problems are of such a scope that they're simple problems. They're not the kind of thing where you need to drag out rails. Don't do that. They don't want to see that. They want to see if you can think through a simple problem. They want to see if when the sales team asks for a certain report, are you going to be able to take some data, munch it around, and come up with it, right? That's what they're looking at. Also, don't use rails means don't use rails, and it also means don't try to recreate rails and then use that. Just that's wrong scope, wrong scope. You're off the map, right? Keep it simple. Along similar lines, right less code, I feel compelled to point out I got mad about this picture because my daughter was not following directions. I told her to draw ones and zeros. So what is this butterfly thing? I don't know. I told you, I've become that interviewer, you know, that one we don't like. But in my defense, I used this picture. I had another one without the butterfly and I used the butterfly one. Seriously, don't gold plate. You have to keep your solution small enough that it doesn't overwhelm me to go through it. If I crack it open, it's 500 lines of code, and the first thing it does is fire up a Lexer and run some stuff through that and hand the tokens off to a parser. My eyes have already glazed over and I don't care what you did. So you're, again, you're off the map. You're in the wrong scope, right? Ignore bonus challenges. Don't do it. It's not worth it. It's a trap. Okay? It's a trap. Luke, it's a trap. Yeah, don't do it. Here's the problem with bonus challenges. They often involve extra work. You probably have to do more data import. You gotta get right some extra UI code. And here's the insidious part. When you read it, you think, oh, I'm gonna write my solution so that when I have time and come back, I've already set it up for the bonus challenge. Okay, you're not gonna end up having that time. So you're not gonna come back and what you did is you made the main problem harder. Right? Don't do it. Ignore the bonus challenge. It's not worth it. If you do that part of testing the core, it's worth 10 times the points of the bonus challenge. Just test the core bit, forget the bonus challenge. This is good news for you. When you read the words extra credit, you can interpret them as I can completely ignore this. It's great. It's like a advantage. Time limits can exist for several different reasons. One might be that the company wants to know what you can do in a certain amount of time. Another might be that they're trying to keep you from sinking massive amounts of your time into something that they glance at for five minutes and say no thanks. Right? So there's lots of different reasons time limits can exist. You don't know what reasoning they have for using it. So if you're working on a problem and you're close and you're not done, go ahead and submit what you have at the time limit. Then if you wanna finish it, go for it. Finish it. If you're 30 minutes over the time limit, wrap it up, send it in and say, had the problem in my teeth, wanted to find that last bug or wanted to handle this other case, here's what I got, feel free to ignore. Right? They can do that. You already submitted what you submitted on time. They may ignore it. They may go with that one. But for me, I will always grade the later one. For me, knowing that you wanted to finish the problem means way more to me than what you could do in the specific time limit. So that, you know, it can't hurt, right? Go ahead and submit. And finally, if you are taking the interview face-to-face, you need to practice your text editing skills. Get good at it. This is a bias, but when people watch you using your text editor and they see you using shortcuts, they think that you work with code all the time, that you've developed these coping mechanisms that you've practiced it. And so you come out looking better, more prepared. You don't need to know every whiz bang feature in your editor. If you're like me and you use Emacs, that's literally impossible. I won't live long enough. But you need to just pick five. It doesn't matter. You won't have that much time to show off that many anyway. Make sure one of the ones you pick is multiple cursors or macros because these are wow features, right? Whenever you see somebody use multiple cursors or macros, you're like, whoa, how did they just change those 10 things at once? That's amazing, right? So it sticks with you. Just make sure you have some editing skills to show off. You probably won't work all of these in every time. That's okay. Interviewing is hard for everybody. That's kind of the point, right? They're watching you struggle with a problem. They want to see you struggle. It's supposed to be hard. But everybody else is doing that too, right? You're not competing against the problem. You're competing against the other candidates, right? So avoid the major mistakes and you're gonna look pretty good compared to those other candidates. So it's okay for it to be tough. But if you work over these things and practice these things, I believe they will increase your chances. All right, thanks for your time and good luck with the interviews.