1 00:00:00,040 --> 00:00:02,460 The following content is provided under a Creative 2 00:00:02,460 --> 00:00:03,870 Commons license. 3 00:00:03,870 --> 00:00:06,910 Your support will help MIT OpenCourseWare continue to 4 00:00:06,910 --> 00:00:10,560 offer high-quality educational resources for free. 5 00:00:10,560 --> 00:00:13,460 To make a donation or view additional materials from 6 00:00:13,460 --> 00:00:19,290 hundreds of MIT courses, visit MIT OpenCourseWare at 7 00:00:19,290 --> 00:00:20,540 ocw.mit.edu. 8 00:00:22,830 --> 00:00:24,710 ERIC GRIMSON: Good morning. 9 00:00:24,710 --> 00:00:27,980 Professor Guttag has to be out of town today. 10 00:00:27,980 --> 00:00:29,130 My name's Professor Grimson. 11 00:00:29,130 --> 00:00:30,390 I'm going to be subbing for him. 12 00:00:30,390 --> 00:00:33,150 And just to show you how much we value education here at 13 00:00:33,150 --> 00:00:36,920 MIT, and especially in EECS, you get the incoming 14 00:00:36,920 --> 00:00:38,570 chancellor as a substitute teacher. 15 00:00:38,570 --> 00:00:40,350 So how cool is that? 16 00:00:40,350 --> 00:00:42,490 All right, maybe not very cool. 17 00:00:42,490 --> 00:00:43,330 But I'm going to talk to you anyway 18 00:00:43,330 --> 00:00:46,100 for the next 50 minutes. 19 00:00:46,100 --> 00:00:49,960 At the end of last lecture, I think Professor Guttag 20 00:00:49,960 --> 00:00:54,760 introduced dictionaries to you, a really powerful type. 21 00:00:54,760 --> 00:00:58,430 It's got a great capability, which is it's a tool, a data 22 00:00:58,430 --> 00:01:01,970 type that lets you association almost any kind of structure 23 00:01:01,970 --> 00:01:03,370 with a key. 24 00:01:03,370 --> 00:01:05,910 So it could be that you're associating keys with numbers, 25 00:01:05,910 --> 00:01:08,000 you're associating keys with strings. 26 00:01:08,000 --> 00:01:10,160 But you could be associating keys with other things, 27 00:01:10,160 --> 00:01:12,046 including dictionaries. 28 00:01:12,046 --> 00:01:14,030 And I don't know if he showed this to you or not, but those 29 00:01:14,030 --> 00:01:16,770 keys themselves can also be really powerful. 30 00:01:16,770 --> 00:01:18,820 It could be just a string. 31 00:01:18,820 --> 00:01:23,220 But the key could also be a tuple, or a list, an x- and 32 00:01:23,220 --> 00:01:25,750 y-coordinate, or a set of names, or other things. 33 00:01:25,750 --> 00:01:28,740 So it's a really great data structure to use. 34 00:01:28,740 --> 00:01:33,630 Now, one of the things you could ask, though, is, gee, 35 00:01:33,630 --> 00:01:37,340 what if Python or whatever language you're using didn't 36 00:01:37,340 --> 00:01:38,730 come with dictionaries? 37 00:01:38,730 --> 00:01:41,190 Could we still get the same power? 38 00:01:41,190 --> 00:01:42,050 And the answer is sure. 39 00:01:42,050 --> 00:01:43,510 So I want to show you a little example. 40 00:01:43,510 --> 00:01:46,390 So on your handout, if we look at this little procedure up 41 00:01:46,390 --> 00:01:51,090 here at the top, key search, I could build it out of lists. 42 00:01:51,090 --> 00:01:53,150 I could just use a list as my way of storing it. 43 00:01:53,150 --> 00:01:54,620 So let's look at what this procedure. 44 00:01:54,620 --> 00:02:01,340 Says it says, OK, if I've got a list, and I've got a key, K, 45 00:02:01,340 --> 00:02:04,960 I could write a little loop that just walks down the list, 46 00:02:04,960 --> 00:02:08,919 saying, is the first part of each element equal to the key 47 00:02:08,919 --> 00:02:10,620 I'm looking for? 48 00:02:10,620 --> 00:02:14,090 And if it is, I'll return the second part of that element. 49 00:02:14,090 --> 00:02:16,460 And if I get to the end of the list, I haven't found it, I 50 00:02:16,460 --> 00:02:18,390 return none. 51 00:02:18,390 --> 00:02:20,540 So notice I'm making a choice here. 52 00:02:20,540 --> 00:02:23,790 I'm assuming that I'm storing in the dictionary things that 53 00:02:23,790 --> 00:02:27,880 are lists too long, key and the associated value, another 54 00:02:27,880 --> 00:02:29,640 key and the associated value, another key and 55 00:02:29,640 --> 00:02:31,070 the associated value. 56 00:02:31,070 --> 00:02:32,070 But this would work fine. 57 00:02:32,070 --> 00:02:33,150 So if I didn't have dictionaries, 58 00:02:33,150 --> 00:02:34,750 I could build it. 59 00:02:34,750 --> 00:02:37,030 If I wanted to make things that had a more complicated 60 00:02:37,030 --> 00:02:38,520 lookup, I'd have to make sure that that 61 00:02:38,520 --> 00:02:39,740 equality test did it. 62 00:02:39,740 --> 00:02:43,210 But you could see how I might do it. 63 00:02:43,210 --> 00:02:45,420 So the question then can be, so why do we bother with 64 00:02:45,420 --> 00:02:48,920 dictionaries, if we could just use it with lists? 65 00:02:48,920 --> 00:02:50,010 Here's my question to you. 66 00:02:50,010 --> 00:02:52,730 So how long in this implementation is it going to 67 00:02:52,730 --> 00:02:55,640 take me to figure out if something's in my dictionary? 68 00:02:58,400 --> 00:03:00,240 Oh my god, he's asking questions at 10 69 00:03:00,240 --> 00:03:01,130 o'clock in the morning. 70 00:03:01,130 --> 00:03:02,210 This is really terrifying. 71 00:03:02,210 --> 00:03:02,700 Somebody help me out. 72 00:03:02,700 --> 00:03:03,890 How long? 73 00:03:03,890 --> 00:03:05,334 Yeah? 74 00:03:05,334 --> 00:03:07,302 AUDIENCE: Probably on average on the order 75 00:03:07,302 --> 00:03:09,270 the size of the list. 76 00:03:09,270 --> 00:03:09,762 ERIC GRIMSON: Yeah. 77 00:03:09,762 --> 00:03:12,870 On average, it's going to take me half the size of the list. 78 00:03:12,870 --> 00:03:14,870 But that's the same thing as being the size of the list. 79 00:03:14,870 --> 00:03:17,810 So if that list is really long, I'm toast. 80 00:03:17,810 --> 00:03:19,830 If it's not in the dictionary, in fact, I'm going to have to 81 00:03:19,830 --> 00:03:22,170 go all the way through the list before I get to the end 82 00:03:22,170 --> 00:03:23,130 to decide it's not there. 83 00:03:23,130 --> 00:03:27,870 So this is not as efficient an implementation as we'd like. 84 00:03:27,870 --> 00:03:30,690 Now, the flip that is you say, OK, how long does it take for 85 00:03:30,690 --> 00:03:33,360 the dictionaries, the built-in associated retrieval that you 86 00:03:33,360 --> 00:03:35,020 have inside of Python? 87 00:03:35,020 --> 00:03:37,960 And the interesting answer there is that that retrieval 88 00:03:37,960 --> 00:03:38,720 is constant. 89 00:03:38,720 --> 00:03:42,170 It takes the same amount of time independent of the size 90 00:03:42,170 --> 00:03:42,800 of the dictionary. 91 00:03:42,800 --> 00:03:45,580 And that's wonderful. 92 00:03:45,580 --> 00:03:47,100 We're not going to talk about how today. 93 00:03:47,100 --> 00:03:48,610 You're going to see that later on in the term. 94 00:03:48,610 --> 00:03:51,360 But it is something that drives home, if you like, the 95 00:03:51,360 --> 00:03:53,010 point that different data structures 96 00:03:53,010 --> 00:03:54,570 have different costs. 97 00:03:54,570 --> 00:03:56,800 And while some are easier to implement in, they may not be 98 00:03:56,800 --> 00:03:58,740 as efficient, some may be a little more difficult to 99 00:03:58,740 --> 00:04:00,570 implement in, but they are much more efficient. 100 00:04:00,570 --> 00:04:02,450 And that's one of the great things about dictionaries. 101 00:04:05,270 --> 00:04:07,380 The second thing I think you saw at the end of last 102 00:04:07,380 --> 00:04:08,990 lecture, and I want to just highlight in a slightly 103 00:04:08,990 --> 00:04:11,150 different way, is I believe Professor Guttag showed you a 104 00:04:11,150 --> 00:04:15,110 little example of a very simple translation function. 105 00:04:15,110 --> 00:04:16,310 We had a little dictionary. 106 00:04:16,310 --> 00:04:18,750 I'm going to give you a version right here, and 107 00:04:18,750 --> 00:04:19,579 un-comment it. 108 00:04:19,579 --> 00:04:25,150 In fact, there's a little dictionary that simply 109 00:04:25,150 --> 00:04:27,290 associates English words with French words. 110 00:04:27,290 --> 00:04:29,160 And yes, it's pretty simple, but it's a little way of 111 00:04:29,160 --> 00:04:31,340 pairing those things up. 112 00:04:31,340 --> 00:04:35,050 And the idea would be if I have a sentence just a string 113 00:04:35,050 --> 00:04:37,600 that consists of a bunch of words, I'd like to translate 114 00:04:37,600 --> 00:04:40,010 that English sentence, if I can, into French. 115 00:04:40,010 --> 00:04:42,130 And let's look at the code that's going to do it. 116 00:04:42,130 --> 00:04:43,470 I'm going to, again, un-comment it here. 117 00:04:43,470 --> 00:04:44,190 It's on your handout. 118 00:04:44,190 --> 00:04:45,570 I want to walk you through it. 119 00:04:49,660 --> 00:04:52,540 So first thing I'm going to do is actually write a little 120 00:04:52,540 --> 00:04:54,550 procedure the says, given a word in English, I want to 121 00:04:54,550 --> 00:04:57,040 find the corresponding word in French. 122 00:04:57,040 --> 00:04:59,020 And that's pretty easy. 123 00:04:59,020 --> 00:05:01,610 It says, if you give me a, word, and you give me a 124 00:05:01,610 --> 00:05:06,080 dictionary, I'm just going to look it up in the dictionary. 125 00:05:06,080 --> 00:05:07,670 That's just that associative retrieval. 126 00:05:07,670 --> 00:05:09,940 It does all the work to go into the dictionary, say, if 127 00:05:09,940 --> 00:05:12,400 that's a key for something in the dictionary, it's going to 128 00:05:12,400 --> 00:05:13,770 give it back to me. 129 00:05:13,770 --> 00:05:18,020 And in particular, I can get it back by simply retrieving 130 00:05:18,020 --> 00:05:20,410 it out of the dictionary. 131 00:05:20,410 --> 00:05:22,410 And notice I'm doing this a little more carefuly. 132 00:05:22,410 --> 00:05:25,370 I'm not just directly going, and saying, give me the thing 133 00:05:25,370 --> 00:05:27,490 corresponding to the word in the dictionary, because it 134 00:05:27,490 --> 00:05:28,600 might not be there. 135 00:05:28,600 --> 00:05:32,530 So that test basically says, if the word is in the 136 00:05:32,530 --> 00:05:34,540 dictionary, it'll return true. 137 00:05:34,540 --> 00:05:38,270 And in that case, I get out the corresponding element. 138 00:05:38,270 --> 00:05:40,280 If it's not in the dictionary, I'm just going to be stuck 139 00:05:40,280 --> 00:05:43,990 with the English words, so we'll just return the word. 140 00:05:43,990 --> 00:05:45,720 Now, let's look at the more fun part of it. 141 00:05:45,720 --> 00:05:50,260 I now want to translate a sentence. 142 00:05:50,260 --> 00:05:54,020 And the sentence is a string of words. 143 00:05:54,020 --> 00:05:55,970 I need to find where the words are. 144 00:05:55,970 --> 00:05:57,260 I need to look them up. 145 00:05:57,260 --> 00:06:00,180 I need to gather together a translation. 146 00:06:00,180 --> 00:06:02,760 So notice what the heart of this thing does, right down 147 00:06:02,760 --> 00:06:04,800 here in this part of the loop that I'm going to highlight 148 00:06:04,800 --> 00:06:05,940 right there. 149 00:06:05,940 --> 00:06:06,750 Oops, I mis-did that. 150 00:06:06,750 --> 00:06:11,410 Let me try it again, right there. 151 00:06:11,410 --> 00:06:13,660 What's that doing? 152 00:06:13,660 --> 00:06:15,510 It's walking down the sentence. 153 00:06:15,510 --> 00:06:16,800 A sentence is some big, long string. 154 00:06:16,800 --> 00:06:20,340 And it says for each character C in the sentence, I need to 155 00:06:20,340 --> 00:06:22,710 find where the word is. 156 00:06:22,710 --> 00:06:26,690 So I'm going to keep walking along until I find a place 157 00:06:26,690 --> 00:06:28,330 where there's a space. 158 00:06:28,330 --> 00:06:33,490 So that first test there is saying, if C is not a space, 159 00:06:33,490 --> 00:06:36,010 just add it onto the end of the word. 160 00:06:36,010 --> 00:06:38,130 Oh, yeah, I need to have inititalized word, which I did 161 00:06:38,130 --> 00:06:38,820 right up here. 162 00:06:38,820 --> 00:06:41,260 I said, let's set word to just be an empty string. 163 00:06:41,260 --> 00:06:45,680 So I'm just walking along the sentence until I find a space. 164 00:06:45,680 --> 00:06:47,640 Until I do that, I'm just gathering together all of 165 00:06:47,640 --> 00:06:48,230 those characters. 166 00:06:48,230 --> 00:06:49,740 So I'm building up the word. 167 00:06:49,740 --> 00:06:54,540 When I get to the place where in fact C is a space, then 168 00:06:54,540 --> 00:06:56,370 here's what I'm going to do. 169 00:06:56,370 --> 00:06:59,480 I'm going to translate the word using that procedure I 170 00:06:59,480 --> 00:06:59,980 just wrote. 171 00:06:59,980 --> 00:07:01,110 It looks it up in the dictionary. 172 00:07:01,110 --> 00:07:03,160 It either gives me back the French word, if it's there, 173 00:07:03,160 --> 00:07:05,890 and if not, it just gives me back the English word. 174 00:07:05,890 --> 00:07:07,680 And, oh yeah, I'm doing a whole long sentence. 175 00:07:07,680 --> 00:07:08,900 So I need to add it together. 176 00:07:08,900 --> 00:07:12,300 So I'm simply going to add it to the end of what I've 177 00:07:12,300 --> 00:07:15,070 translated so far. 178 00:07:15,070 --> 00:07:16,910 And I'm doing a slightly funky thing in there. 179 00:07:16,910 --> 00:07:19,530 I'm inserting a space in between, just to keep the 180 00:07:19,530 --> 00:07:20,690 words separate. 181 00:07:20,690 --> 00:07:23,960 And of course, I need to have initialized translation up 182 00:07:23,960 --> 00:07:26,780 here, which I did, to be an empty string. 183 00:07:26,780 --> 00:07:27,620 So what's this do? 184 00:07:27,620 --> 00:07:29,140 Walks along character by character. 185 00:07:29,140 --> 00:07:31,250 When it gets to a space, it says, I've got a word. 186 00:07:31,250 --> 00:07:33,830 Find the translation, add it to the end of this other 187 00:07:33,830 --> 00:07:36,370 internal variable, and keep going. 188 00:07:36,370 --> 00:07:39,200 And I'll do that until I get to the end of that sentence. 189 00:07:39,200 --> 00:07:42,140 And then I'll just return the translation. 190 00:07:42,140 --> 00:07:44,570 Nice little iterative loop. 191 00:07:44,570 --> 00:07:46,160 And it's simply using two pieces to 192 00:07:46,160 --> 00:07:47,410 make all of this happen. 193 00:07:50,260 --> 00:07:52,200 I lied too you-- sorry, I didn't lie. 194 00:07:52,200 --> 00:07:54,410 I misspoke to you. 195 00:07:54,410 --> 00:07:57,640 Which is, what's that funky thing at the end? 196 00:07:57,640 --> 00:07:58,520 What's it returning? 197 00:07:58,520 --> 00:08:00,770 It's returning this strange thing this says, 198 00:08:00,770 --> 00:08:04,990 "Translation," starting with the first element, a copy of 199 00:08:04,990 --> 00:08:10,190 all of that, plus a translation of the word. 200 00:08:10,190 --> 00:08:14,250 So what assumption am I making about the inputs that causes 201 00:08:14,250 --> 00:08:16,806 me to do this strange thing at the end? 202 00:08:16,806 --> 00:08:19,070 I'm actually making two assumptions about my input. 203 00:08:19,070 --> 00:08:20,810 But I'm making a particular assumption. 204 00:08:20,810 --> 00:08:24,430 Why do I not just return translation when I'm done? 205 00:08:24,430 --> 00:08:27,560 Why am I doing this last piece? 206 00:08:27,560 --> 00:08:29,581 Anybody help me out? 207 00:08:29,581 --> 00:08:32,780 Boy, I notice everybody sits way back at the back, where I 208 00:08:32,780 --> 00:08:34,030 can't make any eye contact. 209 00:08:38,110 --> 00:08:42,080 How do I characterize words in my string? 210 00:08:42,080 --> 00:08:44,430 They have to end with a space. 211 00:08:44,430 --> 00:08:48,115 Ooh, is there a space at the end of my example? 212 00:08:48,115 --> 00:08:50,100 So I guess I haven't shown you an example. 213 00:08:50,100 --> 00:08:52,260 But I'm assuming if I give you a sentence, you don't usually 214 00:08:52,260 --> 00:08:54,240 have spaces at the end of sentences. 215 00:08:54,240 --> 00:08:57,260 So I'm making an assumption, is that the words, except for 216 00:08:57,260 --> 00:08:59,830 the last one, are characterized by spaces. 217 00:08:59,830 --> 00:09:03,640 So this last little piece here is to get the very last word, 218 00:09:03,640 --> 00:09:04,830 and translate it. 219 00:09:04,830 --> 00:09:08,810 Because it won't be a space. 220 00:09:08,810 --> 00:09:10,440 Let's try a couple of examples. 221 00:09:10,440 --> 00:09:15,760 Let's just un-comment these, and see if this does it. 222 00:09:15,760 --> 00:09:18,090 Yes, commenting them again is not a good idea. 223 00:09:18,090 --> 00:09:19,340 We'll go the other direction. 224 00:09:28,130 --> 00:09:30,370 Looks like it did right. 225 00:09:30,370 --> 00:09:32,530 John-- we should have translated John into Jean. 226 00:09:32,530 --> 00:09:34,650 I don't know what the hell Eric is in French, but John 227 00:09:34,650 --> 00:09:38,230 mange du pan, Eric boit du vin. 228 00:09:38,230 --> 00:09:39,050 John has that right. 229 00:09:39,050 --> 00:09:39,760 He's eats bread. 230 00:09:39,760 --> 00:09:41,030 I like to drink wine. 231 00:09:41,030 --> 00:09:45,380 And, of course, tout le monde aime 6.00. 232 00:09:45,380 --> 00:09:47,680 Or in this case, everyone likes 6.00. 233 00:09:47,680 --> 00:09:50,680 You just got HASS credit, by the way, for listening to me 234 00:09:50,680 --> 00:09:53,498 do French really badly. 235 00:09:53,498 --> 00:09:57,390 OK, as I said, I made an assumption, which that the 236 00:09:57,390 --> 00:09:58,250 words end in spaces. 237 00:09:58,250 --> 00:10:00,582 What's the other assumption I made here? 238 00:10:00,582 --> 00:10:02,220 I know you're just looking at the code. 239 00:10:02,220 --> 00:10:04,440 But I made another assumption inside of my code. 240 00:10:04,440 --> 00:10:05,720 And it's always good to figure out what 241 00:10:05,720 --> 00:10:09,110 those assumptions are. 242 00:10:09,110 --> 00:10:10,926 Yeah? 243 00:10:10,926 --> 00:10:14,342 AUDIENCE: That the first word is a noun, so we don't have to 244 00:10:14,342 --> 00:10:15,318 translate it? 245 00:10:15,318 --> 00:10:16,782 ERIC GRIMSON: I didn't assume that. 246 00:10:16,782 --> 00:10:19,020 I could if I was doing a more clever translation. 247 00:10:19,020 --> 00:10:20,000 But I'm actually making no assumptions 248 00:10:20,000 --> 00:10:21,900 linguistically here. 249 00:10:21,900 --> 00:10:23,150 I'll give you a hint. 250 00:10:23,150 --> 00:10:27,390 How many spaces do I have between words? 251 00:10:27,390 --> 00:10:28,560 Just one. 252 00:10:28,560 --> 00:10:30,440 I'm sort of building that into this assumption. 253 00:10:30,440 --> 00:10:32,040 It's a reasonable assumption to make. 254 00:10:32,040 --> 00:10:34,480 But it points out, if I wanted to improve the code, I should 255 00:10:34,480 --> 00:10:35,700 think about these other cases. 256 00:10:35,700 --> 00:10:37,900 And of course, to build a real translation system, I'd need 257 00:10:37,900 --> 00:10:39,150 something much more sophisticated. 258 00:10:42,140 --> 00:10:44,860 So this shows you little example of using the 259 00:10:44,860 --> 00:10:45,200 dictionaries. 260 00:10:45,200 --> 00:10:47,770 But I want to use this to lead into the main part of today's 261 00:10:47,770 --> 00:10:50,980 lecture, which is, why did I write this separate little 262 00:10:50,980 --> 00:10:54,820 procedure up here called translate word? 263 00:10:54,820 --> 00:10:58,670 I could have buried that inside the code. 264 00:10:58,670 --> 00:11:02,420 And the answer is twofold. 265 00:11:02,420 --> 00:11:05,910 First one is it saves a small amount of code. 266 00:11:05,910 --> 00:11:08,790 If I'm going to use it in multiple places, I don't want 267 00:11:08,790 --> 00:11:11,000 to rewrite the code. 268 00:11:11,000 --> 00:11:13,610 And that actually is valuable, not just to save you typing. 269 00:11:13,610 --> 00:11:16,355 It means I only have to debug it once. 270 00:11:16,355 --> 00:11:18,750 It's one piece of code. 271 00:11:18,750 --> 00:11:21,750 But the real reason I wanted to introduce it is it gives me 272 00:11:21,750 --> 00:11:24,210 what you might think of as modular abstraction. 273 00:11:24,210 --> 00:11:27,820 Those are fancy words that basically say I am isolating 274 00:11:27,820 --> 00:11:31,240 that function in one place. 275 00:11:31,240 --> 00:11:35,740 If I decide to change how I'm going to translate words, I 276 00:11:35,740 --> 00:11:38,440 don't have to search through all of my code to find all the 277 00:11:38,440 --> 00:11:40,070 places where I was using that. 278 00:11:40,070 --> 00:11:45,140 I just need to change the definition of that procedure. 279 00:11:45,140 --> 00:11:47,600 And I agree, in a simple example like this, it looks 280 00:11:47,600 --> 00:11:48,150 pretty simple. 281 00:11:48,150 --> 00:11:50,580 But if you've got a million lines of code, you're using it 282 00:11:50,580 --> 00:11:53,500 10,000 different places, you don't want to have to find all 283 00:11:53,500 --> 00:11:54,530 the places to change. 284 00:11:54,530 --> 00:11:59,460 So this is an example of modular abstraction, isolating 285 00:11:59,460 --> 00:12:00,510 where that thing is. 286 00:12:00,510 --> 00:12:03,500 And that is an example, in fact, of a general 287 00:12:03,500 --> 00:12:09,770 problem-solving principle we're going to use, called 288 00:12:09,770 --> 00:12:11,175 divide and conquer. 289 00:12:16,800 --> 00:12:20,370 Divide and conquer is basically the idea of taking a 290 00:12:20,370 --> 00:12:24,380 hard problem, and breaking it up into some simpler pieces, 291 00:12:24,380 --> 00:12:26,890 or into smaller problems, where those smaller problems 292 00:12:26,890 --> 00:12:28,140 have two properties. 293 00:12:33,670 --> 00:12:43,830 Small problems are easier to solve than the original one. 294 00:12:43,830 --> 00:12:49,070 More importantly, the solutions to the small 295 00:12:49,070 --> 00:12:54,680 problems can easily be combined-- 296 00:12:54,680 --> 00:12:56,270 I want to stress easily-- 297 00:13:00,150 --> 00:13:01,400 to solve the big problem. 298 00:13:14,070 --> 00:13:15,370 And we're going to look at a bunch of examples 299 00:13:15,370 --> 00:13:17,740 today to show that. 300 00:13:17,740 --> 00:13:20,130 This is a really old idea. 301 00:13:20,130 --> 00:13:21,840 Julius Caesar used it. 302 00:13:21,840 --> 00:13:22,860 He did it in Latin. 303 00:13:22,860 --> 00:13:25,370 My Latin is terrible, but it's something like divide et 304 00:13:25,370 --> 00:13:28,100 impera, which literally means divide and rule. 305 00:13:28,100 --> 00:13:30,980 That's how he created the Roman Empire. 306 00:13:30,980 --> 00:13:32,330 The British knew this really well. 307 00:13:32,330 --> 00:13:34,300 That's how they control the Indian subcontinent 308 00:13:34,300 --> 00:13:36,990 brilliantly for several decades. 309 00:13:36,990 --> 00:13:39,120 Ben Franklin actually knew it. 310 00:13:39,120 --> 00:13:41,270 In particular, he knew how good the British were at this. 311 00:13:41,270 --> 00:13:42,610 So there's a famous quote. 312 00:13:42,610 --> 00:13:44,640 You may well remember-- when he signed the Declaration of 313 00:13:44,640 --> 00:13:48,270 Independence, he said, quote, "We must all hang together, or 314 00:13:48,270 --> 00:13:51,560 assuredly we will hang separately," meaning divide 315 00:13:51,560 --> 00:13:54,590 and conquer is going to be a real problem. 316 00:13:54,590 --> 00:13:56,210 So second HASS credit for you. 317 00:13:56,210 --> 00:13:57,780 We just did some history. 318 00:13:57,780 --> 00:13:59,070 Why are we going to use it today? 319 00:13:59,070 --> 00:14:01,210 Boy, you're a tough audience, I noticed, by the way. 320 00:14:01,210 --> 00:14:02,800 That's all right. 321 00:14:02,800 --> 00:14:04,880 We're going to use it today, because we're going to use it 322 00:14:04,880 --> 00:14:06,540 as a tool for problem-solving. 323 00:14:06,540 --> 00:14:10,460 And in particular, we're going to use it with 324 00:14:10,460 --> 00:14:11,480 one particular example. 325 00:14:11,480 --> 00:14:14,450 You're going to see divide and conquer later on in the term, 326 00:14:14,450 --> 00:14:17,590 when Professor Guttag talks about algorithm design. 327 00:14:17,590 --> 00:14:20,380 Today, I'm going to show you one great technique for doing 328 00:14:20,380 --> 00:14:22,920 divide and conquer kind of algorithms. 329 00:14:22,920 --> 00:14:24,525 And that is the technique of recursion. 330 00:14:33,040 --> 00:14:35,060 How many people here have heard that term used before by 331 00:14:35,060 --> 00:14:37,680 computer scientists? 332 00:14:37,680 --> 00:14:40,310 OK, not to worry. 333 00:14:40,310 --> 00:14:42,040 If you've heard it, you probably think that it's a 334 00:14:42,040 --> 00:14:45,160 really subtle programming technique. 335 00:14:45,160 --> 00:14:47,220 I'll let you in on a secret. 336 00:14:47,220 --> 00:14:48,950 That's a PR job. 337 00:14:48,950 --> 00:14:50,890 It's what computer scientists tell you to make you think 338 00:14:50,890 --> 00:14:53,620 that they're much smarter than they really are. 339 00:14:53,620 --> 00:14:56,050 It's not subtle, and it's much more than 340 00:14:56,050 --> 00:14:57,070 a programming technique. 341 00:14:57,070 --> 00:14:59,900 And we're going to talk about it. 342 00:14:59,900 --> 00:15:03,190 Now, it gets used not just as a programming technique. 343 00:15:03,190 --> 00:15:05,520 It gets used two other ways in computer science. 344 00:15:05,520 --> 00:15:08,200 And I'm going to talk about both. 345 00:15:08,200 --> 00:15:18,320 It's both a way of describing or defining problems, so it's 346 00:15:18,320 --> 00:15:20,580 a way of characterizing a problem independent of how we 347 00:15:20,580 --> 00:15:21,960 might implement it. 348 00:15:21,960 --> 00:15:24,225 And it is a way of designing solutions. 349 00:15:34,440 --> 00:15:36,625 So an example of divide and conquer. 350 00:15:39,630 --> 00:15:41,612 Let me give you an example just to show you of why it's a 351 00:15:41,612 --> 00:15:44,600 way of defining a problem. 352 00:15:44,600 --> 00:15:49,080 Consider the part of the legal code that defines the notion 353 00:15:49,080 --> 00:15:52,355 of a natural-born US citizen, and remind you, to be eligible 354 00:15:52,355 --> 00:15:55,130 to run for president, which I hope you all do, you have to 355 00:15:55,130 --> 00:15:57,710 be a natural-born US citizen. 356 00:15:57,710 --> 00:15:59,460 Definition has two parts. 357 00:15:59,460 --> 00:16:02,350 Part number one, anyone born within the United States is a 358 00:16:02,350 --> 00:16:04,690 natural-born citizen. 359 00:16:04,690 --> 00:16:08,880 Part number two, anyone born outside the United States, 360 00:16:08,880 --> 00:16:13,050 both of whose parents are citizens of the United States, 361 00:16:13,050 --> 00:16:15,620 is a natural-born citizen, as long as one parent has 362 00:16:15,620 --> 00:16:18,520 lived in the US. 363 00:16:18,520 --> 00:16:19,840 A little more complicated. 364 00:16:19,840 --> 00:16:20,620 What does that actually say? 365 00:16:20,620 --> 00:16:21,730 Well, it's got two parts. 366 00:16:21,730 --> 00:16:24,085 And that's what a recursive definition has. 367 00:16:24,085 --> 00:16:25,925 The first part is simple. 368 00:16:25,925 --> 00:16:29,640 You're born here, natural-born US citizen. 369 00:16:29,640 --> 00:16:30,850 Notice the second part. 370 00:16:30,850 --> 00:16:33,120 It says, you weren't born here, you might still be a 371 00:16:33,120 --> 00:16:33,950 natural-born citizen. 372 00:16:33,950 --> 00:16:34,550 But what you have to do? 373 00:16:34,550 --> 00:16:38,110 You have to decide if your parents are US citizens-- 374 00:16:38,110 --> 00:16:40,360 which they could be by having been born here, but there are 375 00:16:40,360 --> 00:16:42,260 other ways to be naturalized-- 376 00:16:42,260 --> 00:16:44,280 and that may require you determining if your 377 00:16:44,280 --> 00:16:48,970 grandparents are US citizens, which may require you to-- ah. 378 00:16:48,970 --> 00:16:52,890 So you may have to chain down several sets of problems. 379 00:16:52,890 --> 00:16:54,620 Those two parts are what exactly we're going to use 380 00:16:54,620 --> 00:16:56,470 when we talk about recursive definitions. 381 00:16:56,470 --> 00:16:59,430 There's what we call a base part, which typically 382 00:16:59,430 --> 00:17:02,450 describes the simplest version of the problem. 383 00:17:02,450 --> 00:17:08,420 And then there is an inductive part that tends to describe 384 00:17:08,420 --> 00:17:10,690 how you reduce the problem to simpler 385 00:17:10,690 --> 00:17:11,810 versions of the same problem. 386 00:17:11,810 --> 00:17:14,079 So in fact, let me write those both down. 387 00:17:14,079 --> 00:17:15,304 We have-- 388 00:17:15,304 --> 00:17:16,780 it's called a base case. 389 00:17:21,970 --> 00:17:26,720 This typically gives us a direct answer. 390 00:17:26,720 --> 00:17:29,570 It just tells us very simply, using very simple methods, 391 00:17:29,570 --> 00:17:32,060 whether this is something that satisfies that recursive 392 00:17:32,060 --> 00:17:33,650 definition. 393 00:17:33,650 --> 00:17:37,350 And there is the recursive or inductive case. 394 00:17:43,280 --> 00:17:55,360 Here, you reduce to a simpler version of the same problem, 395 00:17:55,360 --> 00:17:56,835 plus some other simple operations. 396 00:18:04,400 --> 00:18:06,040 OK, again, a bunch of words. 397 00:18:06,040 --> 00:18:07,290 Let me show you some examples. 398 00:18:09,800 --> 00:18:11,700 I'm going to start with three or four different examples, 399 00:18:11,700 --> 00:18:13,040 just to show you how quickly we do this. 400 00:18:13,040 --> 00:18:16,340 What I want you to see in all of these examples is that when 401 00:18:16,340 --> 00:18:19,080 I describe the problem, I'm describing it in terms of 402 00:18:19,080 --> 00:18:22,330 what's the simplest case, and then how do I build solutions 403 00:18:22,330 --> 00:18:25,500 to bigger problems from solutions to smaller versions 404 00:18:25,500 --> 00:18:27,680 of the same problems? 405 00:18:27,680 --> 00:18:30,060 OK, here's the first case I'm going to do. 406 00:18:30,060 --> 00:18:34,200 Suppose I tell you I want to build a little procedure to do 407 00:18:34,200 --> 00:18:37,890 exponentiation, integer exponents. 408 00:18:37,890 --> 00:18:39,250 I want to compute b to the n. 409 00:18:39,250 --> 00:18:42,120 But I tell you I've got a really cheap machine, and all 410 00:18:42,120 --> 00:18:43,870 I can do is multiplication. 411 00:18:43,870 --> 00:18:46,820 So I can't use exp. 412 00:18:46,820 --> 00:18:47,540 Mathematician-- 413 00:18:47,540 --> 00:18:51,222 a course 18 person would say, what's b to the n? 414 00:18:51,222 --> 00:18:59,290 That's b times b times b, n times. 415 00:18:59,290 --> 00:19:00,510 How could I solve this? 416 00:19:00,510 --> 00:19:03,380 Well, recursively, I'd like to say, suppose I could solve 417 00:19:03,380 --> 00:19:05,950 smaller versions of the same problem. 418 00:19:05,950 --> 00:19:07,800 And if somebody gave me a solution to that smaller 419 00:19:07,800 --> 00:19:09,480 version, how would I build a solution 420 00:19:09,480 --> 00:19:11,210 to the bigger problem? 421 00:19:11,210 --> 00:19:12,880 Oh, that's easy. 422 00:19:12,880 --> 00:19:24,290 That's the same as b times b to the n minus 1. 423 00:19:24,290 --> 00:19:26,500 All right, I can see you're all going, well, duh. 424 00:19:26,500 --> 00:19:27,750 I guess that's what chancellors know. 425 00:19:27,750 --> 00:19:28,820 They're not very bright. 426 00:19:28,820 --> 00:19:30,490 Of course, you know that. 427 00:19:30,490 --> 00:19:32,340 But notice what I did. 428 00:19:32,340 --> 00:19:34,320 I've now reduced it to a simpler version of the same 429 00:19:34,320 --> 00:19:37,100 problem, recursively. 430 00:19:37,100 --> 00:19:43,090 This basically says I wanted to solve b to the n. 431 00:19:43,090 --> 00:19:48,050 It's b times b to the n minus 1. 432 00:19:48,050 --> 00:19:49,080 Oh, yeah, but I've got to figure out 433 00:19:49,080 --> 00:19:50,710 when to unwrap this. 434 00:19:50,710 --> 00:19:52,430 So there's an if there. 435 00:19:52,430 --> 00:19:57,170 And that's true as long as n is greater than one-- 436 00:19:57,170 --> 00:19:59,120 actually, as long as n is greater than 0. 437 00:19:59,120 --> 00:20:01,150 We'll do it that way. 438 00:20:01,150 --> 00:20:08,860 And if n is equal to 0, I know the answer is just 1. 439 00:20:08,860 --> 00:20:11,850 I know you don't believe me, but that's really cool. 440 00:20:11,850 --> 00:20:12,980 Why is it really cool? 441 00:20:12,980 --> 00:20:13,360 What do I have? 442 00:20:13,360 --> 00:20:15,500 I have a base case. 443 00:20:15,500 --> 00:20:18,140 And if it's equal to 0, I know the answer right away. 444 00:20:18,140 --> 00:20:22,640 If n is bigger than 0, oh, let's assume that I've got 445 00:20:22,640 --> 00:20:24,220 somebody who will give me the solution to 446 00:20:24,220 --> 00:20:25,180 that smaller problem. 447 00:20:25,180 --> 00:20:26,730 When I get it, I can just use it, do the 448 00:20:26,730 --> 00:20:29,260 multiplication, and I'm done. 449 00:20:29,260 --> 00:20:33,710 And so, in fact, here is a simple piece of implementation 450 00:20:33,710 --> 00:20:35,720 of that, which I know is not in your handout, but I'm just 451 00:20:35,720 --> 00:20:39,490 going to show to you, because I simply want you to see the 452 00:20:39,490 --> 00:20:42,780 form of it. 453 00:20:42,780 --> 00:20:45,455 It's an exact Python translation 454 00:20:45,455 --> 00:20:47,590 of what I just said. 455 00:20:47,590 --> 00:20:50,690 It says, if I want to take an exponent of b to the n, if n 456 00:20:50,690 --> 00:20:54,490 is equal to 0, just return 1. 457 00:20:54,490 --> 00:20:59,180 If not, solve a smaller version of the same problem 458 00:20:59,180 --> 00:21:01,950 right there. 459 00:21:01,950 --> 00:21:04,330 Call to the same procedure, same function, 460 00:21:04,330 --> 00:21:05,610 but different argument. 461 00:21:05,610 --> 00:21:08,650 And when I get that answer back, just multiply it by b, 462 00:21:08,650 --> 00:21:11,860 and return that. 463 00:21:11,860 --> 00:21:14,110 This may look a little funky. 464 00:21:14,110 --> 00:21:16,110 This is the kind of thing that your high school geometry 465 00:21:16,110 --> 00:21:17,900 teacher would rap your knuckles with, although 466 00:21:17,900 --> 00:21:19,210 they're not allowed to do that anymore. 467 00:21:19,210 --> 00:21:21,930 You don't define things in terms of themselves. 468 00:21:21,930 --> 00:21:23,160 This is not geometry. 469 00:21:23,160 --> 00:21:24,210 This is programming. 470 00:21:24,210 --> 00:21:26,720 And this is a perfectly legal recursive 471 00:21:26,720 --> 00:21:28,380 definition of a problem. 472 00:21:28,380 --> 00:21:33,690 It will stop, because it will keep unwinding those recursive 473 00:21:33,690 --> 00:21:36,090 calls until it gets down to the base case. 474 00:21:36,090 --> 00:21:39,050 And I'm going to show you an example of that in a second. 475 00:21:39,050 --> 00:21:40,845 I want to show you a much nicer example of recursion. 476 00:21:40,845 --> 00:21:43,190 And again, part of my message here is when you get a 477 00:21:43,190 --> 00:21:45,550 problem, don't instantly start writing code. 478 00:21:45,550 --> 00:21:47,570 Think about, how do I break this down recursively? 479 00:21:47,570 --> 00:21:51,830 So I have brought some very high-tech tools with me today. 480 00:21:51,830 --> 00:21:53,690 This is my version of the tower of Hanoi problem. 481 00:21:53,690 --> 00:21:56,820 How many people know the problem of the tower of Hanoi? 482 00:21:56,820 --> 00:21:57,350 Only a few. 483 00:21:57,350 --> 00:21:59,270 OK, so here's the story. 484 00:21:59,270 --> 00:22:03,460 There's a temple in Hanoi staffed by a bunch of monks. 485 00:22:03,460 --> 00:22:05,610 In that temple, there are three tall, 486 00:22:05,610 --> 00:22:07,680 jewel-encrusted spikes. 487 00:22:07,680 --> 00:22:09,510 Mine aren't nearly as fancy. 488 00:22:09,510 --> 00:22:14,170 And there are 64 golden disks, all of a different size. 489 00:22:14,170 --> 00:22:17,710 Stack starts out on one of those spikes, and the monks 490 00:22:17,710 --> 00:22:20,230 move one disk at a time. 491 00:22:20,230 --> 00:22:23,870 Their goal is to move the entire stack of 64 from one 492 00:22:23,870 --> 00:22:27,170 spike to another. 493 00:22:27,170 --> 00:22:29,830 And the rules are they can it of one disk at a time, but 494 00:22:29,830 --> 00:22:32,210 they can never cover up a smaller disk 495 00:22:32,210 --> 00:22:34,270 with a larger disk. 496 00:22:34,270 --> 00:22:36,640 I have to tell you, I don't know what happens when they 497 00:22:36,640 --> 00:22:37,920 move the entire stack. 498 00:22:37,920 --> 00:22:40,880 I mean, the universe ends, or you all get A's in 600, or 499 00:22:40,880 --> 00:22:43,630 something equally as cool. 500 00:22:43,630 --> 00:22:45,610 Question is, could we write a piece of code to help the 501 00:22:45,610 --> 00:22:47,342 monks, to tell them how to move them? 502 00:22:47,342 --> 00:22:48,970 All right, so let's figure this out. 503 00:22:48,970 --> 00:22:50,430 And I'm going to show you some examples. 504 00:22:50,430 --> 00:22:54,320 So I'm going to move a stack of size one. 505 00:22:54,320 --> 00:22:57,110 Well, that's not very hard. 506 00:22:57,110 --> 00:22:58,240 Watch carefully, because you're going to 507 00:22:58,240 --> 00:22:59,160 write code to do this. 508 00:22:59,160 --> 00:23:01,920 I want to move a stack of size two, so I've got to just make 509 00:23:01,920 --> 00:23:03,270 sure that I move the bottom one off. 510 00:23:03,270 --> 00:23:06,530 That's not so hard. 511 00:23:06,530 --> 00:23:08,330 Now, I want to move a stack of size three. 512 00:23:08,330 --> 00:23:10,550 I've got to be a little more careful, because I can't cover 513 00:23:10,550 --> 00:23:12,270 up the smaller one with a larger one. 514 00:23:12,270 --> 00:23:14,981 But that doesn't look very hard. 515 00:23:14,981 --> 00:23:16,280 Got the solution, right? 516 00:23:16,280 --> 00:23:17,770 Now, we go for stack of size four. 517 00:23:17,770 --> 00:23:19,885 This one definitely takes a little bit more care, because 518 00:23:19,885 --> 00:23:21,320 you really can't cover it up. 519 00:23:21,320 --> 00:23:23,650 But as long as you do it right, you can actually move 520 00:23:23,650 --> 00:23:24,980 the-- oops, and I didn't do it right. 521 00:23:24,980 --> 00:23:26,880 You've got to move the pieces in the right way. 522 00:23:26,880 --> 00:23:29,800 I do this for taking money off of Harvard students in Harvard 523 00:23:29,800 --> 00:23:32,160 Square, by the way. 524 00:23:32,160 --> 00:23:33,420 Got it? 525 00:23:33,420 --> 00:23:34,740 Real easy to see the solution, right? 526 00:23:34,740 --> 00:23:35,920 You could write code for that right now. 527 00:23:35,920 --> 00:23:37,660 I'm not going to do five, but it's really 528 00:23:37,660 --> 00:23:39,360 easy to see the solution. 529 00:23:39,360 --> 00:23:40,610 Yeah. 530 00:23:42,930 --> 00:23:43,530 I blew it, too. 531 00:23:43,530 --> 00:23:46,060 I did one move I had to backtrack on. 532 00:23:46,060 --> 00:23:49,000 Let's think about this recursively. 533 00:23:49,000 --> 00:23:51,230 What's the recursive solution? 534 00:23:51,230 --> 00:23:54,560 Break it down into a simpler problem, or a problem of a 535 00:23:54,560 --> 00:23:56,260 smaller size. 536 00:23:56,260 --> 00:23:58,590 Ah, here's the solution. 537 00:23:58,590 --> 00:24:01,410 To solve this, I've got a stack, I've got a stack I'm 538 00:24:01,410 --> 00:24:02,920 going to, I've got a spare stack. 539 00:24:02,920 --> 00:24:03,590 What's the solution? 540 00:24:03,590 --> 00:24:07,690 You take a stack of size n minus 1, move it onto the 541 00:24:07,690 --> 00:24:09,450 spare stack. 542 00:24:09,450 --> 00:24:10,790 Now I've got a simple problem. 543 00:24:10,790 --> 00:24:13,200 I can always move a stack of size one. 544 00:24:13,200 --> 00:24:18,550 And then I move a stack of size n minus 1 to the target. 545 00:24:18,550 --> 00:24:20,500 And, of course, how I move a stack of size n minus 1? 546 00:24:20,500 --> 00:24:22,560 Well, I just unwrap it one more. 547 00:24:22,560 --> 00:24:26,970 That's a really easy explanation, right? 548 00:24:26,970 --> 00:24:30,230 And it's really easy to write code to do exactly that. 549 00:24:30,230 --> 00:24:33,190 So let me show it to you. 550 00:24:33,190 --> 00:24:34,910 Again, I know this isn't in your handout, but I just 551 00:24:34,910 --> 00:24:37,060 wanted to see it. 552 00:24:37,060 --> 00:24:39,710 And you could write this yourself. 553 00:24:39,710 --> 00:24:41,440 I'm going to write a little procedure 554 00:24:41,440 --> 00:24:43,080 right here called Hanoi. 555 00:24:47,020 --> 00:24:48,570 What are my arguments? 556 00:24:48,570 --> 00:24:49,970 Going to tell how big a stack there is. 557 00:24:49,970 --> 00:24:50,960 That's m. 558 00:24:50,960 --> 00:24:53,760 And I'm just going to give it labels, the from stack, the to 559 00:24:53,760 --> 00:24:56,610 stack, and the spare stack. 560 00:24:56,610 --> 00:24:58,880 Look how simple the code is. 561 00:24:58,880 --> 00:25:02,650 Says, if it's a stack of size 1, just move it. 562 00:25:02,650 --> 00:25:04,040 I'll just print out the instruction. 563 00:25:04,040 --> 00:25:06,500 Move it from the from stack to the target 564 00:25:06,500 --> 00:25:08,490 stack, or the to stack. 565 00:25:08,490 --> 00:25:11,610 If it's bigger than 1, what do I do? 566 00:25:11,610 --> 00:25:16,470 I move a stack of size n minus 1 onto the spare stack. 567 00:25:16,470 --> 00:25:19,450 I move a stack of size 1, which is what's left, onto the 568 00:25:19,450 --> 00:25:20,670 target stack. 569 00:25:20,670 --> 00:25:23,970 And then, I move that stack over here that's on the spare 570 00:25:23,970 --> 00:25:26,490 stack over to the target stack. 571 00:25:26,490 --> 00:25:29,100 It's what I just showed you right there. 572 00:25:29,100 --> 00:25:30,100 OK? 573 00:25:30,100 --> 00:25:31,350 So let's try it. 574 00:25:35,400 --> 00:25:36,900 Yes, I know I still like French. 575 00:25:36,900 --> 00:25:37,710 We're going to do Hanoi. 576 00:25:37,710 --> 00:25:39,030 Move a stack of size 1. 577 00:25:39,030 --> 00:25:40,670 And we'll just give this some labels, just 578 00:25:40,670 --> 00:25:44,130 from, to, and spare. 579 00:25:44,130 --> 00:25:44,670 Well, duh. 580 00:25:44,670 --> 00:25:46,540 You just move it there. 581 00:25:46,540 --> 00:25:46,950 All right. 582 00:25:46,950 --> 00:25:49,710 Let's try a stack of size 2. 583 00:25:54,580 --> 00:25:55,920 It's just what I did. 584 00:25:55,920 --> 00:25:57,940 I'm sure you remember that. 585 00:25:57,940 --> 00:25:59,530 Let's be a little more daring here. 586 00:26:05,060 --> 00:26:06,970 There's the solution to move a stack of size 5. 587 00:26:06,970 --> 00:26:08,880 I'll let you check it separately, 588 00:26:08,880 --> 00:26:12,340 make sure it's right. 589 00:26:12,340 --> 00:26:13,530 One of the things you can also see here-- 590 00:26:13,530 --> 00:26:14,410 I'm not going to talk about it. 591 00:26:14,410 --> 00:26:17,020 You might think about it, ask your TA in recitation is, how 592 00:26:17,020 --> 00:26:20,070 long does it take to solve this problem? 593 00:26:20,070 --> 00:26:22,590 How long is it going to take those monks to actually move a 594 00:26:22,590 --> 00:26:23,850 stack of size 64? 595 00:26:23,850 --> 00:26:25,000 I'll give you a hint. 596 00:26:25,000 --> 00:26:27,880 The answer is measured in billions of years. 597 00:26:27,880 --> 00:26:29,480 This is an exponential problem. 598 00:26:29,480 --> 00:26:31,830 And you can see that growth right away. 599 00:26:31,830 --> 00:26:32,780 That's a separate topic. 600 00:26:32,780 --> 00:26:37,040 But notice coming up with that solution on your own, maybe 601 00:26:37,040 --> 00:26:37,810 not so easy. 602 00:26:37,810 --> 00:26:41,560 Thinking about it recursively, very easy to think about. 603 00:26:41,560 --> 00:26:44,440 And that's the way we want to look at it. 604 00:26:44,440 --> 00:26:48,630 OK, let me give you another example of breaking a problem 605 00:26:48,630 --> 00:26:53,350 down recursively, and then writing the code to do. 606 00:26:53,350 --> 00:26:58,730 I want to decide if a sentence is a palindrome. 607 00:26:58,730 --> 00:27:00,190 Remember what a palindrome is? 608 00:27:00,190 --> 00:27:02,450 It is not an ex-governor from Alaska. 609 00:27:02,450 --> 00:27:04,500 It is a string of characters-- 610 00:27:04,500 --> 00:27:07,450 I guess an airport in Alaska-- it's a string of characters 611 00:27:07,450 --> 00:27:09,240 that have the property that they read the 612 00:27:09,240 --> 00:27:12,290 same front to back. 613 00:27:12,290 --> 00:27:14,030 The most famous one in English-- which is, of course, 614 00:27:14,030 --> 00:27:16,550 amusing because it's attributed to a Frenchman-- is 615 00:27:16,550 --> 00:27:21,140 Napoleon supposedly saying, "Able was I ere I saw Elba." 616 00:27:21,140 --> 00:27:23,270 Same thing back to front. 617 00:27:23,270 --> 00:27:26,330 How would I write a piece of code to decide if something is 618 00:27:26,330 --> 00:27:28,190 a palindrome? 619 00:27:28,190 --> 00:27:28,990 I'm going to do it in a second. 620 00:27:28,990 --> 00:27:29,870 You've got it on the handout. 621 00:27:29,870 --> 00:27:32,610 But let's think about it for a second. 622 00:27:32,610 --> 00:27:34,120 What would the base cases be-- 623 00:27:34,120 --> 00:27:36,090 or base case? 624 00:27:36,090 --> 00:27:36,640 Somebody help me out. 625 00:27:36,640 --> 00:27:38,000 What's a good base case here? 626 00:27:41,250 --> 00:27:45,310 What's the shortest possible sentence I could have? 627 00:27:45,310 --> 00:27:46,520 I? 628 00:27:46,520 --> 00:27:46,980 A? 629 00:27:46,980 --> 00:27:47,440 A? 630 00:27:47,440 --> 00:27:49,050 Don't worry about whether it's a legal sense of not. 631 00:27:49,050 --> 00:27:50,430 It might need a verb in there. 632 00:27:50,430 --> 00:27:53,480 Base case is presumably, if I've got a string one 633 00:27:53,480 --> 00:27:56,130 character long, it's a palindrome. 634 00:27:56,130 --> 00:27:59,120 If I've got a string zero characters long, it's probably 635 00:27:59,120 --> 00:28:02,550 a palindrome as well. 636 00:28:02,550 --> 00:28:05,940 How would I take a longer string and break it down into 637 00:28:05,940 --> 00:28:08,420 a simpler version of the same problem to decide if something 638 00:28:08,420 --> 00:28:09,670 is a palindrome? 639 00:28:11,720 --> 00:28:12,970 Anybody want to help me out? 640 00:28:16,020 --> 00:28:17,680 Is that a hand up there, or are you just 641 00:28:17,680 --> 00:28:18,930 scratching your head? 642 00:28:20,960 --> 00:28:21,940 Well-- yeah? 643 00:28:21,940 --> 00:28:25,206 AUDIENCE: Maybe take the first and the last element, see if 644 00:28:25,206 --> 00:28:25,860 they're equal. 645 00:28:25,860 --> 00:28:28,310 If they are, then cut them off, and-- 646 00:28:28,310 --> 00:28:28,800 ERIC GRIMSON: Yeah. 647 00:28:28,800 --> 00:28:30,270 What's a palindrome? 648 00:28:30,270 --> 00:28:32,400 The easy way to start it is take the things at the end, 649 00:28:32,400 --> 00:28:33,340 first and last character. 650 00:28:33,340 --> 00:28:34,890 If they're not the same, it doesn't matter what's 651 00:28:34,890 --> 00:28:35,630 happening in the middle. 652 00:28:35,630 --> 00:28:36,890 This thing can't be a palindrome. 653 00:28:36,890 --> 00:28:38,642 So let's check those. 654 00:28:38,642 --> 00:28:41,950 And oh, yeah, if those are the same character, and I pull 655 00:28:41,950 --> 00:28:44,005 them off, what do I have? 656 00:28:44,005 --> 00:28:47,290 I have a smaller version of the same problem. 657 00:28:47,290 --> 00:28:50,150 I have a new sentence that's now two characters less. 658 00:28:50,150 --> 00:28:51,030 Do the same thing. 659 00:28:51,030 --> 00:28:53,300 Say, is that a palindrome? 660 00:28:53,300 --> 00:28:55,060 So if these characters match, and that's a 661 00:28:55,060 --> 00:28:55,870 palindrome, I'm done. 662 00:28:55,870 --> 00:28:57,220 How do I tell if that's a palindrome? 663 00:28:57,220 --> 00:28:59,530 Check if their two end characters match, and the 664 00:28:59,530 --> 00:29:02,250 things in the middle. 665 00:29:02,250 --> 00:29:05,460 So let's look a little piece of code to make this happen. 666 00:29:09,090 --> 00:29:12,320 I'm going to do it in a couple of pieces. 667 00:29:12,320 --> 00:29:13,860 Here's the first piece I'm going to write. 668 00:29:13,860 --> 00:29:15,110 I'm going to walk you through it. 669 00:29:18,530 --> 00:29:20,520 First thing I'm going to do is I'm going to do this outside 670 00:29:20,520 --> 00:29:23,000 of the recursive call is I need to convert a string 671 00:29:23,000 --> 00:29:24,950 that's put in to make sure that, in fact, 672 00:29:24,950 --> 00:29:25,770 it's in a form I want. 673 00:29:25,770 --> 00:29:28,300 So I don't care about the spaces. 674 00:29:28,300 --> 00:29:29,850 Able was I ere I saw Elba. 675 00:29:29,850 --> 00:29:31,290 The spaces aren't in the same place. 676 00:29:31,290 --> 00:29:31,400 That's OK. 677 00:29:31,400 --> 00:29:33,350 It's really the characters. 678 00:29:33,350 --> 00:29:35,400 And I don't really care about capitalization. 679 00:29:35,400 --> 00:29:38,560 So this little procedure basically says, given a 680 00:29:38,560 --> 00:29:42,260 string, convert it all into lowercase-- and if you haven't 681 00:29:42,260 --> 00:29:45,050 seen that, I'm just importing from a module called string 682 00:29:45,050 --> 00:29:46,770 some built-in procedures-- 683 00:29:46,770 --> 00:29:48,220 and this one simply takes the string, and 684 00:29:48,220 --> 00:29:50,180 makes it all lowercase. 685 00:29:50,180 --> 00:29:51,150 And then what do I do? 686 00:29:51,150 --> 00:29:53,660 Well, just like we did before, I'm just going to walk down 687 00:29:53,660 --> 00:29:57,020 that string, gathering together all of the 688 00:29:57,020 --> 00:29:58,270 characters. 689 00:29:58,270 --> 00:30:01,900 So this little loop just says, let's initialize ans to be an 690 00:30:01,900 --> 00:30:02,530 empty string. 691 00:30:02,530 --> 00:30:05,910 And then for each character in s, if it is a lowercase 692 00:30:05,910 --> 00:30:07,790 character-- and that little test simply does that. 693 00:30:07,790 --> 00:30:11,590 It says, if it's in the set of lowercase characters I'm going 694 00:30:11,590 --> 00:30:13,050 to add it to the end. 695 00:30:13,050 --> 00:30:15,490 And when I'm done, I'm just going to return ans. 696 00:30:15,490 --> 00:30:18,424 Going to return the answer. 697 00:30:18,424 --> 00:30:19,490 A little procedure. 698 00:30:19,490 --> 00:30:21,360 And, by the way, this is a nice piece of programming 699 00:30:21,360 --> 00:30:22,120 style, as well. 700 00:30:22,120 --> 00:30:25,540 I want to separate out things that I want to do once from 701 00:30:25,540 --> 00:30:27,080 the things I'm going to call multiple times. 702 00:30:27,080 --> 00:30:30,930 So I don't need to re-check every time that my string is 703 00:30:30,930 --> 00:30:34,090 all lowercase, I'm just going to convert it out. 704 00:30:34,090 --> 00:30:39,230 Now, let's look at how do we test this. 705 00:30:39,230 --> 00:30:45,250 Well, it's literally just a translation of what we said. 706 00:30:45,250 --> 00:30:46,860 But let's look at the pieces. 707 00:30:46,860 --> 00:30:50,690 It says, if I give you just a string of characters-- 708 00:30:50,690 --> 00:30:52,680 I've gotten rid of the spaces, I've made it all lowercase-- 709 00:30:52,680 --> 00:30:54,330 what does it say to do? 710 00:30:54,330 --> 00:30:55,560 I've got to check for the base cases. 711 00:30:55,560 --> 00:30:58,060 And here, I'm actually going to be careful. 712 00:30:58,060 --> 00:30:59,810 We could have discovered this if we programmed. 713 00:30:59,810 --> 00:31:02,390 There actually are two base cases here, which is, is the 714 00:31:02,390 --> 00:31:07,620 string of length one, or is of length zero? 715 00:31:07,620 --> 00:31:09,430 Why would I end up with two base cases? 716 00:31:09,430 --> 00:31:13,850 Why don't I just check for a string of length one? 717 00:31:13,850 --> 00:31:14,782 Yeah? 718 00:31:14,782 --> 00:31:17,120 AUDIENCE: [INAUDIBLE] 719 00:31:17,120 --> 00:31:18,040 ERIC GRIMSON: Exactly. 720 00:31:18,040 --> 00:31:20,140 I can have an odd or an even number of characters. 721 00:31:20,140 --> 00:31:22,850 So as I'm clipping them off the ends, I might end up with 722 00:31:22,850 --> 00:31:24,450 nothing in the middle, or I might have one 723 00:31:24,450 --> 00:31:25,200 in the middle exactly. 724 00:31:25,200 --> 00:31:27,040 And we might have discovered it if we tried programming it. 725 00:31:27,040 --> 00:31:28,670 But right, exactly right. 726 00:31:28,670 --> 00:31:31,470 So I can capture that by just saying, if the length is less 727 00:31:31,470 --> 00:31:33,010 than or equal to 1, which gets both of those. 728 00:31:33,010 --> 00:31:36,610 In that case, we know the palindrome will return true. 729 00:31:36,610 --> 00:31:38,140 Otherwise, what do we do? 730 00:31:38,140 --> 00:31:40,010 Well, we do what the gentleman over here suggested. 731 00:31:40,010 --> 00:31:43,970 We take the first and the last character of the string-- 732 00:31:43,970 --> 00:31:47,190 again, remind you s with an index of minus 1 goes 733 00:31:47,190 --> 00:31:49,230 backwards 1, if you like, and gives me the last character. 734 00:31:49,230 --> 00:31:52,460 If those two characters are the same, I've now reduced it 735 00:31:52,460 --> 00:31:54,040 to a simpler version of the same problem. 736 00:31:54,040 --> 00:31:59,360 So I simply say, if that's true, and everything else is a 737 00:31:59,360 --> 00:32:02,480 palindrome, return true. 738 00:32:02,480 --> 00:32:05,750 Now, if you've not seen this particular little funky form 739 00:32:05,750 --> 00:32:13,160 right here, that is taking string s, and saying, give me 740 00:32:13,160 --> 00:32:16,360 a copy of everything starting with the first-- 741 00:32:16,360 --> 00:32:18,320 which means not the 0th element-- 742 00:32:18,320 --> 00:32:21,190 and ending with everything up to, but not including, the 743 00:32:21,190 --> 00:32:22,930 last element. 744 00:32:22,930 --> 00:32:25,130 We'll use this to make copies of other kinds of lists. 745 00:32:25,130 --> 00:32:27,870 But that's all that's doing, is saying, give me what's in 746 00:32:27,870 --> 00:32:30,810 that string, throwing away the first and the last element. 747 00:32:30,810 --> 00:32:32,920 And that gives me exactly the recursive call I want. 748 00:32:32,920 --> 00:32:34,350 I'm now saying what? 749 00:32:34,350 --> 00:32:37,670 If the first and last character are the same, and if 750 00:32:37,670 --> 00:32:41,420 what's left over is itself a palindrome, I'm golden. 751 00:32:44,300 --> 00:32:46,500 Now, let me just wrap all of that up in a 752 00:32:46,500 --> 00:32:49,440 little piece here. 753 00:32:49,440 --> 00:32:50,690 I'll un-comment this. 754 00:32:53,780 --> 00:32:56,080 Which is simply going to say, I'm going to print out, or put 755 00:32:56,080 --> 00:32:56,950 a comment in it. 756 00:32:56,950 --> 00:32:58,680 And I'm simply going to put the two pieces together. 757 00:32:58,680 --> 00:33:01,140 Given a string, I'm going to convert it into all lowercase 758 00:33:01,140 --> 00:33:01,970 characters. 759 00:33:01,970 --> 00:33:05,450 And then I'm going to check, is this thing a palindrome? 760 00:33:05,450 --> 00:33:09,985 So again, let's try some examples. 761 00:33:13,190 --> 00:33:15,730 So we'll pick on Professor Guttag. 762 00:33:15,730 --> 00:33:17,200 His name is almost a palindrome. 763 00:33:20,440 --> 00:33:22,650 Not quite. 764 00:33:22,650 --> 00:33:25,860 So we're going to give him a name change. 765 00:33:25,860 --> 00:33:27,110 It helps if I can type. 766 00:33:37,850 --> 00:33:40,760 Oh, good. 767 00:33:40,760 --> 00:33:43,740 Guttag is not, but Guttug, whatever that means in German, 768 00:33:43,740 --> 00:33:47,400 is, because the Gs, the Us, and the Ts all match up. 769 00:33:47,400 --> 00:33:48,270 Oh, and let's see. 770 00:33:48,270 --> 00:33:49,650 Let's try a couple of other ones here. 771 00:33:49,650 --> 00:33:51,160 And I actually typed these in. 772 00:33:51,160 --> 00:33:54,140 We'll check to see if Napoleon really was right when he used 773 00:33:54,140 --> 00:33:55,390 his palindrome. 774 00:33:58,250 --> 00:34:00,750 If you can't read this last one, it says, "Are we not 775 00:34:00,750 --> 00:34:04,290 drawn onward, we few, drawn onward to--" and I can't read 776 00:34:04,290 --> 00:34:05,540 the tail end of that-- 777 00:34:09,980 --> 00:34:20,530 "to new era." And if we try both of those, they are. 778 00:34:20,530 --> 00:34:24,489 What's my point, you're wondering. 779 00:34:24,489 --> 00:34:27,820 I solved this problem by simply breaking it down into 780 00:34:27,820 --> 00:34:29,380 simpler versions of the same problem. 781 00:34:29,380 --> 00:34:31,670 That's the tool that you want. 782 00:34:31,670 --> 00:34:33,590 If you were just trying to think about, how do I keep 783 00:34:33,590 --> 00:34:35,810 track of my indices as I'm walking along? 784 00:34:35,810 --> 00:34:37,239 I'm going to come in from both ends, so I've 785 00:34:37,239 --> 00:34:38,045 got to add and subtract. 786 00:34:38,045 --> 00:34:39,520 And I got to make sure I'm checking things. 787 00:34:39,520 --> 00:34:42,159 You could write a nice iterative loop 788 00:34:42,159 --> 00:34:42,659 that would do it. 789 00:34:42,659 --> 00:34:44,330 Actually, I'll take back the word nice. 790 00:34:44,330 --> 00:34:46,139 You could write an iterative loop that would do it. 791 00:34:46,139 --> 00:34:48,810 But it is not crisp, it's not clean, and it's really 792 00:34:48,810 --> 00:34:50,600 easy to screw up. 793 00:34:50,600 --> 00:34:53,350 Or you could say, let's take advantage of recursion. 794 00:34:53,350 --> 00:34:55,110 Let's just break it down into a simpler 795 00:34:55,110 --> 00:34:56,730 version of the same problem. 796 00:34:56,730 --> 00:35:00,310 You'd get a very nice, simple piece of code. 797 00:35:00,310 --> 00:35:02,530 Now, this may still feel a little mysterious. 798 00:35:02,530 --> 00:35:04,090 I wouldn't blame you if it did. 799 00:35:04,090 --> 00:35:06,550 So let's do the following. 800 00:35:09,310 --> 00:35:11,700 I'm going to comment these out so that we're not constantly 801 00:35:11,700 --> 00:35:12,950 looking at them. 802 00:35:16,448 --> 00:35:18,800 And I'm going to show you what happens if we actually look 803 00:35:18,800 --> 00:35:20,660 inside of this thing to see what's going on. 804 00:35:20,660 --> 00:35:21,980 So just give me a second here. 805 00:35:21,980 --> 00:35:23,770 We're going to comment all of those out. 806 00:35:26,330 --> 00:35:30,820 And let's build a version of this that just prints out as 807 00:35:30,820 --> 00:35:33,790 we go along. 808 00:35:33,790 --> 00:35:36,560 So I'm going to show you right here. 809 00:35:40,940 --> 00:35:44,150 It's the same basic pieces. 810 00:35:44,150 --> 00:35:45,550 And actually, I realized I need to leave 811 00:35:45,550 --> 00:35:46,660 is characters around. 812 00:35:46,660 --> 00:35:50,410 Let me go find my is characters part-- 813 00:35:50,410 --> 00:35:51,430 two characters part. 814 00:35:51,430 --> 00:35:52,870 Sorry, give me a second here. 815 00:35:55,390 --> 00:35:56,640 Going to need that. 816 00:35:58,824 --> 00:36:00,480 So we'll un-comment that region. 817 00:36:00,480 --> 00:36:02,830 That's just doing the conversion for us. 818 00:36:02,830 --> 00:36:03,740 I think this is going to work. 819 00:36:03,740 --> 00:36:05,900 Let's look at what we're doing here. 820 00:36:05,900 --> 00:36:07,200 This is exactly the same thing. 821 00:36:07,200 --> 00:36:09,580 But I'm just going to put some print statements in it, which 822 00:36:09,580 --> 00:36:11,380 as I'm sure you've already heard from Professor Guttag, 823 00:36:11,380 --> 00:36:13,040 is a good thing to do as well. 824 00:36:13,040 --> 00:36:14,260 I want you to see what happens. 825 00:36:14,260 --> 00:36:18,500 So the only changes I'm making here are when I come into the 826 00:36:18,500 --> 00:36:20,170 thing that's doing the checking, I'm going to print 827 00:36:20,170 --> 00:36:22,760 out a little thing that says, what are you calling me with, 828 00:36:22,760 --> 00:36:25,220 so you can see how it does the work. 829 00:36:25,220 --> 00:36:28,890 And then, if it's a base case, I'm going to print out a 830 00:36:28,890 --> 00:36:30,940 statement that says I'm in the base case. 831 00:36:30,940 --> 00:36:32,940 And otherwise, I'm just going to print out something that 832 00:36:32,940 --> 00:36:35,960 says, here's what I'm about to return for the piece of the 833 00:36:35,960 --> 00:36:38,330 string I'm looking at. 834 00:36:38,330 --> 00:36:40,640 So it's just instrumenting, if you like, what I'm going to do 835 00:36:40,640 --> 00:36:41,320 inside of here. 836 00:36:41,320 --> 00:36:43,800 And the other piece I'm going to do is I'm going to have a 837 00:36:43,800 --> 00:36:48,410 little space called indent, so that every time I call a 838 00:36:48,410 --> 00:36:50,040 smaller version of the problem, I'm just going to 839 00:36:50,040 --> 00:36:55,265 indent over a little bit, so you can see how it unwraps it. 840 00:36:55,265 --> 00:37:03,110 And if we do this, just run that through. 841 00:37:03,110 --> 00:37:06,110 Let's try it. 842 00:37:06,110 --> 00:37:12,530 So if I call is palindrome print with Guttag-- 843 00:37:16,780 --> 00:37:19,230 it would really help if I could type, wouldn't it? 844 00:37:25,900 --> 00:37:27,780 Yes, it would really help if I could type. 845 00:37:27,780 --> 00:37:29,750 You're all being really polite, going, ah, he missed a 846 00:37:29,750 --> 00:37:30,460 character there. 847 00:37:30,460 --> 00:37:32,970 But we're not going to tell him, because he's going to 848 00:37:32,970 --> 00:37:34,320 have to figure it out for himself. 849 00:37:37,030 --> 00:37:39,470 Administrators cannot possibly do this. 850 00:37:43,080 --> 00:37:45,760 Ah, notice what it did. 851 00:37:45,760 --> 00:37:47,730 This is how you can see the recursive unwinding. 852 00:37:47,730 --> 00:37:48,810 It said-- 853 00:37:48,810 --> 00:37:50,910 I'm going to check this thing out. 854 00:37:50,910 --> 00:37:52,520 It said way up there-- actually, 855 00:37:52,520 --> 00:37:53,450 I'll just do it here. 856 00:37:53,450 --> 00:37:57,310 It said, I'm going to call it initially with Guttag. 857 00:37:57,310 --> 00:38:00,230 Oh, the two Gs worked so that recursively-- 858 00:38:00,230 --> 00:38:02,680 and notice the push-in here-- said, I'm calling it again 859 00:38:02,680 --> 00:38:07,200 with U-T-T-A. Oh, that one didn't work. 860 00:38:07,200 --> 00:38:10,535 So I didn't have to check any further, and I pushed it out. 861 00:38:10,535 --> 00:38:21,290 On the other hand, if I do this, ha, you can see all of 862 00:38:21,290 --> 00:38:21,840 the stages. 863 00:38:21,840 --> 00:38:23,170 You can see it unwinding it. 864 00:38:23,170 --> 00:38:26,860 It says, to decide if Guttug is a palindrome, 865 00:38:26,860 --> 00:38:27,940 well, I check the ends. 866 00:38:27,940 --> 00:38:30,800 And I've got to check U-T-T-U. I don't know what that is. 867 00:38:30,800 --> 00:38:32,130 Something interesting. 868 00:38:32,130 --> 00:38:33,510 Which says, I got to check that. 869 00:38:36,040 --> 00:38:37,950 Which means I've got a check, oh, there's that base case of 870 00:38:37,950 --> 00:38:39,060 the empty one. 871 00:38:39,060 --> 00:38:41,670 I can now return true-- and I'm going to open this up so 872 00:38:41,670 --> 00:38:42,760 you can see it-- 873 00:38:42,760 --> 00:38:45,160 from the base case, true for that, true for 874 00:38:45,160 --> 00:38:47,260 that, true for that. 875 00:38:47,260 --> 00:38:51,690 Let's do one last one, assuming I can type. 876 00:38:51,690 --> 00:38:52,940 I can't. 877 00:39:11,480 --> 00:39:14,130 Well, you get the idea, right? 878 00:39:14,130 --> 00:39:15,400 It's a little messy. 879 00:39:15,400 --> 00:39:17,270 But we go up a little bit, you can start seeing-- 880 00:39:17,270 --> 00:39:18,880 I'm obviously just going to run out of those pieces 881 00:39:18,880 --> 00:39:20,830 there-- but notice what it's doing. 882 00:39:20,830 --> 00:39:23,710 It's stripping off each of those characters in turn. 883 00:39:23,710 --> 00:39:25,730 You can see how deep this goes in, which is why you've got 884 00:39:25,730 --> 00:39:27,910 all those weird spaces there as I keep going in. 885 00:39:27,910 --> 00:39:29,430 But it starts off by saying, look at 886 00:39:29,430 --> 00:39:30,640 that, oh, look at that. 887 00:39:30,640 --> 00:39:31,270 I've got to look at-- 888 00:39:31,270 --> 00:39:33,130 [GIBBERISH] 889 00:39:33,130 --> 00:39:35,800 Which says, I've got to look at [GIBBERISH] 890 00:39:35,800 --> 00:39:36,670 You get the idea. 891 00:39:36,670 --> 00:39:37,910 But notice the key thing. 892 00:39:37,910 --> 00:39:39,750 I'm simply reducing it to a simpler 893 00:39:39,750 --> 00:39:41,720 version of the same problem. 894 00:39:41,720 --> 00:39:43,620 You can also see that to get the answer out, I've got to 895 00:39:43,620 --> 00:39:45,580 stack up a whole bunch of things. 896 00:39:45,580 --> 00:39:48,650 All those indents are basically held operations, 897 00:39:48,650 --> 00:39:51,920 which is one of the properties of a recursive procedure. 898 00:39:51,920 --> 00:39:53,970 You have to hold onto intermediate things. 899 00:39:53,970 --> 00:39:56,020 And that can cause, in some languages, 900 00:39:56,020 --> 00:39:57,620 some efficiency issues. 901 00:39:57,620 --> 00:39:59,900 But in terms of solving the problem, this is really easy. 902 00:39:59,900 --> 00:40:01,880 I've just broken it down into those simple pieces. 903 00:40:01,880 --> 00:40:03,130 And that's really nice. 904 00:40:06,940 --> 00:40:09,130 So let me finish up with one last example 905 00:40:09,130 --> 00:40:10,360 of a recursive procedure. 906 00:40:10,360 --> 00:40:12,530 Again, my goal here is to let you see, what am I doing? 907 00:40:12,530 --> 00:40:14,580 I keep repeating this, but it's important. 908 00:40:14,580 --> 00:40:17,870 To solve a problem, figure out how to break it down into a 909 00:40:17,870 --> 00:40:20,386 simpler version of the same problem. 910 00:40:20,386 --> 00:40:26,900 One of the classic examples of recursion is Fibonacci. 911 00:40:26,900 --> 00:40:29,680 How many people here know the Fibonacci numbers? 912 00:40:29,680 --> 00:40:31,200 A few more, good. 913 00:40:31,200 --> 00:40:33,650 For those of you who don't, here's the story. 914 00:40:33,650 --> 00:40:37,260 Probably heard the phrase, "They breed like rabbits." 915 00:40:37,260 --> 00:40:39,610 It's been used to describe a population that the speaker 916 00:40:39,610 --> 00:40:42,020 thinks is growing too quickly. 917 00:40:42,020 --> 00:40:42,840 Works with rabbits. 918 00:40:42,840 --> 00:40:44,540 It works if you put two pennies in a drawer. 919 00:40:44,540 --> 00:40:47,380 There's a whole bunch of ways in which this happens. 920 00:40:47,380 --> 00:40:49,400 The history of this is actually very old. 921 00:40:49,400 --> 00:40:54,750 It goes back to 1202, when an Italian mathematician named 922 00:40:54,750 --> 00:40:58,600 Leonardo of Pisa, also known as Fibonacci, developed a 923 00:40:58,600 --> 00:41:01,220 formula that he thought would help him quantify the notion 924 00:41:01,220 --> 00:41:03,860 of how rapidly do rabbits breed. 925 00:41:03,860 --> 00:41:04,870 And here was his model. 926 00:41:04,870 --> 00:41:06,440 His model is not great, and we'll see that in a second. 927 00:41:06,440 --> 00:41:07,920 But here's his model. 928 00:41:07,920 --> 00:41:10,310 You start with a newborn pair of rabbits, one 929 00:41:10,310 --> 00:41:12,390 male and one female. 930 00:41:12,390 --> 00:41:14,360 You put them in a pen. 931 00:41:14,360 --> 00:41:16,780 You assume that rabbits are able to mate at 932 00:41:16,780 --> 00:41:19,130 the age of one month. 933 00:41:19,130 --> 00:41:21,480 And you further assume that they have a one-month 934 00:41:21,480 --> 00:41:22,320 gestation period. 935 00:41:22,320 --> 00:41:26,590 So they can produce offspring at the end of a month. 936 00:41:26,590 --> 00:41:29,250 Finally, let's suppose that these mythical rabbits never 937 00:41:29,250 --> 00:41:33,770 die and that the female always produces one new pair-- 938 00:41:33,770 --> 00:41:36,020 that is, a male and a female every month from its 939 00:41:36,020 --> 00:41:37,850 second month on. 940 00:41:37,850 --> 00:41:41,650 The question is, how many female rabbits will there be 941 00:41:41,650 --> 00:41:44,044 at the end of a year? 942 00:41:44,044 --> 00:41:45,390 Hm. 943 00:41:45,390 --> 00:41:47,190 OK, let's see if we can figure this out. 944 00:42:02,130 --> 00:42:07,530 OK, at month 0, when it starts off, there's 1 female rabbit 945 00:42:07,530 --> 00:42:09,490 and 1 male rabbit. 946 00:42:09,490 --> 00:42:13,820 At the end of the first month, there's still one female 947 00:42:13,820 --> 00:42:17,050 rabbit, but she's now pregnant. 948 00:42:17,050 --> 00:42:21,340 So there's still 1. 949 00:42:21,340 --> 00:42:24,090 At the end of the second month, what do we have? 950 00:42:24,090 --> 00:42:26,110 Well, that initial female is still there. 951 00:42:26,110 --> 00:42:28,830 And she has produced one pair. 952 00:42:28,830 --> 00:42:30,095 So there is a second female. 953 00:42:33,550 --> 00:42:38,260 At the end of the third month, that initial female has again 954 00:42:38,260 --> 00:42:40,440 been pregnant and has produced. 955 00:42:40,440 --> 00:42:43,810 And these two are still there. 956 00:42:43,810 --> 00:42:47,060 So there are 3. 957 00:42:47,060 --> 00:42:52,540 At the end of the fourth month, both of these females 958 00:42:52,540 --> 00:42:54,460 have now produced offspring. 959 00:42:54,460 --> 00:42:57,246 And those 3 females are now pregnant. 960 00:42:57,246 --> 00:42:58,496 There are 5. 961 00:43:04,020 --> 00:43:08,390 At the end of the fifth month, those 3 females 962 00:43:08,390 --> 00:43:09,590 have produced offspring. 963 00:43:09,590 --> 00:43:11,560 Those 5 are now pregnant. 964 00:43:11,560 --> 00:43:14,980 There are 8. 965 00:43:14,980 --> 00:43:17,940 And at the end of the sixth month, there are 13. 966 00:43:21,340 --> 00:43:23,640 What did I just describe? 967 00:43:23,640 --> 00:43:26,435 I just described a nice recursive relationship. 968 00:43:29,010 --> 00:43:32,110 That says, gee, there ought to be a base case. 969 00:43:32,110 --> 00:43:35,840 And there ought to be a recursive case. 970 00:43:35,840 --> 00:43:41,320 And, in fact, in this case, we can describe this very nicely. 971 00:43:41,320 --> 00:43:48,090 The number of females at month end is the number of females 972 00:43:48,090 --> 00:43:49,740 there were two months earlier-- 973 00:43:49,740 --> 00:43:51,620 because they've all given birth, so that's 974 00:43:51,620 --> 00:43:53,440 that many new females-- 975 00:43:53,440 --> 00:43:58,960 plus the number of females there were at the previous 976 00:43:58,960 --> 00:44:03,370 month, who are now all in whelp. 977 00:44:03,370 --> 00:44:05,790 Ah, that's a recursive relationship. 978 00:44:05,790 --> 00:44:08,770 If I wanted to figure out how many females there are at 979 00:44:08,770 --> 00:44:11,840 month end, what do I have to do? 980 00:44:11,840 --> 00:44:14,380 Well, I just have to say, what's the base case? 981 00:44:14,380 --> 00:44:15,880 Because there's the recursive case. 982 00:44:15,880 --> 00:44:19,470 And the base case is-- 983 00:44:19,470 --> 00:44:20,190 let me do it this way. 984 00:44:20,190 --> 00:44:26,580 If n is equal to 0 or 1, it's 1. 985 00:44:30,710 --> 00:44:34,300 And as a consequence, I should be able to figure out how 986 00:44:34,300 --> 00:44:37,400 quickly do rabbits breed, at least according to 12th 987 00:44:37,400 --> 00:44:41,260 century Italian mathematicians. 988 00:44:41,260 --> 00:44:45,310 A couple of things to notice here, by the way. 989 00:44:45,310 --> 00:44:47,710 Sort of similar to what I saw in the towers of Hanoi 990 00:44:47,710 --> 00:44:52,530 problem, I'm going to have multiple recursive calls. 991 00:44:52,530 --> 00:44:55,950 To solve this problem of size n over here, I've got to solve 992 00:44:55,950 --> 00:44:59,230 two smaller problems, and then do the simple operation of 993 00:44:59,230 --> 00:45:00,250 adding them together. 994 00:45:00,250 --> 00:45:01,560 That's OK. 995 00:45:01,560 --> 00:45:03,350 It's going to change the complexity of my algorithm, 996 00:45:03,350 --> 00:45:06,350 but it's perfectly fine to have multiple recursive calls. 997 00:45:06,350 --> 00:45:09,330 And as I saw in my case of the palindrome, I may have more 998 00:45:09,330 --> 00:45:10,370 than one base case. 999 00:45:10,370 --> 00:45:14,100 That's also OK, as long as I can ground this out. 1000 00:45:14,100 --> 00:45:15,570 All right, so let's just look at it. 1001 00:45:15,570 --> 00:45:16,940 How would we write this? 1002 00:45:16,940 --> 00:45:21,090 Let me get rid of that, comment that out. 1003 00:45:21,090 --> 00:45:22,310 We can write a little 1004 00:45:22,310 --> 00:45:25,800 procedure to compute Fibonacci. 1005 00:45:30,090 --> 00:45:30,980 And there's the procedure. 1006 00:45:30,980 --> 00:45:31,740 It's in your handout. 1007 00:45:31,740 --> 00:45:34,080 I've got some things up at the top here that are just making 1008 00:45:34,080 --> 00:45:36,240 sure that I got the right kinds of arguments to pass in, 1009 00:45:36,240 --> 00:45:38,300 which is a cleaner, crisp way of doing it. 1010 00:45:38,300 --> 00:45:39,300 But what do I say? 1011 00:45:39,300 --> 00:45:44,460 I say, if either x is 0 or x is 1, two base cases, just 1012 00:45:44,460 --> 00:45:47,360 return the answer, which is 1. 1013 00:45:47,360 --> 00:45:50,300 Otherwise, solve two-- 1014 00:45:50,300 --> 00:45:51,810 right there-- 1015 00:45:51,810 --> 00:45:54,100 smaller sub-problems. 1016 00:45:54,100 --> 00:45:55,440 And what's the simple operation? 1017 00:45:55,440 --> 00:45:57,830 Just add the two things together, and return it out. 1018 00:46:00,370 --> 00:46:02,900 And if I do this, we can check to see if we actually compute 1019 00:46:02,900 --> 00:46:05,260 Fibonacci properly. 1020 00:46:05,260 --> 00:46:08,370 All right, let's do a test fib of 0. 1021 00:46:11,900 --> 00:46:14,550 It says, ah, fib of 0 is 1. 1022 00:46:14,550 --> 00:46:20,080 To do a test fib of 1-- there's my other base case. 1023 00:46:20,080 --> 00:46:22,500 Aha, it says, there they go. 1024 00:46:22,500 --> 00:46:27,400 And now, let's do something a little larger. 1025 00:46:31,180 --> 00:46:31,610 There it is. 1026 00:46:31,610 --> 00:46:35,290 As it gets each computation it's doing, it says, to get 1027 00:46:35,290 --> 00:46:37,550 fib of 3, I've got to solve fib of 0, fib of 1028 00:46:37,550 --> 00:46:39,130 1, and fib of 2. 1029 00:46:39,130 --> 00:46:39,970 And there's the answer. 1030 00:46:39,970 --> 00:46:46,480 And just to make sure we're really doing this well, just 1031 00:46:46,480 --> 00:46:47,990 reproduce my table over there. 1032 00:46:50,740 --> 00:46:52,790 Do I expect you to get all of that code right away? 1033 00:46:52,790 --> 00:46:54,490 No, although it's pretty easy to understand. 1034 00:46:54,490 --> 00:46:56,970 What I do expect you to see, though, is notice what I did. 1035 00:46:56,970 --> 00:47:00,180 I took a recursive problem, and broke it down 1036 00:47:00,180 --> 00:47:02,170 into simpler pieces. 1037 00:47:02,170 --> 00:47:05,630 And then I used the solutions of those pieces to give me the 1038 00:47:05,630 --> 00:47:09,150 solution to the larger problem. 1039 00:47:09,150 --> 00:47:14,330 By the way, Leonardo Pisa had it wrong. 1040 00:47:14,330 --> 00:47:17,360 In 1859, as I'm sure many of you know, a wonderful 1041 00:47:17,360 --> 00:47:22,440 Australian farmer named Thomas Austin imported 24 rabbits 1042 00:47:22,440 --> 00:47:25,610 from England to use as targets for hunting. 1043 00:47:25,610 --> 00:47:28,670 10 years later there were 2 million rabbits being shot and 1044 00:47:28,670 --> 00:47:30,700 trapped in Australia. 1045 00:47:30,700 --> 00:47:33,650 And fib, while it grows fast, doesn't go quite that fast. 1046 00:47:33,650 --> 00:47:36,150 So Leonardo of Pisa had it wrong. 1047 00:47:36,150 --> 00:47:38,350 Of course, as you probably also know, Australia, and I 1048 00:47:38,350 --> 00:47:41,170 think New Zealand, have the wonderful property of having 1049 00:47:41,170 --> 00:47:43,440 more sheep than people. 1050 00:47:43,440 --> 00:47:45,340 I don't know what that says, other than it's a great 1051 00:47:45,340 --> 00:47:47,490 recursive problem. 1052 00:47:47,490 --> 00:47:48,810 Fibonacci, by the way, actually 1053 00:47:48,810 --> 00:47:51,036 shows up in other places. 1054 00:47:51,036 --> 00:47:53,560 Again, it may not be a perfect model of rabbit populations, 1055 00:47:53,560 --> 00:47:56,270 but it has some other really interesting properties. 1056 00:47:56,270 --> 00:47:59,640 One of them is, if you let n get close to infinity, and you 1057 00:47:59,640 --> 00:48:03,110 look at the ratio of fib of n over fib of n minus 1-- 1058 00:48:14,242 --> 00:48:16,110 it sounds like a strange thing to look at. 1059 00:48:16,110 --> 00:48:17,970 It basically tells you how quickly does fib grow. 1060 00:48:17,970 --> 00:48:20,346 Does anybody know the answer to this? 1061 00:48:20,346 --> 00:48:27,210 The golden ratio, 1 plus root 5 over 2, which Leonardo-- 1062 00:48:27,210 --> 00:48:29,320 the other Leonardo, the really good Leonardo-- by the way, 1063 00:48:29,320 --> 00:48:30,650 used to design buildings with. 1064 00:48:30,650 --> 00:48:32,650 So there's a very strange connection. 1065 00:48:32,650 --> 00:48:35,360 The other one thing I like about this is that Fibonacci 1066 00:48:35,360 --> 00:48:37,400 shows up, actually, a lot in nature. 1067 00:48:37,400 --> 00:48:41,400 So, for example, did you know that the number of petals on 1068 00:48:41,400 --> 00:48:45,330 most flowers is a Fibonacci number? 1069 00:48:45,330 --> 00:48:48,850 For example, black-eyed Susans, 13 petals. 1070 00:48:51,560 --> 00:48:55,020 Field daisies, 34 petals. 1071 00:48:55,020 --> 00:48:57,130 You might ask why. 1072 00:48:57,130 --> 00:48:58,190 Oh, sorry. 1073 00:48:58,190 --> 00:48:59,800 I'm out of time. 1074 00:48:59,800 --> 00:49:01,650 I won't answer it today. 1075 00:49:01,650 --> 00:49:04,020 But you can ask Professor Guttag next time around why it 1076 00:49:04,020 --> 00:49:07,150 is that petals come in Fibonacci numbers. 1077 00:49:07,150 --> 00:49:09,620 What's the message of this lecture? 1078 00:49:09,620 --> 00:49:11,840 Recursion, divide and conquer. 1079 00:49:11,840 --> 00:49:13,590 Break a problem down into simpler 1080 00:49:13,590 --> 00:49:14,930 versions of the same problem. 1081 00:49:14,930 --> 00:49:16,900 Life is really easy. 1082 00:49:16,900 --> 00:49:18,410 And you'll see Professor Guttag next time.