1 00:00:00,000 --> 00:00:00,530 2 00:00:00,530 --> 00:00:02,960 The following content is provided under a Creative 3 00:00:02,960 --> 00:00:04,370 Commons license. 4 00:00:04,370 --> 00:00:07,410 Your support will help MIT OpenCourseWare continue to 5 00:00:07,410 --> 00:00:11,060 offer high quality educational resources for free. 6 00:00:11,060 --> 00:00:13,960 To make a donation or view additional materials from 7 00:00:13,960 --> 00:00:19,790 hundreds of MIT courses, visit MIT OpenCourseWare at 8 00:00:19,790 --> 00:00:21,040 ocw.mit.edu. 9 00:00:21,040 --> 00:00:24,368 10 00:00:24,368 --> 00:00:28,100 PROFESSOR: So this week the last final 11 00:00:28,100 --> 00:00:29,720 topic we were taught-- 12 00:00:29,720 --> 00:00:32,460 we're really going to talk about in class is dynamic 13 00:00:32,460 --> 00:00:38,065 programming, so who can tell me what the key idea in 14 00:00:38,065 --> 00:00:39,315 dynamic programming is? 15 00:00:39,315 --> 00:00:42,092 16 00:00:42,092 --> 00:00:43,996 AUDIENCE: A way of [INAUDIBLE]. 17 00:00:43,996 --> 00:00:46,860 18 00:00:46,860 --> 00:00:49,540 Instead of optimization tools, you can use [UNINTELLIGIBLE] 19 00:00:49,540 --> 00:00:54,400 20 00:00:54,400 --> 00:00:57,270 PROFESSOR: Sort of. 21 00:00:57,270 --> 00:00:59,790 The key idea is that you don't want to repeat computations 22 00:00:59,790 --> 00:01:01,880 that you've already done before. 23 00:01:01,880 --> 00:01:06,690 So you want to find a way to only do everything once. 24 00:01:06,690 --> 00:01:10,190 So it's a form of laziness. 25 00:01:10,190 --> 00:01:13,820 There are two key attributes for a problem though that need 26 00:01:13,820 --> 00:01:18,600 to exist for it to be solvable with dynamic programming. 27 00:01:18,600 --> 00:01:20,540 Can someone tell me what those are? 28 00:01:20,540 --> 00:01:24,977 29 00:01:24,977 --> 00:01:28,921 AUDIENCE: It's optimal [UNINTELLIGIBLE] 30 00:01:28,921 --> 00:01:32,372 The local optimization has those. 31 00:01:32,372 --> 00:01:40,768 PROFESSOR: There's overlapping sub-properties. 32 00:01:40,768 --> 00:01:42,211 [LAUGHTER] 33 00:01:42,211 --> 00:01:46,300 You had all the right words, just not in the right order. 34 00:01:46,300 --> 00:01:47,825 An optimal substructure. 35 00:01:47,825 --> 00:01:56,510 36 00:01:56,510 --> 00:01:56,880 OK. 37 00:01:56,880 --> 00:02:00,352 Can you describe the first one, or any one? 38 00:02:00,352 --> 00:02:03,733 AUDIENCE: You get to the end solution [UNINTELLIGIBLE] 39 00:02:03,733 --> 00:02:06,631 40 00:02:06,631 --> 00:02:09,370 PROFESSOR: So when they say overlapping sub-problems, it 41 00:02:09,370 --> 00:02:12,490 means that we can take the big problem and we can break it 42 00:02:12,490 --> 00:02:17,550 down to a slightly smaller instance of the same problem. 43 00:02:17,550 --> 00:02:20,520 And then we can use the solution to that smaller 44 00:02:20,520 --> 00:02:25,290 sub-problem in the solution to our bigger problem. 45 00:02:25,290 --> 00:02:28,020 And then optimal substructure is closely related. 46 00:02:28,020 --> 00:02:31,270 It's saying that if we get an optimal solution for one of 47 00:02:31,270 --> 00:02:35,560 those sub-problems, then we can use that optimal solution 48 00:02:35,560 --> 00:02:40,080 for the optimal solution of the big problem. 49 00:02:40,080 --> 00:02:42,226 Does that make sense to everyone? 50 00:02:42,226 --> 00:02:44,058 AUDIENCE: [INAUDIBLE] 51 00:02:44,058 --> 00:02:46,820 PROFESSOR: What's that? 52 00:02:46,820 --> 00:02:48,260 It's closely related. 53 00:02:48,260 --> 00:02:49,510 And so it's-- 54 00:02:49,510 --> 00:02:53,540 55 00:02:53,540 --> 00:02:56,860 yeah, it's closely related but not exactly the same. 56 00:02:56,860 --> 00:03:00,010 57 00:03:00,010 --> 00:03:04,240 So to start off, we're going to do kind of a function that 58 00:03:04,240 --> 00:03:06,000 we're all familiar with, is Fibonacci, right. 59 00:03:06,000 --> 00:03:09,610 60 00:03:09,610 --> 00:03:12,390 We've seen this one a billion times before. 61 00:03:12,390 --> 00:03:18,500 62 00:03:18,500 --> 00:03:21,860 And so it's pretty obvious where the overlapping 63 00:03:21,860 --> 00:03:23,290 sub-problems are. 64 00:03:23,290 --> 00:03:27,903 The solution to f of N is f of N minus 1, and f 65 00:03:27,903 --> 00:03:29,980 of N minus 2, right? 66 00:03:29,980 --> 00:03:33,130 And so if I combine the solutions to these two 67 00:03:33,130 --> 00:03:36,940 instances of Fibonacci, I get the solution for the big 68 00:03:36,940 --> 00:03:39,400 instance of Fibonacci right? 69 00:03:39,400 --> 00:03:47,810 So on the screen, you have an example function. 70 00:03:47,810 --> 00:03:50,640 You've all seen this before. 71 00:03:50,640 --> 00:03:53,640 And so what I'm just going to do is I'm going to run this 72 00:03:53,640 --> 00:03:59,800 Fibonacci function from 0 to 30, or N equals 29 actually. 73 00:03:59,800 --> 00:04:02,850 And we're going to look at how many 74 00:04:02,850 --> 00:04:04,100 steps it takes to execute. 75 00:04:04,100 --> 00:04:11,730 76 00:04:11,730 --> 00:04:15,800 When we get to Fibonacci of 29, it takes about 1.6 million 77 00:04:15,800 --> 00:04:19,300 steps to compute the value. 78 00:04:19,300 --> 00:04:25,380 And if we take a look at a plot here-- 79 00:04:25,380 --> 00:04:31,610 so the y-axis is semi-log, the blue dots represent the actual 80 00:04:31,610 --> 00:04:34,030 number of steps that the function took, so the number 81 00:04:34,030 --> 00:04:36,690 of times that it had to perform the computation. 82 00:04:36,690 --> 00:04:41,600 And then the blue solid line represents 2 to the N. The red 83 00:04:41,600 --> 00:04:44,475 line is the golden ratio to the N, which is the tight 84 00:04:44,475 --> 00:04:48,440 bound for this version of Fibonacci. 85 00:04:48,440 --> 00:04:53,740 And then the green line is a plot of a quadratic function. 86 00:04:53,740 --> 00:04:57,130 So nothing really surprising there. 87 00:04:57,130 --> 00:05:01,080 It's pretty inefficient, and we established that before. 88 00:05:01,080 --> 00:05:04,330 So we could make this more efficient with dynamic 89 00:05:04,330 --> 00:05:05,580 programming, right? 90 00:05:05,580 --> 00:05:07,660 91 00:05:07,660 --> 00:05:10,950 Let's draw out the call tree for f of 5. 92 00:05:10,950 --> 00:05:29,420 93 00:05:29,420 --> 00:05:30,670 Doing a lot of writing. 94 00:05:30,670 --> 00:05:32,960 95 00:05:32,960 --> 00:05:34,940 OK. 96 00:05:34,940 --> 00:05:40,870 So if you look at this, we see that in a lot of places, we're 97 00:05:40,870 --> 00:05:42,740 repeating computations. 98 00:05:42,740 --> 00:05:45,860 So we repeat f of 2 three times. 99 00:05:45,860 --> 00:05:48,970 100 00:05:48,970 --> 00:05:53,305 We also repeat f of 3, this computation, twice. 101 00:05:53,305 --> 00:05:59,650 102 00:05:59,650 --> 00:06:02,260 The idea behind dynamic programming is that instead of 103 00:06:02,260 --> 00:06:06,150 repeating these computations over and over again, we're 104 00:06:06,150 --> 00:06:07,840 just going to compute them once. 105 00:06:07,840 --> 00:06:12,420 So if we look at the implementation of this 106 00:06:12,420 --> 00:06:16,930 recursive Fibonacci, we see that the first recursive call 107 00:06:16,930 --> 00:06:18,720 is going down this side of the tree. 108 00:06:18,720 --> 00:06:21,990 109 00:06:21,990 --> 00:06:29,070 And so the upshot is that this-- 110 00:06:29,070 --> 00:06:34,450 all the values from f5, f4, f3, f2, f1, f0, they all get 111 00:06:34,450 --> 00:06:38,950 computed before any of these branches. 112 00:06:38,950 --> 00:06:46,250 So what we can do is instead of recomputing f2 and f2 here, 113 00:06:46,250 --> 00:06:47,670 we can just compute it here. 114 00:06:47,670 --> 00:06:53,320 Save off this value somewhere in some sort of a brain, and 115 00:06:53,320 --> 00:06:59,030 do the same thing for f3, and f4, but that's 116 00:06:59,030 --> 00:07:01,000 not going to matter. 117 00:07:01,000 --> 00:07:04,290 So when we get to the second recursive call, say when we're 118 00:07:04,290 --> 00:07:09,650 calling Fibonacci of 3, we compute f of 2, get f of 1, we 119 00:07:09,650 --> 00:07:13,150 come back up to Fibonacci of 4, right? 120 00:07:13,150 --> 00:07:16,600 The next recursive call is going to be to Fibonacci of 2. 121 00:07:16,600 --> 00:07:19,140 But since we've already computed it, and we've saved 122 00:07:19,140 --> 00:07:22,250 it off in a brain, we can just look up this value instead of 123 00:07:22,250 --> 00:07:24,790 doing all the computation again. 124 00:07:24,790 --> 00:07:28,440 So when you have a very small tree like this, right, it's 125 00:07:28,440 --> 00:07:29,260 not a huge benefit. 126 00:07:29,260 --> 00:07:33,780 But if you have like a lot, like f of 100, this is going 127 00:07:33,780 --> 00:07:35,920 to make a huge difference. 128 00:07:35,920 --> 00:07:39,114 Is anyone lost? 129 00:07:39,114 --> 00:07:40,364 OK. 130 00:07:40,364 --> 00:07:43,360 131 00:07:43,360 --> 00:07:44,780 So why don't we take a look-- 132 00:07:44,780 --> 00:07:52,760 133 00:07:52,760 --> 00:07:59,870 So this is an implementation of Fib that has an extra 134 00:07:59,870 --> 00:08:01,700 parameter called memo. 135 00:08:01,700 --> 00:08:03,790 And memo is the brain I'm talking about. 136 00:08:03,790 --> 00:08:07,070 This is where we're going to stash those computed values so 137 00:08:07,070 --> 00:08:10,330 we don't have to compute them again. 138 00:08:10,330 --> 00:08:16,760 And when it initially comes in, if memo is none, that is, 139 00:08:16,760 --> 00:08:19,400 we haven't passed in a dictionary or if it's like the 140 00:08:19,400 --> 00:08:23,720 first call to this function, then it's going to set a key 141 00:08:23,720 --> 00:08:26,510 of 0 to 0 and key of 1 to 1. 142 00:08:26,510 --> 00:08:29,990 Those correspond to f of 0 and f of 1, right, actually. 143 00:08:29,990 --> 00:08:36,429 144 00:08:36,429 --> 00:08:39,870 No one pointed that out? 145 00:08:39,870 --> 00:08:42,559 All right. 146 00:08:42,559 --> 00:08:46,030 So, now it's going to-- 147 00:08:46,030 --> 00:08:48,180 after it does that initialization, it's going to 148 00:08:48,180 --> 00:08:52,020 come down to this if statement, and it's going to 149 00:08:52,020 --> 00:08:55,840 check for whether or not N is in memo. 150 00:08:55,840 --> 00:08:59,170 What this is actually asking is, have we 151 00:08:59,170 --> 00:09:01,530 seen this number before? 152 00:09:01,530 --> 00:09:05,580 When we've been computing this number, the big Fibonacci 153 00:09:05,580 --> 00:09:08,640 number, right? 154 00:09:08,640 --> 00:09:13,540 So if it's down here, and it's looking at f of 2, it's 155 00:09:13,540 --> 00:09:16,340 asking, have I seen Fibonacci of 2 when I've done this 156 00:09:16,340 --> 00:09:18,020 computation before? 157 00:09:18,020 --> 00:09:20,870 And if it's in this tree, then the answer is yes because it's 158 00:09:20,870 --> 00:09:22,120 seen it down here. 159 00:09:22,120 --> 00:09:24,170 160 00:09:24,170 --> 00:09:27,750 If it hasn't seen it though, it's got to do the work. 161 00:09:27,750 --> 00:09:31,920 So it's got to actually do the recursive calls. 162 00:09:31,920 --> 00:09:35,400 And this is when it travels down this left 163 00:09:35,400 --> 00:09:37,620 branch of the tree. 164 00:09:37,620 --> 00:09:38,870 Does that makes sense? 165 00:09:38,870 --> 00:09:41,090 166 00:09:41,090 --> 00:09:42,995 And all we're going to do is store it off here. 167 00:09:42,995 --> 00:09:45,960 168 00:09:45,960 --> 00:09:47,200 And then at the end, we just return 169 00:09:47,200 --> 00:09:50,190 whatever's in our memory. 170 00:09:50,190 --> 00:09:52,370 So why don't we take a look at how this runs. 171 00:09:52,370 --> 00:10:00,920 172 00:10:00,920 --> 00:10:07,720 So remember, this is 1.6 million with the old 173 00:10:07,720 --> 00:10:11,540 implementation, and now it's only 57. 174 00:10:11,540 --> 00:10:19,290 And in fact, it's linear and exactly 2 to the N minus 1, or 175 00:10:19,290 --> 00:10:20,540 2 times N minus 1. 176 00:10:20,540 --> 00:10:23,730 177 00:10:23,730 --> 00:10:25,980 Everyone follow that? 178 00:10:25,980 --> 00:10:26,370 Any questions? 179 00:10:26,370 --> 00:10:29,370 AUDIENCE: There's not too much we could do. 180 00:10:29,370 --> 00:10:31,390 PROFESSOR: No. 181 00:10:31,390 --> 00:10:34,130 It saves a lot of work for you. 182 00:10:34,130 --> 00:10:35,300 Because as soon as it-- 183 00:10:35,300 --> 00:10:39,890 so let's say that it's computed f of 4, this entire 184 00:10:39,890 --> 00:10:42,030 sub-tree here. 185 00:10:42,030 --> 00:10:45,090 As soon as it sees f of 3, it's going to look in it's 186 00:10:45,090 --> 00:10:48,110 brain, and you've already seen f of 3, and it says, I've 187 00:10:48,110 --> 00:10:50,590 already seen this, so I don't need to do all this 188 00:10:50,590 --> 00:10:51,740 computation here. 189 00:10:51,740 --> 00:10:53,810 I don't need to do all these recursive calls. 190 00:10:53,810 --> 00:10:56,670 I just have to return whatever's in the dictionary. 191 00:10:56,670 --> 00:10:57,940 That's where your savings come in. 192 00:10:57,940 --> 00:11:01,890 193 00:11:01,890 --> 00:11:05,690 So let's take a look at another example. 194 00:11:05,690 --> 00:11:09,070 195 00:11:09,070 --> 00:11:13,590 The point is, you can have some really huge savings if 196 00:11:13,590 --> 00:11:16,360 you write your code right. 197 00:11:16,360 --> 00:11:19,530 So let's look at a different problem. 198 00:11:19,530 --> 00:11:21,830 Let's say that I have a robot. 199 00:11:21,830 --> 00:11:30,290 200 00:11:30,290 --> 00:11:32,520 And this robot is positioned on the grid. 201 00:11:32,520 --> 00:11:36,510 202 00:11:36,510 --> 00:11:54,060 Let's say that it has N rows, and N columns, or M columns. 203 00:11:54,060 --> 00:11:56,660 204 00:11:56,660 --> 00:12:01,670 Your robot is starting out here, and it 205 00:12:01,670 --> 00:12:03,660 wants to get here. 206 00:12:03,660 --> 00:12:07,850 Your robot though is very stupid, and it can go only 207 00:12:07,850 --> 00:12:10,750 down and to the right. 208 00:12:10,750 --> 00:12:15,240 The question is, how many unique paths are there from 209 00:12:15,240 --> 00:12:18,770 the top left square to the bottom right square, given 210 00:12:18,770 --> 00:12:20,020 those constraints? 211 00:12:20,020 --> 00:12:26,430 212 00:12:26,430 --> 00:12:28,650 If you try and do this analytically, you'll probably 213 00:12:28,650 --> 00:12:29,870 hurt yourself. 214 00:12:29,870 --> 00:12:34,900 The easier way to do it, or at least I think so, is to 215 00:12:34,900 --> 00:12:37,970 realize that in order to get to g, there's only two places 216 00:12:37,970 --> 00:12:38,660 that it can come from. 217 00:12:38,660 --> 00:12:43,730 It can come from here, it can come from here, right. 218 00:12:43,730 --> 00:12:47,780 So the total number of unique paths coming into g are the 219 00:12:47,780 --> 00:12:50,620 total number of unique paths coming into this guy, and the 220 00:12:50,620 --> 00:12:52,760 total number of unique paths coming into this guy. 221 00:12:52,760 --> 00:12:55,880 So there's your overlapping sub-problems, right, and also 222 00:12:55,880 --> 00:12:56,970 your optimal substructure. 223 00:12:56,970 --> 00:12:59,890 If I can figure out these numbers, then I can figure out 224 00:12:59,890 --> 00:13:02,840 this number, right. 225 00:13:02,840 --> 00:13:04,090 So-- 226 00:13:04,090 --> 00:13:07,570 227 00:13:07,570 --> 00:13:10,010 and then these guys, the same condition applies. 228 00:13:10,010 --> 00:13:11,380 If I know these two numbers, then I can 229 00:13:11,380 --> 00:13:13,230 figure out this number. 230 00:13:13,230 --> 00:13:14,420 If I know these two numbers, then I can 231 00:13:14,420 --> 00:13:16,320 figure out this number. 232 00:13:16,320 --> 00:13:21,046 So one implementation-- 233 00:13:21,046 --> 00:13:23,890 well, one other thing. 234 00:13:23,890 --> 00:13:28,940 If I get down to this case where I have a 1 by M grid, 235 00:13:28,940 --> 00:13:30,440 how many different ways are there to get 236 00:13:30,440 --> 00:13:33,090 from here to here? 237 00:13:33,090 --> 00:13:34,340 One, right? 238 00:13:34,340 --> 00:13:37,230 239 00:13:37,230 --> 00:13:40,130 And then same thing for M by N right? 240 00:13:40,130 --> 00:13:44,980 241 00:13:44,980 --> 00:13:49,260 So the first crack at this, here's a recursive function. 242 00:13:49,260 --> 00:13:52,630 243 00:13:52,630 --> 00:13:56,400 All we're going to do is, if we only have 1 row or 1 244 00:13:56,400 --> 00:13:59,850 column, we return 1. 245 00:13:59,850 --> 00:14:04,160 Otherwise, we're going to look for the number of robot paths 246 00:14:04,160 --> 00:14:08,910 in an N minus 1 by M matrix and then the number of paths 247 00:14:08,910 --> 00:14:11,140 in an N by M minus 1 matrix. 248 00:14:11,140 --> 00:14:13,890 249 00:14:13,890 --> 00:14:15,245 So let's take a look. 250 00:14:15,245 --> 00:14:21,450 251 00:14:21,450 --> 00:14:27,410 We're going to do this on a 14 by 14 grid. 252 00:14:27,410 --> 00:14:29,230 And this will take a few seconds. 253 00:14:29,230 --> 00:14:40,550 254 00:14:40,550 --> 00:14:40,736 OK. 255 00:14:40,736 --> 00:14:45,460 So there's a lot. 256 00:14:45,460 --> 00:14:49,560 10 million unique paths, and it took about 20 million steps 257 00:14:49,560 --> 00:14:52,050 to figure it out. 258 00:14:52,050 --> 00:14:56,570 So we're going to pull the same trick for this problem 259 00:14:56,570 --> 00:14:59,450 that we did for Fibonacci. 260 00:14:59,450 --> 00:15:05,080 We're going to memorize, or memoize, the different paths 261 00:15:05,080 --> 00:15:10,750 or the different solutions, except our key is going to be 262 00:15:10,750 --> 00:15:11,520 a little different. 263 00:15:11,520 --> 00:15:14,360 It's just going to be N and M. 264 00:15:14,360 --> 00:15:18,130 So again, if we have-- 265 00:15:18,130 --> 00:15:20,790 well, again, if N and M is not memo, then we 266 00:15:20,790 --> 00:15:22,720 need to compute it. 267 00:15:22,720 --> 00:15:27,750 If either is 1, then we remember it as 1. 268 00:15:27,750 --> 00:15:32,950 And if they're both greater than 1, then we're going to 269 00:15:32,950 --> 00:15:37,950 look at the number of paths in N minus 1 by M, and N 270 00:15:37,950 --> 00:15:41,100 times M minus 1. 271 00:15:41,100 --> 00:15:43,480 And then we also know that the solutions 272 00:15:43,480 --> 00:15:46,030 are symmetric, right. 273 00:15:46,030 --> 00:15:50,780 So it's going to be the same for an N by M and an M by N. 274 00:15:50,780 --> 00:15:52,220 And just return the solution. 275 00:15:52,220 --> 00:15:53,870 So let's try this out. 276 00:15:53,870 --> 00:16:00,880 277 00:16:00,880 --> 00:16:04,380 We get the same answer, but it only takes 104 steps to do it. 278 00:16:04,380 --> 00:16:09,620 So it's a pretty huge savings there. 279 00:16:09,620 --> 00:16:11,890 So the other-- 280 00:16:11,890 --> 00:16:13,930 this is an example of a top-down 281 00:16:13,930 --> 00:16:15,710 dynamic programming solution. 282 00:16:15,710 --> 00:16:19,230 We looked at the big problem, and we broke it down into two 283 00:16:19,230 --> 00:16:20,430 smaller problems. 284 00:16:20,430 --> 00:16:22,320 We looked at those two smaller sub-problems, we broke them 285 00:16:22,320 --> 00:16:27,630 down into two smaller sub-problems a piece. 286 00:16:27,630 --> 00:16:29,245 We can also go from the bottom up. 287 00:16:29,245 --> 00:16:32,210 288 00:16:32,210 --> 00:16:34,080 And we might want to do this for a reason that 289 00:16:34,080 --> 00:16:35,940 I'll show in a second. 290 00:16:35,940 --> 00:16:38,860 So I think I needed that. 291 00:16:38,860 --> 00:16:50,000 292 00:16:50,000 --> 00:16:51,700 This is going to go from the bottom up. 293 00:16:51,700 --> 00:16:54,610 So instead of starting back here and asking how many ways 294 00:16:54,610 --> 00:16:59,010 I can get from these two guys, it's going to start at the 295 00:16:59,010 --> 00:17:01,690 beginning and ask how many ways I can get here. 296 00:17:01,690 --> 00:17:03,380 One, right. 297 00:17:03,380 --> 00:17:11,770 And then here let's imagine that we only have a 2 by 2. 298 00:17:11,770 --> 00:17:17,020 It's going to look at, again, the number of ways to get to 299 00:17:17,020 --> 00:17:19,790 the square to the left and to the square to the 300 00:17:19,790 --> 00:17:22,849 top, and add it here. 301 00:17:22,849 --> 00:17:23,450 Add it here. 302 00:17:23,450 --> 00:17:25,140 So what we're doing here-- 303 00:17:25,140 --> 00:17:31,310 what we're doing in this version is we're growing a 304 00:17:31,310 --> 00:17:34,030 grid towards a solution. 305 00:17:34,030 --> 00:17:37,970 306 00:17:37,970 --> 00:17:39,220 Does that make sense? 307 00:17:39,220 --> 00:17:43,530 308 00:17:43,530 --> 00:17:46,700 This just sets up a matrix. 309 00:17:46,700 --> 00:17:49,520 The top row is going to be initialized to 1. 310 00:17:49,520 --> 00:17:51,110 First column is going to be 1. 311 00:17:51,110 --> 00:17:54,240 312 00:17:54,240 --> 00:18:01,660 And then for everything else, we're just going to add the 313 00:18:01,660 --> 00:18:04,405 row above and the column to the left. 314 00:18:04,405 --> 00:18:08,530 315 00:18:08,530 --> 00:18:12,940 And return whatever's down in this lower right corner. 316 00:18:12,940 --> 00:18:16,620 So it gets the same solution, just in a different direction. 317 00:18:16,620 --> 00:18:19,670 318 00:18:19,670 --> 00:18:32,290 So now you might want to do this because imagine if 319 00:18:32,290 --> 00:18:36,410 instead of 14, we had 1,400. 320 00:18:36,410 --> 00:18:38,260 So this should crash. 321 00:18:38,260 --> 00:18:42,730 322 00:18:42,730 --> 00:18:46,290 Python has a maximum recursion depth. 323 00:18:46,290 --> 00:18:48,210 If you have too many recursive columns, it's going to tell 324 00:18:48,210 --> 00:18:51,750 you, I can't go that deep, and kick you out. 325 00:18:51,750 --> 00:18:58,350 So I have 1,400 rows and 1,400 columns, 326 00:18:58,350 --> 00:18:59,600 that's a lot of recursion. 327 00:18:59,600 --> 00:19:10,720 328 00:19:10,720 --> 00:19:22,800 But if we do it iteratively, where we have no recursion, 329 00:19:22,800 --> 00:19:27,870 that's the number of unique paths, which is a pretty 330 00:19:27,870 --> 00:19:30,890 sizable number. 331 00:19:30,890 --> 00:19:35,380 And that's the number of columns we made, which for a 332 00:19:35,380 --> 00:19:39,040 1,400 by 1,400 matrix is not too bad, right. 333 00:19:39,040 --> 00:19:43,700 334 00:19:43,700 --> 00:19:43,786 All right. 335 00:19:43,786 --> 00:19:44,850 So that was an easy one. 336 00:19:44,850 --> 00:19:46,646 So now we're going to go to little harder one. 337 00:19:46,646 --> 00:19:51,730 338 00:19:51,730 --> 00:19:54,190 Everyone doing all right? 339 00:19:54,190 --> 00:19:55,440 OK. 340 00:19:55,440 --> 00:19:58,740 341 00:19:58,740 --> 00:20:02,460 This is a counting change problem. 342 00:20:02,460 --> 00:20:19,170 The idea is, let's assume I have a currency with coins of 343 00:20:19,170 --> 00:20:20,470 a certain value. 344 00:20:20,470 --> 00:20:23,980 345 00:20:23,980 --> 00:20:27,850 I'm not sure where I got the $0.27 from, but that's 346 00:20:27,850 --> 00:20:31,520 apparently the value for the coins in our currency. 347 00:20:31,520 --> 00:20:34,770 So the problem is-- 348 00:20:34,770 --> 00:20:36,790 let's say that I have a sum total-- 349 00:20:36,790 --> 00:20:39,890 350 00:20:39,890 --> 00:20:42,590 the question is, how many different combinations of 351 00:20:42,590 --> 00:20:46,790 coins are there that equal total? 352 00:20:46,790 --> 00:20:53,300 353 00:20:53,300 --> 00:20:56,090 The way to break this down is-- so does everyone 354 00:20:56,090 --> 00:20:57,710 understand the problem? 355 00:20:57,710 --> 00:21:01,710 So like if I say I want to give change $0.41 to a 356 00:21:01,710 --> 00:21:04,725 customer, then it's like a quarter, a dime, a nickel, and 357 00:21:04,725 --> 00:21:05,975 a penny, right? 358 00:21:05,975 --> 00:21:11,380 359 00:21:11,380 --> 00:21:14,670 We can think of the problem in two ways. 360 00:21:14,670 --> 00:21:18,660 Well, we can break the problem down into two sub-problems by 361 00:21:18,660 --> 00:21:28,800 first considering what the total is-- what the number of 362 00:21:28,800 --> 00:21:34,880 combos would be if I use the largest coin in my set. 363 00:21:34,880 --> 00:21:38,920 364 00:21:38,920 --> 00:21:51,550 We're using at least one of the largest coins. 365 00:21:51,550 --> 00:22:05,600 And then the other is the number of combinations if not 366 00:22:05,600 --> 00:22:10,190 using the largest coin. 367 00:22:10,190 --> 00:22:13,040 368 00:22:13,040 --> 00:22:14,290 OK? 369 00:22:14,290 --> 00:22:16,030 370 00:22:16,030 --> 00:22:19,880 So this turned, actually turns, into a nicer 371 00:22:19,880 --> 00:22:28,850 sub-problem, which is if I have total minus largest-- 372 00:22:28,850 --> 00:22:37,960 so in this case, minus $0.27, what's the number of 373 00:22:37,960 --> 00:22:44,590 combinations for this sub-problem? 374 00:22:44,590 --> 00:22:45,840 You follow? 375 00:22:45,840 --> 00:22:47,540 376 00:22:47,540 --> 00:22:52,890 And then this guy can be formulated as the number-- 377 00:22:52,890 --> 00:23:00,316 so I still have total number of combinations. 378 00:23:00,316 --> 00:23:03,930 379 00:23:03,930 --> 00:23:10,490 But then I take out the largest coin, so coins is now, 380 00:23:10,490 --> 00:23:16,590 instead of 1, instead of having $0.27 as the largest 381 00:23:16,590 --> 00:23:20,330 coin, now has $0.25 as the largest coin. 382 00:23:20,330 --> 00:23:21,580 Does that makes sense to people? 383 00:23:21,580 --> 00:23:24,320 384 00:23:24,320 --> 00:23:30,780 And so the solution here to this big problem is the 385 00:23:30,780 --> 00:23:32,310 solution to-- 386 00:23:32,310 --> 00:23:33,570 or is the sum of the solutions to this 387 00:23:33,570 --> 00:23:36,490 problem and In this problem. 388 00:23:36,490 --> 00:23:39,000 Make sense? 389 00:23:39,000 --> 00:23:41,360 All right. 390 00:23:41,360 --> 00:23:46,450 Why don't we take a look at the first version of this 391 00:23:46,450 --> 00:23:50,270 problem or this implementation. 392 00:23:50,270 --> 00:23:56,080 So we have three base cases. 393 00:23:56,080 --> 00:23:59,110 So the first base case is-- 394 00:23:59,110 --> 00:24:01,610 well, first let me explain the function. 395 00:24:01,610 --> 00:24:07,100 So, total, that's the amount that we want. 396 00:24:07,100 --> 00:24:08,080 Coins-- 397 00:24:08,080 --> 00:24:09,730 it's the set of coins in our currency. 398 00:24:09,730 --> 00:24:12,310 399 00:24:12,310 --> 00:24:20,950 And I only have $0.05, $0.10, $0.25, and $0.27, so, oh well. 400 00:24:20,950 --> 00:24:24,290 The first thing we do is check to see if total is 0. 401 00:24:24,290 --> 00:24:28,340 That means that we're trying to figure out what combination 402 00:24:28,340 --> 00:24:30,580 of coins is equal to 0. 403 00:24:30,580 --> 00:24:33,890 And of course, there's only one combination of coins. 404 00:24:33,890 --> 00:24:35,830 There are no coins. 405 00:24:35,830 --> 00:24:37,160 So that actually is 1. 406 00:24:37,160 --> 00:24:40,610 407 00:24:40,610 --> 00:24:41,860 This case-- 408 00:24:41,860 --> 00:24:43,810 409 00:24:43,810 --> 00:24:47,140 this is if we're trying a particular coin that's a 410 00:24:47,140 --> 00:24:50,640 little too large to fit into our total. 411 00:24:50,640 --> 00:24:52,660 So we wind up going below 0. 412 00:24:52,660 --> 00:24:55,340 That means we can't use that coin for this particular 413 00:24:55,340 --> 00:24:56,350 total, right. 414 00:24:56,350 --> 00:25:01,980 So there are no combinations that work for this. 415 00:25:01,980 --> 00:25:07,170 And then this last case is, if we're no longer using-- 416 00:25:07,170 --> 00:25:10,820 if we have no more coins, and we still have stuff that we 417 00:25:10,820 --> 00:25:16,430 need to make up, like we still have some value in total, then 418 00:25:16,430 --> 00:25:20,950 that means that this particular combination that 419 00:25:20,950 --> 00:25:24,180 we're trying out also doesn't work, so we return 0. 420 00:25:24,180 --> 00:25:31,470 So that's this case, where we've taken out everything, so 421 00:25:31,470 --> 00:25:35,500 our set of coins is the empty set, is nothing. 422 00:25:35,500 --> 00:25:36,750 Does that make sense? 423 00:25:36,750 --> 00:25:41,420 424 00:25:41,420 --> 00:25:48,300 So our first recursive call is looking for the number of ways 425 00:25:48,300 --> 00:25:49,550 without the last coin. 426 00:25:49,550 --> 00:25:52,290 427 00:25:52,290 --> 00:25:54,870 That's this case. 428 00:25:54,870 --> 00:25:56,650 And all we're doing is we're passing in the total we got 429 00:25:56,650 --> 00:26:00,170 before, and all the coins except for the largest one, so 430 00:26:00,170 --> 00:26:01,230 the last one. 431 00:26:01,230 --> 00:26:03,330 So we're stricken one off for each recursive call. 432 00:26:03,330 --> 00:26:07,200 433 00:26:07,200 --> 00:26:11,350 And then the second case here is if we do use at least one 434 00:26:11,350 --> 00:26:13,560 of the largest coins. 435 00:26:13,560 --> 00:26:14,990 In this case, we're just going to subtract 436 00:26:14,990 --> 00:26:17,530 that off the total. 437 00:26:17,530 --> 00:26:21,790 And we're going to pass in coins as is. 438 00:26:21,790 --> 00:26:23,040 Make sense? 439 00:26:23,040 --> 00:26:25,120 440 00:26:25,120 --> 00:26:26,380 And then we just return the sum. 441 00:26:26,380 --> 00:26:43,780 442 00:26:43,780 --> 00:26:44,210 OK. 443 00:26:44,210 --> 00:26:47,120 So not too bad. 444 00:26:47,120 --> 00:26:50,280 Everyone follow that code? 445 00:26:50,280 --> 00:26:52,340 All right. 446 00:26:52,340 --> 00:26:58,480 So this is without doing any memoization, it's just using 447 00:26:58,480 --> 00:27:01,060 recursion, breaking it down into two sub-problems and 448 00:27:01,060 --> 00:27:04,450 figuring out a solution. 449 00:27:04,450 --> 00:27:06,400 But now we're going to use dynamic programming to 450 00:27:06,400 --> 00:27:09,720 optimize this a little bit. 451 00:27:09,720 --> 00:27:13,080 So in this case, we have our little memoization 452 00:27:13,080 --> 00:27:14,970 dictionary-- 453 00:27:14,970 --> 00:27:16,220 you notice a pattern here? 454 00:27:16,220 --> 00:27:19,940 455 00:27:19,940 --> 00:27:20,758 Yeah? 456 00:27:20,758 --> 00:27:22,221 AUDIENCE: Do you have an infinite 457 00:27:22,221 --> 00:27:23,880 amount to supply those? 458 00:27:23,880 --> 00:27:24,770 PROFESSOR: Yes. 459 00:27:24,770 --> 00:27:27,690 So you're assuming that you have an infinite number of 460 00:27:27,690 --> 00:27:31,308 $0.27 cent pieces, $0.25 cent pieces, et cetera. 461 00:27:31,308 --> 00:27:34,272 AUDIENCE: [UNINTELLIGIBLE] 462 00:27:34,272 --> 00:27:35,754 just add 1's [UNINTELLIGIBLE] 463 00:27:35,754 --> 00:27:40,694 464 00:27:40,694 --> 00:27:43,220 PROFESSOR: And it's possible to get below 0. 465 00:27:43,220 --> 00:27:50,070 466 00:27:50,070 --> 00:27:52,380 So let's see. 467 00:27:52,380 --> 00:27:54,060 This is all the same, right? 468 00:27:54,060 --> 00:27:55,310 No surprises there. 469 00:27:55,310 --> 00:27:57,500 470 00:27:57,500 --> 00:28:02,160 But then what we're going to do is we're going to memoize 471 00:28:02,160 --> 00:28:06,040 on the total that we're trying to find and the largest 472 00:28:06,040 --> 00:28:11,140 value-- largest currency piece that we have. 473 00:28:11,140 --> 00:28:15,460 And if it's not in our dictionary, then we're going 474 00:28:15,460 --> 00:28:16,710 to compute it. 475 00:28:16,710 --> 00:28:22,340 476 00:28:22,340 --> 00:28:23,970 And then once we get the solution, we're going to 477 00:28:23,970 --> 00:28:29,470 memoize it and return it. 478 00:28:29,470 --> 00:28:30,720 So let's see how this runs. 479 00:28:30,720 --> 00:28:40,510 480 00:28:40,510 --> 00:28:41,760 It could've been by 4. 481 00:28:41,760 --> 00:28:45,590 482 00:28:45,590 --> 00:28:46,840 That make sense to everyone? 483 00:28:46,840 --> 00:28:49,880 484 00:28:49,880 --> 00:28:52,470 No questions? 485 00:28:52,470 --> 00:28:53,720 Wow. 486 00:28:53,720 --> 00:28:56,740 487 00:28:56,740 --> 00:28:58,190 So now let's try a different formulation. 488 00:28:58,190 --> 00:29:00,750 489 00:29:00,750 --> 00:29:03,835 This one's a little tricky. 490 00:29:03,835 --> 00:29:08,860 491 00:29:08,860 --> 00:29:10,546 Let's imagine that I have a grid. 492 00:29:10,546 --> 00:29:13,190 493 00:29:13,190 --> 00:29:18,375 And down the rows I have numbers up to total. 494 00:29:18,375 --> 00:29:21,420 495 00:29:21,420 --> 00:29:22,670 OK, starting from 0. 496 00:29:22,670 --> 00:29:29,340 497 00:29:29,340 --> 00:29:31,840 Across the columns, I have my different currency pieces. 498 00:29:31,840 --> 00:29:45,440 499 00:29:45,440 --> 00:29:48,080 So the first two implementations we're going 500 00:29:48,080 --> 00:29:49,936 top down, now we're going bottom up. 501 00:29:49,936 --> 00:29:52,920 502 00:29:52,920 --> 00:29:59,440 The way you read this is, if I have a total of 0, this is a 503 00:29:59,440 --> 00:30:05,785 number and my largest currency piece is $0.05, or $0.10, or 504 00:30:05,785 --> 00:30:10,220 $0.25, or $0.27, it's the number of coin combinations I 505 00:30:10,220 --> 00:30:13,090 have that will equal this total, right. 506 00:30:13,090 --> 00:30:20,560 So in this first row, that's my base case, right. 507 00:30:20,560 --> 00:30:23,060 508 00:30:23,060 --> 00:30:28,820 And then down here, we know this is all going to be 0, 509 00:30:28,820 --> 00:30:30,780 because if I have no coin pieces-- 510 00:30:30,780 --> 00:30:35,170 511 00:30:35,170 --> 00:30:39,260 So now, the bottom-up way is, we're going to fill in this 512 00:30:39,260 --> 00:30:40,510 table here. 513 00:30:40,510 --> 00:30:44,080 514 00:30:44,080 --> 00:30:48,090 So we're just going to iterate through all the totals that 515 00:30:48,090 --> 00:30:49,340 are possible. 516 00:30:49,340 --> 00:30:51,590 517 00:30:51,590 --> 00:30:54,250 And for each total, we're going to iterate through all 518 00:30:54,250 --> 00:30:55,500 the largest coin denominations. 519 00:30:55,500 --> 00:30:58,370 520 00:30:58,370 --> 00:31:00,840 Right? 521 00:31:00,840 --> 00:31:04,710 And then we're just going to do two checks. 522 00:31:04,710 --> 00:31:06,540 We're going to look at the current total we're looking 523 00:31:06,540 --> 00:31:13,460 at, so let's say that we're on row one, so our total is 1. 524 00:31:13,460 --> 00:31:17,930 And we're going to subtract the largest denomination of 525 00:31:17,930 --> 00:31:21,270 currency that we're looking at. 526 00:31:21,270 --> 00:31:24,430 We start out here. 527 00:31:24,430 --> 00:31:29,610 So we're going to subtract 5 from total of 1. 528 00:31:29,610 --> 00:31:34,870 And that's less than 0. 529 00:31:34,870 --> 00:31:39,630 And when it's less than 0, all we're going to do is carry the 530 00:31:39,630 --> 00:31:46,690 number of combinations from the current total to the next 531 00:31:46,690 --> 00:31:48,630 smallest largest denomination. 532 00:31:48,630 --> 00:31:52,750 So if we're at 5 and we know we're less than 0, that means 533 00:31:52,750 --> 00:31:56,090 we're going to carry this value over. 534 00:31:56,090 --> 00:31:57,060 And we're now going to do the same thing 535 00:31:57,060 --> 00:31:58,310 for all these values. 536 00:31:58,310 --> 00:32:00,380 537 00:32:00,380 --> 00:32:02,460 Now let's get to an interesting case. 538 00:32:02,460 --> 00:32:17,700 So now we're looking at a total of 5, OK? 539 00:32:17,700 --> 00:32:22,620 540 00:32:22,620 --> 00:32:27,240 When our largest coin is $0.05 and we subtract it from a 541 00:32:27,240 --> 00:32:30,550 total of 5, that's not less than 0, right? 542 00:32:30,550 --> 00:32:31,590 So that means we're going to go into the 543 00:32:31,590 --> 00:32:35,370 second branch of f statement. 544 00:32:35,370 --> 00:32:36,540 So again, the same thing. 545 00:32:36,540 --> 00:32:39,750 We're going to look at the number of ways with the 546 00:32:39,750 --> 00:32:41,930 largest coin. 547 00:32:41,930 --> 00:32:44,790 And to do that, we're going to use our table. 548 00:32:44,790 --> 00:32:50,790 We're going to look at the current total, which is 5, 549 00:32:50,790 --> 00:32:53,080 minus the largest coin that we're looking 550 00:32:53,080 --> 00:32:55,530 at, which is $0.05. 551 00:32:55,530 --> 00:32:59,620 So that's going to index us into this row because 552 00:32:59,620 --> 00:33:02,520 5 minus 5 is 0. 553 00:33:02,520 --> 00:33:04,910 And then we're going to look at the current 554 00:33:04,910 --> 00:33:08,280 coin, which is $0.05. 555 00:33:08,280 --> 00:33:15,330 So that's going to be 1, right? 556 00:33:15,330 --> 00:33:16,900 Well, I skipped a step. 557 00:33:16,900 --> 00:33:19,020 So we're going to get this value, right, so this is the 558 00:33:19,020 --> 00:33:21,900 number of ways with the largest coin. 559 00:33:21,900 --> 00:33:24,840 560 00:33:24,840 --> 00:33:26,910 And then we're going to look at the number of ways without 561 00:33:26,910 --> 00:33:30,070 the last coin, so if this is the largest coin that we're 562 00:33:30,070 --> 00:33:36,000 looking at, then without it, this is all we have. 563 00:33:36,000 --> 00:33:37,730 So that's going to be 0. 564 00:33:37,730 --> 00:33:39,440 So 0 plus 1, that's 1. 565 00:33:39,440 --> 00:33:43,860 566 00:33:43,860 --> 00:33:46,740 And then for 10-- 567 00:33:46,740 --> 00:33:53,150 so again, this becomes 0. 568 00:33:53,150 --> 00:33:56,580 So the next interesting one is going to be 10. 569 00:33:56,580 --> 00:33:58,220 Is everyone following so far what we're doing? 570 00:33:58,220 --> 00:34:01,060 571 00:34:01,060 --> 00:34:02,310 This would be 0. 572 00:34:02,310 --> 00:34:04,780 573 00:34:04,780 --> 00:34:09,409 This is going to be 1 plus 0. 574 00:34:09,409 --> 00:34:13,070 575 00:34:13,070 --> 00:34:16,290 And this is going to be 1 plus 1. 576 00:34:16,290 --> 00:34:20,340 577 00:34:20,340 --> 00:34:22,670 Making sense? 578 00:34:22,670 --> 00:34:23,690 Make an error? 579 00:34:23,690 --> 00:34:25,400 No, OK. 580 00:34:25,400 --> 00:34:30,290 And then this is going to be 0 Everyone get the idea? 581 00:34:30,290 --> 00:34:31,874 So we're just filling in this table. 582 00:34:31,874 --> 00:34:40,179 583 00:34:40,179 --> 00:34:41,432 What's that? 584 00:34:41,432 --> 00:34:44,834 AUDIENCE: [INAUDIBLE] 585 00:34:44,834 --> 00:34:46,778 PROFESSOR: Here? 586 00:34:46,778 --> 00:34:50,666 AUDIENCE: There's only one way to make 10 plus 5. 587 00:34:50,666 --> 00:34:52,060 PROFESSOR: Because-- 588 00:34:52,060 --> 00:34:53,480 the smallest-- 589 00:34:53,480 --> 00:34:58,530 so if I had 1 here, like so I was using a one piece, then 590 00:34:58,530 --> 00:35:01,590 this would be 2. 591 00:35:01,590 --> 00:35:04,440 But because we only have 5, there's only 592 00:35:04,440 --> 00:35:07,010 one way to make 10. 593 00:35:07,010 --> 00:35:09,366 Two 5's. 594 00:35:09,366 --> 00:35:12,234 Make sense? 595 00:35:12,234 --> 00:35:13,668 AUDIENCE: [UNINTELLIGIBLE] 596 00:35:13,668 --> 00:35:17,510 because you can either use one 10 or two 5's. 597 00:35:17,510 --> 00:35:19,894 PROFESSOR: Yes, exactly. 598 00:35:19,894 --> 00:35:24,250 AUDIENCE: So if we're using the table that as-- 599 00:35:24,250 --> 00:35:28,122 so you have $0.05 as the largest coin, so there's only 600 00:35:28,122 --> 00:35:30,542 one way of doing it using $0.05 as the largest coin? 601 00:35:30,542 --> 00:35:33,446 How come that 1 doesn't go all the way across the row? 602 00:35:33,446 --> 00:35:35,020 Because if you have $0.25 as the largest coin 603 00:35:35,020 --> 00:35:37,580 you could use $0.05's. 604 00:35:37,580 --> 00:35:38,830 PROFESSOR: You know what, you're right. 605 00:35:38,830 --> 00:35:41,804 606 00:35:41,804 --> 00:35:43,054 Made an error. 607 00:35:43,054 --> 00:35:49,289 608 00:35:49,289 --> 00:35:52,283 Actually, that would be 0. 609 00:35:52,283 --> 00:35:57,772 610 00:35:57,772 --> 00:35:59,768 AUDIENCE: [INAUDIBLE] 611 00:35:59,768 --> 00:36:03,261 PROFESSOR: What's that? 612 00:36:03,261 --> 00:36:04,511 Yeah, but-- 613 00:36:04,511 --> 00:36:11,744 614 00:36:11,744 --> 00:36:13,740 what can I say? 615 00:36:13,740 --> 00:36:14,990 It can be confusing. 616 00:36:14,990 --> 00:36:17,290 617 00:36:17,290 --> 00:36:20,328 To prove that this crazy thing works, let's run it. 618 00:36:20,328 --> 00:36:29,020 619 00:36:29,020 --> 00:36:33,830 So let's expand this. 620 00:36:33,830 --> 00:36:35,080 Actually, I'm going to use this. 621 00:36:35,080 --> 00:36:38,480 622 00:36:38,480 --> 00:36:40,190 So all three versions-- 623 00:36:40,190 --> 00:36:47,340 624 00:36:47,340 --> 00:36:49,260 what, did I make a mistake? 625 00:36:49,260 --> 00:36:51,635 AUDIENCE: No, it's just how you expanded the window. 626 00:36:51,635 --> 00:36:55,820 PROFESSOR: Oh, you like that? 627 00:36:55,820 --> 00:36:57,748 AUDIENCE: That's what we-- 628 00:36:57,748 --> 00:37:02,086 well, like Tracy's quote is always really, really small. 629 00:37:02,086 --> 00:37:02,580 But. 630 00:37:02,580 --> 00:37:03,830 AUDIENCE: No worries. 631 00:37:03,830 --> 00:37:06,206 632 00:37:06,206 --> 00:37:08,370 PROFESSOR: It's a program called Divvy, if you're 633 00:37:08,370 --> 00:37:09,150 interested. 634 00:37:09,150 --> 00:37:12,040 I think it's like $10 on the Apps store or something, or 635 00:37:12,040 --> 00:37:14,125 maybe it's $5.00. 636 00:37:14,125 --> 00:37:17,760 It just allows you to do those little grid things, so if you 637 00:37:17,760 --> 00:37:19,240 have lots of windows and stuff-- 638 00:37:19,240 --> 00:37:22,410 639 00:37:22,410 --> 00:37:24,360 and if you need to increase your font size, that's a 640 00:37:24,360 --> 00:37:27,641 little bit more involved with Python. 641 00:37:27,641 --> 00:37:30,240 Anyway, so they all give the same output except for the 642 00:37:30,240 --> 00:37:34,140 number of steps that they take, so the initial one took 643 00:37:34,140 --> 00:37:38,100 855, the one with the memoization took 209 steps, 644 00:37:38,100 --> 00:37:41,770 and the one without memoization but from bottom up 645 00:37:41,770 --> 00:37:44,010 took only 337 steps, so-- 646 00:37:44,010 --> 00:37:48,170 647 00:37:48,170 --> 00:37:50,700 it's just-- it's three different ways of attacking 648 00:37:50,700 --> 00:37:53,110 the same problem. 649 00:37:53,110 --> 00:37:57,960 And objectively, the last two are better than the first one. 650 00:37:57,960 --> 00:38:00,820 651 00:38:00,820 --> 00:38:04,650 We might think of cases where we would want to use say the 652 00:38:04,650 --> 00:38:08,010 table-based method over their recursion method. 653 00:38:08,010 --> 00:38:11,740 Like if we had like lots of combinations to explore or 654 00:38:11,740 --> 00:38:14,690 some kind of situation where you got into a really deep 655 00:38:14,690 --> 00:38:18,040 recursion that was too deep for Python to handle and we 656 00:38:18,040 --> 00:38:21,250 got kicked out like we did for the number of robot paths. 657 00:38:21,250 --> 00:38:24,590 So that would be kind of like a criteria for which algorithm 658 00:38:24,590 --> 00:38:25,840 you would choose over the other. 659 00:38:25,840 --> 00:38:29,845