1 00:00:07,797 --> 00:00:09,380 SRINI DEVADAS: Good morning, everyone. 2 00:00:09,380 --> 00:00:13,870 So we come to the end-- one last lecture and puzzle. 3 00:00:13,870 --> 00:00:18,700 Today, we're going to look at a little coin row game and talk 4 00:00:18,700 --> 00:00:21,520 about, obviously, an algorithm to solve the game, 5 00:00:21,520 --> 00:00:22,780 code the algorithm. 6 00:00:22,780 --> 00:00:31,330 And I'm going to introduce this notion of dynamic programming 7 00:00:31,330 --> 00:00:34,270 to you which is an algorithmic technique that's going 8 00:00:34,270 --> 00:00:35,740 to be useful in this game. 9 00:00:35,740 --> 00:00:40,030 Though it's not essential to solving it, 10 00:00:40,030 --> 00:00:42,340 it's going to be important in improving 11 00:00:42,340 --> 00:00:46,510 the efficiency of this first algorithm that we come up with. 12 00:00:46,510 --> 00:00:50,060 So the game itself is very straightforward. 13 00:00:50,060 --> 00:00:56,230 You have coins in a row given to you. 14 00:00:56,230 --> 00:01:01,930 So each of these has different values. 15 00:01:01,930 --> 00:01:05,120 And you can think of all of them as being positive, 16 00:01:05,120 --> 00:01:07,300 but it doesn't really matter. 17 00:01:07,300 --> 00:01:23,440 And your job is to pick coins to maximize total value. 18 00:01:26,140 --> 00:01:29,750 And obviously, that's not very interesting. 19 00:01:29,750 --> 00:01:31,850 You just pick all of them if they're all positive. 20 00:01:31,850 --> 00:01:33,790 And if some of them happen to be negative, 21 00:01:33,790 --> 00:01:35,016 you wouldn't pick those. 22 00:01:35,016 --> 00:01:36,640 So that's not particularly interesting. 23 00:01:36,640 --> 00:01:40,540 But it becomes much more interesting 24 00:01:40,540 --> 00:01:53,490 if you add the constraint that if you pick a coin, 25 00:01:53,490 --> 00:02:01,580 you can't pick the next one, the immediate next one. 26 00:02:10,300 --> 00:02:11,240 All right? 27 00:02:11,240 --> 00:02:14,630 So if I pick 3, I can't pick 27. 28 00:02:14,630 --> 00:02:17,810 If I pick 14, I can't pick 3, but I could pick 27. 29 00:02:17,810 --> 00:02:21,410 So clearly, I can alternate. 30 00:02:21,410 --> 00:02:25,550 Because I could pick, skip, pick, skip, et cetera, 31 00:02:25,550 --> 00:02:28,300 but I just can't pick, pick. 32 00:02:28,300 --> 00:02:31,400 But I could go pick, skip, skip, pick 33 00:02:31,400 --> 00:02:36,530 if I wanted a value that corresponds 34 00:02:36,530 --> 00:02:37,749 to that fourth location. 35 00:02:37,749 --> 00:02:39,290 So there's nothing that's stopping me 36 00:02:39,290 --> 00:02:42,682 from doing 14 and 4. 37 00:02:42,682 --> 00:02:44,390 I mean, the only thing that's stopping me 38 00:02:44,390 --> 00:02:47,660 from doing that is I drop this 27, which is a large value, 39 00:02:47,660 --> 00:02:49,880 and it seems like a bad idea. 40 00:02:49,880 --> 00:02:56,870 But on the other hand, you can think of a different situation 41 00:02:56,870 --> 00:03:01,020 where you wanted 27 and 15. 42 00:03:01,020 --> 00:03:05,480 And so maybe you want to skip 4 and 5, right? 43 00:03:05,480 --> 00:03:09,680 So what is the maximum value for this particular puzzle 44 00:03:09,680 --> 00:03:11,120 that you can come up with? 45 00:03:11,120 --> 00:03:15,520 And what are the coins that you would pick in this case? 46 00:03:18,424 --> 00:03:21,328 Someone? 47 00:03:21,328 --> 00:03:22,300 AUDIENCE: 56. 48 00:03:22,300 --> 00:03:23,120 SRINI DEVADAS: 56. 49 00:03:23,120 --> 00:03:24,050 How did you get 56? 50 00:03:24,050 --> 00:03:27,100 AUDIENCE: By using 14, 27, and 15. 51 00:03:27,100 --> 00:03:29,210 SRINI DEVADAS: You went 14, 27. 52 00:03:29,210 --> 00:03:31,457 And then you went skip, skip. 53 00:03:31,457 --> 00:03:32,540 You didn't want to pick 5. 54 00:03:32,540 --> 00:03:33,540 You could have picked 5. 55 00:03:33,540 --> 00:03:34,700 You can't pick 4. 56 00:03:34,700 --> 00:03:40,530 But you decided that 15 was much better. 57 00:03:40,530 --> 00:03:43,040 So you ended up picking 15, right? 58 00:03:43,040 --> 00:03:51,800 And if, in fact, you had something like 11 here-- 59 00:03:51,800 --> 00:03:53,580 so let me just write that first. 60 00:03:53,580 --> 00:03:56,660 So if you did that, it's 56. 61 00:03:56,660 --> 00:04:02,540 And you're picking 14, 27, and 15. 62 00:04:02,540 --> 00:04:05,520 So is that right? 63 00:04:05,520 --> 00:04:06,470 Is that 56? 64 00:04:06,470 --> 00:04:08,080 Yes, that is 56. 65 00:04:08,080 --> 00:04:09,470 Good. 66 00:04:09,470 --> 00:04:16,880 But if I had something slightly different, 67 00:04:16,880 --> 00:04:20,670 someone else tell me what I should pick here. 68 00:04:20,670 --> 00:04:23,130 What's the maximum value and what should I 69 00:04:23,130 --> 00:04:24,450 pick in terms of coins? 70 00:04:31,100 --> 00:04:32,190 Yeah, go ahead, George. 71 00:04:32,190 --> 00:04:33,800 AUDIENCE: The maximum value is 57 72 00:04:33,800 --> 00:04:36,490 if you just take every other coin, starting 14. 73 00:04:36,490 --> 00:04:38,480 SRINI DEVADAS: So if you go 14, 27-- 74 00:04:38,480 --> 00:04:39,500 that's 41. 75 00:04:39,500 --> 00:04:45,110 Now you want to pick 5, so that's 46. 76 00:04:45,110 --> 00:04:48,290 And then you can't pick 15, but you get to pick 11. 77 00:04:48,290 --> 00:04:50,025 And so you go 57. 78 00:04:53,810 --> 00:04:57,960 Yeah, so this one was alternation, pretty much 79 00:04:57,960 --> 00:05:00,390 strict alternation. 80 00:05:00,390 --> 00:05:06,810 So, well, you guys are getting good at this. 81 00:05:06,810 --> 00:05:08,040 So I'll give you a hard one. 82 00:05:29,886 --> 00:05:31,510 Is that enough or shall we go for more? 83 00:05:34,870 --> 00:05:38,730 All right, this was the final question, final exam. 84 00:05:38,730 --> 00:05:40,500 You got 10 minutes-- 85 00:05:40,500 --> 00:05:42,665 seconds-- 10 seconds. 86 00:05:42,665 --> 00:05:44,940 [LAUGHS] 87 00:05:44,940 --> 00:05:47,310 So clearly, this is not something 88 00:05:47,310 --> 00:05:49,180 you want to do manually. 89 00:05:49,180 --> 00:05:52,420 It's going to take a while. 90 00:05:52,420 --> 00:05:54,912 There's a lot of combinations here, right? 91 00:05:54,912 --> 00:05:56,370 There's a lot of combinations here. 92 00:05:56,370 --> 00:05:58,770 And if you do this, you're going to go-- 93 00:05:58,770 --> 00:06:01,950 well, you can do it in a greedy way. 94 00:06:01,950 --> 00:06:04,680 You can say, I'll just do alternation. 95 00:06:04,680 --> 00:06:07,251 And so you go 3 plus 17-- 96 00:06:07,251 --> 00:06:09,000 you guys are going to have to help me here 97 00:06:09,000 --> 00:06:10,916 because these numbers are going to get large-- 98 00:06:10,916 --> 00:06:11,730 but that's 20. 99 00:06:11,730 --> 00:06:16,950 And then I can't pick 23, so I go 20 plus 11, which is 31. 100 00:06:16,950 --> 00:06:19,470 31 plus 4, 35. 101 00:06:19,470 --> 00:06:22,230 35 plus 17, 52. 102 00:06:22,230 --> 00:06:27,300 52 plus 34-- check my math, please-- 103 00:06:27,300 --> 00:06:28,650 86. 104 00:06:28,650 --> 00:06:33,810 86 plus 18 is 104. 105 00:06:33,810 --> 00:06:41,880 104 plus 12 is 116, is a possibility. 106 00:06:41,880 --> 00:06:46,730 But at this point, you have no idea-- 107 00:06:46,730 --> 00:06:52,260 I know, so I have some idea whether 116 is the highest 108 00:06:52,260 --> 00:06:53,550 or not. 109 00:06:53,550 --> 00:06:56,580 And I'll tell you that it's not, OK? 110 00:06:56,580 --> 00:06:58,890 It's not the highest, you can do better. 111 00:06:58,890 --> 00:07:01,260 And you can maybe go and see if you can twiddle things 112 00:07:01,260 --> 00:07:02,350 here a little bit. 113 00:07:02,350 --> 00:07:05,250 But remember that you, obviously, just 114 00:07:05,250 --> 00:07:06,470 don't want to drop something. 115 00:07:06,470 --> 00:07:09,053 But if you just drop something, you want to pick something up. 116 00:07:09,053 --> 00:07:14,377 Because if you just drop something, you'd lower 116. 117 00:07:14,377 --> 00:07:15,960 And if you want to do better than 116, 118 00:07:15,960 --> 00:07:19,710 you absolutely have to pick something up. 119 00:07:19,710 --> 00:07:21,570 Especially when you're alternating, 120 00:07:21,570 --> 00:07:23,310 clearly, you could have done-- 121 00:07:23,310 --> 00:07:25,020 I mean, can you do a little bit better? 122 00:07:25,020 --> 00:07:28,170 My last thing that I picked was 12. 123 00:07:28,170 --> 00:07:31,680 And because of that, you know what happened. 124 00:07:31,680 --> 00:07:34,440 So can I do a little bit better than 116? 125 00:07:34,440 --> 00:07:37,710 Yeah, by dropping 12 and grabbing 15, 126 00:07:37,710 --> 00:07:39,130 and I get a plus 3. 127 00:07:39,130 --> 00:07:43,320 And you might think that 119 is the optimum. 128 00:07:43,320 --> 00:07:46,440 But it turns out that's not even the optimum. 129 00:07:46,440 --> 00:07:48,100 And so there's a lot of combinations. 130 00:07:48,100 --> 00:07:49,620 And I just looked at something local 131 00:07:49,620 --> 00:07:51,360 here to try and improve things. 132 00:07:51,360 --> 00:07:55,400 But maybe I should-- you know, it's probably 133 00:07:55,400 --> 00:08:00,180 was good that I picked the 34, but I don't really know that. 134 00:08:00,180 --> 00:08:02,880 I mean, it's possible that if I hadn't picked the 34, 135 00:08:02,880 --> 00:08:05,610 that I could've picked the 23 and the 17, 136 00:08:05,610 --> 00:08:07,310 and that is 40, right? 137 00:08:07,310 --> 00:08:10,920 So maybe that was better. 138 00:08:10,920 --> 00:08:12,660 So this is non-trivial. 139 00:08:12,660 --> 00:08:16,170 This is a very simple-- 140 00:08:16,170 --> 00:08:18,180 at least to describe-- puzzle,. 141 00:08:18,180 --> 00:08:22,281 But this is non-trivial in terms of finding the optimum solution 142 00:08:22,281 --> 00:08:25,250 as it gets 143 00:08:25,250 --> 00:08:27,230 --longer, the row gets longer. 144 00:08:27,230 --> 00:08:30,960 The numbers being large is not really the issue. 145 00:08:30,960 --> 00:08:34,549 It's the number of numbers that's the issue, right? 146 00:08:34,549 --> 00:08:36,270 So how are we going to solve this? 147 00:08:36,270 --> 00:08:38,600 What can we do? 148 00:08:38,600 --> 00:08:43,059 And let's not worry about efficiency. 149 00:08:43,059 --> 00:08:45,230 How could we solve this? 150 00:08:45,230 --> 00:08:47,900 And obviously, we've been talking 151 00:08:47,900 --> 00:08:49,400 about recursive algorithms and we've 152 00:08:49,400 --> 00:08:53,450 solved nQueens, which has lots of combinations. 153 00:08:53,450 --> 00:08:57,362 Sudoku, even more combinations. 154 00:08:57,362 --> 00:08:58,820 There's a lot of combinations here. 155 00:08:58,820 --> 00:09:03,230 But honestly, the number of combinations 156 00:09:03,230 --> 00:09:05,750 is dwarfed by the number of combinations 157 00:09:05,750 --> 00:09:08,980 we've already handled in these other puzzles, right? 158 00:09:08,980 --> 00:09:12,569 So yeah, so someone wants to give me some sense of how 159 00:09:12,569 --> 00:09:13,360 this could be done? 160 00:09:17,780 --> 00:09:18,921 Go ahead, Fadi. 161 00:09:18,921 --> 00:09:19,783 AUDIENCE: So if I want to choose numbers here, 162 00:09:19,783 --> 00:09:21,324 we need to know that at least there's 163 00:09:21,324 --> 00:09:22,570 going to be a gap between-- 164 00:09:22,570 --> 00:09:25,760 at least a gap of one number between any two 165 00:09:25,760 --> 00:09:27,065 consecutive numbers. 166 00:09:27,065 --> 00:09:29,460 SRINI DEVADAS: Yeah, you want a gap of at least one. 167 00:09:29,460 --> 00:09:31,043 AUDIENCE: So what we can do with that, 168 00:09:31,043 --> 00:09:36,240 we can iterate, for example, if we have seven numbers, 169 00:09:36,240 --> 00:09:41,360 we have at most four numbers to pick. 170 00:09:41,360 --> 00:09:46,920 Or, for example, if we have more numbers, 171 00:09:46,920 --> 00:09:49,476 we then have more options. 172 00:09:49,476 --> 00:09:53,650 If we can do it, we can carry the gap slice between each two 173 00:09:53,650 --> 00:09:55,769 consecutive numbers and iterate over that, 174 00:09:55,769 --> 00:09:57,810 and see what combination gives us the high stuff. 175 00:09:57,810 --> 00:09:59,351 SRINI DEVADAS: Yeah, you're basically 176 00:09:59,351 --> 00:10:03,320 trying to create some sort of exhaustive search. 177 00:10:03,320 --> 00:10:08,120 Your algorithm was iterating over the gaps. 178 00:10:08,120 --> 00:10:09,920 And there's many gaps, by the way. 179 00:10:09,920 --> 00:10:13,610 You have a gap of one at least, and another gap 180 00:10:13,610 --> 00:10:16,490 of one, another gap of one if I had the strict alternation. 181 00:10:16,490 --> 00:10:18,950 And you have to vary one of the gaps to two. 182 00:10:18,950 --> 00:10:22,670 And that, obviously, impacts the numbers you picked even for-- 183 00:10:22,670 --> 00:10:25,160 the gap might stay the same for the next pair of numbers, 184 00:10:25,160 --> 00:10:27,860 but the numbers will be shifted in the coin row sequence. 185 00:10:27,860 --> 00:10:30,980 And it's fairly complicated, OK? 186 00:10:30,980 --> 00:10:34,250 If you are willing to give up efficiency, 187 00:10:34,250 --> 00:10:48,260 and you have a set of n items, then how many different ways, 188 00:10:48,260 --> 00:10:53,300 how many different subsets of n items do I actually have? 189 00:10:53,300 --> 00:10:55,800 When you have n elements-- 190 00:10:55,800 --> 00:10:59,570 you might have learned this in set algebra. 191 00:10:59,570 --> 00:11:05,210 But if you haven't, we'll go over it here real quick. 192 00:11:05,210 --> 00:11:07,430 But how many combinations, how many subsets 193 00:11:07,430 --> 00:11:11,820 do you have when you have a set of n elements? 194 00:11:11,820 --> 00:11:16,200 You have to count the empty set and the entire set, right? 195 00:11:16,200 --> 00:11:20,670 So if I, say, have a set of one element, 196 00:11:20,670 --> 00:11:24,390 then the empty set is a subset of the one element set. 197 00:11:24,390 --> 00:11:26,280 And then, obviously, the one element set 198 00:11:26,280 --> 00:11:29,580 is a subset of itself, so that's two, right? 199 00:11:29,580 --> 00:11:35,640 And then if I had two elements, A and B, then it's empty, 200 00:11:35,640 --> 00:11:37,980 A, B, and AB. 201 00:11:37,980 --> 00:11:39,150 That's four. 202 00:11:39,150 --> 00:11:41,880 So you get a pattern here? 203 00:11:41,880 --> 00:11:44,310 So it's 2 to the n, right? 204 00:11:44,310 --> 00:11:51,060 So I can generate the 2 to the n subsets that correspond 205 00:11:51,060 --> 00:11:52,620 to the n-element set. 206 00:11:52,620 --> 00:11:56,130 And there's actually library functions in Python, powerset, 207 00:11:56,130 --> 00:11:57,270 that lets you do this. 208 00:11:57,270 --> 00:11:59,910 But that's cheating for this class 209 00:11:59,910 --> 00:12:04,080 because you can't use libraries, OK? 210 00:12:04,080 --> 00:12:06,540 Real programmers don't use libraries. 211 00:12:06,540 --> 00:12:08,182 That's actually not true at all. 212 00:12:08,182 --> 00:12:11,640 [LAUGHS] That is probably the most dishonest statement 213 00:12:11,640 --> 00:12:14,670 made in this course. 214 00:12:14,670 --> 00:12:17,330 Real programmers actually exploit libraries. 215 00:12:17,330 --> 00:12:20,820 But introductory programmers should learn programming 216 00:12:20,820 --> 00:12:23,220 by programming from scratch, right? 217 00:12:26,270 --> 00:12:28,890 But you can generate the 2 to the n subsets, 218 00:12:28,890 --> 00:12:32,790 for example, by just-- 219 00:12:32,790 --> 00:12:34,440 I can show you code for this offline-- 220 00:12:34,440 --> 00:12:39,420 by running through and incrementing an integer 221 00:12:39,420 --> 00:12:41,520 to go from 0 to 2 raised to n. 222 00:12:41,520 --> 00:12:43,570 You know, 2 raised to n could be a million, 223 00:12:43,570 --> 00:12:45,020 which is not that bad. 224 00:12:45,020 --> 00:12:49,080 And then this you could encode as-- you turn it into binary. 225 00:12:49,080 --> 00:12:57,450 So if n happens be 4, then this turns into 0000, 0001. 226 00:12:57,450 --> 00:13:01,606 And each of these is a distinct subset, right? 227 00:13:01,606 --> 00:13:03,480 This means none of the elements are in there. 228 00:13:03,480 --> 00:13:05,670 This means that last element is in there. 229 00:13:05,670 --> 00:13:07,829 This means that all four elements are in there. 230 00:13:07,829 --> 00:13:10,120 And somewhere in here, if you have something like this, 231 00:13:10,120 --> 00:13:13,440 the second one is in there and the fourth one is in there. 232 00:13:13,440 --> 00:13:16,770 So you could, essentially, use iteration 233 00:13:16,770 --> 00:13:18,930 to generate all of the subsets. 234 00:13:18,930 --> 00:13:20,620 And you're not done yet. 235 00:13:20,620 --> 00:13:23,730 What do you have to do now that I've given you all the subsets? 236 00:13:23,730 --> 00:13:26,796 It's two, three lines of code to solve our problem. 237 00:13:26,796 --> 00:13:28,920 Someone tell me what those two, three lines of code 238 00:13:28,920 --> 00:13:33,870 are from a standpoint of operations required. 239 00:13:33,870 --> 00:13:36,120 I'm not looking at each of the subsets. 240 00:13:36,120 --> 00:13:40,390 What do I need to do for a given subset? 241 00:13:40,390 --> 00:13:41,591 Yeah, go ahead, Ryan. 242 00:13:41,591 --> 00:13:43,275 AUDIENCE: To iterate through the subset 243 00:13:43,275 --> 00:13:45,404 and find the sum of all the values. 244 00:13:45,404 --> 00:13:46,570 SRINI DEVADAS: That's right. 245 00:13:46,570 --> 00:13:47,986 I could iterate through the subset 246 00:13:47,986 --> 00:13:50,680 and find the sum of second plus fourth. 247 00:13:50,680 --> 00:13:52,330 I do that for-- 248 00:13:52,330 --> 00:13:56,950 do I do that for all the subsets and pick the maximum? 249 00:13:56,950 --> 00:13:59,850 Or do I do that for a subset of the subsets 250 00:13:59,850 --> 00:14:02,204 and pick the maximum? 251 00:14:02,204 --> 00:14:03,120 AUDIENCE: from subsets 252 00:14:03,120 --> 00:14:05,370 SRINI DEVADAS: What happens with this one? 253 00:14:05,370 --> 00:14:08,110 This is picking every number. 254 00:14:08,110 --> 00:14:10,600 So this is obviously going to be bigger 255 00:14:10,600 --> 00:14:12,440 than all of the other ones. 256 00:14:12,440 --> 00:14:14,220 So did I have to enumerate all of them? 257 00:14:14,220 --> 00:14:16,670 What is wrong with this picture here? 258 00:14:16,670 --> 00:14:19,595 What is wrong with what I just said? 259 00:14:19,595 --> 00:14:21,670 AUDIENCE: violates the constraint. 260 00:14:21,670 --> 00:14:23,420 SRINI DEVADAS: Someone other than Ganatra, 261 00:14:23,420 --> 00:14:28,385 what is wrong with this solution which picks all the numbers? 262 00:14:32,630 --> 00:14:37,040 It's on the board, the answer is on the board. 263 00:14:37,040 --> 00:14:38,674 Yeah, go ahead, Ryan. 264 00:14:38,674 --> 00:14:40,335 AUDIENCE: It violates the constraint. 265 00:14:40,335 --> 00:14:42,335 SRINI DEVADAS: Yeah, it violates the constraint. 266 00:14:46,030 --> 00:14:47,812 So not all of the subsets-- 267 00:14:47,812 --> 00:14:49,270 I mean, if all of the subsets work, 268 00:14:49,270 --> 00:14:51,436 then you don't have to enumerate all of the subsets. 269 00:14:51,436 --> 00:14:54,150 You would just pick the numbers, all the numbers, right? 270 00:14:54,150 --> 00:14:57,490 So you have to now check that-- 271 00:14:57,490 --> 00:14:59,530 and there is some code, too. 272 00:14:59,530 --> 00:15:00,860 I lied. 273 00:15:00,860 --> 00:15:05,149 I guess, I haven't finished with my dishonesty. 274 00:15:05,149 --> 00:15:07,690 But it's not two, three lines of code, it's a little bit more 275 00:15:07,690 --> 00:15:08,380 than that-- 276 00:15:08,380 --> 00:15:13,772 to check that particular subset, whether it violates 277 00:15:13,772 --> 00:15:14,730 the constraints or not. 278 00:15:17,740 --> 00:15:20,160 And so what is the check-- 279 00:15:20,160 --> 00:15:22,110 it's going to be four or five lines of code-- 280 00:15:22,110 --> 00:15:26,140 what is the simple check if I give you a bit string? 281 00:15:26,140 --> 00:15:29,520 What is the simple check that you need to perform in order 282 00:15:29,520 --> 00:15:33,810 to check the violation of the constraint in terms 283 00:15:33,810 --> 00:15:36,190 of 0's and 1's? 284 00:15:36,190 --> 00:15:37,178 Yeah, go ahead. 285 00:15:37,178 --> 00:15:39,010 AUDIENCE: No two consecutive 1's. 286 00:15:39,010 --> 00:15:42,750 SRINI DEVADAS: Yeah, you do not do consecutive 1's. 287 00:15:42,750 --> 00:15:45,150 If you ever see two or more consecutive 1's, you've 288 00:15:45,150 --> 00:15:46,380 got a problem, right? 289 00:15:46,380 --> 00:15:48,830 So that's easy to check. 290 00:15:48,830 --> 00:15:54,460 And this constraint is no two consecutive 1's. 291 00:15:57,130 --> 00:15:59,170 So you can imagine coding this up. 292 00:15:59,170 --> 00:16:03,160 And if you coded that strategy up, 293 00:16:03,160 --> 00:16:08,330 it turns out that this particular thing, it's 294 00:16:08,330 --> 00:16:12,540 a reasonable strategy if n is small. 295 00:16:12,540 --> 00:16:15,290 And it turns out that it would tell you 296 00:16:15,290 --> 00:16:27,300 that you want to pick 15, 23, 4, interesting enough, 17, 34. 297 00:16:27,300 --> 00:16:30,620 So double skip over there because you would really 298 00:16:30,620 --> 00:16:31,790 want to get to 17. 299 00:16:31,790 --> 00:16:39,952 This 34, and 18, and you want 15. 300 00:16:39,952 --> 00:16:40,660 That makes sense. 301 00:16:40,660 --> 00:16:41,910 You don't want 12. 302 00:16:41,910 --> 00:16:44,450 And so this ends up adding up to 126, which 303 00:16:44,450 --> 00:16:47,150 happens to be the optimal. 304 00:16:47,150 --> 00:16:49,070 So you can certainly do that. 305 00:16:51,680 --> 00:16:53,480 You can, as I said, use the powerset 306 00:16:53,480 --> 00:16:55,820 to save yourself some trouble. 307 00:16:55,820 --> 00:16:58,320 But you still have to code the violation of constraints, 308 00:16:58,320 --> 00:16:59,820 right? 309 00:16:59,820 --> 00:17:01,900 We want to do substantially better than this. 310 00:17:01,900 --> 00:17:07,880 Because if n happens to be a 50, 2 raised to 50 311 00:17:07,880 --> 00:17:09,391 is way too large a number. 312 00:17:09,391 --> 00:17:10,849 And we don't want to be enumerating 313 00:17:10,849 --> 00:17:12,170 all of these subsets. 314 00:17:12,170 --> 00:17:17,450 In fact, there's a way of doing this, certainly, 315 00:17:17,450 --> 00:17:19,369 in polynomial time. 316 00:17:19,369 --> 00:17:23,660 And it's going to be something where 317 00:17:23,660 --> 00:17:28,820 we're going to be able to run this algorithm in linear time. 318 00:17:28,820 --> 00:17:31,940 We can make a pass through this list 319 00:17:31,940 --> 00:17:37,130 and get that 126 number blazingly fast 320 00:17:37,130 --> 00:17:41,900 using the notion of memoization, which is 321 00:17:41,900 --> 00:17:43,550 related to dynamic programming. 322 00:17:43,550 --> 00:17:47,330 And so this is a powerful algorithmic technique that 323 00:17:47,330 --> 00:17:50,030 you'll see over and over, especially if you take classes 324 00:17:50,030 --> 00:17:52,870 like 006 and 046. 325 00:17:52,870 --> 00:17:56,360 That gives you exponential improvements in runtime. 326 00:17:56,360 --> 00:17:59,960 Rather than 2 raised to n, growing as 2 raised to n, 327 00:17:59,960 --> 00:18:03,740 you grow as n, which is a huge difference, obviously. 328 00:18:03,740 --> 00:18:07,650 Now, usually, when we talk about dynamic programming, 329 00:18:07,650 --> 00:18:10,850 we start with a recursive strategy, not 330 00:18:10,850 --> 00:18:13,850 this enumerative subset strategy, 331 00:18:13,850 --> 00:18:19,080 to generate the different solutions. 332 00:18:19,080 --> 00:18:22,190 And one of the problems with this 333 00:18:22,190 --> 00:18:24,830 is you're generating a lot of solutions, a lot 334 00:18:24,830 --> 00:18:28,520 of incorrect, invalid subsets. 335 00:18:28,520 --> 00:18:30,680 Because 1111 is an invalid subset. 336 00:18:30,680 --> 00:18:33,740 And there's a lot of them that are invalid. 337 00:18:33,740 --> 00:18:36,620 A better approach, which would still be exponential, 338 00:18:36,620 --> 00:18:42,470 but it is better in terms of numbers than 2 raised to n, 339 00:18:42,470 --> 00:18:49,010 is to only generate recursively the legal combinations 340 00:18:49,010 --> 00:18:53,990 and then pick the best legal combination. 341 00:18:53,990 --> 00:18:56,090 And the legal combination, of course, 342 00:18:56,090 --> 00:18:58,330 in this case, as we described, was 343 00:18:58,330 --> 00:19:02,330 no two consecutive 1's, right? 344 00:19:02,330 --> 00:19:03,470 Now, we've done recursion. 345 00:19:03,470 --> 00:19:05,180 We've looked at recursive code. 346 00:19:05,180 --> 00:19:10,820 So the key thing when you write recursive code is, remember, 347 00:19:10,820 --> 00:19:16,370 you want to get subproblems that look like the problem 348 00:19:16,370 --> 00:19:18,170 that you're solving, right? 349 00:19:18,170 --> 00:19:21,140 They look exactly like the problem you're solving. 350 00:19:21,140 --> 00:19:23,450 Because then you can invoke yourself 351 00:19:23,450 --> 00:19:27,230 as a procedure with different arguments. 352 00:19:27,230 --> 00:19:29,840 And we kind of went through this a couple of times. 353 00:19:29,840 --> 00:19:33,200 So this problem is actually less complicated 354 00:19:33,200 --> 00:19:35,160 than the tiling problem. 355 00:19:35,160 --> 00:19:37,760 It is basically a row of numbers. 356 00:19:37,760 --> 00:19:45,230 And let's just say you have numbers a, b, c, d, e, f. 357 00:19:47,750 --> 00:19:54,590 Try to think of a recursive strategy that says, I want-- 358 00:19:54,590 --> 00:19:57,230 let's call it Coinrow. 359 00:19:57,230 --> 00:20:03,770 And Coinrow is going to have a through f as an argument. 360 00:20:03,770 --> 00:20:04,730 That's the list. 361 00:20:04,730 --> 00:20:06,830 I'm just using pseudocode here. 362 00:20:06,830 --> 00:20:11,510 And I want Coinrow to do some computation. 363 00:20:11,510 --> 00:20:17,060 And it's going to call Coinrow maybe multiple times. 364 00:20:17,060 --> 00:20:26,210 But the key thing is, what are the arguments 365 00:20:26,210 --> 00:20:33,170 that you have inside of those recursive calls for Coinrow? 366 00:20:33,170 --> 00:20:37,160 And that's the biggest question. 367 00:20:37,160 --> 00:20:40,220 The easier question to answer is, 368 00:20:40,220 --> 00:20:43,520 what happens when you have the base case? 369 00:20:43,520 --> 00:20:47,360 And you end up, essentially, saying, 370 00:20:47,360 --> 00:20:52,960 you've got one coin on the row. 371 00:20:52,960 --> 00:20:56,400 So you've got one coin problem, right? 372 00:20:56,400 --> 00:20:57,460 What happens then? 373 00:20:57,460 --> 00:20:58,660 What is the base case? 374 00:20:58,660 --> 00:20:59,950 What do you do? 375 00:20:59,950 --> 00:21:01,630 You pick the coin, OK? 376 00:21:01,630 --> 00:21:05,200 Because if you had two of them, if you happened 377 00:21:05,200 --> 00:21:09,670 to choose the base case to be 2, in this case, e and f, 378 00:21:09,670 --> 00:21:12,760 what would you do in that case? 379 00:21:12,760 --> 00:21:15,910 Compare the two and pick the bigger one, right? 380 00:21:15,910 --> 00:21:18,710 But you have to be a little bit careful here. 381 00:21:18,710 --> 00:21:21,760 Because when you make the recursive calls, 382 00:21:21,760 --> 00:21:24,930 obviously, you can't have-- 383 00:21:24,930 --> 00:21:28,630 would this work if you picked 8? 384 00:21:28,630 --> 00:21:31,210 If I did something like this-- 385 00:21:31,210 --> 00:21:36,370 I do 8 plus Coinrow. 386 00:21:36,370 --> 00:21:44,600 So inside here, I do a plus Coinrow b through f. 387 00:21:44,600 --> 00:21:48,980 If I wrote this code as a plus Coinrow b through f, 388 00:21:48,980 --> 00:21:51,670 what would happen? 389 00:21:51,670 --> 00:21:53,420 What would happened if I had Coinrow, 390 00:21:53,420 --> 00:21:58,330 and then I said I'm going to return a plus Coinrow b through 391 00:21:58,330 --> 00:22:00,140 f, and then I have a base case that 392 00:22:00,140 --> 00:22:02,630 says that if I have a single-- 393 00:22:02,630 --> 00:22:03,710 I still need a base case. 394 00:22:03,710 --> 00:22:05,540 This is just the recursive step. 395 00:22:05,540 --> 00:22:07,640 I need a base case so this would complete. 396 00:22:07,640 --> 00:22:10,580 And then I say that if I ever have an argument of length 1, 397 00:22:10,580 --> 00:22:12,420 I'm going to return that argument. 398 00:22:12,420 --> 00:22:15,310 So what would happen with this code? 399 00:22:15,310 --> 00:22:15,880 Any ideas? 400 00:22:19,210 --> 00:22:19,822 Go ahead, Kye. 401 00:22:19,822 --> 00:22:21,030 AUDIENCE: Pick all the coins. 402 00:22:21,030 --> 00:22:22,821 SRINI DEVADAS: It would pick all the coins. 403 00:22:22,821 --> 00:22:24,790 It would just totally pick all the coins. 404 00:22:24,790 --> 00:22:27,540 Because it would go a plus, and then it'd go b through f. 405 00:22:27,540 --> 00:22:30,430 The constraint hasn't been encoded in here, right? 406 00:22:30,430 --> 00:22:32,230 So we would just pick all the coins. 407 00:22:32,230 --> 00:22:34,210 So that doesn't make sense. 408 00:22:34,210 --> 00:22:35,840 So I have to-- 409 00:22:35,840 --> 00:22:37,900 I have some choices here. 410 00:22:37,900 --> 00:22:42,250 And so this was a giveaway that this would not work. 411 00:22:42,250 --> 00:22:44,650 Because it's not doing any choices, 412 00:22:44,650 --> 00:22:46,510 it's just picking all the coins. 413 00:22:46,510 --> 00:22:51,620 So what happens if I pick a? 414 00:22:51,620 --> 00:22:52,930 What does it mean? 415 00:22:52,930 --> 00:22:55,190 If I pick a, what does that mean? 416 00:22:55,190 --> 00:22:58,150 What does that mean to my value that I 417 00:22:58,150 --> 00:23:01,900 want to return, which eventually needs to be the maximum value? 418 00:23:01,900 --> 00:23:08,440 And what does it mean with respect to the subproblems? 419 00:23:08,440 --> 00:23:10,300 So the first question is easier. 420 00:23:10,300 --> 00:23:13,620 What does it mean with respect to my value? 421 00:23:13,620 --> 00:23:16,410 I need to add it to the value, right? 422 00:23:16,410 --> 00:23:19,400 The second question is, what happens to the-- 423 00:23:19,400 --> 00:23:23,340 if I pick a, what happens to the coin row problem that remains? 424 00:23:23,340 --> 00:23:25,230 What can I say about the coin row 425 00:23:25,230 --> 00:23:28,050 problem that remains that you're going to tell me about? 426 00:23:28,050 --> 00:23:29,190 If I picked a-- 427 00:23:29,190 --> 00:23:32,910 so this might be pick the first one. 428 00:23:32,910 --> 00:23:37,650 Pick first, in this case, which is a. 429 00:23:37,650 --> 00:23:39,550 We'll just put that in brackets. 430 00:23:39,550 --> 00:23:43,320 So what do I need to send as an argument to Coinrow? 431 00:23:43,320 --> 00:23:47,010 As one possibility, what do I need to send as an argument 432 00:23:47,010 --> 00:23:49,820 to Coinrow? 433 00:23:49,820 --> 00:23:51,680 Someone who has an answer? 434 00:23:51,680 --> 00:23:55,570 That should use the constraint. 435 00:23:55,570 --> 00:23:58,030 What do I need to send as an argument to Coinrow? 436 00:24:01,990 --> 00:24:04,870 Yeah, go ahead, I saw Kye first. 437 00:24:04,870 --> 00:24:05,370 Go ahead. 438 00:24:05,370 --> 00:24:06,300 AUDIENCE: c through f. 439 00:24:06,300 --> 00:24:08,190 SRINI DEVADAS: c through f, exactly. 440 00:24:08,190 --> 00:24:10,440 I cannot pick b right? 441 00:24:10,440 --> 00:24:14,640 So I encode the constraint in the recursive call 442 00:24:14,640 --> 00:24:17,460 by saying that if I picked a then 443 00:24:17,460 --> 00:24:24,240 I encode this as c dot dot dot f, OK? 444 00:24:24,240 --> 00:24:27,390 I'll just say c dash f. 445 00:24:27,390 --> 00:24:31,560 And let me go ahead and erase this to give myself 446 00:24:31,560 --> 00:24:33,270 a little bit more room. 447 00:24:33,270 --> 00:24:34,200 But I'm not done yet. 448 00:24:34,200 --> 00:24:39,180 So if I ended up picking a, and I go-- 449 00:24:39,180 --> 00:24:42,270 if I don't write any more code and I ended up 450 00:24:42,270 --> 00:24:47,340 picking up a plus the value that I get from Coinrow c through f, 451 00:24:47,340 --> 00:24:48,900 and if I don't write any more code, 452 00:24:48,900 --> 00:24:52,790 what does that correspond to in terms of an algorithm? 453 00:24:52,790 --> 00:24:54,830 We've actually used that algorithm. 454 00:24:54,830 --> 00:24:58,420 What does that correspond to if I only make one recursive call, 455 00:24:58,420 --> 00:25:01,124 and I pick a, and I go c through f? 456 00:25:01,124 --> 00:25:03,540 What does that correspond to with respect to an algorithm? 457 00:25:06,690 --> 00:25:08,175 Someone who hasn't answered? 458 00:25:08,175 --> 00:25:13,430 This is the your last chance, last lecture. 459 00:25:13,430 --> 00:25:14,851 Yeah, you're thinking about it? 460 00:25:14,851 --> 00:25:15,350 Go ahead. 461 00:25:15,350 --> 00:25:16,849 AUDIENCE: It violates the constraint 462 00:25:16,849 --> 00:25:20,450 because c and d and e and f. 463 00:25:20,450 --> 00:25:23,120 SRINI DEVADAS: So Styliani right? 464 00:25:23,120 --> 00:25:28,340 So Styliani says, basically, it's an alternation algorithm. 465 00:25:28,340 --> 00:25:32,210 You're going to end up picking a, and then c, and then e, 466 00:25:32,210 --> 00:25:33,260 and then f. 467 00:25:33,260 --> 00:25:35,540 You can't pick f because you had to skip f. 468 00:25:35,540 --> 00:25:37,580 So it's alternation. 469 00:25:37,580 --> 00:25:39,430 We did this alternation algorithm. 470 00:25:39,430 --> 00:25:41,240 We knew it wasn't going to be optimal. 471 00:25:41,240 --> 00:25:43,769 So clearly, it's not a solution to our problem, 472 00:25:43,769 --> 00:25:45,560 algorithmically speaking, because it's only 473 00:25:45,560 --> 00:25:48,200 going to give you the alternating coins. 474 00:25:48,200 --> 00:25:51,800 And that might work out, but it didn't work out 475 00:25:51,800 --> 00:25:54,120 in the case of our longer problem, right? 476 00:25:54,120 --> 00:25:55,670 We got-- what was it-- 477 00:25:55,670 --> 00:25:58,240 116. 478 00:25:58,240 --> 00:25:59,600 So that doesn't work. 479 00:25:59,600 --> 00:26:01,610 So what else do I do? 480 00:26:01,610 --> 00:26:03,730 What is the other case that corresponds 481 00:26:03,730 --> 00:26:05,600 do what I have here? 482 00:26:05,600 --> 00:26:06,890 I can pick the coin and? 483 00:26:10,630 --> 00:26:12,790 I could skip the coin. 484 00:26:12,790 --> 00:26:16,240 I could pick the coin and I could skip the coin. 485 00:26:16,240 --> 00:26:19,240 Skip first, a. 486 00:26:19,240 --> 00:26:26,320 Aha, what now can I pass into the Coinrow argument? 487 00:26:26,320 --> 00:26:32,635 What can I pass into the Coinrow argument if I skip a? 488 00:26:32,635 --> 00:26:33,260 Go ahead, Ryan. 489 00:26:33,260 --> 00:26:34,100 AUDIENCE: b through f. 490 00:26:34,100 --> 00:26:35,600 SRINI DEVADAS: b through f, exactly. 491 00:26:35,600 --> 00:26:38,770 So it's different, b through f. 492 00:26:38,770 --> 00:26:40,990 That's it, that's our algorithm. 493 00:26:40,990 --> 00:26:45,520 This is now four lines of code in terms of recursive calls. 494 00:26:45,520 --> 00:26:49,200 One last thing, I did these two things, 495 00:26:49,200 --> 00:26:56,550 I'm going to get values back for each of these. 496 00:26:56,550 --> 00:26:58,134 Because I'm going to get a value back. 497 00:26:58,134 --> 00:26:59,550 That's essentially what I'm doing. 498 00:26:59,550 --> 00:27:01,920 When I'm picking, I'm going to add the value a. 499 00:27:01,920 --> 00:27:06,420 And then I'm going to add it to the return value corresponding 500 00:27:06,420 --> 00:27:08,400 to Coinrow c through f. 501 00:27:08,400 --> 00:27:11,300 And then, in this case, I'm going to get simply the value 502 00:27:11,300 --> 00:27:12,540 corresponding to b through f. 503 00:27:12,540 --> 00:27:16,272 What do I do with val1 and val2? 504 00:27:16,272 --> 00:27:17,730 What do I do with these two values? 505 00:27:17,730 --> 00:27:18,480 Do I look at them? 506 00:27:21,498 --> 00:27:22,929 Yeah. 507 00:27:22,929 --> 00:27:25,607 AUDIENCE: return them? 508 00:27:25,607 --> 00:27:27,940 SRINI DEVADAS: What is the value for the original-- what 509 00:27:27,940 --> 00:27:29,600 is the value that I want to return 510 00:27:29,600 --> 00:27:30,890 for the original problem? 511 00:27:30,890 --> 00:27:33,590 Just like with all of the things we've done, 512 00:27:33,590 --> 00:27:38,060 we've taken values of subproblems, solutions 513 00:27:38,060 --> 00:27:40,520 to subproblems, and we've actually done something 514 00:27:40,520 --> 00:27:44,060 with them to return the value or solution 515 00:27:44,060 --> 00:27:45,400 for the original problem. 516 00:27:45,400 --> 00:27:46,400 So what do I need to do? 517 00:27:46,400 --> 00:27:48,200 What line of code do I need to write 518 00:27:48,200 --> 00:27:50,240 to return a value for the original coin row 519 00:27:50,240 --> 00:27:54,630 problem that had a through f as its arguments? 520 00:27:54,630 --> 00:27:55,710 It's one line of code. 521 00:27:55,710 --> 00:27:59,010 What is that line of code? 522 00:27:59,010 --> 00:27:59,720 Go ahead, George. 523 00:27:59,720 --> 00:28:00,620 AUDIENCE: Put it in the max. 524 00:28:00,620 --> 00:28:01,869 SRINI DEVADAS: Return the max. 525 00:28:01,869 --> 00:28:03,090 That's exactly right. 526 00:28:03,090 --> 00:28:10,820 You return max val1, val2. 527 00:28:13,552 --> 00:28:15,260 And so let me show you the code for that. 528 00:28:18,670 --> 00:28:27,180 So this is a little bit better than the subset solution 529 00:28:27,180 --> 00:28:28,980 that we described. 530 00:28:28,980 --> 00:28:33,860 But as it turns out, it's not a whole lot better, 531 00:28:33,860 --> 00:28:35,260 and we'll talk about that. 532 00:28:35,260 --> 00:28:39,340 But this code now should not be surprising to you 533 00:28:39,340 --> 00:28:43,210 because we talked about it and effectively, collectively we 534 00:28:43,210 --> 00:28:44,200 wrote it, right? 535 00:28:44,200 --> 00:28:46,660 That was a collective coding exercise 536 00:28:46,660 --> 00:28:48,730 called cooperative coding. 537 00:28:48,730 --> 00:28:52,150 Not really, but close enough. 538 00:28:52,150 --> 00:28:55,180 And so you see what I have up there. 539 00:28:55,180 --> 00:28:58,150 And there's only one thing that I 540 00:28:58,150 --> 00:29:03,550 didn't describe to you, which is something that we're 541 00:29:03,550 --> 00:29:04,984 going to get to in a second. 542 00:29:04,984 --> 00:29:06,400 But you see something called table 543 00:29:06,400 --> 00:29:08,230 in there, which is essentially something 544 00:29:08,230 --> 00:29:14,820 that keeps the maximum value corresponding to the smaller 545 00:29:14,820 --> 00:29:16,740 problems that we are looking at. 546 00:29:16,740 --> 00:29:20,580 So it keeps that around. 547 00:29:20,580 --> 00:29:24,630 But you can see that there's a base case if you forget table. 548 00:29:24,630 --> 00:29:26,590 And there's a reason that table is in here. 549 00:29:26,590 --> 00:29:28,590 And I'm going to ask you why in a minute. 550 00:29:28,590 --> 00:29:30,700 But forget about table for a second. 551 00:29:30,700 --> 00:29:32,460 And if len is 0, you're going to return 0. 552 00:29:32,460 --> 00:29:34,250 That's a base case. 553 00:29:34,250 --> 00:29:36,780 If len is 1, you're going to return that coin. 554 00:29:36,780 --> 00:29:39,360 That's also another base case. 555 00:29:39,360 --> 00:29:42,840 And you might end up with one or the other. 556 00:29:42,840 --> 00:29:45,540 Because, obviously, you're skipping coins, right? 557 00:29:45,540 --> 00:29:48,120 So it's possible that you need to take into account 558 00:29:48,120 --> 00:29:49,530 both of these base cases. 559 00:29:49,530 --> 00:29:51,240 You say, why do I need two base cases? 560 00:29:51,240 --> 00:29:52,750 Well, you're taking away a coin. 561 00:29:52,750 --> 00:29:55,170 So you might end up with something that's empty, right? 562 00:29:55,170 --> 00:29:56,850 So you need both of those base cases. 563 00:29:56,850 --> 00:30:01,710 And then pick equals coin row, table. 564 00:30:01,710 --> 00:30:05,920 This thing over here is picking the coin. 565 00:30:05,920 --> 00:30:10,560 And then 2 colon says that you're dropping-- 566 00:30:10,560 --> 00:30:14,670 in our case, we picked a, but we dropped b and started with c. 567 00:30:14,670 --> 00:30:16,800 And skip is you're skipping it. 568 00:30:16,800 --> 00:30:19,950 So you just skipped it and you go row 1 colon. 569 00:30:19,950 --> 00:30:22,350 Makes perfect sense, right? 570 00:30:22,350 --> 00:30:26,760 And I don't know if you guys have ever returned-- 571 00:30:26,760 --> 00:30:31,260 I think you have in exercises-- if you returned multiple values 572 00:30:31,260 --> 00:30:33,400 in the return statement. 573 00:30:33,400 --> 00:30:37,190 And so this thing over here is-- the 0 574 00:30:37,190 --> 00:30:40,922 says that I'm going to look at the first value, not the table. 575 00:30:40,922 --> 00:30:43,380 Because that's a value, and I'm going to add two values up. 576 00:30:43,380 --> 00:30:45,320 And I'm only concerned with this value here. 577 00:30:45,320 --> 00:30:47,700 But I'm actually returning this table thing. 578 00:30:47,700 --> 00:30:49,830 And this table thing, as you can see from here, 579 00:30:49,830 --> 00:30:55,320 is simply computing the optimum values 580 00:30:55,320 --> 00:31:02,610 that correspond to problems of the entire problem 581 00:31:02,610 --> 00:31:08,850 and, essentially, the problems that are smaller. 582 00:31:08,850 --> 00:31:10,740 And so then you end up-- 583 00:31:10,740 --> 00:31:13,180 you're skipping from the beginning. 584 00:31:13,180 --> 00:31:19,150 And so when you look at the table len row minus 1, 585 00:31:19,150 --> 00:31:20,805 that is effectively-- 586 00:31:20,805 --> 00:31:22,930 since you're going from the beginning of the list-- 587 00:31:22,930 --> 00:31:28,210 that is telling you what the optimum is, len row minus 1. 588 00:31:28,210 --> 00:31:30,680 Sorry, len row minus 1-- 589 00:31:30,680 --> 00:31:32,770 yeah, that's right. 590 00:31:32,770 --> 00:31:37,320 The number of entries in the table is len raw plus 1. 591 00:31:37,320 --> 00:31:40,350 The total number of entries in the table starts with 0 always, 592 00:31:40,350 --> 00:31:42,300 so it's len row plus 1. 593 00:31:42,300 --> 00:31:45,360 And so table len row is the entirety, 594 00:31:45,360 --> 00:31:48,030 that's what you want for the original thing. 595 00:31:48,030 --> 00:31:50,910 And len row minus 1 looks at an optimum for that, 596 00:31:50,910 --> 00:31:53,670 skipping the first one, and so on. 597 00:31:53,670 --> 00:31:57,210 So you're skipping from the beginning, so remember that. 598 00:31:57,210 --> 00:31:59,520 Why do you think we have this table in here 599 00:31:59,520 --> 00:32:04,650 if we're only concerned with the maximum value? 600 00:32:04,650 --> 00:32:08,400 Or are we only concerned with the maximum value? 601 00:32:08,400 --> 00:32:11,520 What did I do when I got these numbers up? 602 00:32:11,520 --> 00:32:15,270 What else did I do other than pointing out these numbers? 603 00:32:15,270 --> 00:32:19,000 I also gave you more information, right? 604 00:32:19,000 --> 00:32:20,360 I just said 126. 605 00:32:20,360 --> 00:32:25,465 So if I just told you it was 126, would you believe me? 606 00:32:25,465 --> 00:32:26,740 AUDIENCE: It is hard to check. 607 00:32:26,740 --> 00:32:30,490 SRINI DEVADAS: Well, it's really hard to check. 608 00:32:30,490 --> 00:32:33,550 It was credible because I said 126 609 00:32:33,550 --> 00:32:37,090 and then I told you by circling them what the numbers were, 610 00:32:37,090 --> 00:32:37,690 right? 611 00:32:37,690 --> 00:32:40,420 So if you don't have this table stuff in here, 612 00:32:40,420 --> 00:32:45,400 it turns out that you don't have enough information 613 00:32:45,400 --> 00:32:47,180 to figure out what coins were picked. 614 00:32:47,180 --> 00:32:48,580 You'll get the correct answer. 615 00:32:48,580 --> 00:32:50,660 It is guaranteed to be a correct answer. 616 00:32:50,660 --> 00:32:53,443 But you don't have the information about 15, 617 00:32:53,443 --> 00:32:55,750 23, skipping 11 and 3, and getting 618 00:32:55,750 --> 00:32:58,060 4, and so on and so forth. 619 00:32:58,060 --> 00:33:03,730 So we need more code that takes this collection of subproblems 620 00:33:03,730 --> 00:33:05,020 that each have been solved. 621 00:33:05,020 --> 00:33:07,660 So we actually solved all of the subproblems corresponding 622 00:33:07,660 --> 00:33:10,750 to picking this, and picking that, and then picking this, 623 00:33:10,750 --> 00:33:12,320 and so on and so forth. 624 00:33:12,320 --> 00:33:15,700 And you need to use those values in order 625 00:33:15,700 --> 00:33:21,325 to discover, using a traceback procedure, what the coins are. 626 00:33:21,325 --> 00:33:23,110 Or you could do more work in here. 627 00:33:23,110 --> 00:33:25,660 I chose to-- you'll see why-- 628 00:33:25,660 --> 00:33:28,810 I chose to do it this way where I'm collecting up everything 629 00:33:28,810 --> 00:33:30,870 into table. 630 00:33:30,870 --> 00:33:34,500 And I'm going to eventually-- and we'll 631 00:33:34,500 --> 00:33:38,200 talk about this code, at least briefly. 632 00:33:38,200 --> 00:33:43,380 But this code, traceback, is taking the original problem 633 00:33:43,380 --> 00:33:47,640 and a table and is just iteratively going through-- 634 00:33:47,640 --> 00:33:49,530 there's no enumeration here, this 635 00:33:49,530 --> 00:33:51,450 is very efficient-- is iteratively 636 00:33:51,450 --> 00:33:55,140 going through row and table and discovering 637 00:33:55,140 --> 00:33:58,740 what the selected coins are. 638 00:33:58,740 --> 00:34:04,680 And so that's something that we'll look at in just a minute. 639 00:34:04,680 --> 00:34:08,820 Actually not just a minute, but after we go back to this. 640 00:34:08,820 --> 00:34:11,880 And I'm going to tell you or ask you 641 00:34:11,880 --> 00:34:16,659 about this in terms of its computational complexity, OK? 642 00:34:16,659 --> 00:34:19,690 So anyway, assume that we've done traceback. 643 00:34:19,690 --> 00:34:23,739 And it's not hard to do if you have the table of results. 644 00:34:23,739 --> 00:34:26,290 Then let's go back to this and let's 645 00:34:26,290 --> 00:34:28,760 talk about the recursive calls. 646 00:34:28,760 --> 00:34:32,020 And let's take a look at what's going on here with respect 647 00:34:32,020 --> 00:34:36,250 to how many recursive calls are made. 648 00:34:36,250 --> 00:34:42,560 And then we'll get to memoization 649 00:34:42,560 --> 00:34:44,929 in dynamic programming. 650 00:34:44,929 --> 00:34:49,230 So let me just say, if I had Coins that-- 651 00:34:49,230 --> 00:34:53,530 this is the number of elements-- 652 00:34:53,530 --> 00:34:55,110 so I have 5. 653 00:34:55,110 --> 00:35:05,510 Then I'm going to call Coins 4 and I'm going to call Coins 3. 654 00:35:05,510 --> 00:35:08,590 And so here, I skipped the first one. 655 00:35:08,590 --> 00:35:12,930 Here, I picked the first one, and therefore, I 656 00:35:12,930 --> 00:35:15,930 had to skip the second one, so I have 3 here, right? 657 00:35:15,930 --> 00:35:16,980 That makes sense? 658 00:35:16,980 --> 00:35:21,600 And then over here, what do I need 659 00:35:21,600 --> 00:35:24,990 to write here if I follow exactly the pattern? 660 00:35:24,990 --> 00:35:28,560 I'm going to write Coins 3, right? 661 00:35:28,560 --> 00:35:33,100 So I have Coins 3 over here, and here, it's Coins 2. 662 00:35:35,950 --> 00:35:39,660 And here, I'm just going to write the numbers down-- 663 00:35:39,660 --> 00:35:43,000 2, 1. 664 00:35:43,000 --> 00:35:49,210 And again, I've got 2, 1, and so on. 665 00:35:49,210 --> 00:35:50,370 Now, the base case-- 666 00:35:50,370 --> 00:35:54,450 you might keep going even after 2 because the base cases are-- 667 00:35:54,450 --> 00:36:00,120 you go 1, 0, 1, 0. 668 00:36:00,120 --> 00:36:04,780 What do you see in here that's a little bothersome? 669 00:36:04,780 --> 00:36:06,808 What do you see here that's bothersome? 670 00:36:14,280 --> 00:36:16,860 What is that, symbolically? 671 00:36:16,860 --> 00:36:20,090 If I had some number of elements, n elements, 672 00:36:20,090 --> 00:36:22,100 what do I put here? 673 00:36:22,100 --> 00:36:24,000 It's n, right? 674 00:36:24,000 --> 00:36:27,390 And what do you see here? 675 00:36:27,390 --> 00:36:30,350 It's getting pretty big. 676 00:36:30,350 --> 00:36:32,720 So down here, it's getting pretty big. 677 00:36:32,720 --> 00:36:34,890 So that's the problem. 678 00:36:34,890 --> 00:36:37,760 And one of the reasons it's getting pretty big 679 00:36:37,760 --> 00:36:41,880 is because you're doing work over and over. 680 00:36:41,880 --> 00:36:44,210 You see, Coins 3 here couple of places, 681 00:36:44,210 --> 00:36:46,250 Coins 2 in three places. 682 00:36:46,250 --> 00:36:51,140 And if this were larger, you'd see a lot of subproblems 683 00:36:51,140 --> 00:36:54,260 being solved over and over. 684 00:36:54,260 --> 00:36:57,230 So this code that you see up on the screen 685 00:36:57,230 --> 00:37:01,130 is incredibly inefficient because it's 686 00:37:01,130 --> 00:37:05,990 solving the same problem over and over, OK? 687 00:37:05,990 --> 00:37:10,240 In particular, you would solve Coins 4 exactly once, 688 00:37:10,240 --> 00:37:13,700 but Coins 3 twice, Coins 2 three times. 689 00:37:13,700 --> 00:37:19,010 And if I just went up and made this 10, Coins 10, 690 00:37:19,010 --> 00:37:22,617 then you would see things that are solved tens of times. 691 00:37:22,617 --> 00:37:24,200 And eventually, you'll see things that 692 00:37:24,200 --> 00:37:26,150 are solved hundreds of times. 693 00:37:26,150 --> 00:37:29,510 You're just repeating work over and over. 694 00:37:29,510 --> 00:37:33,680 You can actually write a recurrence relationship 695 00:37:33,680 --> 00:37:43,050 that says that if you had an n-element coin row 696 00:37:43,050 --> 00:37:54,060 problem, then your recurrence corresponds 697 00:37:54,060 --> 00:37:56,280 to the number of calls that are made. 698 00:37:56,280 --> 00:38:00,360 Number of operations therefore that are performed 699 00:38:00,360 --> 00:38:03,690 is A n equals A n minus 1 plus A n minus 2. 700 00:38:03,690 --> 00:38:10,000 And then the base cases are A0 equals 1 and A1 equals 1, 701 00:38:10,000 --> 00:38:12,420 because you're just picking that. 702 00:38:12,420 --> 00:38:17,370 And so if you look at what A2 would be, A2 is 2. 703 00:38:17,370 --> 00:38:20,310 But then A3 is 2 plus-- 704 00:38:20,310 --> 00:38:23,100 initially it grows fairly slowly. 705 00:38:23,100 --> 00:38:26,790 But then, when you get to A4, it becomes 5, and so on. 706 00:38:26,790 --> 00:38:31,200 And have you seen this number before, this recurrence 707 00:38:31,200 --> 00:38:32,850 relationship before? 708 00:38:32,850 --> 00:38:34,540 It's called Fibonacci. 709 00:38:34,540 --> 00:38:36,850 It's called the Fibonacci recurrence, 710 00:38:36,850 --> 00:38:38,550 and this actually shows up here. 711 00:38:38,550 --> 00:38:41,220 So this has a relationship to Fibonacci. 712 00:38:41,220 --> 00:38:45,300 And the number of computations in a recursive Fibonacci 713 00:38:45,300 --> 00:38:50,590 is exactly the same as in this problem. 714 00:38:50,590 --> 00:38:57,780 But if I told you to compute the Fibonacci number F of n, 715 00:38:57,780 --> 00:38:58,800 can you do that quickly? 716 00:39:02,620 --> 00:39:05,756 If I wanted for you just to compute the Fibonacci number, 717 00:39:05,756 --> 00:39:07,380 then you would just do that iteratively 718 00:39:07,380 --> 00:39:08,732 like I'm doing here, right? 719 00:39:08,732 --> 00:39:10,440 The numbers would get bigger, but there's 720 00:39:10,440 --> 00:39:13,704 no reason to do exponential work for Fibonacci. 721 00:39:13,704 --> 00:39:15,870 But here, of course, we're doing something much more 722 00:39:15,870 --> 00:39:18,930 sophisticated than just Fibonacci, 723 00:39:18,930 --> 00:39:21,600 in the sense that we are working with a coin row problem. 724 00:39:21,600 --> 00:39:26,430 But this should give you a sense of the efficiency that 725 00:39:26,430 --> 00:39:29,910 is possible here by thinking about the relationship 726 00:39:29,910 --> 00:39:31,920 between recursive Fibonacci that would 727 00:39:31,920 --> 00:39:34,470 look a lot like this structure that you see here-- 728 00:39:34,470 --> 00:39:40,640 just calling Fib of n. 729 00:39:40,640 --> 00:39:43,083 Sorry, for Fib of n, you're calling Fib of n minus 1 730 00:39:43,083 --> 00:39:46,680 and you're calling Fib of n minus 2 recursively, 731 00:39:46,680 --> 00:39:47,700 you're adding them up. 732 00:39:47,700 --> 00:39:49,500 And the base cases are exactly the same 733 00:39:49,500 --> 00:39:55,220 as you have here, returning for the 0 case, F 0, 734 00:39:55,220 --> 00:39:57,300 you're returning 1, and so on and so forth. 735 00:39:57,300 --> 00:39:59,730 And even Fibonacci, you end up having 736 00:39:59,730 --> 00:40:02,160 redundancy in the recursive formulation, which 737 00:40:02,160 --> 00:40:05,790 is exactly the redundancy that you see here, OK? 738 00:40:05,790 --> 00:40:11,250 And so basically, it turns out that if you want 739 00:40:11,250 --> 00:40:14,010 to go exponential to linear-- 740 00:40:14,010 --> 00:40:16,240 and you kind of see where this is going. 741 00:40:16,240 --> 00:40:18,760 The recursive was exponential. 742 00:40:18,760 --> 00:40:22,380 The iterative, in the case of Fibonacci, is linear. 743 00:40:22,380 --> 00:40:29,250 So two things-- one, you can take this 744 00:40:29,250 --> 00:40:33,090 and you can turn it into iteration and make it linear. 745 00:40:33,090 --> 00:40:39,420 But that is actually a more dramatic transformation 746 00:40:39,420 --> 00:40:40,380 of the code. 747 00:40:40,380 --> 00:40:45,870 You can do something that is equivalent in efficiency 748 00:40:45,870 --> 00:40:48,120 to the iterative version-- 749 00:40:48,120 --> 00:40:50,640 both for Fibonacci and for our coin row problem, 750 00:40:50,640 --> 00:40:52,830 and we'll do it for our coin row problem-- 751 00:40:52,830 --> 00:40:55,560 that corresponds to, as I said, the more 752 00:40:55,560 --> 00:40:58,260 local modification of this code that 753 00:40:58,260 --> 00:41:00,690 eliminates redundancy, that eliminates 754 00:41:00,690 --> 00:41:03,310 redundant computations. 755 00:41:03,310 --> 00:41:05,070 And all of these things are equivalent 756 00:41:05,070 --> 00:41:07,290 and they're all part of dynamic programming. 757 00:41:07,290 --> 00:41:10,830 And we have four lectures on dynamic programming in 006. 758 00:41:10,830 --> 00:41:13,440 So in 10 minutes or 15 minutes, you're 759 00:41:13,440 --> 00:41:16,770 just going to get some sense for what this is all about. 760 00:41:16,770 --> 00:41:20,730 And so this is really a preview or an elevator pitch 761 00:41:20,730 --> 00:41:23,790 perhaps, a trailer, right? 762 00:41:23,790 --> 00:41:28,560 So you end up, essentially, doing equivalent work 763 00:41:28,560 --> 00:41:32,520 in the recursive memoized version of this code 764 00:41:32,520 --> 00:41:34,500 that I'll show you in just a minute that 765 00:41:34,500 --> 00:41:38,250 adds three lines of code to this and makes the complexity go 766 00:41:38,250 --> 00:41:40,230 from exponential to linear. 767 00:41:40,230 --> 00:41:43,350 And all you do in this code that makes this complexity 768 00:41:43,350 --> 00:41:47,310 equivalent into the iterative and that's very efficient 769 00:41:47,310 --> 00:41:50,430 is you remember the results. 770 00:41:50,430 --> 00:41:55,050 You memoize the results of the computation. 771 00:41:55,050 --> 00:41:57,170 And you remember that you've solved 772 00:41:57,170 --> 00:41:59,610 Coins 4, which doesn't really help you 773 00:41:59,610 --> 00:42:01,800 in this particular instance. 774 00:42:01,800 --> 00:42:04,860 But you remember that you've solved Coins 3, 775 00:42:04,860 --> 00:42:08,040 so you don't end up doing all of this work. 776 00:42:08,040 --> 00:42:11,760 You end up just saying, OK-- 777 00:42:11,760 --> 00:42:14,880 I'm sorry, it depends on which direction you went. 778 00:42:14,880 --> 00:42:16,500 Let's say that, for argument's sake, 779 00:42:16,500 --> 00:42:19,902 you went in this direction first, OK? 780 00:42:19,902 --> 00:42:22,110 It totally depends on which direction you went first. 781 00:42:22,110 --> 00:42:24,443 And since I drew this out and I don't want to change it, 782 00:42:24,443 --> 00:42:28,920 let's just assume that you went in terms of Coins 3 first. 783 00:42:28,920 --> 00:42:33,090 Which, in fact, is correct in terms of the code 784 00:42:33,090 --> 00:42:34,800 because if you see what I have there, 785 00:42:34,800 --> 00:42:37,080 I went in the pick direction first, which 786 00:42:37,080 --> 00:42:40,710 meant that I would go ahead and pick that first value. 787 00:42:40,710 --> 00:42:43,500 And then I'd go in the right direction, the right-hand side 788 00:42:43,500 --> 00:42:44,440 direction. 789 00:42:44,440 --> 00:42:46,850 So if I did all of that, I do all of this work, 790 00:42:46,850 --> 00:42:49,687 now there's also memoization going on inside of here. 791 00:42:49,687 --> 00:42:51,520 So it's not like I'm doing all of this work. 792 00:42:51,520 --> 00:42:54,120 I'm not only getting it just a factor of 2 793 00:42:54,120 --> 00:42:56,010 in terms of improvement. 794 00:42:56,010 --> 00:43:00,030 But definitely, once I do this and I get the value, 795 00:43:00,030 --> 00:43:01,554 I can just return that value here 796 00:43:01,554 --> 00:43:03,720 and I don't have to do all the work underneath this. 797 00:43:03,720 --> 00:43:06,150 That's why I put this in a square, OK? 798 00:43:06,150 --> 00:43:09,300 And remember that this is being done recursively. 799 00:43:09,300 --> 00:43:11,280 So I'm going to do it for Coins 2. 800 00:43:11,280 --> 00:43:13,920 And so if I had multiple Coins 2's, then I 801 00:43:13,920 --> 00:43:15,310 wouldn't have to do that. 802 00:43:15,310 --> 00:43:18,900 And then over here, if I had a longer coin row problem 803 00:43:18,900 --> 00:43:23,050 to begin with, there's a lot of memoization that goes on. 804 00:43:23,050 --> 00:43:25,560 And you end up only solving-- 805 00:43:25,560 --> 00:43:27,160 this is the key-- 806 00:43:27,160 --> 00:43:33,030 you end up only solving each subproblem how many times? 807 00:43:33,030 --> 00:43:34,290 Once. 808 00:43:34,290 --> 00:43:36,970 Now the aha moment. 809 00:43:36,970 --> 00:43:41,060 How many subproblems are there? 810 00:43:41,060 --> 00:43:47,510 How many coin row problems are there, given an n-element coin 811 00:43:47,510 --> 00:43:49,490 raw problem? 812 00:43:49,490 --> 00:43:50,750 How many? 813 00:43:50,750 --> 00:43:54,260 All of you together. 814 00:43:54,260 --> 00:43:57,280 How many coin row problems are there? 815 00:43:57,280 --> 00:43:59,050 n, that's it. 816 00:43:59,050 --> 00:44:03,190 There's only n coin row problems. 817 00:44:03,190 --> 00:44:07,660 It's like you had a through f, you had b through f, 818 00:44:07,660 --> 00:44:12,190 you had c through f, you had d through f, you had e, f, and f. 819 00:44:12,190 --> 00:44:18,700 So if you only solve coin row problem once, 820 00:44:18,700 --> 00:44:22,870 and there's only n coin row problems, 821 00:44:22,870 --> 00:44:26,710 the complexity clearly cannot be exponential, 822 00:44:26,710 --> 00:44:28,030 it's going to be linear. 823 00:44:28,030 --> 00:44:32,110 Because whatever work you did for that problem 824 00:44:32,110 --> 00:44:33,820 is all that you have to do. 825 00:44:33,820 --> 00:44:35,800 And so maybe there's a constant factor. 826 00:44:35,800 --> 00:44:38,200 But let's say that the number of operations-- obviously, 827 00:44:38,200 --> 00:44:39,635 this is just the max. 828 00:44:39,635 --> 00:44:40,510 It's not complicated. 829 00:44:40,510 --> 00:44:42,010 We know what that is. 830 00:44:42,010 --> 00:44:45,450 So it would be the complexity of solving 831 00:44:45,450 --> 00:44:50,350 a subproblem times the number of subproblems. 832 00:44:50,350 --> 00:44:54,100 The complexity of solving a subproblem is constant. 833 00:44:54,100 --> 00:44:56,080 It's just a small number of operations. 834 00:44:56,080 --> 00:44:59,680 And the number of subproblems is linear. 835 00:44:59,680 --> 00:45:01,960 So it's linear time, which is exactly the same 836 00:45:01,960 --> 00:45:04,450 as the iterative version. 837 00:45:04,450 --> 00:45:06,980 This is an incredibly powerful notion, 838 00:45:06,980 --> 00:45:09,690 which is why there's classes on this topic, just 839 00:45:09,690 --> 00:45:10,600 this very topic. 840 00:45:10,600 --> 00:45:15,910 And we spend a lot of time on this in 006 as well as 046. 841 00:45:15,910 --> 00:45:20,860 So what I'm going to do, the main thing I want to do 842 00:45:20,860 --> 00:45:26,350 is show you this code that is an incremental modification 843 00:45:26,350 --> 00:45:31,570 of the code I showed you before that takes this complexity 844 00:45:31,570 --> 00:45:34,300 and turns it from exponential to linear using 845 00:45:34,300 --> 00:45:37,390 this notion of memoization. 846 00:45:37,390 --> 00:45:40,720 And then I want to tell you a little bit about the traceback 847 00:45:40,720 --> 00:45:42,640 code because that's interesting. 848 00:45:42,640 --> 00:45:45,580 But from a standpoint of just getting the value back, 849 00:45:45,580 --> 00:45:50,390 you're all good without even understanding traceback. 850 00:45:50,390 --> 00:45:55,970 So all I've done here is I've taken table 851 00:45:55,970 --> 00:46:01,240 and I've turned it into a dictionary, OK? 852 00:46:01,240 --> 00:46:04,230 And I had to do a little bit of work 853 00:46:04,230 --> 00:46:08,740 here with respect to the memoization. 854 00:46:08,740 --> 00:46:12,330 So if I look at the base cases, it's 855 00:46:12,330 --> 00:46:13,920 pretty much exactly the same. 856 00:46:13,920 --> 00:46:18,420 I just have a memo in a table. 857 00:46:18,420 --> 00:46:21,990 And all of these are essentially the same. 858 00:46:21,990 --> 00:46:24,520 I'm sorry, all of these up here are essentially the same. 859 00:46:24,520 --> 00:46:29,210 And then I'm looking at a particular problem. 860 00:46:29,210 --> 00:46:31,980 I see whether the memo table that I have-- 861 00:46:31,980 --> 00:46:35,280 if len row in memo, then if it's in the dictionary, 862 00:46:35,280 --> 00:46:37,860 that means I've already seen this problem before. 863 00:46:37,860 --> 00:46:43,260 And I just return the values stored in that dictionary. 864 00:46:43,260 --> 00:46:49,290 And the value stored in that dictionary is, essentially, 865 00:46:49,290 --> 00:46:58,710 a pair which corresponds to not just the value of the problem, 866 00:46:58,710 --> 00:47:02,550 but also I'm storing-- 867 00:47:02,550 --> 00:47:04,620 I'm sorry, I take that back. 868 00:47:04,620 --> 00:47:07,770 So memo itself is just like table. 869 00:47:07,770 --> 00:47:11,850 This memo here is simply because overall I 870 00:47:11,850 --> 00:47:15,990 want to return both the value and the memo table. 871 00:47:15,990 --> 00:47:19,530 So this memo table is exactly like the original table. 872 00:47:19,530 --> 00:47:29,460 It's simply a set of key-value pairs that go memo 5 equals 56, 873 00:47:29,460 --> 00:47:33,870 memo 4 maybe equals 42, et cetera. 874 00:47:33,870 --> 00:47:37,380 So that's just a simple memo table. 875 00:47:37,380 --> 00:47:39,240 And I just need to return the memo. 876 00:47:39,240 --> 00:47:41,430 And so that's why I had this memo out here. 877 00:47:41,430 --> 00:47:43,770 And this looks exactly the same as it did before. 878 00:47:43,770 --> 00:47:45,610 These three lines are exactly the same. 879 00:47:45,610 --> 00:47:47,250 This is an important line. 880 00:47:47,250 --> 00:47:49,680 So these lines were added because I 881 00:47:49,680 --> 00:47:53,310 wanted to memoize and look up what I solved before. 882 00:47:53,310 --> 00:47:56,014 And this line was added-- 883 00:47:56,014 --> 00:47:58,180 well, added in the sense that it was added for memo, 884 00:47:58,180 --> 00:47:59,760 but I already had it for table. 885 00:47:59,760 --> 00:48:01,440 So it's just a simple replacement, 886 00:48:01,440 --> 00:48:03,490 so perhaps I shouldn't have said added. 887 00:48:03,490 --> 00:48:05,670 But this is important because I'm 888 00:48:05,670 --> 00:48:07,740 putting it into the memo table. 889 00:48:07,740 --> 00:48:12,210 And it's really this if statement that's the key. 890 00:48:12,210 --> 00:48:13,770 Don't do redundant work. 891 00:48:13,770 --> 00:48:15,390 So if you get to this if statement, 892 00:48:15,390 --> 00:48:17,190 you're obviously getting to a return, which 893 00:48:17,190 --> 00:48:19,356 means you're not making these recursive calls, which 894 00:48:19,356 --> 00:48:23,640 is exactly going over here and remembering that you solved 895 00:48:23,640 --> 00:48:26,340 Coins 3 and returning the value of Coins 3 896 00:48:26,340 --> 00:48:27,960 the moment you see it. 897 00:48:27,960 --> 00:48:29,730 All right? 898 00:48:29,730 --> 00:48:30,439 That makes sense? 899 00:48:30,439 --> 00:48:31,605 Everybody is good with that? 900 00:48:31,605 --> 00:48:32,490 Excellent. 901 00:48:32,490 --> 00:48:34,600 Let's just run this. 902 00:48:34,600 --> 00:48:38,040 And I want to show you what this gives you 903 00:48:38,040 --> 00:48:41,047 just so you get some sense of what's going on. 904 00:48:41,047 --> 00:48:42,630 There's a couple of different problems 905 00:48:42,630 --> 00:48:46,545 and I'm running them with the different code. 906 00:48:46,545 --> 00:48:48,330 And so you're getting the same answers. 907 00:48:48,330 --> 00:48:50,380 That's just for verification purposes. 908 00:48:50,380 --> 00:48:54,450 So if you focus in on what happens here, 909 00:48:54,450 --> 00:48:57,900 this is, essentially, solving our first smaller problem. 910 00:48:57,900 --> 00:49:01,950 And it's telling you that if you have the entire problem 911 00:49:01,950 --> 00:49:03,570 with the seven coins, which is what 912 00:49:03,570 --> 00:49:06,690 I have up there, the first problem here, 913 00:49:06,690 --> 00:49:10,110 then what you have is 56. 914 00:49:10,110 --> 00:49:14,670 And if, in fact, you ended up dropping-- it 915 00:49:14,670 --> 00:49:18,120 you're looking at the subproblem that goes from 3 to 1, 916 00:49:18,120 --> 00:49:23,520 and you drop 14, the optimum value for that is 42. 917 00:49:23,520 --> 00:49:26,910 And then, if you drop both 14 and 3, and you went with that, 918 00:49:26,910 --> 00:49:29,310 then you need to go backwards from here-- 919 00:49:29,310 --> 00:49:30,960 56, 42. 920 00:49:30,960 --> 00:49:31,610 It's still 42. 921 00:49:35,980 --> 00:49:38,370 So if you drop 14, it's 42. 922 00:49:38,370 --> 00:49:44,160 If you drop 3, it's still 42 because 27 and 15 give you 923 00:49:44,160 --> 00:49:45,480 your 42. 924 00:49:45,480 --> 00:49:47,020 And that makes sense. 925 00:49:47,020 --> 00:49:48,840 And so you can see that. 926 00:49:48,840 --> 00:49:54,270 And then this other thing here is the bigger problem. 927 00:49:54,270 --> 00:49:57,980 It says, table equals-- 928 00:49:57,980 --> 00:50:06,690 sorry, yikes, Python shell. 929 00:50:06,690 --> 00:50:08,680 Let me just point with the cursor. 930 00:50:08,680 --> 00:50:12,150 This large thing here is our bigger problem. 931 00:50:12,150 --> 00:50:14,290 And you can see the table for this-- 932 00:50:14,290 --> 00:50:15,660 126. 933 00:50:15,660 --> 00:50:18,340 If you dropped the first one, you'd still get 126. 934 00:50:18,340 --> 00:50:21,750 Then if you drop the first two, 3 and 15, 935 00:50:21,750 --> 00:50:25,570 you get, obviously, a smaller result, and so on and so forth. 936 00:50:25,570 --> 00:50:29,050 And this table that I'm getting back, 937 00:50:29,050 --> 00:50:33,285 which is basically the original table that you could 938 00:50:33,285 --> 00:50:36,180 be thinking of as a list, that turned into a dictionary 939 00:50:36,180 --> 00:50:39,000 when I wanted to memoize because I wanted to look it up 940 00:50:39,000 --> 00:50:40,230 very efficiently. 941 00:50:40,230 --> 00:50:46,230 I could have left it, in this case, as a Python list. 942 00:50:46,230 --> 00:50:50,010 I did not need to use a dictionary. 943 00:50:50,010 --> 00:50:52,540 I didn't need the generality of a dictionary 944 00:50:52,540 --> 00:50:58,830 where the indices to a list can be strings or negative numbers. 945 00:50:58,830 --> 00:51:00,060 I'm just indexing into this. 946 00:51:00,060 --> 00:51:03,387 So the dictionary is a bit of a red herring. 947 00:51:03,387 --> 00:51:04,470 I just happened to use it. 948 00:51:04,470 --> 00:51:06,240 But in general, you use dictionaries 949 00:51:06,240 --> 00:51:09,420 because you may have to look up things 950 00:51:09,420 --> 00:51:13,930 that are more complicated than just integer values. 951 00:51:13,930 --> 00:51:16,590 But here, I could just number the subproblems 952 00:51:16,590 --> 00:51:19,590 0 through 7, what have you, and then just look it up. 953 00:51:19,590 --> 00:51:23,850 So the bottom line is I need that information in order 954 00:51:23,850 --> 00:51:28,320 to compute or figure out what coins were selected. 955 00:51:28,320 --> 00:51:31,050 And so the last thing that I will show you 956 00:51:31,050 --> 00:51:36,999 is the traceback routine, which I just put up there briefly. 957 00:51:36,999 --> 00:51:38,790 But I just want to spend one minute on this 958 00:51:38,790 --> 00:51:41,040 and we will close. 959 00:51:41,040 --> 00:51:45,150 And this traceback routine is taking the values that you saw 960 00:51:45,150 --> 00:51:50,250 and figuring out whether you picked a coin or not. 961 00:51:50,250 --> 00:51:52,870 So what it does is it looks at the entire thing 962 00:51:52,870 --> 00:51:57,010 and it knows that the entire thing is 56. 963 00:51:57,010 --> 00:52:02,670 And then it says, if I drop the first one, and I get 42. 964 00:52:02,670 --> 00:52:06,840 And it compares 56 with 42 and says, wait a minute, 965 00:52:06,840 --> 00:52:09,030 the difference there is 14. 966 00:52:09,030 --> 00:52:14,730 And that is exactly the value of the first element, right? 967 00:52:14,730 --> 00:52:18,300 So what this tells me is that if I had the original problem, 968 00:52:18,300 --> 00:52:19,650 I got 56. 969 00:52:19,650 --> 00:52:23,640 If I drop the first one, I get 42 as optimal. 970 00:52:23,640 --> 00:52:25,560 So that implies that for the original problem, 971 00:52:25,560 --> 00:52:28,320 I picked the first coin. 972 00:52:28,320 --> 00:52:32,170 Because 56 minus 42 is 14, that's it. 973 00:52:32,170 --> 00:52:33,880 That's pretty much all you have to do. 974 00:52:33,880 --> 00:52:35,760 You just have to do that over and over. 975 00:52:35,760 --> 00:52:37,920 And it's a little bit more complicated than that 976 00:52:37,920 --> 00:52:41,160 only because you don't want to get into negative indices 977 00:52:41,160 --> 00:52:42,510 for tables. 978 00:52:42,510 --> 00:52:45,125 And so the only reason that first line-- table len 979 00:52:45,125 --> 00:52:47,640 row minus i equals equals raw i-- is there 980 00:52:47,640 --> 00:52:52,500 is for the corner case where you have a single-element list. 981 00:52:52,500 --> 00:52:54,960 And you don't want to get into a situation where-- 982 00:52:54,960 --> 00:52:58,770 this thing here cannot be negative. 983 00:52:58,770 --> 00:53:01,290 If this is negative, then the program crashes. 984 00:53:01,290 --> 00:53:03,150 So you don't want to get to this statement. 985 00:53:03,150 --> 00:53:05,567 It becomes negative, and it's a degenerate case. 986 00:53:05,567 --> 00:53:06,900 And you don't want to get there. 987 00:53:06,900 --> 00:53:08,100 This or takes care of that. 988 00:53:08,100 --> 00:53:11,880 You essentially check for the singleton equality. 989 00:53:11,880 --> 00:53:13,980 And then you don't fall through the second-- 990 00:53:13,980 --> 00:53:17,160 if this part of the statement is true, 991 00:53:17,160 --> 00:53:18,810 then this doesn't get computed. 992 00:53:18,810 --> 00:53:22,860 So if table len row i equals equals row i is true, 993 00:53:22,860 --> 00:53:25,560 then you don't compute that, you don't get a negative index, 994 00:53:25,560 --> 00:53:27,240 and everything works on. 995 00:53:27,240 --> 00:53:30,030 But it comes down to 56 minutes 42 is 14, 996 00:53:30,030 --> 00:53:31,410 and you're all good to go. 997 00:53:31,410 --> 00:53:32,850 All right, good. 998 00:53:32,850 --> 00:53:38,050 So that's all I had, well, for this lecture, for the class. 999 00:53:38,050 --> 00:53:41,250 I'm going to be co-lecturing 6006 next semester. 1000 00:53:41,250 --> 00:53:43,170 I notice that some of you were preregistered, 1001 00:53:43,170 --> 00:53:44,851 so I guess it's not goodbye. 1002 00:53:44,851 --> 00:53:47,100 But it doesn't have to be goodbye for the rest of you. 1003 00:53:47,100 --> 00:53:48,160 You know what I said-- 1004 00:53:48,160 --> 00:53:50,670 happy to talk algorithms and computer science. 1005 00:53:50,670 --> 00:53:54,750 Thanks for being an attentive audience. 1006 00:53:54,750 --> 00:53:56,600 [APPLAUSE]