1 00:00:00,000 --> 00:00:12,584 [SQUEAKING] [RUSTLING] [CLICKING] 2 00:00:12,584 --> 00:00:15,250 JUSTIN SOLOMON: Right, so today is going to be our first, 3 00:00:15,250 --> 00:00:17,050 I believe, of two problem sessions 4 00:00:17,050 --> 00:00:18,670 covering dynamic programming. 5 00:00:21,032 --> 00:00:22,490 I've learned dynamic programming is 6 00:00:22,490 --> 00:00:24,698 one of these interesting parts of an algorithms class 7 00:00:24,698 --> 00:00:26,960 where, somehow, the people that are really good at it 8 00:00:26,960 --> 00:00:28,730 are completely disjoint with the people that 9 00:00:28,730 --> 00:00:31,063 are good at all the other parts of the algorithms class. 10 00:00:31,063 --> 00:00:33,290 So for some of you guys, that might be promising, 11 00:00:33,290 --> 00:00:35,750 and for others, maybe a little bit less so. 12 00:00:35,750 --> 00:00:38,000 So maybe we'll spend just a minute or two reviewing 13 00:00:38,000 --> 00:00:40,490 the basic ideas we're going to apply in these problems 14 00:00:40,490 --> 00:00:43,640 because they'll follow, more or less, the same template. 15 00:00:43,640 --> 00:00:45,560 Although, of course, as usual in 6.006, 16 00:00:45,560 --> 00:00:49,370 we like to put some interesting window dressing around it 17 00:00:49,370 --> 00:00:52,200 so that it's not totally obvious what you're doing. 18 00:00:52,200 --> 00:00:54,960 And then we'll do a bunch of sample problems. 19 00:00:54,960 --> 00:00:55,460 Right. 20 00:00:55,460 --> 00:00:58,880 So let's talk a little bit about dynamic programming 21 00:00:58,880 --> 00:01:01,520 and the basic idea here. 22 00:01:01,520 --> 00:01:05,209 So, dynamic programming is kind of a funny outlier in 6.006 23 00:01:05,209 --> 00:01:06,138 in that-- 24 00:01:06,138 --> 00:01:08,430 for example, in the data structures part of the course, 25 00:01:08,430 --> 00:01:11,260 we learned, like, what-- 26 00:01:11,260 --> 00:01:13,740 now I'm struggling to think of a data structure-- 27 00:01:13,740 --> 00:01:16,530 like a useful-- like trees and arrays or whatever. 28 00:01:16,530 --> 00:01:18,530 And these are actually things that you can code. 29 00:01:18,530 --> 00:01:22,610 if you look and see if there are-- 30 00:01:22,610 --> 00:01:24,590 well, plausibly, it could be an implementation 31 00:01:24,590 --> 00:01:26,810 of a tree in there somewhere. 32 00:01:26,810 --> 00:01:28,280 And so these are useful algorithms 33 00:01:28,280 --> 00:01:29,930 that you can maybe even read the pseudocode. 34 00:01:29,930 --> 00:01:31,555 And there's a universe where you really 35 00:01:31,555 --> 00:01:33,740 do translate that pseudocode into something 36 00:01:33,740 --> 00:01:35,567 inside of your laptop. 37 00:01:35,567 --> 00:01:37,400 Dynamic programming is a little bit less so. 38 00:01:37,400 --> 00:01:38,420 This is more of a meta-- 39 00:01:38,420 --> 00:01:40,337 I don't know if you'd call it a meta algorithm 40 00:01:40,337 --> 00:01:42,590 or problem solving approach or what, 41 00:01:42,590 --> 00:01:44,290 but it's not like you somehow say, 42 00:01:44,290 --> 00:01:46,040 I'm going to apply the dynamic programming 43 00:01:46,040 --> 00:01:48,030 algorithm to this problem. 44 00:01:48,030 --> 00:01:51,410 But rather, it's sort of this big class of things that all 45 00:01:51,410 --> 00:01:55,100 follow a similar template or sort of approach to thinking 46 00:01:55,100 --> 00:01:58,790 about problem solving, which I think sort of explains why, 47 00:01:58,790 --> 00:02:01,940 actually, in some sense, the last couple of lectures that 48 00:02:01,940 --> 00:02:04,762 you've seen-- and, I guess, if I'm getting the time sequence 49 00:02:04,762 --> 00:02:07,220 of our course right, the next couple of years that you will 50 00:02:07,220 --> 00:02:08,815 see-- 51 00:02:08,815 --> 00:02:10,190 and the problem sessions actually 52 00:02:10,190 --> 00:02:13,280 start to coincide in the sense that when Erik was teaching 53 00:02:13,280 --> 00:02:16,080 you guys dynamic programming, how did he do it? 54 00:02:16,080 --> 00:02:17,540 Well, he didn't write down-- well, 55 00:02:17,540 --> 00:02:18,800 he sort of wrote down some template 56 00:02:18,800 --> 00:02:20,300 for dynamic programming, but then we just did 57 00:02:20,300 --> 00:02:21,710 a bunch of sample problems. 58 00:02:21,710 --> 00:02:23,812 And that's exactly what we're going to do today. 59 00:02:23,812 --> 00:02:25,520 So, somehow, all of these things are just 60 00:02:25,520 --> 00:02:28,610 going to converge in this part of our course 61 00:02:28,610 --> 00:02:30,770 because dynamic programming, it's 62 00:02:30,770 --> 00:02:35,203 really more of a way of life than any particular algorithm. 63 00:02:35,203 --> 00:02:36,620 And this is a pattern that I think 64 00:02:36,620 --> 00:02:38,623 you see a lot in advanced algorithms. 65 00:02:38,623 --> 00:02:40,040 Like, for example, in my universe, 66 00:02:40,040 --> 00:02:43,360 in numerical analysis, when you talk about the ADMM algorithm, 67 00:02:43,360 --> 00:02:45,110 it's actually a totally useless algorithm. 68 00:02:45,110 --> 00:02:48,350 What matters is applying it to a particular problem. 69 00:02:48,350 --> 00:02:51,500 And this is sort of, I think, a more mature or grown up 70 00:02:51,500 --> 00:02:53,030 way to think about a lot of things 71 00:02:53,030 --> 00:02:56,900 in algorithms, that pretty soon, this sort of general purpose 72 00:02:56,900 --> 00:02:59,340 stuff that's useful all the time, 73 00:02:59,340 --> 00:03:02,150 I think, it starts to disperse a little bit in favor 74 00:03:02,150 --> 00:03:03,782 of different patterns and mechanisms 75 00:03:03,782 --> 00:03:05,240 that you're used to thinking about. 76 00:03:05,240 --> 00:03:07,100 So there's my 10-second, sort of, 77 00:03:07,100 --> 00:03:09,320 philosophical introduction to what we're doing, 78 00:03:09,320 --> 00:03:10,850 during which I've managed to chase 79 00:03:10,850 --> 00:03:14,870 this table across the room. 80 00:03:14,870 --> 00:03:15,860 You know, I played-- 81 00:03:15,860 --> 00:03:18,183 I did college on the west coast, and I 82 00:03:18,183 --> 00:03:19,850 thought I was going to be a music major. 83 00:03:19,850 --> 00:03:21,517 And there was a piano master class where 84 00:03:21,517 --> 00:03:23,720 we forgot to put the little clips on the wheels 85 00:03:23,720 --> 00:03:26,080 and there was an earthquake, and I just 86 00:03:26,080 --> 00:03:28,580 thought I was really nervous because the piano was literally 87 00:03:28,580 --> 00:03:30,980 slipping away from me. 88 00:03:30,980 --> 00:03:35,160 I can never think of that Chopin nocturne in quite the same way. 89 00:03:35,160 --> 00:03:38,570 But in any event, in dynamic programming, 90 00:03:38,570 --> 00:03:41,240 Erik laid out for you guys a particular, sort of, 91 00:03:41,240 --> 00:03:46,160 set of steps that are a useful problem-solving approach 92 00:03:46,160 --> 00:03:47,738 in the dynamic programming universe. 93 00:03:47,738 --> 00:03:49,280 In today's problem session, I'm going 94 00:03:49,280 --> 00:03:51,770 to try and help you guys translate a little bit 95 00:03:51,770 --> 00:03:55,040 from this template to what it means to actually write code 96 00:03:55,040 --> 00:03:56,990 to implement a dynamic programming algorithm 97 00:03:56,990 --> 00:04:01,260 because I think it's a little easy to forget that here. 98 00:04:01,260 --> 00:04:03,860 But, on the other hand, on your homework, 99 00:04:03,860 --> 00:04:06,480 when you're writing out answers to algorithms problem, 100 00:04:06,480 --> 00:04:09,860 it's perfectly fine to follow this template even letter-- 101 00:04:09,860 --> 00:04:13,058 I guess-- literally letter for letter and answer each 102 00:04:13,058 --> 00:04:13,850 of these questions. 103 00:04:13,850 --> 00:04:17,600 And then the remaining glue that you need to actually write 104 00:04:17,600 --> 00:04:19,910 the code is not terribly exciting 105 00:04:19,910 --> 00:04:22,980 from an algorithms theory perspective. 106 00:04:22,980 --> 00:04:25,010 So the basic idea here is that there's 107 00:04:25,010 --> 00:04:27,560 a lot of different problems that can be written recursively, 108 00:04:27,560 --> 00:04:29,580 in some sense. 109 00:04:29,580 --> 00:04:32,810 Certainly, we've encountered many of those in this course. 110 00:04:32,810 --> 00:04:34,310 In fact, I think the bias in the way 111 00:04:34,310 --> 00:04:35,850 that we've presented algorithms that 112 00:04:35,850 --> 00:04:39,420 don't have to be recursive is to write them in a recursive way. 113 00:04:39,420 --> 00:04:43,370 And the point here is that when you have a recursive call 114 00:04:43,370 --> 00:04:46,790 and you repeat something, you give the function 115 00:04:46,790 --> 00:04:48,680 the same input more than one time, 116 00:04:48,680 --> 00:04:51,542 you might as well remember what you got the last time you saw 117 00:04:51,542 --> 00:04:53,000 that input, and then you don't have 118 00:04:53,000 --> 00:04:54,290 to do that computation again. 119 00:04:54,290 --> 00:04:57,740 Really, in one sentence, I think that's roughly the logic behind 120 00:04:57,740 --> 00:05:00,320 all these dynamic programming things. 121 00:05:00,320 --> 00:05:02,960 So there's no reason to be too redundant with lecture. 122 00:05:02,960 --> 00:05:05,690 For just the 10-second overview, I 123 00:05:05,690 --> 00:05:08,150 think that there's an example which is simultaneously 124 00:05:08,150 --> 00:05:12,050 good and misleading, which is this Fibonacci sequence. 125 00:05:12,050 --> 00:05:15,140 It's good in the sense that the logic of dynamic programming 126 00:05:15,140 --> 00:05:16,010 is really easy. 127 00:05:16,010 --> 00:05:20,075 It's bad in that the runtime is kind of weird to think about. 128 00:05:20,075 --> 00:05:21,950 But remember, though, your Fibonacci sequence 129 00:05:21,950 --> 00:05:27,380 looks something like f of k equals f of k minus 1 130 00:05:27,380 --> 00:05:30,750 plus f of k minus 2. 131 00:05:30,750 --> 00:05:34,740 And if you look at your, sort of, recursive call tree here-- 132 00:05:34,740 --> 00:05:37,490 like, let's say that I do k equals 4. 133 00:05:37,490 --> 00:05:39,800 Then it's going to call-- 134 00:05:39,800 --> 00:05:43,040 my function f is going to have to evaluate it at 3 and 2. 135 00:05:43,040 --> 00:05:46,880 And then the 3 is going to evaluate at 2 and 1, and so on. 136 00:05:46,880 --> 00:05:51,050 And the thing to notice is that when I call f of 4-- 137 00:05:51,050 --> 00:05:54,740 or, rather, f of 3 here, if there were 3 somewhere else 138 00:05:54,740 --> 00:05:56,360 in my tree, I get the same number, so, 139 00:05:56,360 --> 00:05:59,578 in particular, f of 2 and f of 2. 140 00:05:59,578 --> 00:06:01,370 Both of these are going to take some amount 141 00:06:01,370 --> 00:06:03,328 of algorithmic work, but if just the first time 142 00:06:03,328 --> 00:06:05,780 I see a 2 I have a little piece of scratch paper 143 00:06:05,780 --> 00:06:08,870 and I say, oh, any time I see k equals 144 00:06:08,870 --> 00:06:10,400 2, just return this number rather 145 00:06:10,400 --> 00:06:12,980 than doing recursive calls, then, in effect, 146 00:06:12,980 --> 00:06:16,220 if there's any subtree underneath this thing, 147 00:06:16,220 --> 00:06:19,010 I've just pruned it from my tree. 148 00:06:19,010 --> 00:06:22,620 And so that's the basic logic here. 149 00:06:22,620 --> 00:06:24,500 And that's basically the paradigm 150 00:06:24,500 --> 00:06:30,790 that's going on in this SRTBOT acronym, which 151 00:06:30,790 --> 00:06:34,960 is you first take your problem and divide it into subproblems. 152 00:06:34,960 --> 00:06:36,080 That is mysterious. 153 00:06:36,080 --> 00:06:37,150 Why is this board moving? 154 00:06:40,276 --> 00:06:42,901 Oh, there's a phone in my pocket and I bumped against the wall. 155 00:06:48,302 --> 00:06:50,750 I'm not used to this classroom. 156 00:06:50,750 --> 00:06:52,510 Right. 157 00:06:52,510 --> 00:06:53,010 Yeah. 158 00:06:53,010 --> 00:06:54,385 So the first thing you want to do 159 00:06:54,385 --> 00:06:58,272 is to write my problem as this sort of form. 160 00:06:58,272 --> 00:07:00,480 Notice just that we've done this a lot in this class, 161 00:07:00,480 --> 00:07:01,855 we've written things recursively. 162 00:07:01,855 --> 00:07:04,320 The difference here is the sort of argument 163 00:07:04,320 --> 00:07:06,360 that goes into recursion is typically, maybe, 164 00:07:06,360 --> 00:07:10,140 a little simpler than putting some giant data structure 165 00:07:10,140 --> 00:07:11,840 inside of there or something like that. 166 00:07:11,840 --> 00:07:13,680 So, for instance, merge sort, you 167 00:07:13,680 --> 00:07:14,980 could write in this paradigm. 168 00:07:14,980 --> 00:07:16,730 I guess we covered that, but it's probably 169 00:07:16,730 --> 00:07:19,370 not the most natural way to think about merge sort. 170 00:07:19,370 --> 00:07:22,290 Then we need to relate our subproblems to each other. 171 00:07:22,290 --> 00:07:24,920 So, for instance, in the Fibonacci sequence problem, 172 00:07:24,920 --> 00:07:26,750 I just gave you the relation that-- 173 00:07:26,750 --> 00:07:28,500 what defines the problem. 174 00:07:28,500 --> 00:07:32,840 Incidentally, this is, what, a model for the reproduction 175 00:07:32,840 --> 00:07:34,550 of rabbits, I think, if I remember 176 00:07:34,550 --> 00:07:36,710 reading the history of the Fibonacci sequence. 177 00:07:39,250 --> 00:07:41,505 And then, I think, to me, the most-- 178 00:07:41,505 --> 00:07:44,130 not necessarily unnatural-- but I think the thing that maybe is 179 00:07:44,130 --> 00:07:46,422 hardest to translate to an algorithm if you're thinking 180 00:07:46,422 --> 00:07:47,760 about writing code is this-- 181 00:07:47,760 --> 00:07:50,170 oh, man, this is going to be a problem-- 182 00:07:50,170 --> 00:07:53,430 this idea of topological order. 183 00:07:53,430 --> 00:07:57,090 The basic idea here is that if f of 1 depended on f of 2, 184 00:07:57,090 --> 00:08:01,110 and f of 2 depended on f of 1, I'd be in a lot of trouble, 185 00:08:01,110 --> 00:08:03,510 right, because somehow my tree would never 186 00:08:03,510 --> 00:08:06,210 converge, for one thing, if I made these recursive calls 187 00:08:06,210 --> 00:08:09,090 and I'd never be able to memoize or, kind of, 188 00:08:09,090 --> 00:08:10,910 remember a value when I move on. 189 00:08:10,910 --> 00:08:11,410 Right? 190 00:08:11,410 --> 00:08:12,910 And so the idea here is that there's 191 00:08:12,910 --> 00:08:14,370 some ordering of my subproblem so 192 00:08:14,370 --> 00:08:16,630 that I can build up a solution. 193 00:08:16,630 --> 00:08:18,460 And there's, sort of, two dual ways 194 00:08:18,460 --> 00:08:20,490 to think about why that's useful. 195 00:08:20,490 --> 00:08:24,530 So in the memoization universe, what do I do? 196 00:08:24,530 --> 00:08:27,430 I just add an if statement saying if I've already 197 00:08:27,430 --> 00:08:29,560 evaluated f of k, return it. 198 00:08:29,560 --> 00:08:31,640 That's perfectly fine. 199 00:08:31,640 --> 00:08:34,030 The other thing I can do is if I write my problems 200 00:08:34,030 --> 00:08:37,289 in topological order, then I can sort of 201 00:08:37,289 --> 00:08:40,950 go in the reverse direction and build up my memoization table. 202 00:08:40,950 --> 00:08:45,120 So, for instance, for the Fibonacci sequence problem, 203 00:08:45,120 --> 00:08:48,630 I could do f of 1 and then f of 2 and then f of 3 and f of 4 204 00:08:48,630 --> 00:08:51,270 all the way until I get to the k value that I actually wanted. 205 00:08:51,270 --> 00:08:53,400 And those are just duals of the same coin. 206 00:08:53,400 --> 00:08:55,715 They're exactly the same approach. 207 00:08:55,715 --> 00:08:57,090 Although the memoization version, 208 00:08:57,090 --> 00:08:58,860 sometimes you can prune out subproblems 209 00:08:58,860 --> 00:09:00,610 that you didn't actually need to solve. 210 00:09:00,610 --> 00:09:03,430 So, for instance, maybe this was f of k minus 7, 211 00:09:03,430 --> 00:09:06,340 and so I can skip a few indices in my array. 212 00:09:06,340 --> 00:09:08,835 I don't think, typically, that has a big effect on runtime 213 00:09:08,835 --> 00:09:10,210 for the problems that we've seen, 214 00:09:10,210 --> 00:09:13,690 but it could, plausibly, in some universal. 215 00:09:13,690 --> 00:09:15,100 I'd have to think about a problem 216 00:09:15,100 --> 00:09:18,440 where that makes a difference. 217 00:09:18,440 --> 00:09:18,940 Right. 218 00:09:18,940 --> 00:09:20,773 And then I think the BOT part of SRTBOT 219 00:09:20,773 --> 00:09:22,190 is a little easier to think about. 220 00:09:22,190 --> 00:09:25,810 You have to make sure that this recursion has a base case, 221 00:09:25,810 --> 00:09:27,730 like when is this thing going to stop. 222 00:09:27,730 --> 00:09:28,880 That's exactly the same. 223 00:09:28,880 --> 00:09:32,090 It's just any recursive algorithm. 224 00:09:32,090 --> 00:09:35,590 The O for original, I think, is a little bit 225 00:09:35,590 --> 00:09:38,050 retrofit to make SRTBOT sound nice, 226 00:09:38,050 --> 00:09:39,670 but I think the idea here is that you 227 00:09:39,670 --> 00:09:40,960 need to go back to your original problem 228 00:09:40,960 --> 00:09:42,335 and make sure that it corresponds 229 00:09:42,335 --> 00:09:44,830 to one of the function calls that you've written 230 00:09:44,830 --> 00:09:46,390 in all this complicated stuff. 231 00:09:46,390 --> 00:09:48,620 Hopefully that's a reasonable characterization. 232 00:09:48,620 --> 00:09:51,280 And then, finally, the t is more-- 233 00:09:51,280 --> 00:09:53,440 these are for describing your algorithm. 234 00:09:53,440 --> 00:09:55,270 The last one is for analyzing it. 235 00:09:55,270 --> 00:09:57,670 And, again, the BOT part of SRTBOT 236 00:09:57,670 --> 00:10:00,490 almost applies to anything we've done in 6.006, like you should 237 00:10:00,490 --> 00:10:02,780 always analyze your run time. 238 00:10:02,780 --> 00:10:03,280 OK. 239 00:10:03,280 --> 00:10:07,190 So, in any event, that's my 10-minute version 240 00:10:07,190 --> 00:10:10,340 of the last couple lectures and, I think, more or less, 241 00:10:10,340 --> 00:10:13,757 enough to get us started with some sample problems here. 242 00:10:13,757 --> 00:10:14,840 Sorry, I couldn't help it. 243 00:10:14,840 --> 00:10:16,530 I like to teach things. 244 00:10:16,530 --> 00:10:17,030 OK. 245 00:10:17,030 --> 00:10:18,320 So, right. 246 00:10:18,320 --> 00:10:20,570 So in our problem session, we have 247 00:10:20,570 --> 00:10:25,220 a few of the homework problems from last year to go over. 248 00:10:25,220 --> 00:10:26,900 If it makes you guys feel any better, 249 00:10:26,900 --> 00:10:28,648 I got myself all balled up on one of them 250 00:10:28,648 --> 00:10:30,440 last night while I was preparing for today. 251 00:10:30,440 --> 00:10:33,050 And I look forward to doing that in front of all of you guys 252 00:10:33,050 --> 00:10:34,470 now. 253 00:10:34,470 --> 00:10:34,970 Right. 254 00:10:34,970 --> 00:10:40,080 So, I'm afraid of this, so I'm going to go to the next board. 255 00:10:40,080 --> 00:10:40,580 OK. 256 00:10:40,580 --> 00:10:44,690 So in our first problem, Sunny studies-- 257 00:10:44,690 --> 00:10:46,640 this was-- somehow, the cute naming 258 00:10:46,640 --> 00:10:50,210 conventions we have in 6.006 got really meta in this problem, 259 00:10:50,210 --> 00:10:52,340 because there's a problem about Tim the Beaver. 260 00:10:52,340 --> 00:10:55,490 But, as we all know, Tim is MIT backwards, 261 00:10:55,490 --> 00:10:59,840 so he happens to fit into this goofy game 262 00:10:59,840 --> 00:11:02,180 that Jason likes to play in writing homework problems. 263 00:11:02,180 --> 00:11:05,450 Anyway, but it's also the MIT mascot. 264 00:11:05,450 --> 00:11:07,900 Anyway, I got very excited. 265 00:11:07,900 --> 00:11:08,400 Right. 266 00:11:08,400 --> 00:11:11,190 So what's going on in this problem? 267 00:11:11,190 --> 00:11:15,060 So Tim the Beaver has kind of an interesting-- you know, 268 00:11:15,060 --> 00:11:17,660 mathematics, I think you would call this a martingale if you 269 00:11:17,660 --> 00:11:19,910 flip the coin a little bit when he solve this problem. 270 00:11:19,910 --> 00:11:24,890 But luckily, Tim the Beaver is a deterministic kind of a guy. 271 00:11:24,890 --> 00:11:27,230 And he looks at the weather outside, 272 00:11:27,230 --> 00:11:29,570 and if it's a temperature t-- apparently, 273 00:11:29,570 --> 00:11:31,940 Tim the Beaver is OK with boiling. 274 00:11:31,940 --> 00:11:35,570 The higher the temperature, the happier Tim gets. 275 00:11:35,570 --> 00:11:38,630 So this is a first derivative kind of a phenomenon. 276 00:11:38,630 --> 00:11:45,200 In particular, on a given day, if I have a temperature t, 277 00:11:45,200 --> 00:11:47,720 Tim the Beaver has two things that he 278 00:11:47,720 --> 00:11:49,670 can do to change his mood. 279 00:11:49,670 --> 00:11:51,980 Apparently, Tim the Beaver's mood never stays fixed. 280 00:11:51,980 --> 00:11:54,800 It always goes up and down. 281 00:11:54,800 --> 00:12:05,430 In particular, he can either go outside, in which case 282 00:12:05,430 --> 00:12:21,450 the happiness increases by t, OK, or he can stay inside, 283 00:12:21,450 --> 00:12:29,750 in which case his happiness decreases by t. 284 00:12:29,750 --> 00:12:30,340 OK. 285 00:12:30,340 --> 00:12:35,175 So every day, Tim the Beaver, he wakes up he-- 286 00:12:35,175 --> 00:12:37,300 I really want to say that he checks for his shadow, 287 00:12:37,300 --> 00:12:39,400 but that's a gopher, right? 288 00:12:39,400 --> 00:12:42,910 i any event, he wakes up in the morning, he checks the weather, 289 00:12:42,910 --> 00:12:44,432 and he makes the determination does 290 00:12:44,432 --> 00:12:45,640 he want to go outside or not. 291 00:12:45,640 --> 00:12:47,680 And if he goes outside, he gets happier 292 00:12:47,680 --> 00:12:50,320 by an amount that's equal to the temperature. 293 00:12:50,320 --> 00:12:53,808 If he stays inside, he gets less happy by an amount that's 294 00:12:53,808 --> 00:12:54,850 equal to the temperature. 295 00:12:54,850 --> 00:12:56,933 By the way, I think our solution is perfectly fine 296 00:12:56,933 --> 00:13:00,040 if temperatures are negative here, in which case, 297 00:13:00,040 --> 00:13:02,620 I guess, everything would flip intuitively. 298 00:13:02,620 --> 00:13:06,400 But there's no reason to get too hung up on that. 299 00:13:06,400 --> 00:13:09,070 But, of course, there's a twist here. 300 00:13:09,070 --> 00:13:19,040 So Tim, as with many of you, has n days until his final exam. 301 00:13:23,030 --> 00:13:24,840 And he's worried about studying. 302 00:13:24,840 --> 00:13:25,340 Yeah? 303 00:13:25,340 --> 00:13:30,140 So, in particular, he never wants to go-- 304 00:13:30,140 --> 00:13:31,760 he's come up with a personal resolve 305 00:13:31,760 --> 00:13:35,090 to never go outside more than two days in a row. 306 00:13:35,090 --> 00:13:37,040 Yeah? 307 00:13:37,040 --> 00:13:37,940 So, right. 308 00:13:47,590 --> 00:13:52,117 And so the question is-- right, because that way 309 00:13:52,117 --> 00:13:53,950 he has to stay inside and study at least one 310 00:13:53,950 --> 00:13:56,030 out of every three-ish days. 311 00:13:56,030 --> 00:13:56,810 OK. 312 00:13:56,810 --> 00:14:02,490 So the question is how can Tim maximize his happiness. 313 00:14:02,490 --> 00:14:04,350 Incidentally, in machine learning, 314 00:14:04,350 --> 00:14:06,310 sometimes they call that minimizing regret, 315 00:14:06,310 --> 00:14:08,070 which I always found to be a very sad way 316 00:14:08,070 --> 00:14:11,580 to think about algorithms when there's a totally dual version. 317 00:14:11,580 --> 00:14:12,780 But Tim's an optimistic guy. 318 00:14:12,780 --> 00:14:15,180 He wants to maximize his happiness subject to this 319 00:14:15,180 --> 00:14:18,510 constraint that he cannot go outside more than two days 320 00:14:18,510 --> 00:14:19,020 in a row. 321 00:14:19,020 --> 00:14:19,520 Right? 322 00:14:19,520 --> 00:14:21,150 So if I go out on Monday and Tuesday, 323 00:14:21,150 --> 00:14:23,880 I have to stay inside on Wednesday. 324 00:14:23,880 --> 00:14:24,380 Yes? 325 00:14:24,380 --> 00:14:26,547 AUDIENCE: I think there's no effect to his happiness 326 00:14:26,547 --> 00:14:27,290 when he stays in. 327 00:14:27,290 --> 00:14:29,373 JUSTIN SOLOMON: There's no effect to his happiness 328 00:14:29,373 --> 00:14:31,750 when he stays in. 329 00:14:31,750 --> 00:14:34,107 AUDIENCE: At least, that's [INAUDIBLE].. 330 00:14:34,107 --> 00:14:36,440 JUSTIN SOLOMON: No, it says with a decrease in happiness 331 00:14:36,440 --> 00:14:39,998 when t-- oh, when t is negative. 332 00:14:39,998 --> 00:14:42,290 That's not actually going to affect our problem at all. 333 00:14:45,687 --> 00:14:47,270 AUDIENCE: It's not going to affect it. 334 00:14:47,270 --> 00:14:50,838 JUSTIN SOLOMON: Sure, yeah, I can fix this live. 335 00:14:50,838 --> 00:14:52,880 This is what happens when I do the problem myself 336 00:14:52,880 --> 00:14:56,320 before looking at the answer and then don't check it closely. 337 00:14:56,320 --> 00:14:56,820 Fine. 338 00:14:56,820 --> 00:14:59,190 So let's change that. 339 00:14:59,190 --> 00:15:02,010 I like this problem better, somehow, psychologically. 340 00:15:02,010 --> 00:15:03,450 But that's OK. 341 00:15:03,450 --> 00:15:03,950 Right. 342 00:15:03,950 --> 00:15:07,110 So, Jason correctly points out that if you actually 343 00:15:07,110 --> 00:15:11,940 read the problem, what's asked there is slightly different, 344 00:15:11,940 --> 00:15:14,610 that when he goes outside, his happiness increases by t. 345 00:15:14,610 --> 00:15:17,350 If he stays inside, his happiness does nothing. 346 00:15:17,350 --> 00:15:17,850 Right? 347 00:15:17,850 --> 00:15:23,530 So it stays the same. 348 00:15:23,530 --> 00:15:27,110 My apologies, so Tim the Beaver is a particularly optimistic 349 00:15:27,110 --> 00:15:27,610 beaver. 350 00:15:27,610 --> 00:15:30,130 His happiness can only increase in time, 351 00:15:30,130 --> 00:15:33,010 assuming he lives in a climate with positive temperatures. 352 00:15:33,010 --> 00:15:34,030 OK. 353 00:15:34,030 --> 00:15:35,620 I think I've got it right now. 354 00:15:35,620 --> 00:15:36,320 Cool. 355 00:15:36,320 --> 00:15:39,670 We'll see if I can still do this. 356 00:15:39,670 --> 00:15:42,520 Yeah, I think basically nothing changes. 357 00:15:42,520 --> 00:15:45,610 OK, that's great. 358 00:15:45,610 --> 00:15:46,110 All right. 359 00:15:46,110 --> 00:15:46,985 We're going to do it. 360 00:15:51,760 --> 00:15:52,930 OK. 361 00:15:52,930 --> 00:15:56,440 Right, so the question is how do we solve this problem. 362 00:15:56,440 --> 00:15:59,230 And thankfully, I think we put the easiest problem first. 363 00:15:59,230 --> 00:16:03,000 And, in particular, if we're following our SRTBOT paradigm 364 00:16:03,000 --> 00:16:06,480 here, somehow there's a set of subproblems that 365 00:16:06,480 --> 00:16:09,190 are staring us in the face. 366 00:16:09,190 --> 00:16:11,400 That's the word I'm looking for. 367 00:16:11,400 --> 00:16:15,330 In particular, well, there's sort 368 00:16:15,330 --> 00:16:17,160 of only one index in our problem, which 369 00:16:17,160 --> 00:16:18,600 is what day it is. 370 00:16:18,600 --> 00:16:21,150 So the obvious thing to do would be to say, 371 00:16:21,150 --> 00:16:23,550 can we figure out the maximum amount 372 00:16:23,550 --> 00:16:27,810 of happiness for days, say, i to the last day? 373 00:16:27,810 --> 00:16:30,240 By the way, if I do that, I'm using the prefix version 374 00:16:30,240 --> 00:16:31,720 of my problem-- 375 00:16:31,720 --> 00:16:33,700 ah, suffix version of my problem. 376 00:16:33,700 --> 00:16:36,270 I could also do it the opposite way and work from the end 377 00:16:36,270 --> 00:16:37,262 back in. 378 00:16:37,262 --> 00:16:38,970 Maybe if we have time all the way at end, 379 00:16:38,970 --> 00:16:39,970 we'll do the second one. 380 00:16:39,970 --> 00:16:42,240 But it doesn't really matter. 381 00:16:42,240 --> 00:16:42,960 OK. 382 00:16:42,960 --> 00:16:46,840 So, in particular, just to add a little bit of notation, 383 00:16:46,840 --> 00:16:56,370 let's say that t of i is equal to the temperature on day i. 384 00:16:56,370 --> 00:16:57,900 OK. 385 00:16:57,900 --> 00:17:00,600 And now we're going to make a new thing, which 386 00:17:00,600 --> 00:17:02,850 is going to be the actual variable we want to compute. 387 00:17:02,850 --> 00:17:05,670 This is going to be x to i, which, we'll write, 388 00:17:05,670 --> 00:17:15,869 is the maximum happiness that you can achieve if you only 389 00:17:15,869 --> 00:17:22,760 consider the calendar from day i to day n, I guess inclusive. 390 00:17:22,760 --> 00:17:24,650 OK. 391 00:17:24,650 --> 00:17:26,329 Incidentally, just for convenience, 392 00:17:26,329 --> 00:17:28,250 we'll assume that x i is equal to 0 393 00:17:28,250 --> 00:17:32,090 if I go past the end of my array, which I think 394 00:17:32,090 --> 00:17:36,730 is, kind of, a, typical thing to do in these type DP algorithms. 395 00:17:36,730 --> 00:17:37,330 OK. 396 00:17:37,330 --> 00:17:40,060 So the question is can we actually come up 397 00:17:40,060 --> 00:17:42,650 with a recursive algorithm that computes 398 00:17:42,650 --> 00:17:50,080 x i using this nice, sort of, typologically acyclic way 399 00:17:50,080 --> 00:17:51,820 of thinking about our problem. 400 00:17:51,820 --> 00:17:55,060 The answer is obviously yes, or I wouldn't be here today. 401 00:17:55,060 --> 00:17:58,390 And so in the absence of a smarter idea, 402 00:17:58,390 --> 00:18:01,720 let's just do the Toucan Sam approach here and follow 403 00:18:01,720 --> 00:18:06,610 our nose and see if we can just write our problem in terms 404 00:18:06,610 --> 00:18:08,120 of other ones. 405 00:18:08,120 --> 00:18:10,330 So, in general, let's say that Tim the Beaver 406 00:18:10,330 --> 00:18:12,160 wakes up on day i. 407 00:18:12,160 --> 00:18:16,030 He has, basically, two decisions that he can make, right? 408 00:18:16,030 --> 00:18:20,410 He can either stay inside or he can not stay inside. 409 00:18:20,410 --> 00:18:22,360 He can go outside, right? 410 00:18:22,360 --> 00:18:27,320 So let's just basically handle these three cases. 411 00:18:27,320 --> 00:18:30,460 So in case, one he stays inside. 412 00:18:33,430 --> 00:18:36,790 Well, now what happens to his happiness? 413 00:18:36,790 --> 00:18:39,430 Well, according to my revised version 414 00:18:39,430 --> 00:18:44,870 of this problem, nothing, so, in particular, what do we know? 415 00:18:44,870 --> 00:18:47,302 Well, if he stays inside, then he has-- 416 00:18:47,302 --> 00:18:49,510 any decision he can make tomorrow, it doesn't matter. 417 00:18:49,510 --> 00:18:51,190 He can go inside, he can go outside, 418 00:18:51,190 --> 00:18:53,530 whatever, because by having stayed inside, 419 00:18:53,530 --> 00:18:56,890 he's earned himself two free days of going outside 420 00:18:56,890 --> 00:18:57,810 if he wants. 421 00:18:57,810 --> 00:18:58,420 Right? 422 00:18:58,420 --> 00:19:02,500 So, in particular, in this case, we can convince ourselves 423 00:19:02,500 --> 00:19:08,170 that this is true, I think. 424 00:19:08,170 --> 00:19:12,520 Yes, so, in other words, while he gets no utility for today, 425 00:19:12,520 --> 00:19:14,770 he wakes up tomorrow and he can make whatever decision 426 00:19:14,770 --> 00:19:16,400 he wants. 427 00:19:16,400 --> 00:19:18,860 OK. 428 00:19:18,860 --> 00:19:20,900 The second thing he can do is go out. 429 00:19:25,760 --> 00:19:28,110 This is where things get a little tricky. 430 00:19:28,110 --> 00:19:28,610 Right? 431 00:19:28,610 --> 00:19:34,170 Can I just do, like, take t i and add it to x i plus 1? 432 00:19:34,170 --> 00:19:37,468 What goes wrong? 433 00:19:37,468 --> 00:19:38,940 AUDIENCE: You go out three days-- 434 00:19:38,940 --> 00:19:41,440 JUSTIN SOLOMON: Maybe you go out three days in a row, right? 435 00:19:41,440 --> 00:19:43,770 Somehow, you have to remember that, right? 436 00:19:43,770 --> 00:19:47,295 And so that's where things are a little bit of a headache, 437 00:19:47,295 --> 00:19:51,530 that, in particular, if I go out today and tomorrow, 438 00:19:51,530 --> 00:19:54,080 I can't go out the day after that. 439 00:19:54,080 --> 00:19:57,020 And somehow, if we just dealt with this one case 440 00:19:57,020 --> 00:19:59,870 as t i plus x i plus 1, we wouldn't remember that. 441 00:19:59,870 --> 00:20:01,890 And that's a problem. 442 00:20:01,890 --> 00:20:04,100 So, instead, what we can do is think of there 443 00:20:04,100 --> 00:20:06,470 being two subcases, right? 444 00:20:06,470 --> 00:20:08,900 So what we're going to assume is that not only does he 445 00:20:08,900 --> 00:20:12,348 go out today, but that he's free to go out tomorrow. 446 00:20:12,348 --> 00:20:14,390 And we're going to make that recursive assumption 447 00:20:14,390 --> 00:20:16,910 as we move down our array. 448 00:20:16,910 --> 00:20:21,860 So if we do that, well, now we have case a and case b. 449 00:20:21,860 --> 00:20:27,630 So in case a, he goes out today and he stays in tomorrow. 450 00:20:27,630 --> 00:20:28,130 Yeah. 451 00:20:35,160 --> 00:20:35,910 OK. 452 00:20:35,910 --> 00:20:38,010 So what happens in this case, well-- 453 00:20:40,800 --> 00:20:43,260 by the way, I'm using this kind of weird arrow notation. 454 00:20:43,260 --> 00:20:44,310 I don't know if this is good or not, 455 00:20:44,310 --> 00:20:45,450 but, essentially, the point is that I'm 456 00:20:45,450 --> 00:20:47,490 keeping track of cases, and then eventually I'm 457 00:20:47,490 --> 00:20:49,032 going to want to have to take the max 458 00:20:49,032 --> 00:20:50,382 overall of these things. 459 00:20:50,382 --> 00:20:52,590 So I don't like the equal sign because somehow that's 460 00:20:52,590 --> 00:20:54,750 a little misleading. 461 00:20:54,750 --> 00:20:55,250 Right. 462 00:20:55,250 --> 00:20:58,050 So in that case, well, he gets the utility 463 00:20:58,050 --> 00:21:01,540 of having gone out today. 464 00:21:01,540 --> 00:21:04,778 Tomorrow he stays in, which means 465 00:21:04,778 --> 00:21:07,070 that the day after tomorrow he can do whatever the heck 466 00:21:07,070 --> 00:21:08,360 he wants. 467 00:21:08,360 --> 00:21:09,260 He has free reign. 468 00:21:09,260 --> 00:21:15,500 So I can write that using this recursive call. 469 00:21:15,500 --> 00:21:16,280 OK. 470 00:21:16,280 --> 00:21:22,910 Similarly-- right. 471 00:21:26,450 --> 00:21:29,940 I'm getting the hang of this. 472 00:21:29,940 --> 00:21:32,330 Sorry, this is way too entertaining for me. 473 00:21:32,330 --> 00:21:34,260 I can play with this board all day. 474 00:21:34,260 --> 00:21:34,760 OK. 475 00:21:34,760 --> 00:21:39,665 So in case 2b, he goes out today and he goes out tomorrow. 476 00:21:45,500 --> 00:21:46,020 OK? 477 00:21:46,020 --> 00:21:46,520 So-- 478 00:21:46,520 --> 00:21:47,570 AUDIENCE: He's a party animal. 479 00:21:47,570 --> 00:21:49,070 JUSTIN SOLOMON: He's a party animal. 480 00:21:49,070 --> 00:21:51,500 He is an animal and he's going out a lot. 481 00:21:51,500 --> 00:21:53,300 Right, so in that case, what happens? 482 00:21:53,300 --> 00:21:55,460 Well, he gets that. 483 00:21:55,460 --> 00:21:59,090 He gets today's utility. 484 00:21:59,090 --> 00:22:01,370 He gets tomorrow's utility. 485 00:22:04,410 --> 00:22:06,770 The day after, he has to stay in, 486 00:22:06,770 --> 00:22:09,140 so we might as well skip it. 487 00:22:09,140 --> 00:22:14,790 And then he can do whatever he wants the day after that. 488 00:22:14,790 --> 00:22:16,390 OK? 489 00:22:16,390 --> 00:22:20,580 So if we go back, I guess, technically, we 490 00:22:20,580 --> 00:22:23,770 should revise our definition of x a tiny bit, 491 00:22:23,770 --> 00:22:25,800 that it's not the maximum of happiness-- well, 492 00:22:25,800 --> 00:22:27,925 we can convince ourselves that it's the same thing. 493 00:22:27,925 --> 00:22:30,900 But really, it's not the maximum happiness for day i through n. 494 00:22:30,900 --> 00:22:32,340 It's the maximum happiness for day 495 00:22:32,340 --> 00:22:34,890 i through n under the assumption that he has 496 00:22:34,890 --> 00:22:37,040 permission to go out on day i. 497 00:22:37,040 --> 00:22:37,540 Right? 498 00:22:37,540 --> 00:22:39,090 And that's really what's going on 499 00:22:39,090 --> 00:22:42,010 in our recursive set of calls here. 500 00:22:42,010 --> 00:22:42,510 OK. 501 00:22:42,510 --> 00:22:45,900 So does our recursion make sense here? 502 00:22:45,900 --> 00:22:46,860 Cool. 503 00:22:46,860 --> 00:22:47,940 All right. 504 00:22:47,940 --> 00:22:49,930 So let's see here. 505 00:22:49,930 --> 00:22:51,865 So if we're following our SRTBOT-- 506 00:22:51,865 --> 00:22:54,240 I keep reviewing papers that use the word paradigm a lot, 507 00:22:54,240 --> 00:22:56,110 so I feel like I should do that. 508 00:22:56,110 --> 00:22:57,510 So what is t? 509 00:22:57,510 --> 00:22:59,710 It's the topological order. 510 00:22:59,710 --> 00:23:08,060 Notice that x i only depends on larger i's. 511 00:23:10,610 --> 00:23:12,187 So in terms of our topological order, 512 00:23:12,187 --> 00:23:13,770 the dependence graph is really simple. 513 00:23:13,770 --> 00:23:17,060 It's just a line, so remember that you 514 00:23:17,060 --> 00:23:18,590 can think about topological order 515 00:23:18,590 --> 00:23:20,475 or you can think about being acyclic graph. 516 00:23:20,475 --> 00:23:21,350 Those are equivalent. 517 00:23:21,350 --> 00:23:22,790 We covered that in this course. 518 00:23:22,790 --> 00:23:25,820 I kind of like thinking about acyclic graphs. 519 00:23:25,820 --> 00:23:29,240 So x1 depends on x2 depends on x3 depends on x4. 520 00:23:29,240 --> 00:23:33,770 That graph has no cycles, so we're good. 521 00:23:33,770 --> 00:23:35,150 Right. 522 00:23:35,150 --> 00:23:38,090 So next we have to come up with our base 523 00:23:38,090 --> 00:23:40,130 case for our recursion. 524 00:23:40,130 --> 00:23:43,730 Notice that the way I have chosen to solve this problem 525 00:23:43,730 --> 00:23:47,360 is by calling future indices, which 526 00:23:47,360 --> 00:23:50,650 means that my base case sits at the end of my array 527 00:23:50,650 --> 00:23:53,150 because that's sort of like the lowest down on the recursion 528 00:23:53,150 --> 00:23:53,650 train. 529 00:23:53,650 --> 00:23:56,030 The recursion chain is what I was going for, 530 00:23:56,030 --> 00:23:59,120 but I kind of like the recursion train better. 531 00:23:59,120 --> 00:24:02,600 In particular, on day n-- 532 00:24:02,600 --> 00:24:06,670 well, if he has permission to go out on day n, 533 00:24:06,670 --> 00:24:07,970 he can do one of two things. 534 00:24:07,970 --> 00:24:09,137 He can either go out or not. 535 00:24:09,137 --> 00:24:10,780 It doesn't matter, right? 536 00:24:10,780 --> 00:24:16,220 So, in particular, we can say that that's the max of 0 537 00:24:16,220 --> 00:24:17,675 or t of n. 538 00:24:17,675 --> 00:24:19,550 Remember, I didn't tell you that temperatures 539 00:24:19,550 --> 00:24:21,770 have to be positive. 540 00:24:21,770 --> 00:24:24,800 Maybe he's a Celsius kind of a beaver. 541 00:24:24,800 --> 00:24:26,610 OK. 542 00:24:26,610 --> 00:24:27,110 Right. 543 00:24:27,110 --> 00:24:31,070 And then in addition to the-- 544 00:24:31,070 --> 00:24:33,053 for convenience, notice that, like, 545 00:24:33,053 --> 00:24:35,470 there's a universe where I look beyond the end of my array 546 00:24:35,470 --> 00:24:38,920 in my recursive call here, so I should probably think about 547 00:24:38,920 --> 00:24:40,600 a few extra x's. 548 00:24:40,600 --> 00:24:43,390 Obviously, the utility of going out on a day that doesn't exist 549 00:24:43,390 --> 00:24:44,890 is 0. 550 00:24:44,890 --> 00:24:52,270 So we can say that x n plus 1 equals x n plus 2 equals 0. 551 00:24:52,270 --> 00:24:53,440 OK. 552 00:24:53,440 --> 00:24:55,570 I've managed to use way too much space for one 553 00:24:55,570 --> 00:24:57,210 simple algorithms problem. 554 00:25:00,770 --> 00:25:01,270 OK. 555 00:25:09,120 --> 00:25:10,460 Yeah? 556 00:25:10,460 --> 00:25:11,410 I get credit for that? 557 00:25:11,410 --> 00:25:12,940 OK. 558 00:25:12,940 --> 00:25:13,440 Right. 559 00:25:13,440 --> 00:25:16,430 So now we need to do the o and the t. 560 00:25:16,430 --> 00:25:20,280 So what's our original problem? 561 00:25:20,280 --> 00:25:22,950 Well, remember that he wants to maximize his happiness starting 562 00:25:22,950 --> 00:25:32,510 on day one, so our original problem is just x of 1, 563 00:25:32,510 --> 00:25:33,680 or is it? 564 00:25:33,680 --> 00:25:36,140 So, remember that Tim the Beaver-- 565 00:25:36,140 --> 00:25:37,640 your instructor is very sloppy when 566 00:25:37,640 --> 00:25:39,390 it comes to actually reading the problems, 567 00:25:39,390 --> 00:25:41,630 as you saw at the beginning. 568 00:25:41,630 --> 00:25:43,940 A second mistake for which I would have personally 569 00:25:43,940 --> 00:25:46,730 lost points were I to solve this problem on my homework 570 00:25:46,730 --> 00:25:50,540 is that it didn't ask for just the maximum amount of happiness 571 00:25:50,540 --> 00:25:52,370 that Tim could achieve-- 572 00:25:52,370 --> 00:25:55,520 that's not very practical for your everyday beaver-- 573 00:25:55,520 --> 00:25:57,945 but rather, he wants to know the actual plan. 574 00:25:57,945 --> 00:26:00,320 He wants to know what days he can go out and what days he 575 00:26:00,320 --> 00:26:00,890 can't. 576 00:26:00,890 --> 00:26:01,460 Yeah? 577 00:26:01,460 --> 00:26:03,710 And I haven't actually told you how to do that, right? 578 00:26:03,710 --> 00:26:05,085 I've only told you how to compute 579 00:26:05,085 --> 00:26:09,660 x, which is just the maximum amount of happiness. 580 00:26:09,660 --> 00:26:11,340 If I were you guys, I think this is 581 00:26:11,340 --> 00:26:13,317 a perfectly reasonable simplification that's 582 00:26:13,317 --> 00:26:14,650 like a warm up problem to solve. 583 00:26:14,650 --> 00:26:17,220 In fact, I would argue it's less of a warm up and more 584 00:26:17,220 --> 00:26:18,642 the crux of the problem-- 585 00:26:18,642 --> 00:26:20,100 and then going back and making sure 586 00:26:20,100 --> 00:26:22,142 you can convince yourself that you could actually 587 00:26:22,142 --> 00:26:24,960 reconstruct the solution. 588 00:26:24,960 --> 00:26:27,067 My way of solving this was ever so slightly 589 00:26:27,067 --> 00:26:28,650 different from the one in the problem, 590 00:26:28,650 --> 00:26:31,740 but they're equivalent, which is to say 591 00:26:31,740 --> 00:26:33,332 I can make a second array-- 592 00:26:33,332 --> 00:26:36,050 I won't write it down, because I'm slow at writing-- 593 00:26:36,050 --> 00:26:39,110 that just says on every day, whether I took option 1, option 594 00:26:39,110 --> 00:26:41,712 2a, or option 2b. 595 00:26:41,712 --> 00:26:43,920 And now I can reconstruct my plan very easily, right? 596 00:26:43,920 --> 00:26:48,330 So I look at x1, if I took option 1, then I stay in 597 00:26:48,330 --> 00:26:50,580 and I look at day two. 598 00:26:50,580 --> 00:26:55,870 If I took option 2a, then I can label today, tomorrow, 599 00:26:55,870 --> 00:26:56,720 and the day after. 600 00:26:56,720 --> 00:26:59,910 Oh, wait-- yeah, that's right. 601 00:26:59,910 --> 00:27:02,400 I can label today's choice, tomorrow's choice, the day's 602 00:27:02,400 --> 00:27:05,460 after choice, and then look three days later 603 00:27:05,460 --> 00:27:07,500 and recurse that way. 604 00:27:07,500 --> 00:27:10,260 Option b is kind of similar. 605 00:27:10,260 --> 00:27:13,432 So a reasonable way to reconstruct the actual set 606 00:27:13,432 --> 00:27:15,390 of what days you go out and what days you go in 607 00:27:15,390 --> 00:27:19,950 is just to remember, as you do your memoization or whatever, 608 00:27:19,950 --> 00:27:22,140 whether you did option 1, 2a, or 2b. 609 00:27:22,140 --> 00:27:24,420 And then it's pretty easy to reconstruct from there. 610 00:27:24,420 --> 00:27:26,212 Maybe I'll let you guys convince yourselves 611 00:27:26,212 --> 00:27:28,290 of that at home or in the last 8 seconds 612 00:27:28,290 --> 00:27:31,530 if you happen to be the two audience members that I have. 613 00:27:31,530 --> 00:27:36,760 And then, finally, we need to do our time thing. 614 00:27:36,760 --> 00:27:38,478 And most of the time arguments here 615 00:27:38,478 --> 00:27:40,020 follow more or less the same pattern, 616 00:27:40,020 --> 00:27:41,610 which is you count the number of subproblems 617 00:27:41,610 --> 00:27:44,027 and the time per subproblem, you multiply those two things 618 00:27:44,027 --> 00:27:45,935 together, and you get your runtime. 619 00:27:45,935 --> 00:27:47,310 We're going to see in one problem 620 00:27:47,310 --> 00:27:49,920 on this problem set that's not quite right because we 621 00:27:49,920 --> 00:27:52,260 have to account for some precomputation. 622 00:27:52,260 --> 00:27:53,910 But in this case, it is. 623 00:27:57,220 --> 00:27:59,752 Right, so let's see, what are our subproblems here? 624 00:27:59,752 --> 00:28:01,960 Well, essentially-- I guess I didn't actually say it, 625 00:28:01,960 --> 00:28:06,210 but you have to take the max of these three values. 626 00:28:06,210 --> 00:28:08,130 This is the max of three expressions which 627 00:28:08,130 --> 00:28:10,380 have a constant number of plus signs and lookups 628 00:28:10,380 --> 00:28:12,610 and memory and all that good stuff. 629 00:28:12,610 --> 00:28:21,310 So each subproblem takes order one time. 630 00:28:21,310 --> 00:28:23,300 How many problems are there? 631 00:28:23,300 --> 00:28:26,830 Well, there's, I guess, n plus 2 max, 632 00:28:26,830 --> 00:28:29,080 if you want to be conservative about it. 633 00:28:29,080 --> 00:28:34,750 So, in particular, there's order n subproblems, right? 634 00:28:34,750 --> 00:28:37,210 So all I have to do is multiply these two things together, 635 00:28:37,210 --> 00:28:40,880 and my algorithm takes order n time. 636 00:28:43,610 --> 00:28:47,730 And that's our solution to problem number one. 637 00:28:47,730 --> 00:28:49,620 Any questions so far? 638 00:28:49,620 --> 00:28:50,120 Yes? 639 00:28:50,120 --> 00:28:51,552 Uh-oh. 640 00:28:51,552 --> 00:28:54,010 AUDIENCE: When I was thinking about the problem beforehand, 641 00:28:54,010 --> 00:28:57,450 I was wondering could you use base cases-- 642 00:28:57,450 --> 00:29:00,590 right now, we have two different kinds of base case, 643 00:29:00,590 --> 00:29:05,130 a base case for x of n and a base case for things after. 644 00:29:05,130 --> 00:29:08,280 Can I remove the first one and add an x of n 645 00:29:08,280 --> 00:29:10,740 plus 3 equals 0 as well? 646 00:29:10,740 --> 00:29:11,997 What would that do? 647 00:29:11,997 --> 00:29:13,830 JUSTIN SOLOMON: Could I remove the first one 648 00:29:13,830 --> 00:29:16,930 and add an x of n plus 3? 649 00:29:16,930 --> 00:29:19,960 Yeah, I guess that's fine. 650 00:29:19,960 --> 00:29:22,270 I'm sorry, that's not a particularly helpful answer 651 00:29:22,270 --> 00:29:24,340 for the people watching on video. 652 00:29:24,340 --> 00:29:28,150 My answer to this question you can't hear is yes. 653 00:29:28,150 --> 00:29:33,550 So the question, to repeat, was this base case was somehow 654 00:29:33,550 --> 00:29:35,350 kind of complicated-looking. 655 00:29:35,350 --> 00:29:36,970 To be fair, it's the one that I was 656 00:29:36,970 --> 00:29:40,420 given in [INAUDIBLE] assignment, but that's OK. 657 00:29:40,420 --> 00:29:43,540 But the question was is this truly necessary. 658 00:29:43,540 --> 00:29:46,270 In particular, can I get rid of the x n case 659 00:29:46,270 --> 00:29:50,690 and instead add a third day past the end of time, 660 00:29:50,690 --> 00:29:52,600 which also has value 0? 661 00:29:52,600 --> 00:29:59,640 And if you, kind of, look at that plus case b, I think-- 662 00:29:59,640 --> 00:30:00,807 or rather, case a-- 663 00:30:00,807 --> 00:30:02,640 think you can convince-- well, case a and b, 664 00:30:02,640 --> 00:30:04,973 for that matter-- you can convince yourselves that these 665 00:30:04,973 --> 00:30:05,970 are equivalent, right? 666 00:30:05,970 --> 00:30:06,970 That's absolutely right. 667 00:30:06,970 --> 00:30:11,100 So I could add a third day after the end of this thing, which 668 00:30:11,100 --> 00:30:12,570 also has value 0. 669 00:30:12,570 --> 00:30:16,260 Or, by the way, I could just say in my code if n is-- 670 00:30:16,260 --> 00:30:18,390 if i is bigger than n, return 0. 671 00:30:18,390 --> 00:30:21,472 That's the same thing. 672 00:30:21,472 --> 00:30:22,930 Yeah, and then I guess I don't have 673 00:30:22,930 --> 00:30:24,360 to worry about that x n case. 674 00:30:24,360 --> 00:30:26,610 Yeah, these are the same. 675 00:30:26,610 --> 00:30:28,740 To each their own. 676 00:30:28,740 --> 00:30:29,620 Fabulous question. 677 00:30:29,620 --> 00:30:34,030 Any others that I can answer while we're at it? 678 00:30:34,030 --> 00:30:35,010 Cool. 679 00:30:35,010 --> 00:30:35,510 All right. 680 00:30:35,510 --> 00:30:36,427 So that's problem one. 681 00:30:39,016 --> 00:30:41,980 Writing too big-- I don't like this big chalk, you know. 682 00:30:41,980 --> 00:30:42,480 OK. 683 00:30:42,480 --> 00:30:44,362 So problem two is the one that got me all hot 684 00:30:44,362 --> 00:30:45,320 and bothered yesterday. 685 00:30:45,320 --> 00:30:47,880 So let's see if we do any better in front of people, 686 00:30:47,880 --> 00:30:50,010 because that's usually the best way to improve 687 00:30:50,010 --> 00:30:52,230 a problem solving skill. 688 00:30:52,230 --> 00:30:53,280 Right. 689 00:30:53,280 --> 00:30:56,430 So in problem two, which, annoyingly, 690 00:30:56,430 --> 00:30:58,860 is also probably the most practical problem 691 00:30:58,860 --> 00:31:00,240 on this problem set. 692 00:31:00,240 --> 00:31:02,162 Essentially, you have a-- 693 00:31:02,162 --> 00:31:03,870 I suppose I should write some stuff down. 694 00:31:06,450 --> 00:31:07,770 So in problem-- 695 00:31:07,770 --> 00:31:10,410 I used the wrong side-- 696 00:31:10,410 --> 00:31:16,090 two, you have an operating system Menix-- 697 00:31:16,090 --> 00:31:19,864 whatever-- which is-- 698 00:31:19,864 --> 00:31:21,442 apparently, it's very simple. 699 00:31:21,442 --> 00:31:23,170 AUDIENCE: Menix, Unix. 700 00:31:23,170 --> 00:31:24,478 JUSTIN SOLOMON: Oh, I get it. 701 00:31:24,478 --> 00:31:27,950 [LAUGHS] It doesn't mean I have to like it. 702 00:31:27,950 --> 00:31:28,450 Right. 703 00:31:28,450 --> 00:31:35,830 [LAUGHS] So, in Menix, apparently, 704 00:31:35,830 --> 00:31:37,840 the only thing that my operating system can do 705 00:31:37,840 --> 00:31:41,590 is compute edit distance between files. 706 00:31:41,590 --> 00:31:43,730 And it wants to do so efficiently. 707 00:31:43,730 --> 00:31:50,315 So we have that a file is a sequence of strings. 708 00:31:54,940 --> 00:31:57,840 And I believe we say their length is 709 00:31:57,840 --> 00:31:59,310 less than or equal to k. 710 00:31:59,310 --> 00:32:02,940 That's going to come into play a little bit later. 711 00:32:02,940 --> 00:32:05,100 And the strings are basically just lines 712 00:32:05,100 --> 00:32:08,020 of the different files. 713 00:32:08,020 --> 00:32:13,103 So there's three different ways that we can change a file. 714 00:32:13,103 --> 00:32:14,520 So here are the changes we can do. 715 00:32:18,030 --> 00:32:20,760 Change number 1 is to add a line. 716 00:32:23,390 --> 00:32:26,780 Change number 2 is to remove a line. 717 00:32:29,730 --> 00:32:34,590 And change number 3 is to swap. 718 00:32:34,590 --> 00:32:40,170 But a caveat for this interesting model 719 00:32:40,170 --> 00:32:45,390 of what's cheap and what's not is that, apparently, 720 00:32:45,390 --> 00:32:48,150 swapping two lines is cheap because they exist in memory. 721 00:32:48,150 --> 00:32:50,910 Like, maybe I'm, I don't know, using a linked 722 00:32:50,910 --> 00:32:53,160 list or something to store files, 723 00:32:53,160 --> 00:32:56,520 and so swapping two pointers isn't so bad. 724 00:32:56,520 --> 00:32:58,320 But inserting and removing a line 725 00:32:58,320 --> 00:33:01,140 is hard because, I don't know, memory allocation is expensive, 726 00:33:01,140 --> 00:33:04,740 like Menix is actually operating on clay tablets. 727 00:33:04,740 --> 00:33:08,940 And I can chop my clay tablets into different slices 728 00:33:08,940 --> 00:33:11,880 and just pick them up and swap them, and that's fine, 729 00:33:11,880 --> 00:33:13,530 but if I want to add a line in my file, 730 00:33:13,530 --> 00:33:17,810 I have to go to the Tigris and Euphrates and pull out the-- 731 00:33:17,810 --> 00:33:20,280 or whatever it was, the Eugris and the 732 00:33:20,280 --> 00:33:23,660 Tiphrates-- and pull out a stone. 733 00:33:23,660 --> 00:33:27,960 It's a lot of work to make a new line or to dispose. 734 00:33:27,960 --> 00:33:35,680 So these are expensive and this is cheap. 735 00:33:35,680 --> 00:33:38,920 And so the question that I'm trying to sa-- 736 00:33:38,920 --> 00:33:41,890 that I'm trying to say and that the problem is trying to ask 737 00:33:41,890 --> 00:33:52,800 is that you are given files A and B with n lines each. 738 00:33:57,680 --> 00:34:03,710 We want to know what the minimum number of non-swap operations 739 00:34:03,710 --> 00:34:05,890 it'll take, and so, in other words, 740 00:34:05,890 --> 00:34:08,780 the minimum number of time for you to add and remove lines 741 00:34:08,780 --> 00:34:20,300 to transform A into B, essentially, with low cost. 742 00:34:23,040 --> 00:34:25,920 And, in fact, just to be nice-- 743 00:34:25,920 --> 00:34:29,460 I think it's actually kind of a critical hint in this problem-- 744 00:34:29,460 --> 00:34:32,190 we give you the runtime. 745 00:34:32,190 --> 00:34:34,273 And I'm going to, kind of, ignore it in my answer, 746 00:34:34,273 --> 00:34:36,398 notice that I did something wrong, and then go back 747 00:34:36,398 --> 00:34:36,969 and fix it. 748 00:34:36,969 --> 00:34:38,400 This is different from the way the answer is written, 749 00:34:38,400 --> 00:34:41,463 where god came in and said, like, oh, we observe that we're 750 00:34:41,463 --> 00:34:42,880 probably going to need this thing, 751 00:34:42,880 --> 00:34:44,520 so we're going to go ahead and do it here. 752 00:34:44,520 --> 00:34:46,770 I think that's, maybe, not representative of the logic 753 00:34:46,770 --> 00:34:48,150 here. 754 00:34:48,150 --> 00:34:53,250 Right, so the runtime here is k n plus n squared. 755 00:34:53,250 --> 00:34:57,330 The first thing to note is there is a k here. 756 00:34:57,330 --> 00:35:02,480 Yeah, and so someday we're going to have to compare strings, 757 00:35:02,480 --> 00:35:03,980 because that's what k is. 758 00:35:03,980 --> 00:35:05,408 And I think that's the hint that's 759 00:35:05,408 --> 00:35:06,450 implicit in this problem. 760 00:35:06,450 --> 00:35:07,940 It's easy to miss. 761 00:35:07,940 --> 00:35:10,280 And so, indeed, what we're going to notice 762 00:35:10,280 --> 00:35:11,863 is we're going to look at our solution 763 00:35:11,863 --> 00:35:14,720 and say, well, wait a second, if we didn't incur a factor of k, 764 00:35:14,720 --> 00:35:16,850 we must have done something wrong. 765 00:35:16,850 --> 00:35:18,890 And, indeed, that's going to be the case, 766 00:35:18,890 --> 00:35:23,942 but it's only a minor fix to change it. 767 00:35:23,942 --> 00:35:25,900 AUDIENCE: There's another important distinction 768 00:35:25,900 --> 00:35:26,850 on this [INAUDIBLE]. 769 00:35:26,850 --> 00:35:28,100 JUSTIN SOLOMON: Oh, I'm sorry. 770 00:35:28,100 --> 00:35:35,006 Yeah, right, when I swap things, they have to be adjacent. 771 00:35:35,006 --> 00:35:38,570 I can't write at the bottom of the board. 772 00:35:38,570 --> 00:35:41,893 That's supposed to be a, d, j, for those watching at home. 773 00:35:41,893 --> 00:35:43,310 But they have to be-- you can only 774 00:35:43,310 --> 00:35:45,800 swap lines that are adjacent, as they 775 00:35:45,800 --> 00:35:47,668 appear in their original file. 776 00:35:47,668 --> 00:35:50,210 I'll say it out loud rather than try and write it because you 777 00:35:50,210 --> 00:35:52,460 it's going to take the rest of the lecture to do that. 778 00:35:52,460 --> 00:35:56,237 OK, any other things I've forgotten? 779 00:35:56,237 --> 00:35:57,320 There's a high likelihood. 780 00:35:57,320 --> 00:35:58,970 I'm bad at this. 781 00:35:58,970 --> 00:35:59,510 OK. 782 00:35:59,510 --> 00:36:02,870 So this one was annoying. 783 00:36:02,870 --> 00:36:04,650 And it's not actually annoying. 784 00:36:04,650 --> 00:36:07,730 It's actually a relatively easy instance of a very well-known 785 00:36:07,730 --> 00:36:11,780 dynamic program plus a tiny bit of additional stuff, which 786 00:36:11,780 --> 00:36:13,660 is called edit distance. 787 00:36:13,660 --> 00:36:15,910 In fact, I think if you guys are looking for intuition 788 00:36:15,910 --> 00:36:18,380 on this problem, you might google 789 00:36:18,380 --> 00:36:21,847 that one first as, sort of, a-- 790 00:36:21,847 --> 00:36:22,430 what was that? 791 00:36:22,430 --> 00:36:23,120 AUDIENCE: [INAUDIBLE] 792 00:36:23,120 --> 00:36:24,320 JUSTIN SOLOMON: Oh, in fact you're doing a recitation. 793 00:36:24,320 --> 00:36:26,690 Oh, that's why it's not totally unreasonable to come 794 00:36:26,690 --> 00:36:29,185 up with the answer here, even better. 795 00:36:29,185 --> 00:36:30,560 But even if you hadn't, you know, 796 00:36:30,560 --> 00:36:32,820 this is just another dynamic programming problem 797 00:36:32,820 --> 00:36:35,450 that's just a little bit more annoying 798 00:36:35,450 --> 00:36:38,720 than your average dynamic programming problem. 799 00:36:38,720 --> 00:36:41,180 Now, the solution written out in the course notes 800 00:36:41,180 --> 00:36:44,480 works from, sort of, the last line of the file 801 00:36:44,480 --> 00:36:47,210 downward, in some sense-- 802 00:36:47,210 --> 00:36:51,230 upward, whatever. 803 00:36:51,230 --> 00:36:53,240 I, like, literally lost two hours of my life 804 00:36:53,240 --> 00:36:56,330 trying to think about editing files from the end up 805 00:36:56,330 --> 00:36:58,768 and just getting myself all upset and confused. 806 00:36:58,768 --> 00:37:01,310 So here, I'm going to attempt to do it in the other direction 807 00:37:01,310 --> 00:37:04,170 and probably introduce a bunch of mistakes in the process. 808 00:37:04,170 --> 00:37:06,975 So what do we do in dynamic programming 809 00:37:06,975 --> 00:37:08,350 if we don't know what else to do? 810 00:37:08,350 --> 00:37:12,040 We do sort stuff, SRTBOT. 811 00:37:12,040 --> 00:37:13,910 And so let's do that here. 812 00:37:13,910 --> 00:37:17,110 So, in particular, what are our subproblems? 813 00:37:17,110 --> 00:37:19,902 This is a little bit funky. 814 00:37:19,902 --> 00:37:21,860 So actually, even before we do the S of SRTBOT, 815 00:37:21,860 --> 00:37:23,652 let's think about our problem a little bit. 816 00:37:26,000 --> 00:37:27,920 Let's think about what it actually 817 00:37:27,920 --> 00:37:30,380 means to edit a file because this 818 00:37:30,380 --> 00:37:33,500 is what helped me think about the right answer 819 00:37:33,500 --> 00:37:35,558 here, which is to say, you know-- 820 00:37:35,558 --> 00:37:36,350 so what's going on? 821 00:37:36,350 --> 00:37:38,570 I have, like, two documents. 822 00:37:38,570 --> 00:37:43,370 This is document A. This is document B. Each one of them 823 00:37:43,370 --> 00:37:46,130 is composed of a bunch of lines. 824 00:37:46,130 --> 00:37:47,930 And I'm basically trying to turn A into B. 825 00:37:47,930 --> 00:37:51,260 And the only thing I can do is scroll out of line, 826 00:37:51,260 --> 00:37:54,110 insert, just hit the Enter key, or do a third thing 827 00:37:54,110 --> 00:37:56,423 where I kind of like swap two things that 828 00:37:56,423 --> 00:37:57,590 are adjacent to one another. 829 00:37:57,590 --> 00:37:59,980 That is the only thing I can do. 830 00:37:59,980 --> 00:38:03,553 And the way I like to think about this problem-- 831 00:38:03,553 --> 00:38:04,970 there's kind of an annoyance here, 832 00:38:04,970 --> 00:38:06,550 which I think is a typical annoyance 833 00:38:06,550 --> 00:38:08,133 in dynamic programming problems, which 834 00:38:08,133 --> 00:38:12,900 is that the order of operations suggests that this problem is 835 00:38:12,900 --> 00:38:16,050 a lot, combinatorially, more difficult than it is, because, 836 00:38:16,050 --> 00:38:16,832 like-- 837 00:38:16,832 --> 00:38:19,290 OK, let's think about how I actually edit documents-- like, 838 00:38:19,290 --> 00:38:22,080 I spend 2/3 of my day editing bad grad student writing-- 839 00:38:22,080 --> 00:38:24,900 is like I'm jumping all over the place between different lines. 840 00:38:24,900 --> 00:38:26,460 Like, first I delete this line, then 841 00:38:26,460 --> 00:38:28,085 maybe I go to the bottom of my document 842 00:38:28,085 --> 00:38:29,220 and delete some other one. 843 00:38:29,220 --> 00:38:32,430 That would be a big problem from a dynamic programming 844 00:38:32,430 --> 00:38:33,120 perspective. 845 00:38:33,120 --> 00:38:35,070 I can't jump all over my document, 846 00:38:35,070 --> 00:38:37,950 because keeping track of that whole edit history 847 00:38:37,950 --> 00:38:41,620 is going to be somehow combinatorially ginormous. 848 00:38:41,620 --> 00:38:42,120 Right? 849 00:38:42,120 --> 00:38:45,120 I'm not the Track Changes button in Microsoft Word. 850 00:38:45,120 --> 00:38:47,910 I want the minimum number of changes. 851 00:38:47,910 --> 00:38:51,030 And if I have to recurse over all possible edits 852 00:38:51,030 --> 00:38:53,070 to every single line in any order, 853 00:38:53,070 --> 00:38:54,750 that's an awful lot of factorials 854 00:38:54,750 --> 00:38:57,240 and 2 to the n's floating around that I don't want to have. 855 00:38:57,240 --> 00:38:57,740 Right? 856 00:38:57,740 --> 00:39:01,320 And so that's the sort of crux of the challenge here, 857 00:39:01,320 --> 00:39:05,670 is to organize my approach to editing these files 858 00:39:05,670 --> 00:39:07,890 in a way that doesn't require me to have 859 00:39:07,890 --> 00:39:11,088 to do this sort of combinatorial jumping all over the place. 860 00:39:11,088 --> 00:39:13,380 And I think it's also the one where there's a sort of-- 861 00:39:13,380 --> 00:39:15,088 like I know Jerry Caine at Stanford talks 862 00:39:15,088 --> 00:39:18,480 a lot about the recursive leap of faith. 863 00:39:18,480 --> 00:39:20,370 Like, somehow dividing your problem 864 00:39:20,370 --> 00:39:22,290 into organized subproblems, that's 865 00:39:22,290 --> 00:39:25,690 really where the challenge lives here. 866 00:39:25,690 --> 00:39:28,990 So if I were a more organized PhD advisor, 867 00:39:28,990 --> 00:39:33,990 the way that I would edit a file, or a clay tablet, 868 00:39:33,990 --> 00:39:37,540 I guess, in this case, would be linearly, 869 00:39:37,540 --> 00:39:39,480 that I might as well do whatever the heck 870 00:39:39,480 --> 00:39:42,960 I'm going to do to line one before I move on the line two. 871 00:39:42,960 --> 00:39:45,202 And at the end of the day, even if I did stuff 872 00:39:45,202 --> 00:39:47,160 in a different order, you can convince yourself 873 00:39:47,160 --> 00:39:48,630 that I could always order it in such a way 874 00:39:48,630 --> 00:39:50,588 that all the edits that I do to the first line, 875 00:39:50,588 --> 00:39:54,920 kind of, happen before lines later in the document, 876 00:39:54,920 --> 00:39:57,980 with the possible exception of this swap thing. 877 00:39:57,980 --> 00:40:00,440 But we'll see that somehow doesn't matter. 878 00:40:00,440 --> 00:40:03,730 And, moreover, if I do an edit, I 879 00:40:03,730 --> 00:40:07,300 might as well do the edit to make things better, right? 880 00:40:07,300 --> 00:40:09,640 There's no reason to start willy-nilly inserting 881 00:40:09,640 --> 00:40:11,680 and removing lines. 882 00:40:11,680 --> 00:40:15,890 I might as well always do an operation that improves stuff. 883 00:40:15,890 --> 00:40:19,656 And so thinking about that sort of logic leads me-- 884 00:40:19,656 --> 00:40:23,260 ta-da-- to a particular way that I might write down 885 00:40:23,260 --> 00:40:26,262 my S, my some problems here, which 886 00:40:26,262 --> 00:40:28,720 is to say that I'm going to think about editing my document 887 00:40:28,720 --> 00:40:31,000 line by line. 888 00:40:31,000 --> 00:40:33,810 So, in other words, once I've dealt with line one, 889 00:40:33,810 --> 00:40:36,330 meaning that I found some way to mess with it 890 00:40:36,330 --> 00:40:39,170 and make it match line one of the other guy, 891 00:40:39,170 --> 00:40:41,570 I'm just going to think about removing it 892 00:40:41,570 --> 00:40:44,190 and then think about the rest of the document. 893 00:40:44,190 --> 00:40:47,210 You start saying, aha, that sentence sounds like recursion. 894 00:40:47,210 --> 00:40:47,930 And that's right. 895 00:40:47,930 --> 00:40:49,620 That's how we're going to solve this problem. 896 00:40:49,620 --> 00:40:50,180 OK? 897 00:40:50,180 --> 00:40:53,033 So, in particular, here's going to be our thing. 898 00:40:53,033 --> 00:40:55,450 I'm going to do a slightly different one in the solution-- 899 00:40:55,450 --> 00:40:57,830 so you guys should all be vigilant-- 900 00:40:57,830 --> 00:41:06,470 which is I'm going to write x ij to be the min work to convert. 901 00:41:11,000 --> 00:41:15,560 I'm not a Python programmer, but hopefully I got this right. 902 00:41:15,560 --> 00:41:18,710 i colon is going to be everything from i 903 00:41:18,710 --> 00:41:20,730 to the end of the file. 904 00:41:20,730 --> 00:41:26,310 So in other words, this is the suffix version of our problem-- 905 00:41:26,310 --> 00:41:36,600 and into B j colon, like that. 906 00:41:36,600 --> 00:41:37,680 OK. 907 00:41:37,680 --> 00:41:39,780 So, in other words, I have a little-- 908 00:41:39,780 --> 00:41:42,570 it's kind of like a video-- like, think about Tetris. 909 00:41:42,570 --> 00:41:44,288 Once you get that full line of blocks, 910 00:41:44,288 --> 00:41:46,080 you can just throw that line of blocks away 911 00:41:46,080 --> 00:41:47,850 and the whole video game moves down. 912 00:41:47,850 --> 00:41:48,990 There's somehow something very similar 913 00:41:48,990 --> 00:41:50,615 going on here, which is the second I've 914 00:41:50,615 --> 00:41:52,710 managed to get a match for line one of document 915 00:41:52,710 --> 00:41:54,810 into line one of the next document, 916 00:41:54,810 --> 00:41:58,230 I'm just going to throw it away and pretend 917 00:41:58,230 --> 00:42:01,500 like I have two documents with one less line in them. 918 00:42:01,500 --> 00:42:05,152 Now, the thing that got me all hung up last night, 919 00:42:05,152 --> 00:42:07,360 my original problem assumes that both of my documents 920 00:42:07,360 --> 00:42:09,600 have the same length. 921 00:42:09,600 --> 00:42:12,840 But here, I'm not making that assumption, right? 922 00:42:12,840 --> 00:42:15,030 And, essentially, what we're going to figure out 923 00:42:15,030 --> 00:42:17,072 is that that actually doesn't matter a whole lot, 924 00:42:17,072 --> 00:42:20,340 that if I end up with one document of length k-- 925 00:42:20,340 --> 00:42:21,750 well, I shouldn't use k-- 926 00:42:21,750 --> 00:42:25,380 one document of length l and another document of length 0, 927 00:42:25,380 --> 00:42:27,850 what's the amount of work that I should do to convert? 928 00:42:27,850 --> 00:42:33,300 Well, l, because my only choice is to insert a bunch of lines 929 00:42:33,300 --> 00:42:36,785 in one document, by the way, or delete a bunch of lines 930 00:42:36,785 --> 00:42:37,410 from the other. 931 00:42:37,410 --> 00:42:38,660 Those are dual to one another. 932 00:42:38,660 --> 00:42:40,290 They're exactly the same. 933 00:42:40,290 --> 00:42:43,050 I'm philosophizing a lot because I'm also convincing myself 934 00:42:43,050 --> 00:42:45,420 that my answer is OK in the process. 935 00:42:45,420 --> 00:42:46,930 OK. 936 00:42:46,930 --> 00:42:49,080 So this is going to be our set subproblems. 937 00:42:49,080 --> 00:42:53,070 And now we have to do the r, right? 938 00:42:53,070 --> 00:42:57,770 We have to relate, something we struggle with in the math 939 00:42:57,770 --> 00:43:00,020 department sometimes. 940 00:43:00,020 --> 00:43:03,230 And, essentially, the way that I went about this 941 00:43:03,230 --> 00:43:05,720 is to just do a billion different cases 942 00:43:05,720 --> 00:43:08,600 of all the possible edits that I could do to line i and line j. 943 00:43:08,600 --> 00:43:10,350 And that's perfectly fine in this problem. 944 00:43:10,350 --> 00:43:11,870 I think the problem is a little slick. 945 00:43:11,870 --> 00:43:13,500 And the way that they're written the solution, 946 00:43:13,500 --> 00:43:15,020 they've convinced themselves that some things are 947 00:43:15,020 --> 00:43:16,743 equivalent to others and removed them. 948 00:43:16,743 --> 00:43:17,660 But you don't have to. 949 00:43:17,660 --> 00:43:19,160 As long as there's a constant number 950 00:43:19,160 --> 00:43:22,610 of cases, your golden Ponyboy. 951 00:43:22,610 --> 00:43:25,770 So, in particular, let's think about some cases. 952 00:43:25,770 --> 00:43:32,040 So first of all, if line i matches line j of my document-- 953 00:43:32,040 --> 00:43:33,650 remember that it's not really line j. 954 00:43:33,650 --> 00:43:35,450 It's like making a document that just 955 00:43:35,450 --> 00:43:37,930 happens to start at line j. 956 00:43:37,930 --> 00:43:39,600 It's like taking scissors. 957 00:43:39,600 --> 00:43:42,170 Well, then I can match them with zero-cost 958 00:43:42,170 --> 00:43:44,600 because the beginnings are in the same place. 959 00:43:44,600 --> 00:43:46,850 And I can move my Tetris came down one, 960 00:43:46,850 --> 00:43:48,752 and that's perfectly fine. 961 00:43:48,752 --> 00:43:50,460 So case one, I think, is the easiest one, 962 00:43:50,460 --> 00:43:58,680 which is if A i equals B j, then I can just 963 00:43:58,680 --> 00:44:00,510 remove that line from both documents 964 00:44:00,510 --> 00:44:02,920 and move forward, in which case-- 965 00:44:02,920 --> 00:44:04,635 I'll use my same goofy notation-- 966 00:44:04,635 --> 00:44:05,760 I'm going to get that x ij. 967 00:44:08,290 --> 00:44:10,340 Well, I'm going to just increment i and j 968 00:44:10,340 --> 00:44:15,560 and keep going, like that. 969 00:44:15,560 --> 00:44:17,380 Cool? 970 00:44:17,380 --> 00:44:20,260 So what's something else I could do? 971 00:44:20,260 --> 00:44:22,040 I could delete a line. 972 00:44:22,040 --> 00:44:23,713 Yeah, so what happens-- 973 00:44:27,270 --> 00:44:28,650 OK. 974 00:44:28,650 --> 00:44:36,210 So case two is delete A i, right? 975 00:44:36,210 --> 00:44:38,498 That's a different thing I can do the line i. 976 00:44:38,498 --> 00:44:39,790 Well, now what do I have to do? 977 00:44:39,790 --> 00:44:41,450 I have a document on the left-hand side, 978 00:44:41,450 --> 00:44:42,450 which is 1 line shorter. 979 00:44:42,450 --> 00:44:44,590 And on the right-hand side, nothing changed. 980 00:44:44,590 --> 00:44:47,920 But deleting a line cost me a dollar. 981 00:44:47,920 --> 00:44:53,020 So, in particular, I have that x ij. 982 00:44:53,020 --> 00:44:53,890 Well, what happens? 983 00:44:53,890 --> 00:45:02,800 Well, I got rid of one line, but I had to pay. 984 00:45:02,800 --> 00:45:03,310 OK. 985 00:45:03,310 --> 00:45:05,740 Let's think about some other things. 986 00:45:05,740 --> 00:45:07,570 You could delete B j. 987 00:45:10,693 --> 00:45:12,360 This case actually isn't in the solution 988 00:45:12,360 --> 00:45:14,745 because it turns out to be unnecessary. 989 00:45:14,745 --> 00:45:16,620 AUDIENCE: Well, we're only allowed to edit A. 990 00:45:16,620 --> 00:45:18,180 JUSTIN SOLOMON: Oh, I'm only allowed to edit A? 991 00:45:18,180 --> 00:45:20,160 Oh, in that case, I don't have to delete B j. 992 00:45:20,160 --> 00:45:22,202 I really didn't read these problems very closely. 993 00:45:22,202 --> 00:45:23,260 That's my bad. 994 00:45:23,260 --> 00:45:24,760 This would have made it much easier. 995 00:45:24,760 --> 00:45:27,770 I really should read these things. 996 00:45:27,770 --> 00:45:30,670 Cool, so that eliminates half of the cases on my notes. 997 00:45:30,670 --> 00:45:31,960 Fabulous. 998 00:45:31,960 --> 00:45:35,430 Incidentally, you could do these things on the other direction 999 00:45:35,430 --> 00:45:38,830 and it really wouldn't change this problem a whole lot. 1000 00:45:38,830 --> 00:45:40,600 Sorry, you know, I have this bad habit 1001 00:45:40,600 --> 00:45:43,030 when I'm reading research papers of reading the research paper I 1002 00:45:43,030 --> 00:45:44,590 wanted to be there instead of the one 1003 00:45:44,590 --> 00:45:46,210 that's actually on the paper. 1004 00:45:46,210 --> 00:45:48,980 And, somehow, it's very similar phenomenon here. 1005 00:45:48,980 --> 00:45:49,480 OK. 1006 00:45:49,480 --> 00:45:49,980 Right. 1007 00:45:49,980 --> 00:45:50,810 So, great. 1008 00:45:50,810 --> 00:45:52,330 So I can only edit document A, which 1009 00:45:52,330 --> 00:45:55,510 makes this probably easier than what I was worried about. 1010 00:45:55,510 --> 00:45:56,110 Fabulous. 1011 00:45:56,110 --> 00:46:00,400 In that case-- ah, bananas. 1012 00:46:00,400 --> 00:46:05,670 With our third case here, well, let's see, 1013 00:46:05,670 --> 00:46:10,140 I could also insert a line. 1014 00:46:10,140 --> 00:46:10,640 Let's see. 1015 00:46:10,640 --> 00:46:12,120 So what ends up happening there? 1016 00:46:12,120 --> 00:46:14,783 So I can only edit document A? 1017 00:46:14,783 --> 00:46:16,700 So that makes my cases different than the ones 1018 00:46:16,700 --> 00:46:17,742 I wrote down on my notes. 1019 00:46:24,506 --> 00:46:25,410 Sorry. 1020 00:46:25,410 --> 00:46:25,910 OK. 1021 00:46:36,270 --> 00:46:36,770 OK. 1022 00:46:36,770 --> 00:46:38,198 So if I insert-- 1023 00:46:38,198 --> 00:46:38,990 let's do this live. 1024 00:46:38,990 --> 00:46:42,551 Yeah, OK, so if I insert a line at line i, 1025 00:46:42,551 --> 00:46:44,930 I might as well make it match B j. 1026 00:46:44,930 --> 00:46:46,430 There's no reason not to. 1027 00:46:46,430 --> 00:46:47,030 Right? 1028 00:46:47,030 --> 00:46:49,980 I might as well kill off one element of B while I'm at it. 1029 00:46:49,980 --> 00:46:50,480 Yeah? 1030 00:46:50,480 --> 00:46:53,520 So if I do that, what ends up happening? 1031 00:46:53,520 --> 00:46:55,520 Well, I still have to match line i. 1032 00:46:55,520 --> 00:46:57,650 I've just, kind of, moved it lower in my file. 1033 00:46:57,650 --> 00:47:01,730 But I've, in essence, killed one line in file B 1034 00:47:01,730 --> 00:47:04,613 by making it match this new line that I inserted. 1035 00:47:04,613 --> 00:47:06,530 In my notes, because I thought I could edit B, 1036 00:47:06,530 --> 00:47:08,720 I said, OK, I can just delete the line in B instead. 1037 00:47:08,720 --> 00:47:11,303 And somehow, logically, that's a little easier to think about. 1038 00:47:11,303 --> 00:47:13,830 But these are exactly dual to one another. 1039 00:47:13,830 --> 00:47:17,540 So, in that case, I have x ij. 1040 00:47:17,540 --> 00:47:19,100 Well, I still have to deal with A i. 1041 00:47:19,100 --> 00:47:20,225 I haven't gotten rid of it. 1042 00:47:20,225 --> 00:47:22,130 But I've matched line j. 1043 00:47:22,130 --> 00:47:27,740 So I paid $1 for inserting a line. 1044 00:47:27,740 --> 00:47:30,890 And now I have that because I've gotten rid 1045 00:47:30,890 --> 00:47:33,978 of a line in the other file. 1046 00:47:33,978 --> 00:47:36,520 If I stopped here, by the way, I would have it at a distance. 1047 00:47:36,520 --> 00:47:40,000 But, unfortunately for me, I have one additional case, 1048 00:47:40,000 --> 00:47:46,420 which is mild irritant, as they say, which is that I can swap. 1049 00:47:49,710 --> 00:47:52,930 First of all, can I always swap? 1050 00:47:52,930 --> 00:47:55,230 I mean, I can, but if I swap two lines 1051 00:47:55,230 --> 00:47:57,730 and they still don't match the lines on the right-hand side, 1052 00:47:57,730 --> 00:47:59,870 I'm kind of hosed, right, because you can convince 1053 00:47:59,870 --> 00:48:01,328 yourself that in the next step, I'm 1054 00:48:01,328 --> 00:48:03,520 going to have to delete something anyway. 1055 00:48:03,520 --> 00:48:04,518 Swapping was free. 1056 00:48:04,518 --> 00:48:07,060 If I swap and delete, that's the same thing as just deleting, 1057 00:48:07,060 --> 00:48:09,160 so it doesn't really matter. 1058 00:48:09,160 --> 00:48:10,630 So, in particular, what that means 1059 00:48:10,630 --> 00:48:13,270 is I might as well only check the swap if it actually 1060 00:48:13,270 --> 00:48:14,080 helps me. 1061 00:48:14,080 --> 00:48:14,830 Yeah? 1062 00:48:14,830 --> 00:48:20,692 So, in other words, if I have A-- 1063 00:48:20,692 --> 00:48:23,240 now you have to be a little bit careful because I'm swapping. 1064 00:48:23,240 --> 00:48:28,030 So if the next guy in A equals B, the current guy in B 1065 00:48:28,030 --> 00:48:36,260 and the current guy in A equals the next guy in B. Well, 1066 00:48:36,260 --> 00:48:39,560 now I can swap this guy and kill off two lines in my files 1067 00:48:39,560 --> 00:48:40,850 while I'm at it, right? 1068 00:48:40,850 --> 00:48:46,190 So, in this case, I get that X ij. 1069 00:48:46,190 --> 00:48:48,050 Well, swapping doesn't cost me anything, 1070 00:48:48,050 --> 00:48:49,560 and I killed off two things. 1071 00:48:49,560 --> 00:48:56,663 So that's the recursion. 1072 00:48:56,663 --> 00:48:58,580 So if I were to write this out on my homework, 1073 00:48:58,580 --> 00:48:59,450 what should I do? 1074 00:48:59,450 --> 00:49:01,610 Well, I shouldn't-- I mean, probably if you use this error 1075 00:49:01,610 --> 00:49:03,260 notation, I don't think it would be a big deal. 1076 00:49:03,260 --> 00:49:04,730 But really, you should add a line 1077 00:49:04,730 --> 00:49:07,010 at the bottom saying that I can choose 1078 00:49:07,010 --> 00:49:08,130 to do any of these things. 1079 00:49:08,130 --> 00:49:09,860 So really, my recursive call is x 1080 00:49:09,860 --> 00:49:14,330 ij gets the min of all of these 1, 1081 00:49:14,330 --> 00:49:17,140 2, 3, 4 expressions that I've written here. 1082 00:49:17,140 --> 00:49:19,113 OK. 1083 00:49:19,113 --> 00:49:21,363 AUDIENCE: What if you have the first condition but not 1084 00:49:21,363 --> 00:49:21,988 the second one? 1085 00:49:21,988 --> 00:49:24,405 JUSTIN SOLOMON: What if I have the first condition but not 1086 00:49:24,405 --> 00:49:25,230 the second one? 1087 00:49:25,230 --> 00:49:28,390 Ah, so that's a great question. 1088 00:49:28,390 --> 00:49:30,460 Yeah, so the question was like, OK, well, 1089 00:49:30,460 --> 00:49:35,820 what if I can match the next line but not the current one. 1090 00:49:35,820 --> 00:49:37,820 Well, there's two different things you could do. 1091 00:49:37,820 --> 00:49:39,653 You could either make another case for that. 1092 00:49:39,653 --> 00:49:40,630 That's perfectly fine. 1093 00:49:40,630 --> 00:49:41,690 In fact, you could do that. 1094 00:49:41,690 --> 00:49:43,480 You could do that I matched the second condition, not 1095 00:49:43,480 --> 00:49:44,488 the first one, whatever. 1096 00:49:44,488 --> 00:49:46,030 You can just enumerate as many things 1097 00:49:46,030 --> 00:49:47,530 you want as long as they're all true 1098 00:49:47,530 --> 00:49:48,820 and there's a constant number. 1099 00:49:48,820 --> 00:49:50,487 Alternatively, you can convince yourself 1100 00:49:50,487 --> 00:49:53,410 that actually is unnecessary here because a different-- 1101 00:49:53,410 --> 00:49:55,850 so that's like swapping. 1102 00:49:55,850 --> 00:49:58,130 But then one of those two lines is still a mismatch, 1103 00:49:58,130 --> 00:49:59,922 so you're going to have to delete something 1104 00:49:59,922 --> 00:50:00,920 in the next step. 1105 00:50:00,920 --> 00:50:03,130 So you might as well just delete first, rather than 1106 00:50:03,130 --> 00:50:05,560 swap and then delete. 1107 00:50:05,560 --> 00:50:07,850 And so that's why that case isn't necessary. 1108 00:50:07,850 --> 00:50:08,350 Yeah? 1109 00:50:08,350 --> 00:50:10,017 AUDIENCE: [INAUDIBLE] in the first case. 1110 00:50:10,017 --> 00:50:11,320 JUSTIN SOLOMON: Exactly. 1111 00:50:11,320 --> 00:50:11,860 Exactly. 1112 00:50:11,860 --> 00:50:13,900 So if you swapped and you killed a line, then, in effect, 1113 00:50:13,900 --> 00:50:15,858 I think it's a combination of case 1 and case 2 1114 00:50:15,858 --> 00:50:18,710 here, if you, kind of, expand your recursion out. 1115 00:50:18,710 --> 00:50:20,710 But if you're having trouble convincing yourself 1116 00:50:20,710 --> 00:50:23,320 of that, that's fine, just add a case here. 1117 00:50:23,320 --> 00:50:25,167 Yeah. 1118 00:50:25,167 --> 00:50:26,000 Any other questions? 1119 00:50:26,000 --> 00:50:28,625 I'm going to ask quickly because this problem makes me nervous. 1120 00:50:28,625 --> 00:50:32,675 AUDIENCE: [INAUDIBLE] 1121 00:50:32,675 --> 00:50:33,550 JUSTIN SOLOMON: Sure. 1122 00:50:33,550 --> 00:50:33,870 OK. 1123 00:50:33,870 --> 00:50:35,912 In the worst case, if we've done something wrong, 1124 00:50:35,912 --> 00:50:39,010 you can certainly add another case here. 1125 00:50:39,010 --> 00:50:40,640 I'll think about it at home. 1126 00:50:40,640 --> 00:50:41,140 OK. 1127 00:50:41,140 --> 00:50:44,202 So since I've managed to pontificate too long, 1128 00:50:44,202 --> 00:50:45,160 let's keep moving here. 1129 00:50:45,160 --> 00:50:47,882 AUDIENCE: Can we swap them if they [INAUDIBLE] match? 1130 00:50:47,882 --> 00:50:49,590 JUSTIN SOLOMON: Oh, you know, the problem 1131 00:50:49,590 --> 00:50:50,910 is it might have been-- 1132 00:50:50,910 --> 00:50:53,050 AUDIENCE: --used in the final file. 1133 00:50:53,050 --> 00:50:55,680 So if you can make swap one match one of them and not 1134 00:50:55,680 --> 00:50:58,803 the other, then that's not OK. 1135 00:50:58,803 --> 00:51:00,970 JUSTIN SOLOMON: Yeah, because at the end of the day, 1136 00:51:00,970 --> 00:51:02,010 the files have to agree. 1137 00:51:02,010 --> 00:51:03,810 Like, you have to match B to A. 1138 00:51:03,810 --> 00:51:05,310 AUDIENCE: Swap and delete is cheaper 1139 00:51:05,310 --> 00:51:07,573 than doing two deletes and two inserts. 1140 00:51:07,573 --> 00:51:10,380 AUDIENCE: No, no, no, but the swap and delete 1141 00:51:10,380 --> 00:51:12,725 is illegal because you have to use both ones. 1142 00:51:12,725 --> 00:51:14,100 That's a condition in the pocket. 1143 00:51:14,100 --> 00:51:15,350 JUSTIN SOLOMON: Oh, I'm sorry. 1144 00:51:15,350 --> 00:51:16,370 That's a better answer. 1145 00:51:16,370 --> 00:51:18,037 So Jason points out that if I swap, then 1146 00:51:18,037 --> 00:51:21,120 I can't delete it because the way the problem is written. 1147 00:51:21,120 --> 00:51:23,350 So that effectively removes this case. 1148 00:51:23,350 --> 00:51:24,330 Otherwise, I think-- 1149 00:51:24,330 --> 00:51:25,320 I guess Erik is-- 1150 00:51:25,320 --> 00:51:26,460 AUDIENCE: Actually, there are two important conditions-- 1151 00:51:26,460 --> 00:51:27,150 JUSTIN SOLOMON: Oh, sorry. 1152 00:51:27,150 --> 00:51:28,620 I've managed to totally botch this, 1153 00:51:28,620 --> 00:51:30,960 which is totally unsurprising. 1154 00:51:30,960 --> 00:51:31,820 Yeah. 1155 00:51:31,820 --> 00:51:34,590 So I think the problem also states that if you swap, 1156 00:51:34,590 --> 00:51:37,460 the swap has to be useful. 1157 00:51:37,460 --> 00:51:39,390 And that's why this additional case 1158 00:51:39,390 --> 00:51:42,150 that Erik is asking about where you swap and then you 1159 00:51:42,150 --> 00:51:45,600 match one line but not the other is unnecessary. 1160 00:51:45,600 --> 00:51:48,058 You might be able to relax that by just adding a case here, 1161 00:51:48,058 --> 00:51:49,600 but since the problem doesn't ask it, 1162 00:51:49,600 --> 00:51:50,920 I'm not going to think about. 1163 00:51:50,920 --> 00:51:51,670 OK. 1164 00:51:51,670 --> 00:51:52,815 Right. 1165 00:51:52,815 --> 00:51:54,690 So, under all the assumptions of this problem 1166 00:51:54,690 --> 00:51:56,857 that I didn't read but are very important to solving 1167 00:51:56,857 --> 00:51:59,070 this problem correctly, I believe 1168 00:51:59,070 --> 00:52:03,940 we really have written down all of our cases here. 1169 00:52:03,940 --> 00:52:04,440 OK. 1170 00:52:04,440 --> 00:52:09,210 So let's continue with our SRTBOT paradigm. 1171 00:52:09,210 --> 00:52:12,540 So now we have all of our recursion. 1172 00:52:12,540 --> 00:52:17,010 The topological order here is a little bit trickier than normal 1173 00:52:17,010 --> 00:52:19,230 because now you've got a two-dimensional array, 1174 00:52:19,230 --> 00:52:22,000 but it follows a pattern that's pretty typical here, 1175 00:52:22,000 --> 00:52:31,740 which is that x ij only depends on other x ij's 1176 00:52:31,740 --> 00:52:38,150 with higher i plus j. 1177 00:52:38,150 --> 00:52:41,030 So I think about my graph of subproblems. 1178 00:52:41,030 --> 00:52:43,370 If I wrote this in a 2D matrix, it always, kind of, 1179 00:52:43,370 --> 00:52:45,590 points down and to the right, maybe, 1180 00:52:45,590 --> 00:52:47,870 which is what's making it acyclic. 1181 00:52:47,870 --> 00:52:49,790 This is a very typical pattern in these sort 1182 00:52:49,790 --> 00:52:52,710 of two-dimensional dynamic programming problem. 1183 00:52:52,710 --> 00:52:53,210 All right. 1184 00:52:53,210 --> 00:52:55,310 So let's see here, SRTBOT. 1185 00:52:55,310 --> 00:52:57,993 So we need our base case. 1186 00:52:57,993 --> 00:52:59,660 This isn't too bad because, essentially, 1187 00:52:59,660 --> 00:53:02,600 when you have boring documents, they're 1188 00:53:02,600 --> 00:53:05,500 very easy to match to one another. 1189 00:53:05,500 --> 00:53:12,735 So, in particular, for any i, if I'm at line n plus 1-- 1190 00:53:12,735 --> 00:53:15,110 in other words, I have a blank document that I'm matching 1191 00:53:15,110 --> 00:53:16,730 to document i-- 1192 00:53:16,730 --> 00:53:20,140 well, how much work do I have to do? 1193 00:53:20,140 --> 00:53:21,640 You have to be a little bit careful. 1194 00:53:21,640 --> 00:53:24,120 This is where the suffix version of this problem is a little bit 1195 00:53:24,120 --> 00:53:25,750 more annoying than the prefix one-- 1196 00:53:25,750 --> 00:53:29,070 or have I managed to swap those backward again-- 1197 00:53:29,070 --> 00:53:32,010 that, in particular, the remaining number of lines 1198 00:53:32,010 --> 00:53:38,140 looks like n plus 1 minus i, which is 1199 00:53:38,140 --> 00:53:39,390 different than in the problem. 1200 00:53:39,390 --> 00:53:40,848 It's just i because they're working 1201 00:53:40,848 --> 00:53:43,740 in the other direction-- in the solution, rather. 1202 00:53:43,740 --> 00:53:46,570 And similarly, you need a second case for those two here, right? 1203 00:53:46,570 --> 00:53:58,248 So you have x n plus 1 j is going to be n plus 1 minus j. 1204 00:53:58,248 --> 00:53:59,730 Cool. 1205 00:53:59,730 --> 00:54:01,050 OK. 1206 00:54:01,050 --> 00:54:03,620 So we're going to continue with SRTBOT here. 1207 00:54:06,232 --> 00:54:07,440 So what is our original case? 1208 00:54:07,440 --> 00:54:13,530 Kind of by definition it's x 1, 1 or 0 0, 1209 00:54:13,530 --> 00:54:15,780 depending on how you index. 1210 00:54:15,780 --> 00:54:19,450 And then, finally, what's our runtime? 1211 00:54:19,450 --> 00:54:27,180 Well, let's see, there's n plus 1 squared subproblems, 1212 00:54:27,180 --> 00:54:31,050 and, of course, that's equal to order n squared. 1213 00:54:31,050 --> 00:54:34,530 The subproblems are just a constant amount of work, 1214 00:54:34,530 --> 00:54:38,780 so they're each with constant work. 1215 00:54:41,750 --> 00:54:46,210 So our entire runtime is order n squared. 1216 00:54:46,210 --> 00:54:49,900 And hopefully by watching me be confused in front of you 1217 00:54:49,900 --> 00:54:51,550 and think through this problem, you too 1218 00:54:51,550 --> 00:54:55,000 will see how the problem solving procedure 1219 00:54:55,000 --> 00:54:57,920 can happen in your own disorganized brains. 1220 00:54:57,920 --> 00:54:58,420 OK. 1221 00:54:58,420 --> 00:55:03,780 So that concludes our treatment of this problem here. 1222 00:55:03,780 --> 00:55:05,300 That, I think, is the hardest one. 1223 00:55:05,300 --> 00:55:08,820 So the other two, thankfully, are much easier to think about, 1224 00:55:08,820 --> 00:55:10,327 I thought. 1225 00:55:10,327 --> 00:55:11,660 But I never liked edit distance. 1226 00:55:11,660 --> 00:55:13,961 I remember seeing that and undergrad algorithms getting 1227 00:55:13,961 --> 00:55:14,670 confused. 1228 00:55:14,670 --> 00:55:15,190 OK. 1229 00:55:15,190 --> 00:55:22,800 So the next problem, problem 3 here, deals with Saggy Mimsin. 1230 00:55:22,800 --> 00:55:25,260 And she has a bunch of block, and she 1231 00:55:25,260 --> 00:55:28,420 wants to stack them on top of each other, as one does. 1232 00:55:28,420 --> 00:55:31,740 And as a young structural engineer, 1233 00:55:31,740 --> 00:55:34,790 she has a few criteria on her problem. 1234 00:55:37,850 --> 00:55:40,110 Let me go to the right page in my notes here. 1235 00:55:44,190 --> 00:55:46,140 Right. 1236 00:55:46,140 --> 00:55:48,090 So this is problem 3. 1237 00:55:48,090 --> 00:55:59,040 So we have that block bi has size that looks like width wi 1238 00:55:59,040 --> 00:56:03,950 by height hi by length li. 1239 00:56:03,950 --> 00:56:06,090 I remember getting confused in elementary school 1240 00:56:06,090 --> 00:56:08,580 about the difference between width and length all the time. 1241 00:56:08,580 --> 00:56:10,320 To me, those always sounded the same. 1242 00:56:10,320 --> 00:56:12,112 But it doesn't really matter, because she's 1243 00:56:12,112 --> 00:56:16,740 happy to rotate her cubes any way that she pleases. 1244 00:56:16,740 --> 00:56:19,680 There's a key detail which I did remember to actually read 1245 00:56:19,680 --> 00:56:24,450 in this problem, which is that she has at least three 1246 00:56:24,450 --> 00:56:31,333 of each type, where type here means that I can permute 1247 00:56:31,333 --> 00:56:32,750 these three numbers any way that I 1248 00:56:32,750 --> 00:56:35,180 want because that's the same as just rotating a block. 1249 00:56:35,180 --> 00:56:38,240 But any time she has one block that's like 1 by 2 by 3, 1250 00:56:38,240 --> 00:56:41,200 she has at least two more in her bag somewhere. 1251 00:56:41,200 --> 00:56:41,746 OK. 1252 00:56:41,746 --> 00:56:44,240 APPLE WATCH: It's 6. 1253 00:56:44,240 --> 00:56:46,940 JUSTIN SOLOMON: Oh, 1 times 2 times 3 is equal to 6. 1254 00:56:46,940 --> 00:56:48,900 Thank you, Apple Watch. 1255 00:56:48,900 --> 00:56:49,560 OK. 1256 00:56:49,560 --> 00:56:51,490 So that's odd. 1257 00:56:51,490 --> 00:56:53,060 So she can orient her block any way 1258 00:56:53,060 --> 00:56:58,010 that she wants, meaning she can rotate it in any fashion 1259 00:56:58,010 --> 00:56:59,150 that she'd like. 1260 00:56:59,150 --> 00:57:02,930 And so what we're trying to do, what we want 1261 00:57:02,930 --> 00:57:10,380 is the max height where she's stacking her n blocks. 1262 00:57:10,380 --> 00:57:15,720 I suppose I should say they're n blocks. 1263 00:57:15,720 --> 00:57:18,210 So she wants the max height that she can achieve. 1264 00:57:18,210 --> 00:57:22,120 But just to be kind of annoying, or because, again, 1265 00:57:22,120 --> 00:57:24,120 she's very concerned with structural stability-- 1266 00:57:24,120 --> 00:57:25,680 she lives in an earthquake zone-- 1267 00:57:25,680 --> 00:57:29,670 she would like with the condition 1268 00:57:29,670 --> 00:57:33,360 that each block is strictly supported on the block 1269 00:57:33,360 --> 00:57:34,000 beneath it. 1270 00:57:34,000 --> 00:57:34,500 Right? 1271 00:57:40,350 --> 00:57:44,580 So in other words, if this is the base of one block, 1272 00:57:44,580 --> 00:57:46,980 then the next block that's stacked on top of it 1273 00:57:46,980 --> 00:57:51,950 has to be strictly contained within the block below it. 1274 00:57:51,950 --> 00:57:52,980 Right? 1275 00:57:52,980 --> 00:57:54,615 So does the problem make sense? 1276 00:57:54,615 --> 00:57:56,668 Have I omitted any critical details? 1277 00:57:56,668 --> 00:57:57,960 I don't think I have this time. 1278 00:57:57,960 --> 00:57:59,618 This one's a little easier. 1279 00:57:59,618 --> 00:58:01,748 AUDIENCE: [INAUDIBLE] 1280 00:58:01,748 --> 00:58:02,790 JUSTIN SOLOMON: Oh, yeah. 1281 00:58:02,790 --> 00:58:04,123 And she can't do anything crazy. 1282 00:58:04,123 --> 00:58:06,660 She can't do a weird, like, balance it 1283 00:58:06,660 --> 00:58:09,000 on this edge kind of thing, which-- 1284 00:58:09,000 --> 00:58:12,802 Erik is absolutely right-- could actually give her a taller 1285 00:58:12,802 --> 00:58:14,760 tower than you could get if you're only allowed 1286 00:58:14,760 --> 00:58:16,320 to rotate blocks 90 degrees. 1287 00:58:16,320 --> 00:58:18,900 I don't think the problem states that explicitly, but this 1288 00:58:18,900 --> 00:58:21,900 isn't a trigonometry class, so I think we're in good shape. 1289 00:58:21,900 --> 00:58:23,710 OK. 1290 00:58:23,710 --> 00:58:24,210 Right. 1291 00:58:24,210 --> 00:58:27,337 So that's our basic problem here. 1292 00:58:27,337 --> 00:58:28,920 And this is one of these problems that 1293 00:58:28,920 --> 00:58:30,795 is going to be a dynamic programming problem, 1294 00:58:30,795 --> 00:58:33,180 but, again, similar to many of the things that we 1295 00:58:33,180 --> 00:58:36,000 saw in lecture, is not totally obvious how, 1296 00:58:36,000 --> 00:58:39,720 because somehow she has this big, disorganized bag 1297 00:58:39,720 --> 00:58:40,440 of blocks. 1298 00:58:40,440 --> 00:58:41,880 You could imagine a universe where 1299 00:58:41,880 --> 00:58:45,155 there's 2 to the n different things she could do, right? 1300 00:58:45,155 --> 00:58:46,530 For every single block, she could 1301 00:58:46,530 --> 00:58:48,747 decide whether or not to put it in her stack, 1302 00:58:48,747 --> 00:58:50,580 and then she has to do a bunch of other work 1303 00:58:50,580 --> 00:58:52,950 to verify whether she can stack them 1304 00:58:52,950 --> 00:58:56,410 while supporting the strict support condition or not. 1305 00:58:56,410 --> 00:58:59,200 So, initially, that seems kind of annoying. 1306 00:58:59,200 --> 00:59:01,137 So what we have to do, which, again, 1307 00:59:01,137 --> 00:59:02,970 is pretty common to a lot of these problems, 1308 00:59:02,970 --> 00:59:05,520 is place some order on it. 1309 00:59:05,520 --> 00:59:07,300 I mean that both in the entropy sense, 1310 00:59:07,300 --> 00:59:09,930 and also, like, literally, were going to order stuff. 1311 00:59:09,930 --> 00:59:12,420 And, in particular, we'll see that this problem has 1312 00:59:12,420 --> 00:59:14,610 a lot in common with that longest 1313 00:59:14,610 --> 00:59:17,880 common subsequence problem that we saw in lecture-- increasing 1314 00:59:17,880 --> 00:59:20,670 subsequence, sorry. 1315 00:59:20,670 --> 00:59:21,750 Right. 1316 00:59:21,750 --> 00:59:26,860 So here's some observations about our problem 1317 00:59:26,860 --> 00:59:28,350 which are going to help. 1318 00:59:28,350 --> 00:59:33,260 First of all, when we stack our blocks, 1319 00:59:33,260 --> 00:59:36,860 we might as well always align the shorter side of the block 1320 00:59:36,860 --> 00:59:40,470 on top to the shorter side of the block underneath it. 1321 00:59:40,470 --> 00:59:40,970 Right? 1322 00:59:43,598 --> 00:59:45,140 Let me draw a picture of what I mean. 1323 00:59:50,900 --> 00:59:52,645 So let's say I have a really-- 1324 00:59:52,645 --> 00:59:54,920 a block whose base kind of looks like that 1325 00:59:54,920 --> 00:59:58,300 and then another block which is also rectangular 1326 00:59:58,300 --> 01:00:01,390 that I sit on top of it like that. 1327 01:00:01,390 --> 01:00:04,748 Then notice I could-- so in this case, the shorter edge of one 1328 01:00:04,748 --> 01:00:06,790 block is aligned to the longer edge of the other. 1329 01:00:06,790 --> 01:00:09,640 Notice I can rotate it 90 degrees and it 1330 01:00:09,640 --> 01:00:11,780 still supports on one another. 1331 01:00:11,780 --> 01:00:13,240 So there's never a case-- 1332 01:00:13,240 --> 01:00:16,030 you convince yourself with just a few inequalities-- 1333 01:00:16,030 --> 01:00:18,640 where I don't, kind of, always put the long side parallel 1334 01:00:18,640 --> 01:00:21,040 to the long side of the guy underneath and the short side 1335 01:00:21,040 --> 01:00:22,740 parallel to the short guy underneath it. 1336 01:00:22,740 --> 01:00:24,570 Does that makes sense? 1337 01:00:24,570 --> 01:00:25,070 Cool. 1338 01:00:25,070 --> 01:00:26,640 So that's observation one. 1339 01:00:29,990 --> 01:00:33,350 Observation two, can they ever-- like, 1340 01:00:33,350 --> 01:00:36,650 let's say that Maggie actually-- sorry, 1341 01:00:36,650 --> 01:00:41,000 Saggy actually had not just three blocks of a type, 1342 01:00:41,000 --> 01:00:43,020 but like 25. 1343 01:00:43,020 --> 01:00:46,670 So she's just has hella blocks. 1344 01:00:46,670 --> 01:00:49,110 My question is does it matter. 1345 01:00:49,110 --> 01:00:54,978 The answer is no because this word here is really critical, 1346 01:00:54,978 --> 01:00:56,520 which is that there's strict support. 1347 01:00:56,520 --> 01:00:59,880 So your block only has so many faces. 1348 01:00:59,880 --> 01:01:03,330 And, in fact, by observation one, 1349 01:01:03,330 --> 01:01:07,230 really all that matters is which of the three types of faces 1350 01:01:07,230 --> 01:01:11,080 is sitting on top because we can just always rotate it. 1351 01:01:11,080 --> 01:01:17,400 So there's three configurations of every block, so, at most, 1352 01:01:17,400 --> 01:01:20,380 can any one configuration appear more than one time? 1353 01:01:20,380 --> 01:01:22,530 No, because of the strict support condition. 1354 01:01:22,530 --> 01:01:23,030 Right? 1355 01:01:23,030 --> 01:01:24,738 Otherwise, the rectangles would match up, 1356 01:01:24,738 --> 01:01:27,570 and that's against the rules. 1357 01:01:27,570 --> 01:01:32,470 So, in particular-- oops, the number after two is-- 1358 01:01:32,470 --> 01:01:37,280 the number after 1 is 2, which looks like that. 1359 01:01:37,280 --> 01:01:38,960 OK. 1360 01:01:38,960 --> 01:01:39,460 Right. 1361 01:01:39,460 --> 01:01:43,430 So, in particular, there are only three orientations. 1362 01:01:47,530 --> 01:01:49,630 This is just which of the three edges of the block 1363 01:01:49,630 --> 01:01:52,810 is the one that's going away from the floor, the normal 1364 01:01:52,810 --> 01:01:54,130 to the ground. 1365 01:01:54,130 --> 01:02:01,810 And moreover, each can appear less than or equal to 1 time. 1366 01:02:01,810 --> 01:02:05,210 That's good because it limits the size of our problem. 1367 01:02:05,210 --> 01:02:13,840 And, finally-- oops, I collapsed two of the cases in my notes 1368 01:02:13,840 --> 01:02:15,100 into one case here. 1369 01:02:15,100 --> 01:02:16,363 But that's OK. 1370 01:02:16,363 --> 01:02:18,280 And, in fact, notice that the problem tells us 1371 01:02:18,280 --> 01:02:20,210 that she has at least three of each type. 1372 01:02:20,210 --> 01:02:23,960 So, in a sense, if the problem-- 1373 01:02:23,960 --> 01:02:26,870 if you observe one of a block you might as well just 1374 01:02:26,870 --> 01:02:28,760 throw away the rest because you know that you 1375 01:02:28,760 --> 01:02:30,230 can use it at most three times. 1376 01:02:30,230 --> 01:02:31,652 And she has three of that block. 1377 01:02:31,652 --> 01:02:33,860 We can't use it more than three times, so in a sense, 1378 01:02:33,860 --> 01:02:36,200 that's just superfluous information. 1379 01:02:36,200 --> 01:02:37,420 OK. 1380 01:02:37,420 --> 01:02:37,920 Right. 1381 01:02:37,920 --> 01:02:42,620 So this allows us to put a little bit of order 1382 01:02:42,620 --> 01:02:45,290 here, because notice that when I look at the stack of blocks 1383 01:02:45,290 --> 01:02:46,790 here, what do we know? 1384 01:02:46,790 --> 01:02:49,940 If I look at the length of the long side 1385 01:02:49,940 --> 01:02:54,050 and the length of the short side in the plane of the ground, 1386 01:02:54,050 --> 01:02:57,780 those numbers have to decrease on every level of my block. 1387 01:02:57,780 --> 01:02:58,780 They can never increase. 1388 01:02:58,780 --> 01:03:00,738 That's what the strict support conditions says, 1389 01:03:00,738 --> 01:03:03,350 combined with observation one, actually, even 1390 01:03:03,350 --> 01:03:07,345 without observation one, which is good news, right? 1391 01:03:07,345 --> 01:03:09,470 So this is what's going to allow us to impose order 1392 01:03:09,470 --> 01:03:12,290 on our problem, namely, that we can sort by the edge lengths 1393 01:03:12,290 --> 01:03:14,670 because we know that we have this support condition. 1394 01:03:14,670 --> 01:03:15,170 OK. 1395 01:03:15,170 --> 01:03:18,015 So let's fill in some details of our algorithm. 1396 01:03:20,550 --> 01:03:21,050 OK. 1397 01:03:26,310 --> 01:03:30,090 So originally-- already we can see that our list of blocks 1398 01:03:30,090 --> 01:03:32,000 is kind of useless because the width, length, 1399 01:03:32,000 --> 01:03:36,150 and values are sorted in ways that don't matter. 1400 01:03:36,150 --> 01:03:39,030 Moreover, if we have more than three of a given block, 1401 01:03:39,030 --> 01:03:42,130 that's somehow not super useful. 1402 01:03:42,130 --> 01:03:47,500 So, instead of that, without loss of generality, 1403 01:03:47,500 --> 01:03:48,310 let's assume-- 1404 01:03:48,310 --> 01:03:56,238 so WLOG here-- we can always take our block and assume-- 1405 01:03:56,238 --> 01:03:58,530 I'm going to do this slightly different from my notes-- 1406 01:03:58,530 --> 01:04:06,553 that the width is less than or equal to the height is less 1407 01:04:06,553 --> 01:04:07,720 than or equal to the length. 1408 01:04:07,720 --> 01:04:08,220 OK. 1409 01:04:08,220 --> 01:04:10,570 So every block, if this isn't the case, 1410 01:04:10,570 --> 01:04:12,460 I could go down my array of blocks and sort. 1411 01:04:12,460 --> 01:04:15,700 And sorting a list of three numbers is constant time. 1412 01:04:15,700 --> 01:04:17,800 OK? 1413 01:04:17,800 --> 01:04:18,820 Right. 1414 01:04:18,820 --> 01:04:21,100 So what does this allow me to do? 1415 01:04:21,100 --> 01:04:24,670 Well, I'm going to say that a block type actually 1416 01:04:24,670 --> 01:04:28,450 is an ordered set where the third number is going 1417 01:04:28,450 --> 01:04:30,710 to be the axis that points up. 1418 01:04:30,710 --> 01:04:32,210 And the reason to do that is that we 1419 01:04:32,210 --> 01:04:34,160 know that we can never use that more than once 1420 01:04:34,160 --> 01:04:35,600 for any type of a block. 1421 01:04:35,600 --> 01:04:36,260 Yeah? 1422 01:04:36,260 --> 01:04:47,360 So now I'm going to make a new list of blocks with a capital B 1423 01:04:47,360 --> 01:04:50,390 because I like blocks. 1424 01:04:50,390 --> 01:04:52,590 And it's going to look like the following. 1425 01:04:52,590 --> 01:04:57,673 So if width-- so if w is less than h is less than l, 1426 01:04:57,673 --> 01:04:59,090 then I'm going to take every block 1427 01:04:59,090 --> 01:05:02,488 and duplicate it three times. 1428 01:05:02,488 --> 01:05:04,780 Notice that I might end up with a list with, like, nine 1429 01:05:04,780 --> 01:05:09,100 times of every block, but we'll fix that later. 1430 01:05:09,100 --> 01:05:09,610 Right. 1431 01:05:09,610 --> 01:05:12,670 And it's going to look like the following, which 1432 01:05:12,670 --> 01:05:19,270 is that, OK, I'm going to have wi, hi, li. 1433 01:05:19,270 --> 01:05:22,000 This is like describing a way to stack my block because it's 1434 01:05:22,000 --> 01:05:25,240 saying this is the short side, this is the long side, 1435 01:05:25,240 --> 01:05:28,210 this is the vertical side. 1436 01:05:28,210 --> 01:05:30,730 And there are three cases where any one of these guys 1437 01:05:30,730 --> 01:05:31,810 can be the vertical side. 1438 01:05:31,810 --> 01:05:33,080 So there's one. 1439 01:05:33,080 --> 01:05:36,370 Let's say that the h is the vertical side, 1440 01:05:36,370 --> 01:05:38,380 then w has to go before l. 1441 01:05:38,380 --> 01:05:45,010 So it would be wi, li, hi, and a third one 1442 01:05:45,010 --> 01:05:48,010 where the third guy is w. 1443 01:05:48,010 --> 01:05:52,420 H is less than l, so it would be hi, li, wi. 1444 01:05:52,420 --> 01:05:53,920 And those are all the different ways 1445 01:05:53,920 --> 01:05:57,730 that I can, sort of, orient these blocks in my stacking, 1446 01:05:57,730 --> 01:06:02,710 assuming that I impose condition one for convenience here. 1447 01:06:02,710 --> 01:06:03,737 OK. 1448 01:06:03,737 --> 01:06:05,320 I'm going to make a new list of blocks 1449 01:06:05,320 --> 01:06:07,507 where I take every block in my original set 1450 01:06:07,507 --> 01:06:09,340 and I just duplicate it three times this way 1451 01:06:09,340 --> 01:06:12,730 after I sort its coordinates. 1452 01:06:12,730 --> 01:06:14,655 And now, well, what do I need to do? 1453 01:06:14,655 --> 01:06:16,780 For one thing, this thing may have too many blocks. 1454 01:06:16,780 --> 01:06:19,072 I might have a block that's repeated more than one time 1455 01:06:19,072 --> 01:06:20,198 and I can't do that. 1456 01:06:20,198 --> 01:06:22,240 And moreover, it's going to be convenient to have 1457 01:06:22,240 --> 01:06:25,090 this sorted because I've got to stack these guys eventually. 1458 01:06:25,090 --> 01:06:25,810 Yeah? 1459 01:06:25,810 --> 01:06:30,670 So I'm going to sort that list. 1460 01:06:30,670 --> 01:06:31,960 And I want to do it-- 1461 01:06:31,960 --> 01:06:34,790 I can never say this word-- lexicographically, 1462 01:06:34,790 --> 01:06:37,630 meaning that I'm going sort out the first coordinate, and then 1463 01:06:37,630 --> 01:06:45,410 the second and the third lexicographically. 1464 01:06:45,410 --> 01:06:49,190 Notice this length is 3 n if I had n blocks to start with. 1465 01:06:49,190 --> 01:06:54,830 So this entire thing takes order n log n time, which 1466 01:06:54,830 --> 01:06:57,570 is important to account for. 1467 01:06:57,570 --> 01:06:59,210 And then I can remove duplicates. 1468 01:07:03,072 --> 01:07:04,530 I'll let you guys convince yourself 1469 01:07:04,530 --> 01:07:06,510 you can do this in order n time. 1470 01:07:06,510 --> 01:07:08,970 An easier way would've been making second array and just 1471 01:07:08,970 --> 01:07:09,570 kind of move-- 1472 01:07:09,570 --> 01:07:11,520 and only add stuff when you didn't 1473 01:07:11,520 --> 01:07:13,410 see the same thing before. 1474 01:07:13,410 --> 01:07:14,430 OK. 1475 01:07:14,430 --> 01:07:18,030 And, finally, now these are ordered in a really nice way 1476 01:07:18,030 --> 01:07:20,970 because I can stack my blocks, but only 1477 01:07:20,970 --> 01:07:22,620 ever looking to the right in my sorted 1478 01:07:22,620 --> 01:07:28,880 list, assuming that I'm stacking from the top of my tower down, 1479 01:07:28,880 --> 01:07:33,050 which is, I think, sort of what's going on in this thing. 1480 01:07:33,050 --> 01:07:33,590 OK. 1481 01:07:33,590 --> 01:07:37,080 So now, finally, we can do our SRTBOT. 1482 01:07:37,080 --> 01:07:40,092 And I might do S and R and T and then allow you 1483 01:07:40,092 --> 01:07:42,050 guys to think about the rest because, as usual, 1484 01:07:42,050 --> 01:07:43,680 I'm talking too much. 1485 01:07:43,680 --> 01:07:44,180 OK. 1486 01:07:44,180 --> 01:07:49,580 So now this is starting to look like a subsequence problem 1487 01:07:49,580 --> 01:07:52,460 because, essentially, when I stuck my blocks, if I 1488 01:07:52,460 --> 01:07:54,140 use this block here-- 1489 01:07:54,140 --> 01:07:57,560 again, if I'm stacking from my tower from the top down-- 1490 01:07:57,560 --> 01:08:00,200 all the blocks that can sit underneath this one 1491 01:08:00,200 --> 01:08:03,680 have to be further to the right in my array because of the way 1492 01:08:03,680 --> 01:08:06,190 that I sorted. 1493 01:08:06,190 --> 01:08:08,740 Now, that doesn't mean that I can put anything 1494 01:08:08,740 --> 01:08:10,510 on the right underneath this guy, 1495 01:08:10,510 --> 01:08:12,640 but it does mean that I know nothing to the left 1496 01:08:12,640 --> 01:08:13,780 can go underneath this guy. 1497 01:08:13,780 --> 01:08:15,460 That's the way to think about it. 1498 01:08:15,460 --> 01:08:16,120 OK. 1499 01:08:16,120 --> 01:08:18,220 So it is going to be SRTBOT. 1500 01:08:18,220 --> 01:08:23,439 So S, what I'm going to say is that x i here 1501 01:08:23,439 --> 01:08:27,700 is equal to the maximum height of my tower, and I'm going to-- 1502 01:08:27,700 --> 01:08:29,140 taking a little bit of inspiration 1503 01:08:29,140 --> 01:08:32,350 from our subsequence problem that we've already seen, 1504 01:08:32,350 --> 01:08:34,720 I'm going to force myself to use block i. 1505 01:08:34,720 --> 01:08:36,105 We'll see if that's convenient. 1506 01:08:46,310 --> 01:08:54,729 i and possibly-- just for fun, maybe we'll 1507 01:08:54,729 --> 01:08:58,460 do the prefix version of this problem this time. 1508 01:08:58,460 --> 01:09:04,310 So now I can use any of the previous blocks. 1509 01:09:04,310 --> 01:09:06,800 So I can use the first i blocks to make a tower, 1510 01:09:06,800 --> 01:09:08,547 but I'm forced to use block i. 1511 01:09:08,547 --> 01:09:10,380 By the way, from now on, when I use indices, 1512 01:09:10,380 --> 01:09:12,290 it's into this sorted array. 1513 01:09:12,290 --> 01:09:14,840 OK. 1514 01:09:14,840 --> 01:09:15,740 So this is a problem. 1515 01:09:15,740 --> 01:09:18,260 Obviously, if I could solve for x, 1516 01:09:18,260 --> 01:09:20,600 I would be done, because I could get the maximum height 1517 01:09:20,600 --> 01:09:23,330 by just iterating over all the x's and choosing the biggest 1518 01:09:23,330 --> 01:09:25,770 possible value here. 1519 01:09:25,770 --> 01:09:27,979 And the question is, how do I do this recursively? 1520 01:09:32,950 --> 01:09:33,450 OK. 1521 01:09:33,450 --> 01:09:37,600 So here's our recursive step. 1522 01:09:37,600 --> 01:09:42,029 So let's say that I use block i, well, 1523 01:09:42,029 --> 01:09:43,830 because we know we have to. 1524 01:09:43,830 --> 01:09:44,760 Right? 1525 01:09:44,760 --> 01:09:49,140 So, in particular, we have-- 1526 01:09:49,140 --> 01:09:51,779 now I'm seeing why they didn't use this notation 1527 01:09:51,779 --> 01:09:53,130 in their answer, but that's OK. 1528 01:10:00,370 --> 01:10:03,010 Let's use another letter to refer to the third coordinate. 1529 01:10:06,413 --> 01:10:08,080 AUDIENCE: v i for vertical [INAUDIBLE].. 1530 01:10:08,080 --> 01:10:09,700 JUSTIN SOLOMON: Yeah, let's say v i is always 1531 01:10:09,700 --> 01:10:10,210 the third coordinate. 1532 01:10:10,210 --> 01:10:11,620 We've already used w, h, and l, and I'm 1533 01:10:11,620 --> 01:10:13,210 afraid if I reuse them after sorting, 1534 01:10:13,210 --> 01:10:14,980 it's going to confuse people. 1535 01:10:14,980 --> 01:10:22,030 So v i is the third coordinate of the i-th element 1536 01:10:22,030 --> 01:10:23,920 of my sorted array. 1537 01:10:23,920 --> 01:10:26,560 That's fine, OK. 1538 01:10:26,560 --> 01:10:31,600 Right, so what is my height if I use x i here? 1539 01:10:31,600 --> 01:10:34,155 Well, I get some height from vi. 1540 01:10:34,155 --> 01:10:35,780 And in addition to that, I get whatever 1541 01:10:35,780 --> 01:10:39,220 I stack underneath that guy. 1542 01:10:39,220 --> 01:10:43,652 So, in particular, I get that xi. 1543 01:10:43,652 --> 01:10:45,110 Well, I get the height of the block 1544 01:10:45,110 --> 01:10:47,390 that I just decided to use. 1545 01:10:47,390 --> 01:10:50,930 And now, what are all my cases? 1546 01:10:50,930 --> 01:10:53,120 Well, I could decide to do nothing else, 1547 01:10:53,120 --> 01:10:55,110 like, just not use any other blocks. 1548 01:10:55,110 --> 01:10:57,740 That gives me a height of 0. 1549 01:10:57,740 --> 01:11:02,940 Or, well, let's see here. 1550 01:11:02,940 --> 01:11:05,100 I could use the x's, but I have to be careful 1551 01:11:05,100 --> 01:11:07,140 that I can actually stack them. 1552 01:11:07,140 --> 01:11:12,225 So, in particular, well, I need-- 1553 01:11:15,330 --> 01:11:20,220 yeah, I can take an x j value, but I've 1554 01:11:20,220 --> 01:11:22,500 got to be careful that I can stick it underneath. 1555 01:11:22,500 --> 01:11:26,710 So, in particular, what do we know? 1556 01:11:26,710 --> 01:11:34,410 Well, I can do anything from 1 to i minus 1 1557 01:11:34,410 --> 01:11:37,800 because that's sort of the definition of xi. 1558 01:11:37,800 --> 01:11:43,090 But, in particular, I can stack it on top. 1559 01:11:45,970 --> 01:11:48,490 So one easy way to do this is I just array-- 1560 01:11:48,490 --> 01:11:52,150 I iterate through the first i minus 1 elements of my array, 1561 01:11:52,150 --> 01:11:53,830 and I just check my stacking condition 1562 01:11:53,830 --> 01:11:55,480 for every single one of them relative 1563 01:11:55,480 --> 01:11:59,830 to block j, so, in other words, that the width and the height-- 1564 01:11:59,830 --> 01:12:02,080 or rather, the first and the second coordinate 1565 01:12:02,080 --> 01:12:04,450 satisfy the strict inequalities that I need. 1566 01:12:04,450 --> 01:12:06,910 I'm phrasing this sentence neutrally 1567 01:12:06,910 --> 01:12:10,310 because I forget whether this is increasing or decreasing. 1568 01:12:10,310 --> 01:12:11,530 But in any event-- 1569 01:12:11,530 --> 01:12:12,290 so what do I do? 1570 01:12:12,290 --> 01:12:15,070 I check all of the blocks that I could possibly 1571 01:12:15,070 --> 01:12:17,035 stack from the index of the array perspective. 1572 01:12:17,035 --> 01:12:18,910 I make sure that I could actually stack them, 1573 01:12:18,910 --> 01:12:21,460 thanks to the size of the current block 1574 01:12:21,460 --> 01:12:24,070 that I just decided to add to my stack. 1575 01:12:24,070 --> 01:12:26,530 And I move recursively. 1576 01:12:26,530 --> 01:12:27,260 OK. 1577 01:12:27,260 --> 01:12:27,760 Right. 1578 01:12:27,760 --> 01:12:30,010 So this is great because now we're 1579 01:12:30,010 --> 01:12:31,870 in exactly the recursive scenario we wanted 1580 01:12:31,870 --> 01:12:36,140 to be in, because x i only depends on x j, where 1581 01:12:36,140 --> 01:12:37,630 j is smaller than i. 1582 01:12:37,630 --> 01:12:40,780 And that is exactly our topological 1583 01:12:40,780 --> 01:12:43,450 ordering that we need. 1584 01:12:43,450 --> 01:12:47,260 If you do that on your homework, you get a minus n for large n. 1585 01:12:47,260 --> 01:12:48,730 OK. 1586 01:12:48,730 --> 01:12:50,920 Similarly, what's our base case? 1587 01:12:50,920 --> 01:12:56,020 Well, obviously, if I only have one block, 1588 01:12:56,020 --> 01:12:58,030 I might as well use it. 1589 01:12:58,030 --> 01:13:03,190 So in that case, we have x1 is equal to v(1) our notation here 1590 01:13:03,190 --> 01:13:05,380 like that. 1591 01:13:05,380 --> 01:13:08,510 Our original one, we have to be a little bit careful because 1592 01:13:08,510 --> 01:13:12,670 of the way that I've defined x, because x assumes that I've 1593 01:13:12,670 --> 01:13:16,760 used a particular block, so I have to say, 1594 01:13:16,760 --> 01:13:19,870 well, I might not have actually chosen the very last block 1595 01:13:19,870 --> 01:13:21,880 as the one I want to keep. 1596 01:13:21,880 --> 01:13:22,840 So I have to iterate. 1597 01:13:22,840 --> 01:13:26,500 I can say that, really, my original 1598 01:13:26,500 --> 01:13:27,927 is the max over i of x i. 1599 01:13:27,927 --> 01:13:30,010 So one of these blocks has to be the block on top. 1600 01:13:30,010 --> 01:13:32,177 I'm just going to iterate over all the possible ones 1601 01:13:32,177 --> 01:13:33,490 and find it. 1602 01:13:33,490 --> 01:13:38,740 And then our final thing to do is the runtime t. 1603 01:13:38,740 --> 01:13:42,520 This one is mildly trickier than the previous runtimes 1604 01:13:42,520 --> 01:13:45,370 that we've done so far in our example problem. 1605 01:13:45,370 --> 01:13:50,000 In particular, how many subproblems are there? 1606 01:13:50,000 --> 01:13:52,360 Well, there's n subproblems-- 1607 01:13:52,360 --> 01:13:54,610 or I'll say order n because I'm always off by 1-- 1608 01:13:59,630 --> 01:14:04,347 corresponding to each block in my stack here. 1609 01:14:04,347 --> 01:14:05,930 But how much time does each subproblem 1610 01:14:05,930 --> 01:14:08,540 take, at least the way that I've written it here? 1611 01:14:08,540 --> 01:14:10,220 Well, what I have to do? 1612 01:14:10,220 --> 01:14:12,500 I have to loop over all of the possible blocks 1613 01:14:12,500 --> 01:14:16,290 and find the one that I can stack on top of 1614 01:14:16,290 --> 01:14:17,310 and then take the max. 1615 01:14:17,310 --> 01:14:22,480 So there's a loop here from 1 to i. i is upper bounded by n. 1616 01:14:22,480 --> 01:14:27,280 So this is order n subproblems times order n 1617 01:14:27,280 --> 01:14:32,510 work per subproblem. 1618 01:14:32,510 --> 01:14:35,860 So at the end of the day, my algorithm 1619 01:14:35,860 --> 01:14:38,700 is going to be order n squared time. 1620 01:14:38,700 --> 01:14:39,720 And, of course, again-- 1621 01:14:39,720 --> 01:14:42,450 I guess I promised it and then I didn't actually do it-- 1622 01:14:42,450 --> 01:14:44,197 to actually implement this algorithm, 1623 01:14:44,197 --> 01:14:46,030 there's sort of two different ways to do it. 1624 01:14:46,030 --> 01:14:49,640 I could write a recursive call plus a table. 1625 01:14:49,640 --> 01:14:51,990 The tables maybe initialized to a bunch of NaNs. 1626 01:14:51,990 --> 01:14:54,630 And then I implement this function recursively. 1627 01:14:54,630 --> 01:14:58,343 But before I do that, I say, if the table does not equal NaN, 1628 01:14:58,343 --> 01:14:59,760 just return the value in the table 1629 01:14:59,760 --> 01:15:03,030 and otherwise call this recursion. 1630 01:15:03,030 --> 01:15:06,300 Or I can just have a four loop from 1 to n 1631 01:15:06,300 --> 01:15:09,060 and build up the table one element at a time. 1632 01:15:09,060 --> 01:15:11,010 And both of those are exactly the same 1633 01:15:11,010 --> 01:15:13,550 from a runtime perspective. 1634 01:15:13,550 --> 01:15:14,050 OK. 1635 01:15:14,050 --> 01:15:15,800 So I think I've managed to watch that much 1636 01:15:15,800 --> 01:15:18,160 more than my notes or the written solution, 1637 01:15:18,160 --> 01:15:19,660 but the problem itself is actually 1638 01:15:19,660 --> 01:15:20,490 pretty straightforward. 1639 01:15:20,490 --> 01:15:22,720 So if you guys read through the answer plus some of-- 1640 01:15:22,720 --> 01:15:24,762 I think, actually, the hard parts of this problem 1641 01:15:24,762 --> 01:15:26,170 were not the dynamic programming, 1642 01:15:26,170 --> 01:15:28,253 it was all the observations you need to get there. 1643 01:15:28,253 --> 01:15:31,270 So that's why I spent a little more time there. 1644 01:15:31,270 --> 01:15:31,870 OK. 1645 01:15:31,870 --> 01:15:33,940 So, as usual, I haven't left myself enough time 1646 01:15:33,940 --> 01:15:35,740 for the last problem. 1647 01:15:35,740 --> 01:15:37,810 But we have a few minutes and that'll 1648 01:15:37,810 --> 01:15:39,825 be sufficient to set up the parts. 1649 01:15:39,825 --> 01:15:41,200 I actually found the last problem 1650 01:15:41,200 --> 01:15:44,020 to be easier even though it technically is, sort of, 1651 01:15:44,020 --> 01:15:46,000 two dynamic programs in one. 1652 01:15:46,000 --> 01:15:48,380 So I think the logic is a little easier. 1653 01:15:48,380 --> 01:15:49,240 OK. 1654 01:15:49,240 --> 01:15:53,130 So 1655 01:15:53,130 --> 01:15:55,603 AUDIENCE: Use the backboard [INAUDIBLE].. 1656 01:15:55,603 --> 01:15:57,520 JUSTIN SOLOMON: I think this is the backboard. 1657 01:15:57,520 --> 01:16:00,070 Yeah, I was just realizing that this room doesn't work 1658 01:16:00,070 --> 01:16:02,680 the same way as the other one. 1659 01:16:02,680 --> 01:16:03,880 Yeah, this is embarrassing. 1660 01:16:03,880 --> 01:16:05,963 You know, I spent all day thinking about topology, 1661 01:16:05,963 --> 01:16:10,770 and this is like a classic kind of problem in that universe. 1662 01:16:14,450 --> 01:16:15,110 OK. 1663 01:16:15,110 --> 01:16:17,120 Well, we'll just erase one board at a time, 1664 01:16:17,120 --> 01:16:20,703 and I'll try not to write three feet wide this time. 1665 01:16:20,703 --> 01:16:22,828 Oh, this is probably the one board I shouldn't use. 1666 01:16:26,040 --> 01:16:29,060 I don't think I like this classroom. 1667 01:16:29,060 --> 01:16:29,560 OK. 1668 01:16:29,560 --> 01:16:36,360 So, right, in our final problem, we're given an n-by-n grid. 1669 01:16:36,360 --> 01:16:40,980 And on our n-by-n grid, Princess Apple-- 1670 01:16:40,980 --> 01:16:41,855 Banana-- 1671 01:16:41,855 --> 01:16:42,480 AUDIENCE: Plum. 1672 01:16:42,480 --> 01:16:42,840 JUSTIN SOLOMON: --Plum. 1673 01:16:42,840 --> 01:16:43,560 Princess Plum. 1674 01:16:46,590 --> 01:16:48,300 Right, so here's our basic setup. 1675 01:16:48,300 --> 01:16:53,753 There's a big grid of stuff, or maybe a small grid 1676 01:16:53,753 --> 01:16:55,170 because I don't feel like drawing. 1677 01:16:55,170 --> 01:16:58,570 And every grid square can have one of three things. 1678 01:16:58,570 --> 01:16:59,920 We can have a mushroom. 1679 01:16:59,920 --> 01:17:01,350 We can have a tree. 1680 01:17:01,350 --> 01:17:03,540 Or it can have nothing at all. 1681 01:17:03,540 --> 01:17:09,180 And our princess starts here, and she goes-- 1682 01:17:09,180 --> 01:17:11,490 she wants to go there. 1683 01:17:11,490 --> 01:17:15,330 And moreover, there's a couple of things 1684 01:17:15,330 --> 01:17:16,720 that are worth noting here. 1685 01:17:16,720 --> 01:17:24,330 So, first of all, her path is quick, meaning 1686 01:17:24,330 --> 01:17:35,600 that she can only traverse 2n minus 1 grid squares 1687 01:17:35,600 --> 01:17:38,610 to get from one corner to the other. 1688 01:17:38,610 --> 01:17:40,850 And, apparently, she's very into mushrooms, 1689 01:17:40,850 --> 01:17:44,390 and she'd like to accumulate as many as possible 1690 01:17:44,390 --> 01:17:45,320 along her path. 1691 01:17:45,320 --> 01:17:46,640 That's the basic setup here. 1692 01:17:46,640 --> 01:17:50,440 So she wants to get from the upper left to lower right. 1693 01:17:50,440 --> 01:17:54,670 And, in order to do so, she wants to take a quick path. 1694 01:17:54,670 --> 01:17:56,530 Her main priority is to be efficient. 1695 01:17:56,530 --> 01:17:59,050 But among the different quick paths, 1696 01:17:59,050 --> 01:18:01,270 she wants to pick up a lot of mushrooms. 1697 01:18:01,270 --> 01:18:02,188 It's understandable. 1698 01:18:02,188 --> 01:18:03,730 AUDIENCE: And not walk through trees. 1699 01:18:03,730 --> 01:18:05,980 JUSTIN SOLOMON: And not only through trees, thank you. 1700 01:18:05,980 --> 01:18:07,780 So maybe there's some grid squares 1701 01:18:07,780 --> 01:18:09,863 that are marked with a tree, meaning that you just 1702 01:18:09,863 --> 01:18:11,190 can't go there. 1703 01:18:11,190 --> 01:18:13,230 That's a tree. 1704 01:18:13,230 --> 01:18:15,190 OK. 1705 01:18:15,190 --> 01:18:17,530 Right, so that's our basic setup here. 1706 01:18:17,530 --> 01:18:18,480 But the problem does-- 1707 01:18:18,480 --> 01:18:19,855 it takes a bit of a twist, right? 1708 01:18:19,855 --> 01:18:22,410 It's not saying just could be the shortest path, which 1709 01:18:22,410 --> 01:18:26,400 would be very much like the last kind of unit in 6.006. 1710 01:18:26,400 --> 01:18:29,220 But rather, the question is, sort of, 1711 01:18:29,220 --> 01:18:33,240 what is the number of paths that she can take from one side 1712 01:18:33,240 --> 01:18:38,143 to the other and what is the maximum number of mushrooms, is 1713 01:18:38,143 --> 01:18:39,810 roughly the question asking, or at least 1714 01:18:39,810 --> 01:18:41,750 what I remember from reading it last night. 1715 01:18:41,750 --> 01:18:44,832 AUDIENCE: The number of paths that maximizes the same number. 1716 01:18:44,832 --> 01:18:46,040 JUSTIN SOLOMON: That's right. 1717 01:18:46,040 --> 01:18:48,890 So she has to take the most number of mushrooms 1718 01:18:48,890 --> 01:18:51,380 she can, but there may be more than one path that 1719 01:18:51,380 --> 01:18:53,013 gets you there that is quick, that 1720 01:18:53,013 --> 01:18:54,680 satisfies this condition, in which case, 1721 01:18:54,680 --> 01:18:56,720 she wants the count of the total number of ways 1722 01:18:56,720 --> 01:18:58,512 you could get from one corner to the other. 1723 01:18:58,512 --> 01:18:59,460 Why, you might ask-- 1724 01:18:59,460 --> 01:19:01,740 why not? 1725 01:19:01,740 --> 01:19:02,240 OK. 1726 01:19:02,240 --> 01:19:04,700 So, right. 1727 01:19:04,700 --> 01:19:10,530 So, for instance, maybe there's a mushroom here. 1728 01:19:10,530 --> 01:19:13,280 Now there's a quick path that gets her there 1729 01:19:13,280 --> 01:19:14,720 and collects one mushroom. 1730 01:19:14,720 --> 01:19:15,740 So there's exactly one. 1731 01:19:15,740 --> 01:19:21,620 But maybe if there's a mushroom there, well, initially, 1732 01:19:21,620 --> 01:19:24,230 it feels like maybe she could get two mushrooms. 1733 01:19:24,230 --> 01:19:27,050 She could go there, go pick up the second mushroom, 1734 01:19:27,050 --> 01:19:28,560 and get back. 1735 01:19:28,560 --> 01:19:31,880 But we're going to see that this quick condition actually 1736 01:19:31,880 --> 01:19:33,620 allows-- it doesn't allow you to do that. 1737 01:19:33,620 --> 01:19:34,460 OK? 1738 01:19:34,460 --> 01:19:37,520 So, in fact, it'll turn out that quick paths can only 1739 01:19:37,520 --> 01:19:40,100 collect one mushroom in this 3-by-3 case, 1740 01:19:40,100 --> 01:19:44,150 so there's at least two different paths. 1741 01:19:44,150 --> 01:19:49,360 Well, there's 1, 2, 3 different ways 1742 01:19:49,360 --> 01:19:52,890 that she could collect one mushroom and have a quick path. 1743 01:19:52,890 --> 01:19:55,060 OK. 1744 01:19:55,060 --> 01:19:57,280 So the first thing to notice is the instructions 1745 01:19:57,280 --> 01:20:01,450 are a little bit sneaky by defining quick paths, 1746 01:20:01,450 --> 01:20:03,880 basically, by giving her no slack at all. 1747 01:20:03,880 --> 01:20:05,320 Right? 1748 01:20:05,320 --> 01:20:08,280 And here's a basic observation. 1749 01:20:08,280 --> 01:20:10,280 Notice that in order to give from the upper left 1750 01:20:10,280 --> 01:20:11,947 to the bottom right, she's going to have 1751 01:20:11,947 --> 01:20:13,390 to go down and to the right. 1752 01:20:13,390 --> 01:20:14,800 Plausibly, she could also go up. 1753 01:20:14,800 --> 01:20:19,752 She could try and go around a tree, but only plausibly. 1754 01:20:19,752 --> 01:20:22,210 And, in particular, the question is how many times does she 1755 01:20:22,210 --> 01:20:23,960 have to go down and how many times did she 1756 01:20:23,960 --> 01:20:25,490 have to go to the right. 1757 01:20:25,490 --> 01:20:28,230 Well, she has to get to the bottom of the grid. 1758 01:20:28,230 --> 01:20:30,115 So she's on grid square number 1. 1759 01:20:30,115 --> 01:20:32,240 She has to go down, in this case, at least two more 1760 01:20:32,240 --> 01:20:34,730 times, so, in general, n minus 1 times. 1761 01:20:34,730 --> 01:20:38,592 She has to go to the right n minus 1 times. 1762 01:20:38,592 --> 01:20:39,550 So what does that mean? 1763 01:20:39,550 --> 01:20:43,100 She has to make 2n minus 2 moves. 1764 01:20:43,100 --> 01:20:44,447 And that's a lower bound, right? 1765 01:20:44,447 --> 01:20:46,780 So if she goes up, she's going to have to go down again, 1766 01:20:46,780 --> 01:20:48,120 so it's only going to make it bigger. 1767 01:20:48,120 --> 01:20:48,770 Right? 1768 01:20:48,770 --> 01:20:55,670 So at the very least, she has to do 2n minus 2 moves 1769 01:20:55,670 --> 01:21:01,310 down and right to get from the upper left to the lower right. 1770 01:21:01,310 --> 01:21:03,620 How many squares does she touch when she's doing that? 1771 01:21:03,620 --> 01:21:05,040 This is a fence post problem. 1772 01:21:05,040 --> 01:21:06,710 So she made 2n minus 2 moves, and she 1773 01:21:06,710 --> 01:21:09,380 had a place where she started. 1774 01:21:09,380 --> 01:21:13,070 That implies that just by moving down and to the right, 1775 01:21:13,070 --> 01:21:17,150 she makes 2n minus 1 squares-- 1776 01:21:17,150 --> 01:21:20,020 she touches, rather. 1777 01:21:20,020 --> 01:21:22,460 So can she ever move up? 1778 01:21:22,460 --> 01:21:23,060 No. 1779 01:21:23,060 --> 01:21:24,710 Can she ever move to the left? 1780 01:21:24,710 --> 01:21:25,947 No. 1781 01:21:25,947 --> 01:21:28,405 And that, basically, is all you need to solve this problem. 1782 01:21:28,405 --> 01:21:30,170 The rest of it's actually pretty easy. 1783 01:21:30,170 --> 01:21:32,937 So the basic observation here is she can only move down 1784 01:21:32,937 --> 01:21:35,270 and to the right because if she moved up or to the left, 1785 01:21:35,270 --> 01:21:37,490 her path would no longer be called quick, 1786 01:21:37,490 --> 01:21:38,880 and that would be a problem. 1787 01:21:38,880 --> 01:21:41,750 Moreover, every path that moves down and to the right 1788 01:21:41,750 --> 01:21:45,330 is a quick path, assuming she reaches their target 1789 01:21:45,330 --> 01:21:46,980 and doesn't hit a tree. 1790 01:21:46,980 --> 01:21:49,080 OK? 1791 01:21:49,080 --> 01:21:50,460 So that's the basic observation. 1792 01:21:50,460 --> 01:21:52,560 And notice that that already basically suggests-- 1793 01:21:52,560 --> 01:21:54,253 it's, like, screaming out to you-- 1794 01:21:54,253 --> 01:21:56,670 how to do dynamic programming because, literally, you have 1795 01:21:56,670 --> 01:22:01,450 a table looking at you on the blackboard right now, 1796 01:22:01,450 --> 01:22:05,530 and you have an ordering down and to the right that 1797 01:22:05,530 --> 01:22:06,410 is acyclic. 1798 01:22:06,410 --> 01:22:07,370 Yeah? 1799 01:22:07,370 --> 01:22:07,870 OK. 1800 01:22:07,870 --> 01:22:09,730 Have I slammed on the board enough times? 1801 01:22:09,730 --> 01:22:11,350 The first time I taught at Stanford, 1802 01:22:11,350 --> 01:22:14,620 I got negative course feedback that I had too much coffee 1803 01:22:14,620 --> 01:22:18,070 and was slamming on the board a lot, apparently. 1804 01:22:18,070 --> 01:22:21,050 I watched the video later, and, indeed, that was not wrong. 1805 01:22:21,050 --> 01:22:22,180 OK. 1806 01:22:22,180 --> 01:22:23,830 So, right. 1807 01:22:23,830 --> 01:22:27,520 So, we're going to call k-- 1808 01:22:27,520 --> 01:22:34,090 this is going to be the max mushrooms she 1809 01:22:34,090 --> 01:22:36,550 can get going on the entire path from the upper left 1810 01:22:36,550 --> 01:22:37,447 of the lower right. 1811 01:22:37,447 --> 01:22:39,280 So we want to know the number of quick paths 1812 01:22:39,280 --> 01:22:42,150 that can achieve this number k. 1813 01:22:42,150 --> 01:22:42,650 OK. 1814 01:22:42,650 --> 01:22:48,496 So let's do SRTBOT really fast because I've got four minutes-- 1815 01:22:48,496 --> 01:22:51,150 actually, a tiny bit more than that because we started late. 1816 01:22:51,150 --> 01:22:51,650 OK. 1817 01:22:55,300 --> 01:22:57,700 Now, the kind of annoyance here is 1818 01:22:57,700 --> 01:23:01,180 that there's two different numbers that we don't know. 1819 01:23:01,180 --> 01:23:03,820 One of them is k, and the other is the number of paths. 1820 01:23:03,820 --> 01:23:06,790 The problem didn't tell you how many mushrooms she can pick up. 1821 01:23:06,790 --> 01:23:08,830 It does tell you that there's some path 1822 01:23:08,830 --> 01:23:10,360 to get from the upper left to the bottom right, 1823 01:23:10,360 --> 01:23:12,068 that there's not just like a row of trees 1824 01:23:12,068 --> 01:23:17,660 somewhere, which I feel in my commute sometimes. 1825 01:23:17,660 --> 01:23:21,740 But it doesn't tell you the number 1826 01:23:21,740 --> 01:23:23,600 that she has to accomplish. 1827 01:23:23,600 --> 01:23:25,890 And, initially, that's kind of annoying. 1828 01:23:25,890 --> 01:23:27,680 So maybe the first thing that we do 1829 01:23:27,680 --> 01:23:30,170 is just compute k, like, the maximum number 1830 01:23:30,170 --> 01:23:34,660 of mushrooms that she can collect on any quick path. 1831 01:23:34,660 --> 01:23:37,070 And then we go back and compute that other count. 1832 01:23:37,070 --> 01:23:38,820 That would be one problem-solving approach 1833 01:23:38,820 --> 01:23:41,750 that we could think about a little bit. 1834 01:23:41,750 --> 01:23:50,065 So, in particular, let's define our k ij to be equal to-- 1835 01:23:50,065 --> 01:23:51,940 well, we can generalize our problem slightly, 1836 01:23:51,940 --> 01:23:54,250 and say what is the number of mushrooms 1837 01:23:54,250 --> 01:23:57,340 that I can get on any kind of rectangle embedded inside 1838 01:23:57,340 --> 01:23:59,260 of my full problem, right? 1839 01:23:59,260 --> 01:24:04,540 So, in other words, this is the max number of mushrooms, 1840 01:24:04,540 --> 01:24:14,987 or m's for short, on a quick path to ij. 1841 01:24:14,987 --> 01:24:17,320 So, in other words, she always starts in the upper left, 1842 01:24:17,320 --> 01:24:20,020 but now she stops at any other grid cell. 1843 01:24:20,020 --> 01:24:20,520 OK? 1844 01:24:23,570 --> 01:24:25,925 Because I'm running low on time-- 1845 01:24:25,925 --> 01:24:28,050 no, I'm going to do this the way I want to do this. 1846 01:24:28,050 --> 01:24:29,758 No, so we're just going to think about k. 1847 01:24:29,758 --> 01:24:30,600 Yeah? 1848 01:24:30,600 --> 01:24:34,620 So the question is could we compute just 1849 01:24:34,620 --> 01:24:38,160 as value k, which certainly seems convenient. 1850 01:24:38,160 --> 01:24:41,343 Princess Plum, she might as well know her enemy. 1851 01:24:41,343 --> 01:24:43,260 She might as well know the number of mushrooms 1852 01:24:43,260 --> 01:24:44,880 she's targeting, if she can get it. 1853 01:24:47,640 --> 01:24:53,830 So how could we do this recursively? 1854 01:24:53,830 --> 01:24:58,120 Well, she has to get to position ij. 1855 01:24:58,120 --> 01:25:00,430 And from our argument up there, she 1856 01:25:00,430 --> 01:25:04,640 has to get there by either coming from up or to the left, 1857 01:25:04,640 --> 01:25:07,020 the way we've chosen to write down this problem. 1858 01:25:07,020 --> 01:25:09,980 So what are our different cases? 1859 01:25:09,980 --> 01:25:12,080 Well, first of all, if there's a tree, 1860 01:25:12,080 --> 01:25:13,200 you can't do a damn thing. 1861 01:25:13,200 --> 01:25:14,750 She shouldn't even be able to get there. 1862 01:25:14,750 --> 01:25:16,490 And for convenience, we're going to find 1863 01:25:16,490 --> 01:25:18,590 you can argue that it's 0. 1864 01:25:18,590 --> 01:25:20,750 We're going to mark this with a special number, 1865 01:25:20,750 --> 01:25:22,500 and we'll see that that makes our notation 1866 01:25:22,500 --> 01:25:23,540 a little convenient. 1867 01:25:23,540 --> 01:25:28,430 So one is if there exists a tree, 1868 01:25:28,430 --> 01:25:32,723 then we're going to say k ij is minus infinity. 1869 01:25:32,723 --> 01:25:34,640 Again, there's a philosophical question there. 1870 01:25:34,640 --> 01:25:36,380 Does she get minus infinity mushrooms 1871 01:25:36,380 --> 01:25:38,180 if she is standing on top of a tree? 1872 01:25:38,180 --> 01:25:39,060 I don't know, because she shouldn't 1873 01:25:39,060 --> 01:25:40,220 stand on top of a tree. 1874 01:25:40,220 --> 01:25:42,500 But at least it's going to let us know that something 1875 01:25:42,500 --> 01:25:44,720 went wrong in this grid square in the other parts 1876 01:25:44,720 --> 01:25:46,130 of our recursion. 1877 01:25:46,130 --> 01:25:48,320 OK? 1878 01:25:48,320 --> 01:25:55,720 And otherwise, well, what are our different cases here? 1879 01:25:55,720 --> 01:25:58,100 Well, she always picks up a mushroom if it's there. 1880 01:25:58,100 --> 01:25:58,850 She might as well. 1881 01:25:58,850 --> 01:26:00,370 She's maximizing. 1882 01:26:00,370 --> 01:26:02,385 In fact, the problem even says that she's really 1883 01:26:02,385 --> 01:26:03,010 into mushrooms. 1884 01:26:03,010 --> 01:26:05,950 She collects them automatically, right? 1885 01:26:05,950 --> 01:26:07,720 So what do we get? 1886 01:26:10,710 --> 01:26:13,110 I use unnecessarily fancy notation. 1887 01:26:13,110 --> 01:26:19,140 This is an indicator of whether there exists a mushroom 1888 01:26:19,140 --> 01:26:27,030 at position ij, meaning this is a 1 if there is, 1889 01:26:27,030 --> 01:26:29,280 and there's a 0 if there's not. 1890 01:26:29,280 --> 01:26:32,790 Sometimes this is indicated with a 1 with a little subscript, 1891 01:26:32,790 --> 01:26:34,830 but whatever. 1892 01:26:34,830 --> 01:26:36,870 In addition to that, she might have picked up 1893 01:26:36,870 --> 01:26:38,490 mushrooms along paths. 1894 01:26:38,490 --> 01:26:41,580 And we know that her path to position ij either 1895 01:26:41,580 --> 01:26:44,480 came from up or to the left. 1896 01:26:44,480 --> 01:26:51,140 So, in other words, we know that she 1897 01:26:51,140 --> 01:26:53,600 could have gotten the max from any path ending above her 1898 01:26:53,600 --> 01:26:55,250 or any path to the left of her. 1899 01:26:55,250 --> 01:27:00,380 So that's k i minus 1j, which, I guess, 1900 01:27:00,380 --> 01:27:07,210 is to the left, and k ij minus 1, like that. 1901 01:27:07,210 --> 01:27:11,620 And this can be used to fill in our whole table of k values. 1902 01:27:11,620 --> 01:27:13,120 In fact, since I'm low on time, I'll 1903 01:27:13,120 --> 01:27:18,650 let you do the TBOT for the remainder of this problem. 1904 01:27:18,650 --> 01:27:21,395 Essentially, I think the key observation is this one. 1905 01:27:21,395 --> 01:27:23,270 Obviously, when she starts in the upper left, 1906 01:27:23,270 --> 01:27:24,620 she gets 0 mushrooms because she's not 1907 01:27:24,620 --> 01:27:25,578 standing on top of one. 1908 01:27:25,578 --> 01:27:27,750 The problem says that. 1909 01:27:27,750 --> 01:27:30,360 And this allows us to fill in our whole table k. 1910 01:27:30,360 --> 01:27:32,610 So, in particular, this gives us our enemy now. 1911 01:27:32,610 --> 01:27:36,952 We now know how many mushrooms she should have 1912 01:27:36,952 --> 01:27:38,160 at every step of her journey. 1913 01:27:38,160 --> 01:27:39,660 In fact, it tells us a tiny bit more 1914 01:27:39,660 --> 01:27:42,240 than that because it says if I'm at this grid 1915 01:27:42,240 --> 01:27:46,020 sq-- at this particular grid square during my path, 1916 01:27:46,020 --> 01:27:47,560 I should have this many mushrooms. 1917 01:27:47,560 --> 01:27:49,950 If I didn't, then something went wrong. 1918 01:27:49,950 --> 01:27:51,343 Yeah? 1919 01:27:51,343 --> 01:27:53,010 So the way that the solution is written, 1920 01:27:53,010 --> 01:27:55,272 they do two pieces of the recursion at once. 1921 01:27:55,272 --> 01:27:57,480 You actually could have just solved for this k matrix 1922 01:27:57,480 --> 01:27:59,550 first and then gone back and done the second half 1923 01:27:59,550 --> 01:28:00,300 of this problem. 1924 01:28:00,300 --> 01:28:02,770 And those are exactly the same. 1925 01:28:02,770 --> 01:28:04,458 And when I was writing my solution, 1926 01:28:04,458 --> 01:28:06,750 this is the way I thought about it, because, somehow, I 1927 01:28:06,750 --> 01:28:07,980 kind of felt like she might as well know 1928 01:28:07,980 --> 01:28:09,990 how many mushrooms she wants to collect before she starts 1929 01:28:09,990 --> 01:28:10,615 counting paths. 1930 01:28:10,615 --> 01:28:13,620 That's like a secondary question, you know. 1931 01:28:13,620 --> 01:28:15,760 And so this is one way to do it. 1932 01:28:15,760 --> 01:28:18,820 So in our remaining negative 2 minutes, 1933 01:28:18,820 --> 01:28:20,920 let's think about the recursion for computing. 1934 01:28:20,920 --> 01:28:24,600 Remember that we want to know the number of paths needed 1935 01:28:24,600 --> 01:28:28,770 to collect that many mushrooms, the maximum number 1936 01:28:28,770 --> 01:28:31,690 of mushrooms. 1937 01:28:31,690 --> 01:28:34,300 Please let there not be a whole lot of stuff on this board. 1938 01:28:34,300 --> 01:28:35,967 Ah, there's not any stuff on this board. 1939 01:28:35,967 --> 01:28:36,860 That's great. 1940 01:28:36,860 --> 01:28:38,320 OK. 1941 01:28:38,320 --> 01:28:42,690 So, in particular, now I'm going to define a second thing 1942 01:28:42,690 --> 01:28:45,360 that I also I'm going to do dynamic programming on. 1943 01:28:45,360 --> 01:28:51,540 I'm going to say that x ij is equal to-- and I'm going 1944 01:28:51,540 --> 01:28:55,270 to make it kind of a sneaky definition here, 1945 01:28:55,270 --> 01:29:12,320 which is the number of quick paths that end at ij with-- 1946 01:29:12,320 --> 01:29:15,930 now, let's anticipate our problem a little bit. 1947 01:29:15,930 --> 01:29:18,677 So at the end of the day, we're going to do x of n comma n 1948 01:29:18,677 --> 01:29:21,260 because she wants to end up all the way down and to the right. 1949 01:29:21,260 --> 01:29:23,135 And how many mushrooms does she want to have, 1950 01:29:23,135 --> 01:29:24,290 now that we know k? 1951 01:29:24,290 --> 01:29:27,770 She wants to have k of n comma n mushrooms. 1952 01:29:27,770 --> 01:29:31,100 Along the way, it would be kind of ambitious 1953 01:29:31,100 --> 01:29:32,780 if she wanted to have k of n comma n 1954 01:29:32,780 --> 01:29:35,120 mushrooms the entire path. 1955 01:29:35,120 --> 01:29:37,970 But it would be slightly less ambitious to have 1956 01:29:37,970 --> 01:29:42,080 k of ij mushrooms because, somehow, that's 1957 01:29:42,080 --> 01:29:45,900 exactly what we just constructed in the previous thing 1958 01:29:45,900 --> 01:29:48,290 where it was paths. 1959 01:29:48,290 --> 01:29:50,102 Well, the last guy looks like a max. 1960 01:29:50,102 --> 01:29:52,310 Now we're going to expect to see some plus signs here 1961 01:29:52,310 --> 01:29:54,980 because we're adding up how many paths we have. 1962 01:29:54,980 --> 01:29:56,000 OK? 1963 01:29:56,000 --> 01:29:59,480 And now let's come up with a recursive rule for the array x, 1964 01:29:59,480 --> 01:30:01,560 and then we'll call it a day. 1965 01:30:01,560 --> 01:30:10,980 So, in particular, [INAUDIBLE] one, if there's a tree, 1966 01:30:10,980 --> 01:30:12,770 how many paths are there? 1967 01:30:12,770 --> 01:30:15,560 There are no paths, because I can't get there. 1968 01:30:15,560 --> 01:30:19,730 So then ij equals 0. 1969 01:30:19,730 --> 01:30:20,330 OK? 1970 01:30:20,330 --> 01:30:23,450 Otherwise, there ain't a tree. 1971 01:30:23,450 --> 01:30:27,770 And now I have to be a little careful, right? 1972 01:30:27,770 --> 01:30:30,890 So I need to write this like a little piece of code. 1973 01:30:30,890 --> 01:30:34,400 You could have written this as a giant max, instead, or a bunch 1974 01:30:34,400 --> 01:30:37,380 of cases and whatever. 1975 01:30:37,380 --> 01:30:39,770 So let's think about it like a piece of code. 1976 01:30:39,770 --> 01:30:42,560 So, initially, I think there are no paths that 1977 01:30:42,560 --> 01:30:44,030 get me k ij mushrooms. 1978 01:30:44,030 --> 01:30:45,995 That's perfectly fine. 1979 01:30:45,995 --> 01:30:47,370 And remember, we're going to keep 1980 01:30:47,370 --> 01:30:48,745 applying the same piece of logic, 1981 01:30:48,745 --> 01:30:51,990 which is that a path can only come from to the left and up. 1982 01:30:51,990 --> 01:30:56,770 And let's think about those two cases. 1983 01:30:56,770 --> 01:30:58,560 And by the way, we're going to use chi 1984 01:30:58,560 --> 01:31:01,710 to equal this chi of stuff that we 1985 01:31:01,710 --> 01:31:04,500 had in the previous expression. 1986 01:31:04,500 --> 01:31:07,470 So chi is 1 if there's a mushroom at this place, 1987 01:31:07,470 --> 01:31:09,610 and 0 if there is not. 1988 01:31:09,610 --> 01:31:12,290 OK. 1989 01:31:12,290 --> 01:31:15,650 So my path can come from the left or up. 1990 01:31:15,650 --> 01:31:20,030 I know that it can't come from up if the number of mushrooms 1991 01:31:20,030 --> 01:31:23,150 that I got from up plus, potentially, the one that I got 1992 01:31:23,150 --> 01:31:25,460 here doesn't align with the number of mushrooms 1993 01:31:25,460 --> 01:31:28,670 that I should have by the k ij standard 1994 01:31:28,670 --> 01:31:31,100 that I have set for myself. 1995 01:31:31,100 --> 01:31:34,325 So if I want to write that out in code, the way I do that is I 1996 01:31:34,325 --> 01:31:37,910 would say, if k of-- 1997 01:31:37,910 --> 01:31:40,217 so let's say I look to the left first. 1998 01:31:40,217 --> 01:31:42,800 This is like, you know, look to your left, look to your right, 1999 01:31:42,800 --> 01:31:46,160 one of you will pass this exam kind of scenario. 2000 01:31:46,160 --> 01:31:49,730 And I potentially add a mushroom at my current position 2001 01:31:49,730 --> 01:31:52,140 if there is one. 2002 01:31:52,140 --> 01:31:55,568 If that is equal to k ij, well, what does that mean? 2003 01:31:55,568 --> 01:31:57,360 That means that paths that went to the left 2004 01:31:57,360 --> 01:31:59,910 were able to collect the number of mushrooms I need to get 2005 01:31:59,910 --> 01:32:01,560 to the position I am now. 2006 01:32:01,560 --> 01:32:08,700 So now I can add all of the different ways. 2007 01:32:08,700 --> 01:32:14,940 Maybe I'll do a plus equals x of i minus 1j 2008 01:32:14,940 --> 01:32:16,815 because any path that got to the previous guy 2009 01:32:16,815 --> 01:32:18,607 and collected the right number of mushrooms 2010 01:32:18,607 --> 01:32:21,050 can now reach me and get the right number of mushrooms. 2011 01:32:21,050 --> 01:32:24,300 And similarly, I can look up and do exactly the same logic. 2012 01:32:24,300 --> 01:32:33,040 So if k of ij minus 1 plus this number is equal to k ij, 2013 01:32:33,040 --> 01:32:43,980 then x ij gets an additional number of paths, like that. 2014 01:32:43,980 --> 01:32:46,770 And now I do think it's worth spending 8 seconds thinking 2015 01:32:46,770 --> 01:32:50,040 about our base cases here because, initially, 2016 01:32:50,040 --> 01:32:52,050 when I first saw this, I panicked a little bit 2017 01:32:52,050 --> 01:32:54,217 because it kind of looks like this would just end up 2018 01:32:54,217 --> 01:32:56,643 getting a bunch of 0's because I'm just adding 2019 01:32:56,643 --> 01:32:57,810 values of x's to themselves. 2020 01:32:57,810 --> 01:32:59,352 I don't have, like, a 1 plus anything 2021 01:32:59,352 --> 01:33:02,593 anywhere, which is kind of weird if you think about it. 2022 01:33:02,593 --> 01:33:04,760 So all of the reason why the positive numbers appear 2023 01:33:04,760 --> 01:33:07,310 in this problem is from the base case, which is kind of cool, 2024 01:33:07,310 --> 01:33:07,810 I think. 2025 01:33:07,810 --> 01:33:09,810 This is like, I think, one of these things where 2026 01:33:09,810 --> 01:33:12,020 if you anticipated a problem, then it's cool, 2027 01:33:12,020 --> 01:33:13,415 and if you didn't anticipate the problem to begin with 2028 01:33:13,415 --> 01:33:15,080 and you just wrote down these formulas, 2029 01:33:15,080 --> 01:33:17,990 you probably wouldn't even think that it's interesting. 2030 01:33:17,990 --> 01:33:21,420 But in any event, what is our base case? 2031 01:33:21,420 --> 01:33:24,440 So, we'll do the B in SRTBOT. 2032 01:33:24,440 --> 01:33:30,053 So, first of all, what is k of 1, 1? 2033 01:33:30,053 --> 01:33:31,720 Remember, that's the number of mushrooms 2034 01:33:31,720 --> 01:33:33,637 she can collect by starting at the left square 2035 01:33:33,637 --> 01:33:34,890 and going nowhere. 2036 01:33:34,890 --> 01:33:37,530 And that's 0 because the problem says there's 2037 01:33:37,530 --> 01:33:40,430 no mushrooms in the upper left. 2038 01:33:40,430 --> 01:33:43,012 What's x of 1, 1? 2039 01:33:43,012 --> 01:33:44,720 Well, this is the number of paths from 1, 2040 01:33:44,720 --> 01:33:49,570 1 to itself that collects 0 mushrooms, so that's 1. 2041 01:33:49,570 --> 01:33:50,530 OK. 2042 01:33:50,530 --> 01:33:52,930 And I think that the rest of the SRTBOT table 2043 01:33:52,930 --> 01:33:56,360 here isn't terribly difficult to fill in. 2044 01:33:56,360 --> 01:33:58,370 So I noticed that in kind of a funny way, 2045 01:33:58,370 --> 01:34:00,287 all of these recursive steps are just adding 1 2046 01:34:00,287 --> 01:34:02,745 to itself a bunch of times. 2047 01:34:02,745 --> 01:34:04,870 But, of course, the way you do that, the reason why 2048 01:34:04,870 --> 01:34:06,040 you get a number that is interesting, 2049 01:34:06,040 --> 01:34:08,123 is because of all these if statements and the fact 2050 01:34:08,123 --> 01:34:10,090 that you can add two different pluses coming 2051 01:34:10,090 --> 01:34:11,870 from two different sources. 2052 01:34:11,870 --> 01:34:12,430 OK. 2053 01:34:12,430 --> 01:34:13,990 So I actually do encourage you guys 2054 01:34:13,990 --> 01:34:16,540 to look at the code in the problem solution 2055 01:34:16,540 --> 01:34:18,580 because I think it's a nice example of taking 2056 01:34:18,580 --> 01:34:20,920 this recursive formula and then unrolling it into, 2057 01:34:20,920 --> 01:34:22,802 like, iterating over a table. 2058 01:34:22,802 --> 01:34:25,010 And that's a useful skill that I intended to do today 2059 01:34:25,010 --> 01:34:27,645 and then didn't actually do very carefully. 2060 01:34:27,645 --> 01:34:29,770 But with that, as usual, we've gone over time here. 2061 01:34:29,770 --> 01:34:31,240 So we'll call it for the day. 2062 01:34:31,240 --> 01:34:34,720 And I will see you guys when I see you guys. 2063 01:34:34,720 --> 01:34:36,420 All right.