 I want to talk about algorithms today and what they are and why we want to use them and a few other examples. So algorithms is a list of instructions for accomplishing a task. We follow algorithms every day when it comes to activities like getting to work, like making ice cream, like baking bread for example. So I think that many developers like baking bread because it's so appealing exactly because it's a function of five things, five or six things. So you take flour, water, salt, yeast, thyme and temperature and you mix them together in all kinds of ways to create your final product. Mine, I did that two weeks ago. So algorithms I use with computers are in mathematics and must be very detailed to resolve the ambiguities that we take for granted in our lives. For example, if I say to you, go and make me a sandwich, you know exactly what to do, sort of. You ask me what I want on it but pretty much you know how to make a sandwich. When you tell a computer how to make a sandwich, for example, you need to be a bit more specific, something like grab the fine a bread knife, slice two pieces of bread, butter one side on each side and so on and so on. Computers just don't understand the general, they need more detailed instructions. An algorithm also embodies the search for efficiency and perfection. So basically it's the most two important things about an algorithm that it solves the problems that you have at hand and then it does so efficiently. Now we always need to find the balance between those two things and know when to stop when our program is just, is it good enough or can it be better? Not all algorithms are used online. Some of the non-web users that we see all the time is in traffic control. It is estimated that an intelligent traffic control system can save billions of dollars every year by reducing idling time at traffic lights. So traffic control systems are based on dynamic programming, algorithms that consider the time needed for God to go between a string of lights until it gets to its destination, what we usually call the green wave. In everyday life, we have algorithms that are somewhat learned like arithmetic, some that we figure ourselves, for example, looking up a dictionary definition and others that are written instructions, for example, recipes, driving instructions, or everybody's favorite assembly and Ikea feature. If we can define an algorithm in one sentence by saying that it's a precise systematic method for producing a specific result. Algorithms can help us entangle very human questions and give us strategies for how to live our lives. They can explain how to have better hunches, how to deal with overwhelming choices and when not to overthink a decision. They help us deal with unknowns in complete information and an unforeseeable future. They can also help us find a partner or the shortest path to a destination. In this talk, I want to introduce eight different problems and different algorithms that we can use to solve them. So shall we start with the first one? One that everybody always mentioned about job interviews, like when are we ever going to need binary search? So let's tackle that one. So let's suppose that we want to search for a word in the dictionary and we learn that if we look for the word Ruby, for example, we will open the dictionary somewhere in the middle and we'll figure out are we, is it before or after and then we'll adjust accordingly. So binary search works very similar. It's an algorithm that takes an input of a sorted list of elements and then if the element that we are looking for is in that list, it will return the index of where the object is. If it can't find it, it will return a null. So for a different example, I'm thinking of a number between 1 to 100 and I'm asking you to guess the number. In the fewest tries possible, with every guess, I will tell you if you are too low, you are too high, or you're just right. So if we took an approach that say I'll ask you, is it one? I'll say too low. Is it two? Too low. Three, too low. Four, still too low. So this is not very efficient. We can try something a bit better. So a better approach will be you can ask me if it's 50 and if I'll say it's still too low, then we already eliminated 15 numbers in our search. Next, we will do exactly the same. Take between 51 to 100. We'll take the middle and you can ask me if it's 75. And then I'll say, oh, this time it's too high. So this time we eliminated another 25 more numbers. And we do the same until we find the last one. So if we start with 100, the first time we eliminated 50, the second we eliminated 25, then 13, 7, 4, 1, 2, till we get to our one number that we looked for. So it took us from 100 numbers, seven steps to get there. If we take that number up to 1,000, we can go, we can find the number within 17 steps. If we take that number even higher to 100,000, sorry, for 1,000, that's 10 steps. For 100,000, that's 17 steps, which is, so the number 17 comes from a binary log of 100,000, which is almost 17. So what is that exactly? So usually this should be very familiar to everybody. So 2 squared is 4, 2 to the power of 3 is 8. We all see that number 16, 32, 64, and we can continue onwards. Let's switch them around. So this time the binary log of 4 is 2. The binary log of 8 is 3. If we'll take the 100, we get our 7 steps, or 6.643. If we take 100,000, we get our 17 steps. So it's a lot more efficient using binary search to find something that you're looking for. We know exactly the maximum number of steps that it's going to take us to find that. Take away from binary search is that it only works with sorted lists. It will not work otherwise. Let's assume for a moment that we are searching for a new place, and our assumption is that we are looking for the sake of simplicity that we care only about maximizing our chance of getting the very best apartment available. So how are we to know that an apartment is indeed the best one that we can find if we don't have a baseline to judge it by? Now, how do we establish that baseline unless we look and possibly lose a number of apartments? So the more information that we gather, the better we will know the right opportunity when we see it. But it also means that we are likely have missed it already. So what can we do? How can we make an informed decision when the very act of getting informed jeopardizes the outcome? The same you can say about finding a significant other. When practicing serial monogamy, we are faced with a fundamental problem. When have we met enough people to know our best matches and exactly the same problem as before? What if acquiring that knowledge cost us that very match? This is a problem of optimal stopping. And in any kinds of those problems, the crucial dilemma is not which option to pick, but how many options to even consider? This problem was introduced in the 50s as the secretary problem, if anybody is familiar with this one. In this case, in this problem, we are interviewing a set of applicants for a position as a secretary. And our goal is to maximize the chance of hiring the single best applicants in the pool of applicants. In our search for secretary, there are two ways we can fail. We can stop too early or we can stop too late. Again, as we said before, if we stop too early, we'll leave the best applicants undiscovered. If we stop too late, then we hold out for better applicants who doesn't expect. The optimal strategy will clearly require finding the right balance between looking too much and not enough. It includes two stages of what we call look-dennerly pool. We set a pretty fine amount of time for looking. So explore our options, gathering data, not making any decisions in which we categorically don't make a decision no matter how impressive the person is. Then we enter the leap phase, where we are prepared to instantly commit to anyone who outchines the best applicants that we saw in the look phase. To know when to enter the leap phase, there is a simple rule that says 37%. Research says that we should be looking for 37% of our time and then be ready to leap. So 37, in this case, is our magic number. As it turns out, following this advice ultimately gives us the 37 chance of finding the best option anyway. This changes if we have full information. For example, if we decide that we want to hire a secretary based on spit type, so we set a threshold, then we have full information and we can decide to hire the first person that matches or outchines that threshold. In an optimal stopping problems, when we don't know all the options, then optimal stopping tells us when to stop and make a decision. Let's say we're going to visit grandma and we go up to grandma's attic and we are looking for a diary that we left there. And grandma tells us that it's in this one box where. And when we look inside the box, it contains small boxes in it. So one way, one approach that we can use to solve this problem is to go through a loop. So we make a pile of boxes. While the pile is not empty, then we grab a box. If we find another box, we add it to the pile of boxes and then we go back to the pile and start again. If by any chance we find a diary, we add that. Simple loop. Every programming language has some kind of a loop that we can use. But again, we can do slightly better. Let's say we go through each item in the box. If we find a box, we go back to the beginning. And then we go through each item in that box and then we start again. If we find a diary, then we are done. That's pretty much what recursion is. It's a method that calls on itself. It can be applied whenever a problem can be solved by divining it into smaller problem that can use the same algorithm for solving them. Think about Russian dolls. Every time you open a doll, a smaller one will be inside and we repeat the process again and again. A recursive method calls on itself again which is easy to write a method that ends up in an infinite loop. Therefore, we need to tell it when to stop. It's easy to explain that when we look at a factorial method. So in a factorial methods, we have a recursive case when the method calls on itself and then we have a base case when the function doesn't and it actually exits. So in our case, in a factorial case, when we call factorial four, it will call four times factorial three. Factorial three, we'll call three times factorial of two. Factorial two, we'll call two times factorial one and one will pretty much return one and not calling itself again, which gives us four times three times two times one, which is a 24. So recursion can be applied whenever a problem can be solved by dividing it into smaller problems and then you always need a recursion case and a recursive case and a base case. Next problem. Imagine that we want to alphabetize a bookshelf or collections of books. The first sorting algorithms that we can find could be or a natural approach could be just to run across the shelf looking for out of order items. For example, Tolkien follows by Adams and then switch them around. Put Adam in front of Tolkien's and then continue with our scan. When we get the end of the shelf, we start again. Whenever we get to a point where we don't find any out of order matches or out of order pairs, then we are done. Very inefficient. This is called bubble sort and it's not very efficient. So let's try a different sorting algorithm. This time let's pull all the books off the shelf and put them back in place one by one. So we'll grab one, first book and we put it in the middle. We'll grab the second book and we'll decide to put it to the left or to the right. And then pick in the third one. We decide again where to insert that until we are done with the whole stack. This is called insertion sort and it's slightly better but it's still not a winner. Shall we try again? Sure. Third go. Once again, we pull all the books off the shelves but this time we divide and conquer. We divide them into two stacks and then we sort each stack exactly like we did before. Once we have two sorted stacks, then it's easy to sort them back on the shelf. We just compare the top two and decide which one goes first and which ones are next and then continue with the rest of the list. This is called merge sort, so slightly better but I wanna talk about another sorting algorithms. There are more but I wanna mention one more. The next one I want to give an example of arrays and this is called quick sort and again we will use a divide and conquer technique. When we are looking at arrays, if we have an empty array or we have an array with just one element in it then we don't need to sort that. It's already sorted for us. So this will be a base case. You can just return those arrays as is. There's nothing to sort. If we have two elements, we can check which one is smaller than the second one. If the first one is smaller than the second one and if not, we can switch them. But if we have an array with more elements on them, then we're going to start by picking a pivot and in this case, let's pick the first element in the array. The next thing that we're going to do is we're going to divide the rest of the array base if it's less or more or greater than our pivot. Again, if you look at the two arrays that we are left with, they are not sorted as well but we can pretty much use the same function again to sort those once more. This time, if they were sorted, we can pretty much just have done left array plus a pivot plus a right array and get a sorted array in the end. So if we apply the quicksort on both of those side arrays, we can reapply them and get a sorted arrays on each side which we can then combine together to get a sorted list. The question that we should be asking ourselves when we think about sorting algorithm is should we be sorting at all? Once again, we should consider the balance between sorting and searching in this case. How much effort does it take to sort our inbox versus how much time it takes us to search through it later? So an unsorted might be a good idea to do or reasonable thing to do but when we consider our inbox, for example, it's certainly not. There's a lot of time wasted sorting emails when searching bits sorting very easily. I listened to a podcast by, I can't remember, I think it was Rails five by five that they interviewed John Medina when he was talking about how when you teach people you really should have intermissions every now and again just to keep focus up. So I guess we got that. Okay, next problem I wanna talk about is single machine scheduling or getting things done. So I mean that we have a backlog of things that we wanna get done and then we need to decide what to do, when to do and in what order to do those things. Now we always manage to get a list of things of to do done in some way, one or another but generally we don't consider ourselves very good at doing that. Hence the perennial time management guides that we get all the time. All those guidebooks gives us different strategies to solve that problem. For example, and they can be very inconsistent at times. For example, getting things done advocates a policy of immediately doing any task that takes less than two minutes or less. A different advice can be to begin with the most difficult task and move towards easier ones later. One more suggests scheduling fun things first and then filling them in with worth stuff. And then others make the case for waiting and deliberately not doing things right away. So everyone has a different system and it's hard to know who to listen to. But when we talk about single machine scheduling literally before we even begin we need to make a goal explicit because if we can't declare some schedule a winner until we know how we are keeping score. Before we make a plan we need to just define a metric. We can have one strategy which is the earliest due date. So if we are concerned with minimizing being late the best strategy to start with the task the task that you did you soonest and work back towards the task that you lost. Another strategy could be more algorithm. So in this case we want to minimize the number of spoiled foods that we have in our fridge. This algorithm says that we start just as before with scheduling a produce in order of spoilage date earliest first one item at a time but the minute this doesn't work out for us and it looks like we're not gonna get to eat the next item on the list then we pause and we reconsider what items we have left we review the meal plans that we have and then we throw out the biggest items that we have the one that's gonna take us the longest to eat and then we continue with whatever we have left. So for instance it might mean that for going the in my case it was a watermelon I think it would have been more appropriate to use a pumpkin that would make half a dozen servings to eat. So not even attempting it will means getting to everything on our list much easier. One more strategy that we can consider is the shortest processing time. So maybe due dates is not a concern for us. Maybe we just wanna get stuff done as quickly as we can. Considering that we cannot change how long it's gonna take us to go through the list anyway it's gonna take us the same amount of time to finish all of them. But let's think about this problem tiny bit different. Let's consider each task as a waiting client. Then there is a way to take up as much or as little of their waiting time while we finish our tasks. For example imagine if we start on a Monday and we have a four day task and a one day task. If we look at the first one we say four days task it's gonna take a client four waiting days to wait to get the project completed. And but if we look at the second client then they will have to wait five days to actually get their project or their deliverables done. So in this case we have a complete of nine days of waiting for both of those tasks. But what about if we switch them around? In reverse if we reverse the order we can finish the small task on Monday. So one client gets one day of waiting time. And then the next client will have five days of waiting time. So we have a total of six days of waiting. So it's a full work week for us but we saved our clients three days of their compiling times of waiting. Scheduling theories call this metric the sum of completion times. So minimizing the sum of completion times leads to a very simple optimal algorithm that's called shortest processing time. So we always do the quickest tasks that we can find. It also helps us with it reduces the number of outstanding tasks as quickly as we can which reduces mental load which makes it easier for us to focus on what we have left to do. Next problem. Suppose we wanna find a magician in our network of friends and you can choose whichever network if you use Facebook, LinkedIn, whichever. To solve this problem it's easy to think or to use something that is called a graph. A graph models a set of connections and models how things are connected to one another. In a graph we have a node and an edge. A node is for example in our case could be people and then they are connected to other nodes with what we call an edge. If we look at an example of my network of friends most of those people should be here. So we have and really the person that I'm looking for is Keith. Keith is a Rubyist from Australia who in 2007 won Young Magician of the Year. In a Ruby conference in Australia in 2014 he made his wallet go up in flames on stage. Trying to convince somebody and this was his point. If we look at the graph that we have we have I have my first degree connections and then those are my second degree connections and if the other person that you're not recognizing here is Michelle she's gonna be at the after party tonight so you'll get a chance to meet her. She's awesome, she's to ride horses or guide people on horses in Mongolia. Some conversation starter for later. So we usually prefer first degree connections to second degree connections and then we'll prefer second degree connections to a third degree connections and so on. This search radiates out from our starting point which in this case it's me and we'll check first degree connections first and second degree later until once we exhausted the first one. We can use a hash to define our graph. So in this case you can see everybody's connection as the values and then you can see also my first degree connections and once we go through them they get added. They get added to the hash as we go. So breadth first search works only when we search in the same order in which the people or the nodes were added to our hash. It also brings up different problems that is quite known which is called the traveling salesperson. In this problems you have a salesperson and he or she needs to travel through a certain number of cities and they are not allowed to go back through a city that they've been to already and you need to find the shortest way they can go through each city. So in this case if we take an example they might go this way or they might go this way or they might go that way so there's endless possibilities. In this problem on the other hand if we are allowed for backtracking are you going through the same point again then it makes it easier for us to find a solution. It might not be the optimal solution but if you're willing to accept solutions that are close enough then finding a solution becomes heaps easier. This is called constraint relaxations which just means by removing some of the problems constraints then we are set to solve the problem that we wish we had from the beginning and then later on we can just add a few more constraints later on. So the idea to take from that is just relax by relaxing the constraints we make it easier to find solutions. Next problem that we wanna solve is building a recommendation system. So suppose we are Netflix and we want to recommend movies to our users. We can approach each user on a graph to calculate the closest nearby users and therefore the people that are closest to us are plotted by similarities so the users similar to us have similar taste in movies and therefore if I like certain movies then probably the people that are close to me like the same movies again. In this case we can plot a graph that looks in this case on two axis and if we wanna find the distance between two point then Pythagoras comes to our rescue. Let's calculate the distance between A and B. To calculate that then we are told that we can grab on the X side we can grab the location of A and B and on the Y we do the same and we square them and we add them and we find the right. Simple. So in this case it will give us that which we can reduce to that which we get in the end a factor K of 2.236 and we can see just with eyes that A is closer to B then B is closer to C. Let's do this exact same calculations for B and C and to see if the numbers are different and we grab that the same and we do the same and we get a K factor of 4.473 so we can use that number to tell us whose closest to us. If we go back to our Netflix problems and again thank you Hannah, Caleb and Lachlan for helping me. I asked the guys to give me their ratings for each category of movies. So if we wanna recommend movies for Hannah for example we need to find users that are closest to her and if we look at that we can see that both Hannah and Caleb like comedy and action but they're not really into romance. On the other hand Lachlan for the sake of this example really like drama and romance but really not into action. We can use exactly the same algorithm or the same formula to find the distance between the users. We can plot them that way and then mathematicians would say that instead of calculating the distance between two dimensions we are now calculating the distance in five dimensions but the distance formula remains the same. So in this case if you look at Hannah and Caleb we get those numbers that reduce to those numbers and we get a k factor of 2.64. Shall we do the same for Hannah and Lachlan? Once again we calculate the difference between each dimension which in this case we get a k factor of 5.74 which means Hannah is closer in taste to Caleb than to Lachlan. And we can use whatever movies Caleb likes to recommend them to Hannah. So the Canearest Neighbours uses feature extractions which means converting an item into a list of numbers that then you can compare them in that algorithm. Thinking less. When Giles Darwin was trying to decide whether he should propose to his cousin Emma Wedgwood he got out of pencil and paper and weighed every possible consequences. In favour of marriage enlisted children, companionship and the charms of music and female chit chat. Against marriage he listed the terrible loss of time, lack of freedom to go where he wished, the burden of visiting relatives, the expense and anxiety provoked by children, the concern that perhaps my wife won't like London and having less money to spend on books. Valid points. Weighing one column against the other produced a narrow margin of victory for him and at the bottom Darwin scrolled Mary, Mary, Mary, QED. And himself he said then restated in English it's been proved necessary to marry, obviously. When we think about thinking it's easy to assume that more is better the more we consider things the better decisions we will make. The question of how hard to think and how many factors to consider is the problem that we call overfitting. And dealing with that problem reveals that there's a wisdom to thinking less. The problem with having too many facts is that they add noise and erroneous data to our decision. Stephen Krug in his book Don't Make Me Think said that, talked about user testing and he reckons that a fewer tests are better than too many because the more tests that you do the more noise that you get from them. Whereas when we do a few tests then we get the most pressing problems with the website or web applications. Occam's razor principle suggests that all things being equal the simplest possible hypothesis is probably the correct one. So just trying to keep it simple. Strategies for dealing with overthinking or overfitting is, for example, regularization. So introduce that, for example, limit the number of pros and cons that you can list. We did a retrospective once and we gave people only two posted notes for good things and bad things. Try to think of what's the most pressing thing that you have on your mind. Add weight to your points. So by marking them off, so if you mark off a point that weighs two points then you mark two ones with a one point which you remain the ones that are most important for you in the equations in the end. You can use early stopping. So the more you have time to think, the more complexity we introduce to the problem. Giving ourselves more time to decide about something does not necessarily mean that we will make a better decision. But it does guarantee that we'll end up considering more factors, more apotheticals, more pros and cons, and thus risk overthinking the problem. For example, state cliff on final details that we can relate to that, for example, when we do wireframes. So we should really use sharpies rather than fine pins to sketch our ideas. So we don't get caught up in the fine details of a wireframe. Pretty much the whole idea is that less is more. Deciding, going back to Charles Darwin, deciding whether to propose could probably have been resolved based on just the few pros and cons that he had on his list. Darwin identified that with subsequent ones, adding to the time and anxiety expending on the decision without necessarily adding its resolution. So what seems to make up his mind was the thought that it was intolerable to think of spending one's whole life like a new to be working, working and nothing after all. Children and companionships, the very first few points that he mentioned were precisely those that ultimately swayed him in favor of marriage. His book budget was a destruction after all. On April 9th, 2017, United Airlines Flight 3411 was preparing to take off from Chicago when flight attendant discovered that the plane was overbooked. They tried to get volunteers to give up their seats by offering travel vouchers, hotel accommodations, but not too many people took them up on those offers. So United ended up calling some airport security officers who boarded the plane and forcibly removed the passenger named Dr. David Dale. They ripped him his seat and carrying down the island off the plane. How did he ended up being the unlucky passenger? An algorithm that looked at the cost of the ticket, the time checking in, the part if they were part of a reward systems and a few other things decided that he was the least valuable customer on that flight. Yeah. Kathy O'Neill says that every algorithm reflects the subjective choices of its human designers. So we design algorithms, so we need to consider who that affects. It doesn't necessarily make the algorithms bad, but how should we address poorly designed algorithms? So think about maybe is trying to make them transparent and another thing to think about is paying attention to the people that get affected by them the most and what demographics that affects. And that's it for me. Thank you very much.