1 00:00:00,000 --> 00:00:02,400 ANNOUNCER: Open content is provided under a creative 2 00:00:02,400 --> 00:00:03,840 commons license. 3 00:00:03,840 --> 00:00:06,840 Your support will help MIT OpenCourseWare continue to 4 00:00:06,840 --> 00:00:10,510 offer high quality educational resources for free. 5 00:00:10,510 --> 00:00:13,390 To make a donation, or view additional materials from 6 00:00:13,390 --> 00:00:17,490 hundreds of MIT courses, visit MIT OpenCourseWare at 7 00:00:17,490 --> 00:00:19,930 ocw.mit.edu . 8 00:00:19,930 --> 00:00:23,380 PROFESSOR JOHN GUTTAG: OK. 9 00:00:23,380 --> 00:00:27,360 I finished up last time talking about lists. 10 00:00:27,360 --> 00:00:30,780 And I pointed out that lists are mutable, showed you some 11 00:00:30,780 --> 00:00:34,770 examples of mutation. 12 00:00:34,770 --> 00:00:39,010 We can look at it here; we looked at append, which added 13 00:00:39,010 --> 00:00:43,980 things to lists, we looked at delete, deleting things from a 14 00:00:43,980 --> 00:00:49,010 list. You can also assign to a list, or to an element of a 15 00:00:49,010 --> 00:00:55,880 list. So ivy sub 1, for example, could be assigned 16 00:00:55,880 --> 00:01:03,970 minus 15, and that will actually mutate the list. 17 00:01:03,970 --> 00:01:08,190 So heretofore, when we wrote assignment, what we always 18 00:01:08,190 --> 00:01:13,370 meant, was changing the binding of a variable to a 19 00:01:13,370 --> 00:01:15,960 different object. 20 00:01:15,960 --> 00:01:22,460 Here, we are overloading the notation to say, no, no, ivys 21 00:01:22,460 --> 00:01:29,430 is still bound to the same object, but an element of ivys 22 00:01:29,430 --> 00:01:33,050 is bound to a different object. 23 00:01:33,050 --> 00:01:37,060 If you think about it, that makes sense, because when we 24 00:01:37,060 --> 00:01:49,040 have a list, what a list is, is a sequence of objects. 25 00:01:49,040 --> 00:01:55,890 And what this says is, is the object named by the expression 26 00:01:55,890 --> 00:02:03,820 ivys sub 1, is now bound to the object, if you will, named 27 00:02:03,820 --> 00:02:08,250 by the constant minus 15. 28 00:02:08,250 --> 00:02:20,170 So we can watch this run here. 29 00:02:20,170 --> 00:02:25,500 Idle can-- that's exciting. 30 00:02:25,500 --> 00:02:30,230 I hadn't expected that answer. 31 00:02:30,230 --> 00:02:31,150 All right, your question. 32 00:02:31,150 --> 00:02:32,880 STUDENT: [INAUDIBLE] four elements to ivys, and you tell 33 00:02:32,880 --> 00:02:36,340 it to change the fifth element of ivys to negative 15, will 34 00:02:36,340 --> 00:02:42,230 it add it or [INAUDIBLE] 35 00:02:42,230 --> 00:02:44,680 PROFESSOR JOHN GUTTAG: Well, I'll tell you how ol-- let's 36 00:02:44,680 --> 00:02:48,590 answer that the easy way. 37 00:02:48,590 --> 00:02:55,660 We'll start up a shell and we'll try it. 38 00:02:55,660 --> 00:02:59,360 All right, we'll just get out of what we were doing here. 39 00:02:59,360 --> 00:03:05,050 And so, we now have some things, so we, for example, 40 00:03:05,050 --> 00:03:11,740 have ivys, I can print ivys , and it's only got three 41 00:03:11,740 --> 00:03:14,200 elements but your question probably is just as good for 42 00:03:14,200 --> 00:03:17,380 adding the fourth as adding the fifth, so what would 43 00:03:17,380 --> 00:03:24,370 happen if we say ivys sub 3-- because that of course is the 44 00:03:24,370 --> 00:03:32,590 fourth element, right? 45 00:03:32,590 --> 00:03:36,020 Let's find out. 46 00:03:36,020 --> 00:03:36,880 OK. 47 00:03:36,880 --> 00:03:45,120 Because what that does is, it's changing the binding of 48 00:03:45,120 --> 00:03:49,080 the name ivys, in this case, sub 1. 49 00:03:49,080 --> 00:03:52,860 What it looked at here, with the name ivys sub 3, and said 50 00:03:52,860 --> 00:03:56,750 that name doesn't-- isn't bound, right? 51 00:03:56,750 --> 00:03:58,160 That isn't there. 52 00:03:58,160 --> 00:04:00,880 So it couldn't do it, so instead that's what append is 53 00:04:00,880 --> 00:04:05,910 for, is to stick things on to the end of the list. But a 54 00:04:05,910 --> 00:04:08,840 very good question. 55 00:04:08,840 --> 00:04:16,020 So we can see what we did here, and, but of course I can 56 00:04:16,020 --> 00:04:25,070 now, if I choose, say something like, ivys sub 1 is 57 00:04:25,070 --> 00:04:32,540 assigned minus 15, and now if I print ivys, there it is. 58 00:04:32,540 --> 00:04:35,570 And again, this points out something I wanted to me-- 59 00:04:35,570 --> 00:04:41,260 I mentioned last time, list can be heterogeneous, in the 60 00:04:41,260 --> 00:04:45,100 sense that the elements can be multiple different types. 61 00:04:45,100 --> 00:04:47,480 As you see here, some of the elements are strings and some 62 00:04:47,480 --> 00:04:51,760 of the elements are integers. 63 00:04:51,760 --> 00:04:56,800 Let's look at another example. 64 00:04:56,800 --> 00:05:01,390 Let's suppose, we'll start with the list, 65 00:05:01,390 --> 00:05:08,960 I'll call it l 1. 66 00:05:08,960 --> 00:05:12,430 This, by the way, is a really bad thing I just did. 67 00:05:12,430 --> 00:05:15,690 What was-- what's really bad about calling a list l 1? 68 00:05:15,690 --> 00:05:18,640 STUDENT: [INAUDIBLE] 69 00:05:18,640 --> 00:05:22,050 PROFESSOR JOHN GUTTAG: Is it l 1, or is it 11, or is it l l? 70 00:05:22,050 --> 00:05:27,680 It's a bad habit to get into when you write programs, so I 71 00:05:27,680 --> 00:05:30,510 never use lowercase L except when I'm spelling the word 72 00:05:30,510 --> 00:05:33,920 where it's obvious, because otherwise I get all sorts of 73 00:05:33,920 --> 00:05:35,870 crazy things going on. 74 00:05:35,870 --> 00:05:41,780 All right, so let's make it the list 123. 75 00:05:41,780 --> 00:05:43,050 All right? 76 00:05:43,050 --> 00:05:50,680 Now, I'll say L 2 equals L 1. 77 00:05:50,680 --> 00:05:54,630 Now I'll print L 2. 78 00:05:54,630 --> 00:05:57,380 Kind of what you'd guess, but here's the interesting 79 00:05:57,380 --> 00:06:05,410 question: if I say L 1 is assigned 0, L 1 sub 0 is 80 00:06:05,410 --> 00:06:10,950 assigned 4, I'll print L 1. 81 00:06:10,950 --> 00:06:13,530 That's what you expect, but what's going to happen 82 00:06:13,530 --> 00:06:22,190 if I print L 2? 83 00:06:22,190 --> 00:06:27,590 423 as well, and that's because what happened is I had 84 00:06:27,590 --> 00:06:32,540 this model, which we looked at last time, where I had the 85 00:06:32,540 --> 00:06:44,120 list L 1, which was bound to an object, and then the 86 00:06:44,120 --> 00:06:51,170 assignment L 2 gets L 1, bound the name L 2 to the same 87 00:06:51,170 --> 00:06:58,240 object, so when I mutated this object, which I reached 88 00:06:58,240 --> 00:07:05,190 through the name L 1 to make that 4, since this name was 89 00:07:05,190 --> 00:07:12,440 bound to the same object, when I print it, I got 423. 90 00:07:12,440 --> 00:07:17,470 So that's the key thing to-- to realize; that what the 91 00:07:17,470 --> 00:07:21,090 assignment did was have two separate 92 00:07:21,090 --> 00:07:25,330 paths to the same object. 93 00:07:25,330 --> 00:07:28,310 So I could get to that object either through this path or 94 00:07:28,310 --> 00:07:31,750 through that path, it didn't matter which path I use to 95 00:07:31,750 --> 00:07:35,720 modify it, I would see it when I looked at the other. 96 00:07:35,720 --> 00:07:36,020 Yes. 97 00:07:36,020 --> 00:07:44,260 STUDENT: [INAUDIBLE] 98 00:07:44,260 --> 00:07:50,220 PROFESSOR JOHN GUTTAG: So the question, if I said a is 99 00:07:50,220 --> 00:07:56,530 assigned 2, b is assigned a, and then a is assigned 3. 100 00:07:56,530 --> 00:07:58,200 Is that your question? 101 00:07:58,200 --> 00:08:06,580 So the question is, a is assigned 1, b is assigned a, a 102 00:08:06,580 --> 00:08:18,070 is assigned 2, and then if I print b, I'll get 1. 103 00:08:18,070 --> 00:08:24,330 Because these are not mutable, this is going to be assigned 104 00:08:24,330 --> 00:08:29,340 to an object in the store, so we'll draw the picture over 105 00:08:29,340 --> 00:08:36,480 here, that we had initially a is bound to an object with 1 106 00:08:36,480 --> 00:08:46,270 in it, and then b got bound to the same object, but then when 107 00:08:46,270 --> 00:08:51,750 I did the assignment, what that did was it broke this 108 00:08:51,750 --> 00:08:56,480 connection, and now had a assigned to a different 109 00:08:56,480 --> 00:09:04,310 object, with the number, in this case, 2 in it. 110 00:09:04,310 --> 00:09:12,480 Whereas the list assignment you see here did not rebind 111 00:09:12,480 --> 00:09:18,150 the object l 1, it changed this. 112 00:09:18,150 --> 00:09:18,850 OK? 113 00:09:18,850 --> 00:09:21,680 Now formally I could have had this pointing off to another 114 00:09:21,680 --> 00:09:26,620 object containing 4, but that just seemed excessive, right? 115 00:09:26,620 --> 00:09:28,400 But you see the difference. 116 00:09:28,400 --> 00:09:32,550 Great question, and a very important thing to understand, 117 00:09:32,550 --> 00:09:35,870 and that's why I'm belaboring this point, since this is 118 00:09:35,870 --> 00:09:39,060 where people tend to get pretty confused, and this is 119 00:09:39,060 --> 00:09:42,910 why mutation is very important to understand. 120 00:09:42,910 --> 00:09:43,170 Yeah. 121 00:09:43,170 --> 00:09:45,900 STUDENT: [UNINTELLIGIBLE] 122 00:09:45,900 --> 00:09:46,700 PROFESSOR JOHN GUTTAG: I'm just assuming 123 00:09:46,700 --> 00:09:47,710 it'll be a great question. 124 00:09:47,710 --> 00:09:57,670 STUDENT: [INAUDIBLE] 125 00:09:57,670 --> 00:09:59,260 PROFESSOR JOHN GUTTAG: Exactly. 126 00:09:59,260 --> 00:10:05,140 So if-- very good question-- so, for example, we can just 127 00:10:05,140 --> 00:10:07,770 do it here. 128 00:10:07,770 --> 00:10:15,150 The question was, suppose I now type L 1 equals the empty 129 00:10:15,150 --> 00:10:30,760 list. I can print L 1, and I can print L 2, because again, 130 00:10:30,760 --> 00:10:34,480 that's analogous to this example, where I just swung 131 00:10:34,480 --> 00:10:37,190 the binding of the identifier. 132 00:10:37,190 --> 00:10:40,770 So this is important, it's a little bit subtle, but if you 133 00:10:40,770 --> 00:10:44,960 don't really understand this deeply, you'll find yourself 134 00:10:44,960 --> 00:10:48,790 getting confused a lot. 135 00:10:48,790 --> 00:10:50,500 All right? 136 00:10:50,500 --> 00:10:51,020 OK. 137 00:10:51,020 --> 00:10:59,550 Let me move on, and I want to talk about one more type. 138 00:10:59,550 --> 00:11:02,070 By the way, if you look at the handout from last time, you'll 139 00:11:02,070 --> 00:11:04,710 see that there's some other examples of mutation, 140 00:11:04,710 --> 00:11:07,200 including a function that does mutation. 141 00:11:07,200 --> 00:11:09,690 It's kind of interesting, but I don't think we need-- think 142 00:11:09,690 --> 00:11:11,960 we've probably done enough here that I 143 00:11:11,960 --> 00:11:15,310 hope it now make sense. 144 00:11:15,310 --> 00:11:34,120 That one type I want to talk about still is dictionaries. 145 00:11:34,120 --> 00:11:47,650 Like lists, dictionaries are mutable, like lists, they can 146 00:11:47,650 --> 00:11:58,320 be heterogeneous, but unlike lists, they're not ordered. 147 00:11:58,320 --> 00:12:01,730 The elements in them don't have an order, and 148 00:12:01,730 --> 00:12:17,580 furthermore, we have generalized the indexing. 149 00:12:17,580 --> 00:12:24,620 So lists and strings, we can only get at elements by 150 00:12:24,620 --> 00:12:29,320 numbers, by integers, really. 151 00:12:29,320 --> 00:12:33,850 Here what we use is, think of every element of the 152 00:12:33,850 --> 00:12:48,350 dictionary as a key value pair, where the keys are used 153 00:12:48,350 --> 00:12:51,720 as the indices. 154 00:12:51,720 --> 00:13:01,420 So we can have an example, let's look at it. 155 00:13:01,420 --> 00:13:05,920 So, if you look at the function show dics here, 156 00:13:05,920 --> 00:13:11,260 you'll see I've declared a variable called e to f, ah, 157 00:13:11,260 --> 00:13:15,020 think of that as English to French, and I've defined a 158 00:13:15,020 --> 00:13:18,650 dictionary to do translations. 159 00:13:18,650 --> 00:13:25,690 And so, we see that the string one corresponds the-- the key 160 00:13:25,690 --> 00:13:32,670 one corresponds to the value un the key soccer corresponds 161 00:13:32,670 --> 00:13:39,370 to the French word football, et cetera. 162 00:13:39,370 --> 00:13:45,760 It's kind of bizarre, but the French call soccer football. 163 00:13:45,760 --> 00:13:49,110 And then I can index in it. 164 00:13:49,110 --> 00:13:53,100 So if I print e to f of soccer, it will print the 165 00:13:53,100 --> 00:13:56,340 string football. 166 00:13:56,340 --> 00:14:07,170 So you can imagine that this is a very powerful mechanism. 167 00:14:07,170 --> 00:14:09,440 So let's look what happens when I run-- 168 00:14:09,440 --> 00:14:29,200 start to run this. 169 00:14:29,200 --> 00:14:30,780 All right. 170 00:14:30,780 --> 00:14:35,820 So, it says not defined-- and why did it say not defined, 171 00:14:35,820 --> 00:14:36,950 there's an interesting question. 172 00:14:36,950 --> 00:14:41,850 Let's just make sure we get this right, and we start the 173 00:14:41,850 --> 00:14:55,380 show up again-- 174 00:14:55,380 --> 00:14:58,950 All right, so, I run it, and sure 175 00:14:58,950 --> 00:15:02,180 enough, it shows football. 176 00:15:02,180 --> 00:15:10,710 What happens if I go e to f of 0? 177 00:15:10,710 --> 00:15:13,350 I get a key error. 178 00:15:13,350 --> 00:15:16,010 Because, remember, these things are not ordered. 179 00:15:16,010 --> 00:15:19,820 There is no 0th element. 180 00:15:19,820 --> 00:15:24,430 0 is not a key of this particular object. 181 00:15:24,430 --> 00:15:28,970 Now I could have made 0 a key, keys don't have to be strings, 182 00:15:28,970 --> 00:15:32,590 but as it happened, I didn't. 183 00:15:32,590 --> 00:15:55,480 So let's comment that out, so we don't get stuck again. 184 00:15:55,480 --> 00:15:59,880 Where we were before, I've printed it here, you might be 185 00:15:59,880 --> 00:16:01,890 a little surprised of the order. 186 00:16:01,890 --> 00:16:04,710 Why is soccer first? 187 00:16:04,710 --> 00:16:07,190 Because the order of this doesn't matter. 188 00:16:07,190 --> 00:16:10,050 That's why it's using set braces, so 189 00:16:10,050 --> 00:16:12,650 don't worry about that. 190 00:16:12,650 --> 00:16:19,690 The next thing I'm doing is-- so that's that, and then-- 191 00:16:19,690 --> 00:16:24,690 I'm now going to create another one, n to s, for 192 00:16:24,690 --> 00:16:29,125 numbers to strings, where my keys are numbers, in this case 193 00:16:29,125 --> 00:16:33,040 the number 1 corresponds to the word one, and 194 00:16:33,040 --> 00:16:35,660 interestingly enough, I'm also going to have the word one 195 00:16:35,660 --> 00:16:38,260 corresponding to the number 1. 196 00:16:38,260 --> 00:16:41,020 I can use anything I want for keys, I can use anything I 197 00:16:41,020 --> 00:16:45,210 want for values. 198 00:16:45,210 --> 00:16:50,890 And now if we look at this, we see, I can get this. 199 00:16:50,890 --> 00:16:51,420 All right. 200 00:16:51,420 --> 00:16:56,020 So these are extremely valuable. 201 00:16:56,020 --> 00:16:59,440 I can do lots of things with these, and you'll see that as 202 00:16:59,440 --> 00:17:01,950 we get to future assignments, we'll make heavy use of 203 00:17:01,950 --> 00:17:03,850 dictionaries. 204 00:17:03,850 --> 00:17:04,070 Yeah. 205 00:17:04,070 --> 00:17:04,480 Question. 206 00:17:04,480 --> 00:17:07,480 STUDENT: [INAUDIBLE] 207 00:17:07,480 --> 00:17:09,020 PROFESSOR JOHN GUTTAG: You can, but you don't know what 208 00:17:09,020 --> 00:17:11,650 order you'll get them in. 209 00:17:11,650 --> 00:17:16,040 What you can do is you can iterate keys, which gives you 210 00:17:16,040 --> 00:17:20,100 the keys in the dictionary, and then you can choose them, 211 00:17:20,100 --> 00:17:22,530 but there's no guarantee in the order in 212 00:17:22,530 --> 00:17:25,280 which you get keys. 213 00:17:25,280 --> 00:17:28,970 Now you might wonder, why do we have dictionaries? 214 00:17:28,970 --> 00:17:33,330 It would be pretty easy to implement them with lists, 215 00:17:33,330 --> 00:17:37,390 because you could have a list where each element of the list 216 00:17:37,390 --> 00:17:41,850 was a key value pair, and if I wanted to find the value 217 00:17:41,850 --> 00:17:46,410 corresponding to a key, I could say for e in the list, 218 00:17:46,410 --> 00:17:49,520 if the first element of e is the key, then I get the value, 219 00:17:49,520 --> 00:17:52,620 otherwise I look at the next element in the list. 220 00:17:52,620 --> 00:17:56,570 So adding dictionaries, as Professor Grimson said with so 221 00:17:56,570 --> 00:17:58,480 many other things, doesn't give you any more 222 00:17:58,480 --> 00:18:01,940 computational power. 223 00:18:01,940 --> 00:18:04,740 It gives you a lot of expressive convenience, you 224 00:18:04,740 --> 00:18:08,470 can write the programs much more cleanly, but most 225 00:18:08,470 --> 00:18:12,060 importantly, it's fast. 226 00:18:12,060 --> 00:18:15,080 Because if you did what I suggested with the list, the 227 00:18:15,080 --> 00:18:17,890 time to look up the key would be linear in the length of the 228 00:18:17,890 --> 00:18:20,120 list. You'd have to look at each element until 229 00:18:20,120 --> 00:18:21,970 you found the key. 230 00:18:21,970 --> 00:18:25,970 Dictionaries are implemented using a magic technique called 231 00:18:25,970 --> 00:18:32,180 hashing, which we'll look at a little bit later in the term, 232 00:18:32,180 --> 00:18:36,730 which allows us to retrieve keys in constant time. 233 00:18:36,730 --> 00:18:39,980 So it doesn't matter how big the dictionary is, you can 234 00:18:39,980 --> 00:18:45,020 instantaneously retrieve the value associated with the key. 235 00:18:45,020 --> 00:18:46,650 Extremely powerful. 236 00:18:46,650 --> 00:18:49,520 Not in the next problems set but in the problem set after 237 00:18:49,520 --> 00:18:54,660 that, we'll be exploiting that facility of dictionaries. 238 00:18:54,660 --> 00:18:55,190 All right. 239 00:18:55,190 --> 00:18:58,320 Any questions about this? 240 00:18:58,320 --> 00:19:02,410 If not, I will turn the podium over to Professor Grimson. 241 00:19:02,410 --> 00:19:04,220 PROFESSOR ERIC GRIMSON: I've stolen it. 242 00:19:04,220 --> 00:19:24,040 This is like tag team wrestling, right? 243 00:19:24,040 --> 00:19:25,980 Professor Guttag has you on the ropes, I get 244 00:19:25,980 --> 00:19:31,990 to finish you off. 245 00:19:31,990 --> 00:19:34,080 Try this again. 246 00:19:34,080 --> 00:19:35,820 OK. 247 00:19:35,820 --> 00:19:37,730 We wanted to finish up that section, we're now going to 248 00:19:37,730 --> 00:19:42,920 start on a new section, and I want to try and do one and a 249 00:19:42,920 --> 00:19:44,700 half things in the remaining time. 250 00:19:44,700 --> 00:19:46,730 I'm going to introduce one topic that we're going to deal 251 00:19:46,730 --> 00:19:50,590 with fairly quickly, and then we tackle the second topic, 252 00:19:50,590 --> 00:19:52,920 it's going to start today, and we're going to carry on. 253 00:19:52,920 --> 00:19:54,380 So let me tell the two things I want to do. 254 00:19:54,380 --> 00:19:57,580 I want to talk a little bit about how you use the things 255 00:19:57,580 --> 00:19:59,690 we've been building in terms of functions to help you 256 00:19:59,690 --> 00:20:01,930 structure and organize your code. 257 00:20:01,930 --> 00:20:05,010 It's a valuable tool that you want to have as a programmer. 258 00:20:05,010 --> 00:20:07,430 And then we're going to turn to the question of efficiency. 259 00:20:07,430 --> 00:20:09,340 How do we measure efficiency of algorithms? 260 00:20:09,340 --> 00:20:11,140 Which is going to be a really important thing that we want 261 00:20:11,140 --> 00:20:13,340 to deal with, and we'll start it today, it's undoubtedly 262 00:20:13,340 --> 00:20:16,550 going to take us a couple more lectures to finish it off. 263 00:20:16,550 --> 00:20:19,100 Right, so how do you use the idea of 264 00:20:19,100 --> 00:20:21,370 functions to organize code? 265 00:20:21,370 --> 00:20:24,305 We've been doing it implicitly, ever since we 266 00:20:24,305 --> 00:20:25,040 introduced functions. 267 00:20:25,040 --> 00:20:27,050 I want to make it a little more explicit, and I want to 268 00:20:27,050 --> 00:20:29,280 show you a tool for doing that. 269 00:20:29,280 --> 00:20:31,270 And I think the easy way to do is-- is to 270 00:20:31,270 --> 00:20:32,290 do it with an example. 271 00:20:32,290 --> 00:20:34,840 So let's take a really simple example. 272 00:20:34,840 --> 00:20:37,080 I want to compute the length of the 273 00:20:37,080 --> 00:20:39,360 hypotenuse of a right triangle. 274 00:20:39,360 --> 00:20:41,220 And yeah, I know you know how to do it, but let's think 275 00:20:41,220 --> 00:20:43,160 about what might happen if I wanted to do that. 276 00:20:43,160 --> 00:20:47,672 And in particular, if I think about that problem-- actually 277 00:20:47,672 --> 00:20:57,405 I want to do this-- if I think about that problem, I'm going 278 00:20:57,405 --> 00:20:59,710 to write a little piece of pseudo code. 279 00:20:59,710 --> 00:21:03,910 Just to think about how I would break that problem up. 280 00:21:03,910 --> 00:21:04,630 Pseudo code. 281 00:21:04,630 --> 00:21:08,540 Now, you're all linguistic majors, pseudo means false, 282 00:21:08,540 --> 00:21:10,990 this sounds like code that ain't going to run, and that's 283 00:21:10,990 --> 00:21:12,250 not the intent of the term. 284 00:21:12,250 --> 00:21:14,950 When I say pseudo code, what I mean is, I'm going to write a 285 00:21:14,950 --> 00:21:18,160 description of the steps, but not in a particular 286 00:21:18,160 --> 00:21:19,160 programming language. 287 00:21:19,160 --> 00:21:20,665 I'm going to simply write a description of what 288 00:21:20,665 --> 00:21:22,250 do I want to do. 289 00:21:22,250 --> 00:21:24,270 So if I were to solve this problem, here's the way I 290 00:21:24,270 --> 00:21:24,670 would do it. 291 00:21:24,670 --> 00:21:28,060 I would say, first thing I want to do, is I want to input 292 00:21:28,060 --> 00:21:38,420 a value for the base as a float. 293 00:21:38,420 --> 00:21:40,890 Need to get the base in. 294 00:21:40,890 --> 00:21:43,440 Second thing I want to do, I need to get the height, so I'm 295 00:21:43,440 --> 00:21:49,760 going to input a value for the height, also as a float, a 296 00:21:49,760 --> 00:21:51,930 floating point. 297 00:21:51,930 --> 00:21:52,170 OK. 298 00:21:52,170 --> 00:21:54,570 I get the two values in, what do I need to do, well, you 299 00:21:54,570 --> 00:21:55,480 sort of know that, right? 300 00:21:55,480 --> 00:22:04,510 I want to then do, I need to find the square root-- b 301 00:22:04,510 --> 00:22:07,320 squared plus h squared, right? 302 00:22:07,320 --> 00:22:09,270 The base plus the height, that's the thing I want for 303 00:22:09,270 --> 00:22:17,390 the hypotenuse-- and I'm going to save that as a float in 304 00:22:17,390 --> 00:22:20,560 hyp, for hypotenuse. 305 00:22:20,560 --> 00:22:28,170 And then finally I need to print something out, using the 306 00:22:28,170 --> 00:22:34,260 value in hyp. 307 00:22:34,260 --> 00:22:34,760 OK. 308 00:22:34,760 --> 00:22:35,830 Whoop-dee-doo, right? 309 00:22:35,830 --> 00:22:36,150 Come on. 310 00:22:36,150 --> 00:22:37,930 We know how to do this. 311 00:22:37,930 --> 00:22:40,300 But notice what I did. 312 00:22:40,300 --> 00:22:42,660 First of all, I've used the notion of modularity. 313 00:22:42,660 --> 00:22:45,370 I've listed a sequence of modules, the things that I 314 00:22:45,370 --> 00:22:46,930 want to do. 315 00:22:46,930 --> 00:22:49,500 Second thing to notice, is that little piece of pseudo 316 00:22:49,500 --> 00:22:53,770 code is telling me things about values. 317 00:22:53,770 --> 00:22:55,256 I need to have a float. 318 00:22:55,256 --> 00:22:57,450 I need to have another float here, it's giving me some 319 00:22:57,450 --> 00:22:58,860 information. 320 00:22:58,860 --> 00:23:01,850 Third thing to notice is, there's a flow of control. 321 00:23:01,850 --> 00:23:04,450 The order which these things are going to happen. 322 00:23:04,450 --> 00:23:07,740 And the fourth thing to notice is, I've used abstraction. 323 00:23:07,740 --> 00:23:11,530 I've said nothing about how I'm going to make square root. 324 00:23:11,530 --> 00:23:13,010 I'm using it as an abstraction, saying I'm going 325 00:23:13,010 --> 00:23:14,740 to have square root from somewhere, maybe I'll build it 326 00:23:14,740 --> 00:23:17,760 myself, maybe somebody gives it to me as part of a library, 327 00:23:17,760 --> 00:23:20,930 so I'm burying the details inside of it. 328 00:23:20,930 --> 00:23:23,610 I know this is a simple example, but when you mature 329 00:23:23,610 --> 00:23:25,790 as a programmer, one of the first things you should do 330 00:23:25,790 --> 00:23:28,330 when you sit down to tackle some problem is write 331 00:23:28,330 --> 00:23:30,120 something like this pseudo code. 332 00:23:30,120 --> 00:23:31,870 I know Professor Guttag does it all the time. 333 00:23:31,870 --> 00:23:33,080 I know, for a lot of you, it's like, OK, 334 00:23:33,080 --> 00:23:34,450 I got a heavy problem. 335 00:23:34,450 --> 00:23:39,400 Let's see, def Foobar open paren, a bunch of parameters. 336 00:23:39,400 --> 00:23:40,210 Wrong way to start. 337 00:23:40,210 --> 00:23:41,970 Start by thinking about what are the sequences. 338 00:23:41,970 --> 00:23:44,980 This also, by the way, in some sense, gives me the beginnings 339 00:23:44,980 --> 00:23:47,190 of my comments for what the structure of my 340 00:23:47,190 --> 00:23:48,920 code is going to be. 341 00:23:48,920 --> 00:23:49,490 OK. 342 00:23:49,490 --> 00:23:52,200 If we do that, if you look at the handout then, I can now 343 00:23:52,200 --> 00:23:54,100 start implementing this. 344 00:23:54,100 --> 00:23:56,610 I wanted to show you that, so, first thing I'm going to do is 345 00:23:56,610 --> 00:23:58,500 say, all right, I know I'm going to need square root in 346 00:23:58,500 --> 00:24:03,400 here, so I'm going to, in fact, import math. 347 00:24:03,400 --> 00:24:05,440 That's a little different from other import statements. 348 00:24:05,440 --> 00:24:08,930 This says I'm going to get the entire math library and bring 349 00:24:08,930 --> 00:24:10,830 it in so I can use it. 350 00:24:10,830 --> 00:24:12,170 And then, what's the first thing I wanted to do? 351 00:24:12,170 --> 00:24:15,250 I need to get a value for base as a float. 352 00:24:15,250 --> 00:24:16,940 Well OK, and that sounds like I'm going to need to do input 353 00:24:16,940 --> 00:24:20,490 of something, you can see that statement there, it's-- got 354 00:24:20,490 --> 00:24:21,840 the wrong glasses on but right there-- 355 00:24:21,840 --> 00:24:24,230 I'm going to do an input with a little message, and I'm 356 00:24:24,230 --> 00:24:26,500 going to store it in base. 357 00:24:26,500 --> 00:24:28,220 But here's where I'm going to practice a little bit of 358 00:24:28,220 --> 00:24:30,030 defensive programming. 359 00:24:30,030 --> 00:24:32,670 I can't rely on Professor Guttag if I give this-- if 360 00:24:32,670 --> 00:24:36,500 this code to him, I can't rely on him to type in a float. 361 00:24:36,500 --> 00:24:38,700 Actually I can, because he's a smart guy, but in general, I 362 00:24:38,700 --> 00:24:39,750 can't rely on the user-- 363 00:24:39,750 --> 00:24:42,040 PROFESSOR JOHN GUTTAG: I wouldn't do it right 364 00:24:42,040 --> 00:24:42,300 to see if you did. 365 00:24:42,300 --> 00:24:42,633 PROFESSOR ERIC GRIMSON: Actually, 366 00:24:42,633 --> 00:24:43,220 he's right, you know. 367 00:24:43,220 --> 00:24:45,360 He would not do it, just to see if I'm doing it right. 368 00:24:45,360 --> 00:24:47,110 I can't rely on the user. 369 00:24:47,110 --> 00:24:48,790 I want to make sure I get a float in it, 370 00:24:48,790 --> 00:24:49,700 so how do I do that? 371 00:24:49,700 --> 00:24:52,090 Well, here's one nice little trick. 372 00:24:52,090 --> 00:24:56,300 First of all, having read in that value, I can check to 373 00:24:56,300 --> 00:24:57,750 see, is it of the right type? 374 00:24:57,750 --> 00:24:59,960 Now, this is not the nicest way to do it but it'll work. 375 00:24:59,960 --> 00:25:03,190 I can look at the type of the value of base and compare it 376 00:25:03,190 --> 00:25:05,690 to the type of an actual float and see, are they the same? 377 00:25:05,690 --> 00:25:08,490 Is this a real or a float? 378 00:25:08,490 --> 00:25:10,450 If it is, I'm done. 379 00:25:10,450 --> 00:25:12,690 How do I go back if it isn't? 380 00:25:12,690 --> 00:25:14,520 Well, I'm going to create a little infinite loop. 381 00:25:14,520 --> 00:25:16,400 Not normally a good idea. 382 00:25:16,400 --> 00:25:19,360 I set up a variable here, called input OK. 383 00:25:19,360 --> 00:25:21,870 Initially it's false, because I have no input. 384 00:25:21,870 --> 00:25:25,360 And then I run a loop in which I read something in, I check 385 00:25:25,360 --> 00:25:28,120 to see if it's the right type, if it is, I change that 386 00:25:28,120 --> 00:25:31,440 variable to say it's now the correct type, which means the 387 00:25:31,440 --> 00:25:34,320 next time through the loop, I'm going to say I'm all set 388 00:25:34,320 --> 00:25:35,720 and I'm going to bounce out. 389 00:25:35,720 --> 00:25:38,850 But if it is not, it's going to print out a message here 390 00:25:38,850 --> 00:25:42,580 saying, you screwed up, somewhat politely, and it's 391 00:25:42,580 --> 00:25:43,500 going to go back around. 392 00:25:43,500 --> 00:25:45,800 So it'll just cycle until I get something 393 00:25:45,800 --> 00:25:47,450 of the right type. 394 00:25:47,450 --> 00:25:49,230 Nice way of doing it. 395 00:25:49,230 --> 00:25:50,270 Right, what's the second thing I do? 396 00:25:50,270 --> 00:25:53,950 Well, I get the same sort of thing to read in the height, 397 00:25:53,950 --> 00:25:56,680 once I have that I'm going to take base squared plus height 398 00:25:56,680 --> 00:25:59,210 squared, and there's a form that we've just seen once 399 00:25:59,210 --> 00:26:02,690 before, and it's going to repeat it, that is math.SQRT 400 00:26:02,690 --> 00:26:07,470 and it says the following: it says, take from the math 401 00:26:07,470 --> 00:26:11,370 library the function called sqrt. 402 00:26:11,370 --> 00:26:12,320 OK. 403 00:26:12,320 --> 00:26:13,960 We're going to come back to this when we get to objects, 404 00:26:13,960 --> 00:26:16,880 it's basically picking up that object and it's applying that, 405 00:26:16,880 --> 00:26:19,710 putting that value into hype, and then just printing 406 00:26:19,710 --> 00:26:21,200 something out. 407 00:26:21,200 --> 00:26:23,420 And again, if I just run this, just to show that it's going 408 00:26:23,420 --> 00:26:28,390 to do the right thing, it says enter base, I'm obnoxious, it 409 00:26:28,390 --> 00:26:33,180 says oops, wasn't a float, so we'll be nice about it, and I 410 00:26:33,180 --> 00:26:37,010 enter a height, and it prints out what I expected. 411 00:26:37,010 --> 00:26:39,120 I just concatenated those strings together, by the way, 412 00:26:39,120 --> 00:26:39,610 at the end. 413 00:26:39,610 --> 00:26:41,520 All right. 414 00:26:41,520 --> 00:26:43,720 Notice what I did. 415 00:26:43,720 --> 00:26:44,770 OK. 416 00:26:44,770 --> 00:26:47,010 I went from this description, it gives me [UNINTELLIGIBLE] 417 00:26:47,010 --> 00:26:48,000 some information. 418 00:26:48,000 --> 00:26:49,330 I need to have a particular type. 419 00:26:49,330 --> 00:26:51,390 I made sure I had the particular type. 420 00:26:51,390 --> 00:26:55,360 I've used some abstraction to suppress some details here. 421 00:26:55,360 --> 00:26:58,590 Now if you look at that list, there is actually something I 422 00:26:58,590 --> 00:27:03,060 didn't seem to check, which is, I said I wanted a float 423 00:27:03,060 --> 00:27:04,830 stored in hyp. 424 00:27:04,830 --> 00:27:07,820 How do I know I've got a float in hyp? 425 00:27:07,820 --> 00:27:11,080 Well I'm relying on the contract, if you like, that 426 00:27:11,080 --> 00:27:13,280 the manufacturer of square root put together, which is, 427 00:27:13,280 --> 00:27:15,830 if I know I'm giving it two floats, which I do because I 428 00:27:15,830 --> 00:27:18,240 make sure they're floats, the contract, if you like, of 429 00:27:18,240 --> 00:27:20,020 square root says I'll give you back a float. 430 00:27:20,020 --> 00:27:24,240 So I can guarantee I've got something of the right type. 431 00:27:24,240 --> 00:27:24,820 OK. 432 00:27:24,820 --> 00:27:26,980 I know this is boring as whatever. 433 00:27:26,980 --> 00:27:28,520 But there's an important point here. 434 00:27:28,520 --> 00:27:31,530 Having now used this pseudo code to line things up, I can 435 00:27:31,530 --> 00:27:33,410 start putting some additional structure on this. 436 00:27:33,410 --> 00:27:37,030 And in particular, I'm sure you're looking at this going-- 437 00:27:37,030 --> 00:27:39,170 will look at it if we look at the right piece-- 438 00:27:39,170 --> 00:27:41,780 going, wait a minute. 439 00:27:41,780 --> 00:27:46,420 This chunk of code and this chunk of code, they're really 440 00:27:46,420 --> 00:27:48,660 doing the same thing. 441 00:27:48,660 --> 00:27:49,980 And this is something I want to use. 442 00:27:49,980 --> 00:27:53,090 If I look at those two pieces of computation, I can see a 443 00:27:53,090 --> 00:27:53,724 pattern there. 444 00:27:53,724 --> 00:27:56,650 It's an obvious pattern of what I'm doing. 445 00:27:56,650 --> 00:27:59,060 And in particular, I can then ask the following question, 446 00:27:59,060 --> 00:28:01,230 which is, what's different between those 447 00:28:01,230 --> 00:28:03,520 two pieces of code? 448 00:28:03,520 --> 00:28:05,440 And I suggest two things, right? 449 00:28:05,440 --> 00:28:07,960 One is, what's the thing I print out when 450 00:28:07,960 --> 00:28:09,900 I ask for the input? 451 00:28:09,900 --> 00:28:12,970 The second thing is, what do I print out if I actually don't 452 00:28:12,970 --> 00:28:14,060 get the right input in? 453 00:28:14,060 --> 00:28:17,410 And so the only two differences are, right there, 454 00:28:17,410 --> 00:28:20,970 and there versus here and here. 455 00:28:20,970 --> 00:28:23,130 So this is a good place to think about, OK, let me 456 00:28:23,130 --> 00:28:24,280 capture that. 457 00:28:24,280 --> 00:28:26,660 Let me write a function, in fact the literal thing I would 458 00:28:26,660 --> 00:28:30,920 do is to say, identify the things that change, give each 459 00:28:30,920 --> 00:28:33,100 of them a variable name because I want to refer to 460 00:28:33,100 --> 00:28:35,850 them, and then write a function that captures the 461 00:28:35,850 --> 00:28:37,910 rest of that computation just with those 462 00:28:37,910 --> 00:28:39,660 variable names inside. 463 00:28:39,660 --> 00:28:42,140 And in fact, if you look down-- and I'm just going to 464 00:28:42,140 --> 00:28:43,980 highlight this portion, I'm not going to run it-- but if 465 00:28:43,980 --> 00:28:48,230 you look down here, that's exactly what that does. 466 00:28:48,230 --> 00:28:50,050 I happen to have it commented out, right? 467 00:28:50,050 --> 00:28:50,480 What does it do? 468 00:28:50,480 --> 00:28:52,770 It has height, it says, I've got two names of things: the 469 00:28:52,770 --> 00:28:54,780 request message and the error message. 470 00:28:54,780 --> 00:28:57,540 The body of that function looks exactly like the 471 00:28:57,540 --> 00:29:00,440 computation up above, except I'm simply using those in 472 00:29:00,440 --> 00:29:04,190 place of the specific message I had before. 473 00:29:04,190 --> 00:29:06,020 And then the only other difference is obviously, it's 474 00:29:06,020 --> 00:29:07,265 a function I need to return a value. 475 00:29:07,265 --> 00:29:10,380 So when I'm done, I'm going to give the value back out. 476 00:29:10,380 --> 00:29:11,540 All right? 477 00:29:11,540 --> 00:29:17,870 And that then let's me get to, basically, this code. 478 00:29:17,870 --> 00:29:20,880 Having done that, I simply call base with get float, I 479 00:29:20,880 --> 00:29:23,070 call height with get float, and do the rest of the work. 480 00:29:23,070 --> 00:29:24,890 All right. 481 00:29:24,890 --> 00:29:27,130 What's the point of doing this? 482 00:29:27,130 --> 00:29:28,010 Well, notice again. 483 00:29:28,010 --> 00:29:28,510 What have I done? 484 00:29:28,510 --> 00:29:31,880 I've captured a module inside of a function. 485 00:29:31,880 --> 00:29:33,730 And even though it's a simple little thing here, there's 486 00:29:33,730 --> 00:29:36,100 some a couple of really nice advantages to this. 487 00:29:36,100 --> 00:29:37,870 All right? 488 00:29:37,870 --> 00:29:39,390 First one is there's less code to read. 489 00:29:39,390 --> 00:29:40,230 It's easier to debug. 490 00:29:40,230 --> 00:29:42,540 I don't have as much to deal with. 491 00:29:42,540 --> 00:29:45,400 But the more important thing is, I've now separated out 492 00:29:45,400 --> 00:29:48,250 implementation from functionality, or 493 00:29:48,250 --> 00:29:50,470 implementation from use. 494 00:29:50,470 --> 00:29:51,570 What does that mean? 495 00:29:51,570 --> 00:29:55,650 It means anybody using that little function get float 496 00:29:55,650 --> 00:29:57,470 doesn't have to worry about what's inside of it. 497 00:29:57,470 --> 00:29:59,580 So for example, I decide I want to change the message I 498 00:29:59,580 --> 00:30:02,500 print out, I don't have to change the function, I just 499 00:30:02,500 --> 00:30:04,450 pass in a different parameter. 500 00:30:04,450 --> 00:30:08,400 Well if I-- you know, with [UNINTELLIGIBLE PHRASE sorry, 501 00:30:08,400 --> 00:30:09,030 let me say it differently. 502 00:30:09,030 --> 00:30:11,550 I don't need to worry about how checking is done, it's 503 00:30:11,550 --> 00:30:14,420 handled inside of that function. 504 00:30:14,420 --> 00:30:17,670 If I decide there's a better way to get input, and there 505 00:30:17,670 --> 00:30:20,960 is, then I can make it to change what I don't have to 506 00:30:20,960 --> 00:30:23,110 change the code that uses the input. 507 00:30:23,110 --> 00:30:27,100 So, if you like, I've built a separation between the user 508 00:30:27,100 --> 00:30:28,420 and the implementer. 509 00:30:28,420 --> 00:30:31,070 And that's exactly one of the reasons why I want to have the 510 00:30:31,070 --> 00:30:33,820 functions, because I've separated those out. 511 00:30:33,820 --> 00:30:37,250 Another way of saying it is, anything that uses get float 512 00:30:37,250 --> 00:30:39,880 doesn't care what the details are inside or shouldn't, and 513 00:30:39,880 --> 00:30:42,520 if I change that definition, I don't have to change anything 514 00:30:42,520 --> 00:30:46,300 elsewhere in my code, whereas if I just have the raw code in 515 00:30:46,300 --> 00:30:48,800 there, I have to go off and do it. 516 00:30:48,800 --> 00:30:50,780 Right, so the things we want you to take away from this 517 00:30:50,780 --> 00:30:54,700 are, get into the habit of using pseudo code when you sit 518 00:30:54,700 --> 00:30:57,920 down to start a problem, write out what are the steps. 519 00:30:57,920 --> 00:31:00,150 I will tell you that a good programmer, at least in my 520 00:31:00,150 --> 00:31:03,390 mind, may actually go back and modify the pseudo code as they 521 00:31:03,390 --> 00:31:05,350 realize they're missing things, but it's easier to do 522 00:31:05,350 --> 00:31:08,690 that when you're looking at a simple set of steps, than when 523 00:31:08,690 --> 00:31:10,630 you're in the middle of a pile of code. 524 00:31:10,630 --> 00:31:13,340 And get into the habit of using it to help you define 525 00:31:13,340 --> 00:31:14,910 what is the flow of control. 526 00:31:14,910 --> 00:31:17,910 What are the basic modules, what information needs to be 527 00:31:17,910 --> 00:31:19,750 passed between those modules in order to 528 00:31:19,750 --> 00:31:22,610 make the code work. 529 00:31:22,610 --> 00:31:23,290 OK. 530 00:31:23,290 --> 00:31:25,110 That was the short topic. 531 00:31:25,110 --> 00:31:26,730 I will come back to this some more and you're going to get 532 00:31:26,730 --> 00:31:28,480 lots of practice with this. 533 00:31:28,480 --> 00:31:30,070 What I want to do is to start talking 534 00:31:30,070 --> 00:31:31,640 about a different topic. 535 00:31:31,640 --> 00:31:33,740 Which is efficiency. 536 00:31:33,740 --> 00:31:36,780 And this is going to sound like a weird topic, we're 537 00:31:36,780 --> 00:31:39,170 going to see why it's of value in a second. 538 00:31:39,170 --> 00:31:43,580 I want to talk about efficiency, and we're going 539 00:31:43,580 --> 00:31:47,750 to, or at least I'm going to, at times also refer to this as 540 00:31:47,750 --> 00:31:51,230 orders of growth, for reasons that you'll see over the next 541 00:31:51,230 --> 00:31:54,890 few minutes. 542 00:31:54,890 --> 00:31:57,660 Now, efficiency is obviously an important consideration 543 00:31:57,660 --> 00:32:00,300 when you're designing code, although I have to admit, at 544 00:32:00,300 --> 00:32:02,590 least for me, I usually want to at least start initially 545 00:32:02,590 --> 00:32:05,570 with code that works, and then worry about how I might go 546 00:32:05,570 --> 00:32:07,480 back and come up with more efficient implementation. 547 00:32:07,480 --> 00:32:09,340 I like to have something I can rely on, but it is an 548 00:32:09,340 --> 00:32:11,060 important issue. 549 00:32:11,060 --> 00:32:14,390 And our goal over the next couple of lectures, is 550 00:32:14,390 --> 00:32:16,045 basically to give you a sense of this. 551 00:32:16,045 --> 00:32:17,990 So we're not going to turn you into an expert on 552 00:32:17,990 --> 00:32:19,910 computational efficiency. 553 00:32:19,910 --> 00:32:21,560 That's, there are whole courses on that, there's some 554 00:32:21,560 --> 00:32:23,640 great courses here on that, it takes some mathematical 555 00:32:23,640 --> 00:32:26,490 sophistication, we're going to push that off a little bit. 556 00:32:26,490 --> 00:32:28,710 But what we-- what we do want to do, is to give you some 557 00:32:28,710 --> 00:32:30,770 intuition about how to approach questions of 558 00:32:30,770 --> 00:32:31,950 efficiency. 559 00:32:31,950 --> 00:32:36,440 We want you to have a sense of why some programs complete 560 00:32:36,440 --> 00:32:39,890 almost before you're done typing it. 561 00:32:39,890 --> 00:32:42,160 Some programs run overnight. 562 00:32:42,160 --> 00:32:45,350 Some programs won't stop until I'm old and gray. 563 00:32:45,350 --> 00:32:49,080 Some programs won't stop until you're old and gray. 564 00:32:49,080 --> 00:32:51,050 And these are really different efficiencies, and we want to 565 00:32:51,050 --> 00:32:53,560 give you a sense of how do you reason about those different 566 00:32:53,560 --> 00:32:55,460 kinds of programs. 567 00:32:55,460 --> 00:32:57,850 And part of it is we want you to learn how to have a 568 00:32:57,850 --> 00:33:00,240 catalog, if you like, of different classes of 569 00:33:00,240 --> 00:33:03,720 algorithms, so that when you get a problem, you try and map 570 00:33:03,720 --> 00:33:07,760 it into an appropriate class, and use the leverage, if you 571 00:33:07,760 --> 00:33:08,500 like, of that class 572 00:33:08,500 --> 00:33:12,030 of algorithms. Now. 573 00:33:12,030 --> 00:33:13,970 It's a quick sidebar, I've got to say, I'm sure talking about 574 00:33:13,970 --> 00:33:17,310 efficiency to folks like you probably seems really strange. 575 00:33:17,310 --> 00:33:20,280 I mean, you grew up in an age when computers were blazingly 576 00:33:20,280 --> 00:33:23,220 fast, and have tons of memory, so why in the world do you 577 00:33:23,220 --> 00:33:24,910 care about efficiency? 578 00:33:24,910 --> 00:33:27,070 Some of us were not so lucky. 579 00:33:27,070 --> 00:33:32,070 So I'll admit, my first computer I program was a PDP6, 580 00:33:32,070 --> 00:33:34,535 only Professor Guttag even knows what PDP stands for, it 581 00:33:34,535 --> 00:33:37,080 was made by Digital Equipment Company, which does not exist 582 00:33:37,080 --> 00:33:39,110 anymore, is now long gone. 583 00:33:39,110 --> 00:33:41,210 It had, I know, this is old guy stories, but 584 00:33:41,210 --> 00:33:46,550 it had 160k of memory. 585 00:33:46,550 --> 00:33:46,920 Yeah. 586 00:33:46,920 --> 00:33:46,960 160k. 587 00:33:46,960 --> 00:33:50,800 160 kilobits of memory. 588 00:33:50,800 --> 00:33:53,530 I mean, your flash cards have more than that, right? 589 00:33:53,530 --> 00:33:56,720 It had a processor speed of one megahertz. 590 00:33:56,720 --> 00:34:00,810 It did a million operations per second. 591 00:34:00,810 --> 00:34:02,310 So let's think about it. 592 00:34:02,310 --> 00:34:04,920 This sucker, what's it got in there? 593 00:34:04,920 --> 00:34:07,470 That Air Mac, it's, see, it's got, its go-- my Air Mac, I 594 00:34:07,470 --> 00:34:09,820 don't know about John's, his is probably better, mine has 595 00:34:09,820 --> 00:34:12,190 1.8 gigahertz speed. 596 00:34:12,190 --> 00:34:15,210 That's 1800 times faster. 597 00:34:15,210 --> 00:34:18,350 But the real one that blows me away is, it has 2 gig of 598 00:34:18,350 --> 00:34:19,850 memory inside of it. 599 00:34:19,850 --> 00:34:23,540 That's 12 thousand times more memory. 600 00:34:23,540 --> 00:34:24,310 Oh, and by the way? 601 00:34:24,310 --> 00:34:27,350 The PDP6, it was in a rack about this tall. 602 00:34:27,350 --> 00:34:29,810 From the floor, not from the table. 603 00:34:29,810 --> 00:34:31,990 All right, so you didn't grow up in the late 1800s like I 604 00:34:31,990 --> 00:34:33,240 did, you don't have to worry about this 605 00:34:33,240 --> 00:34:34,480 sort of stuff, right? 606 00:34:34,480 --> 00:34:36,410 But a point I'm trying to make is, it sounds like anymore 607 00:34:36,410 --> 00:34:39,160 computers have gotten so blazingly fast, why should you 608 00:34:39,160 --> 00:34:39,550 worry about it? 609 00:34:39,550 --> 00:34:42,370 Let me give you one other anecdote that I can't resist. 610 00:34:42,370 --> 00:34:44,530 This is the kind of thing you can use at cocktail parties to 611 00:34:44,530 --> 00:34:45,930 impress your friends from Harvard. 612 00:34:45,930 --> 00:34:47,390 OK. 613 00:34:47,390 --> 00:34:50,010 Imagine I have a little lamp, a little goose-- one of those 614 00:34:50,010 --> 00:34:52,220 little gooseneck lamps, I'd put it on the table here, I'd 615 00:34:52,220 --> 00:34:55,390 put the height about a f-- about a foot off the table. 616 00:34:55,390 --> 00:34:58,610 And if I was really good, I could hit, or time it so that 617 00:34:58,610 --> 00:35:00,120 when I hurt-- yeah, try again. 618 00:35:00,120 --> 00:35:03,070 When I turn this on switch on in the lamp, at exactly the 619 00:35:03,070 --> 00:35:05,580 same time, I'm going to hit a key on my computer and start 620 00:35:05,580 --> 00:35:07,010 it running. 621 00:35:07,010 --> 00:35:07,910 OK. 622 00:35:07,910 --> 00:35:12,200 In the length of time it takes for the light to get from that 623 00:35:12,200 --> 00:35:16,840 bulb to the table, this machine processes two 624 00:35:16,840 --> 00:35:19,810 operations. 625 00:35:19,810 --> 00:35:21,670 Oh come on, that's amazing. 626 00:35:21,670 --> 00:35:22,750 Two operations. 627 00:35:22,750 --> 00:35:24,800 You know, you can do the simple numbers, right? 628 00:35:24,800 --> 00:35:25,820 [UNINTELLIGIBLE PHRASE] 629 00:35:25,820 --> 00:35:28,860 Light travels basically a foot in a nanosecond. 630 00:35:28,860 --> 00:35:30,400 Simple rule of thumb. 631 00:35:30,400 --> 00:35:32,650 Now, the nanosecond is what, 10 to the minus 9 seconds. 632 00:35:32,650 --> 00:35:38,430 This thing does 2 gig worth of operations. 633 00:35:38,430 --> 00:35:40,600 A gig is 10 to the 9, so it does two operations in the 634 00:35:40,600 --> 00:35:43,270 length of time it takes light to get from one foot off the 635 00:35:43,270 --> 00:35:44,070 table down to the table. 636 00:35:44,070 --> 00:35:45,320 That's amazing. 637 00:35:45,320 --> 00:35:48,160 So why in the world do you care about efficiency? 638 00:35:48,160 --> 00:35:52,710 Well the problem is that the problems grow faster than the 639 00:35:52,710 --> 00:35:55,220 computers speed up. 640 00:35:55,220 --> 00:35:56,440 I'll give you two examples. 641 00:35:56,440 --> 00:35:57,700 I happen to work in medical imaging. 642 00:35:57,700 --> 00:35:58,720 Actually, so does Professor Guttag. 643 00:35:58,720 --> 00:36:02,100 In my in my area of research, it's common for us to want to 644 00:36:02,100 --> 00:36:04,690 process about 100 images a second in order to get real 645 00:36:04,690 --> 00:36:05,850 time display. 646 00:36:05,850 --> 00:36:08,470 Each image has about a million elements in it. 647 00:36:08,470 --> 00:36:12,220 I've got to process about a half a gig of data a second in 648 00:36:12,220 --> 00:36:14,610 order to get anything out of it. 649 00:36:14,610 --> 00:36:15,870 Second example. 650 00:36:15,870 --> 00:36:18,170 Maybe one that'll hit a little more home to you. 651 00:36:18,170 --> 00:36:20,450 I'm sure you all use Google, I'm sure it's a verb in your 652 00:36:20,450 --> 00:36:22,000 vocabulary, right? 653 00:36:22,000 --> 00:36:24,590 Now, Google processes-- ten million? 654 00:36:24,590 --> 00:36:25,550 Ten billion pages? 655 00:36:25,550 --> 00:36:25,756 John? 656 00:36:25,756 --> 00:36:27,390 I think ten billion was the last number I heard. 657 00:36:27,390 --> 00:36:28,230 Does that sound about right? 658 00:36:28,230 --> 00:36:30,862 PROFESSOR JOHN GUTTAG: I think it might 659 00:36:30,862 --> 00:36:31,160 actually be more by now. 660 00:36:31,160 --> 00:36:32,150 PROFESSOR ERIC GRIMSON: Maybe more by now. 661 00:36:32,150 --> 00:36:34,730 But let's, for the sake of argument, ten billion pages. 662 00:36:34,730 --> 00:36:38,140 Imagine you want to search through Google to find a 663 00:36:38,140 --> 00:36:39,600 particular page. 664 00:36:39,600 --> 00:36:41,930 You want to do it in a second. 665 00:36:41,930 --> 00:36:43,880 And you're going to just do it the brute force way, assuming 666 00:36:43,880 --> 00:36:46,480 you could even reach all of those pages in that time. 667 00:36:46,480 --> 00:36:49,420 Well, if you're going to do that, you've got to be able to 668 00:36:49,420 --> 00:36:53,480 find what you're looking for in a page in two steps. 669 00:36:53,480 --> 00:36:57,470 Where a step is a comparison or an arithmetic operation. 670 00:36:57,470 --> 00:36:58,850 Ain't going to happen, right? 671 00:36:58,850 --> 00:36:59,930 You just can't do it. 672 00:36:59,930 --> 00:37:03,300 So again, part of the point here is that things grow-- or 673 00:37:03,300 --> 00:37:05,420 to rephrase it, interesting things grow at 674 00:37:05,420 --> 00:37:06,720 an incredible rate. 675 00:37:06,720 --> 00:37:09,960 And as a consequence, brute force methods are typically 676 00:37:09,960 --> 00:37:12,240 not going to work. 677 00:37:12,240 --> 00:37:12,550 OK. 678 00:37:12,550 --> 00:37:14,430 So that then leads to the question about what should we 679 00:37:14,430 --> 00:37:14,990 do about this? 680 00:37:14,990 --> 00:37:17,240 And probably the obvious thing you'll think about is, we'll 681 00:37:17,240 --> 00:37:19,140 come up with a clever algorithm. 682 00:37:19,140 --> 00:37:21,430 And I want to disabuse you of that notion. 683 00:37:21,430 --> 00:37:23,190 It's a great idea if you can do it, 684 00:37:23,190 --> 00:37:24,090 The guy who-- 685 00:37:24,090 --> 00:37:25,510 I think I'm going to say this right, John, right? 686 00:37:25,510 --> 00:37:26,060 Sanjay? 687 00:37:26,060 --> 00:37:29,120 Ghemawat?-- with a guy who was a graduate of our department, 688 00:37:29,120 --> 00:37:31,610 who is the heart and soul behind Google's really fast 689 00:37:31,610 --> 00:37:34,480 search, is an incredibly smart guy, and he did come up with a 690 00:37:34,480 --> 00:37:36,950 really clever algorithm about how you structure that search, 691 00:37:36,950 --> 00:37:37,820 in order to make it happen. 692 00:37:37,820 --> 00:37:39,880 And he probably made a lot of money along the way. 693 00:37:39,880 --> 00:37:41,790 So if you have a great idea, you know, talk to a good 694 00:37:41,790 --> 00:37:44,220 patent attorney and get it locked away. 695 00:37:44,220 --> 00:37:46,460 But in general, it's hard to come up with the 696 00:37:46,460 --> 00:37:48,120 really clever algorithm. 697 00:37:48,120 --> 00:37:51,200 What you're much better at doing is saying how do I take 698 00:37:51,200 --> 00:37:54,970 the problem I've got and map it into a class of algorithms 699 00:37:54,970 --> 00:37:58,500 about which I know and use the efficiencies of those to try 700 00:37:58,500 --> 00:38:00,390 and figure out how to make it work. 701 00:38:00,390 --> 00:38:03,880 So what we want to do, is, I guess another way of saying it 702 00:38:03,880 --> 00:38:12,590 is, efficiency is really about choice of algorithm. 703 00:38:12,590 --> 00:38:18,620 And we want to help you learn how to map a problem into a 704 00:38:18,620 --> 00:38:24,970 class of algorithms of some efficiency. 705 00:38:24,970 --> 00:38:27,970 That's our goal. 706 00:38:27,970 --> 00:38:28,950 OK. 707 00:38:28,950 --> 00:38:31,190 So to do this, we need a little more abstract way of 708 00:38:31,190 --> 00:38:34,030 talking about efficiency, and so, the question is, how do we 709 00:38:34,030 --> 00:38:35,630 think about efficiency? 710 00:38:35,630 --> 00:38:39,080 Typically there's two things we want to measure. 711 00:38:39,080 --> 00:38:43,820 Space and time. 712 00:38:43,820 --> 00:38:46,650 Sounds like an astrophysics course, right? 713 00:38:46,650 --> 00:38:51,120 Now, space usually we-- ach, try it again. 714 00:38:51,120 --> 00:38:54,210 When we talk about space, what we usually refer to is, how 715 00:38:54,210 --> 00:38:57,790 much computer memory does it take to complete a computation 716 00:38:57,790 --> 00:38:59,240 of a particular size? 717 00:38:59,240 --> 00:39:08,240 So let me write that down, it's how much memory do I need 718 00:39:08,240 --> 00:39:09,560 to complete a computation. 719 00:39:09,560 --> 00:39:13,760 And by that, I mean, not how much memory do I need to store 720 00:39:13,760 --> 00:39:16,290 the size of the input, it's really how much internal 721 00:39:16,290 --> 00:39:19,100 memory do I use up as I go through the computation? 722 00:39:19,100 --> 00:39:20,850 I've got some internal variables I have to store, 723 00:39:20,850 --> 00:39:24,500 what kinds of things do I have to keep track of? 724 00:39:24,500 --> 00:39:26,580 You're going to see the arguments about space if you 725 00:39:26,580 --> 00:39:28,570 take some of the courses that follow on, and again, some 726 00:39:28,570 --> 00:39:29,690 nice courses about that. 727 00:39:29,690 --> 00:39:31,510 For this course, we're not going to worry 728 00:39:31,510 --> 00:39:33,190 about space that much. 729 00:39:33,190 --> 00:39:36,110 What we're really going to focus on is time. 730 00:39:36,110 --> 00:39:37,060 OK. 731 00:39:37,060 --> 00:39:39,210 So we're going to focus here. 732 00:39:39,210 --> 00:39:44,510 And the obvious question I could start with is, and 733 00:39:44,510 --> 00:39:49,120 suppose I ask you, how long does the algorithm implemented 734 00:39:49,120 --> 00:39:52,370 by this program take to run? 735 00:39:52,370 --> 00:39:56,380 How might I answer that question? 736 00:39:56,380 --> 00:40:01,140 Any thoughts? 737 00:40:01,140 --> 00:40:01,460 Yeah. 738 00:40:01,460 --> 00:40:06,440 STUDENT: [INAUDIBLE] 739 00:40:06,440 --> 00:40:06,990 PROFESSOR ERIC GRIMSON: Ah, you're jumping 740 00:40:06,990 --> 00:40:07,700 ahead of me, great. 741 00:40:07,700 --> 00:40:09,750 The answer was, find a mathematical expression 742 00:40:09,750 --> 00:40:11,060 depending on the number of inputs. 743 00:40:11,060 --> 00:40:12,560 It was exactly where I want to go. 744 00:40:12,560 --> 00:40:13,960 Thank you. 745 00:40:13,960 --> 00:40:18,620 I was hoping for a simpler answer, which is, just run it. 746 00:40:18,620 --> 00:40:20,440 Which is, yeah I know, seems like a dumb 747 00:40:20,440 --> 00:40:21,950 thing to say, right? 748 00:40:21,950 --> 00:40:23,670 One of the things you could imagine is just try it on and 749 00:40:23,670 --> 00:40:25,940 input, see how long it takes. 750 00:40:25,940 --> 00:40:28,240 You're all cleverer than that, but I want to point out why 751 00:40:28,240 --> 00:40:29,270 that's not a great idea. 752 00:40:29,270 --> 00:40:30,940 First of all, that depends on which input I've picked. 753 00:40:30,940 --> 00:40:32,520 All right? 754 00:40:32,520 --> 00:40:34,850 Obviously the algorithm is likely to depend on the size 755 00:40:34,850 --> 00:40:36,900 of the input, so this is not a great idea. 756 00:40:36,900 --> 00:40:38,760 Second one is, it depends on which machine I'm running on. 757 00:40:38,760 --> 00:40:41,980 If I'm using a PDP6, it's going to take a whole lot 758 00:40:41,980 --> 00:40:44,200 longer than if I'm using an Air Mac. 759 00:40:44,200 --> 00:40:45,040 All right? 760 00:40:45,040 --> 00:40:47,050 Third one is, it may depend on which version 761 00:40:47,050 --> 00:40:48,890 of Python I'm running. 762 00:40:48,890 --> 00:40:51,340 Depends on how clever the implementer of Python was. 763 00:40:51,340 --> 00:40:53,720 Fourth one is, it may depend on which programming language 764 00:40:53,720 --> 00:40:54,260 I'm doing it in. 765 00:40:54,260 --> 00:40:57,290 So I could do it empirically, but I don't want to do that 766 00:40:57,290 --> 00:40:58,940 typically, it's just not a great way to get at it. 767 00:40:58,940 --> 00:41:02,020 And so in fact, what we want is exactly what 768 00:41:02,020 --> 00:41:02,890 the young lady said. 769 00:41:02,890 --> 00:41:06,240 I'm going to ask the following question, which is-- let me 770 00:41:06,240 --> 00:41:16,750 write it down-- what is the number of the basic steps 771 00:41:16,750 --> 00:41:31,270 needed as a function of the input size? 772 00:41:31,270 --> 00:41:35,170 That's the question we're going to try and address. 773 00:41:35,170 --> 00:41:37,750 If we can do this, this is good, because first of all, it 774 00:41:37,750 --> 00:41:40,000 removes any questions about what machine I'm running on, 775 00:41:40,000 --> 00:41:41,910 it's talking about fundamentally, how hard is 776 00:41:41,910 --> 00:41:44,960 this problem, and the second thing is, it is going to do it 777 00:41:44,960 --> 00:41:47,870 specifically in terms of the input. 778 00:41:47,870 --> 00:41:50,780 Which is one of the things that I was worried about. 779 00:41:50,780 --> 00:41:51,110 OK. 780 00:41:51,110 --> 00:41:54,210 So to do this, we're going to have to do a couple of things. 781 00:41:54,210 --> 00:41:57,620 All right, the first one is, what do we mean by input size? 782 00:41:57,620 --> 00:42:00,630 And unfortunately, this depends on the problem. 783 00:42:00,630 --> 00:42:03,500 It could be what's the size of the integer I pass in as an 784 00:42:03,500 --> 00:42:04,960 argument, if that's what I'm passing in. 785 00:42:04,960 --> 00:42:08,190 It could be, how long is the list, if I'm processing a list 786 00:42:08,190 --> 00:42:10,180 or a tuple It could be, how many bits 787 00:42:10,180 --> 00:42:11,290 are there in something. 788 00:42:11,290 --> 00:42:13,380 So it-- that is something where we have to simply be 789 00:42:13,380 --> 00:42:17,100 clear about specifying what we're using as input size. 790 00:42:17,100 --> 00:42:19,950 And we want to characterize it mathematically as some number, 791 00:42:19,950 --> 00:42:22,820 or some variable rather, the length of the list, the size 792 00:42:22,820 --> 00:42:25,680 of the integer, would be the thing we'd want to do. 793 00:42:25,680 --> 00:42:28,140 Second thing we've got to worry about is, 794 00:42:28,140 --> 00:42:29,160 what's a basic step? 795 00:42:29,160 --> 00:42:33,820 All right, if I bury a whole lot of computation inside of 796 00:42:33,820 --> 00:42:36,550 something, I can say, wow, this program, you know, runs 797 00:42:36,550 --> 00:42:37,490 in one step. 798 00:42:37,490 --> 00:42:40,080 Unfortunately, that one step calls the Oracle at Delphi and 799 00:42:40,080 --> 00:42:41,350 gets an answer back. 800 00:42:41,350 --> 00:42:43,710 Maybe not quite what you want. 801 00:42:43,710 --> 00:42:47,050 We're typically going to use as basic steps the built-in 802 00:42:47,050 --> 00:42:49,130 primitives that a machine comes with. 803 00:42:49,130 --> 00:42:50,730 Or another way of saying it is, we're going to use as the 804 00:42:50,730 --> 00:42:53,960 basic steps, those operations that run in constant time, so 805 00:42:53,960 --> 00:42:55,500 arithmetic operations. 806 00:42:55,500 --> 00:42:57,180 Comparisons. 807 00:42:57,180 --> 00:42:59,300 Memory access, and in fact one of the things we're going to 808 00:42:59,300 --> 00:43:08,230 do here, is we're going to assume a particular model, 809 00:43:08,230 --> 00:43:16,340 called a random access model, which basically says, we're 810 00:43:16,340 --> 00:43:19,100 going to assume that the length of time it takes me to 811 00:43:19,100 --> 00:43:23,450 get to any location in memory is constant. 812 00:43:23,450 --> 00:43:25,050 It's not true, by the way, of all programming languages. 813 00:43:25,050 --> 00:43:26,990 In fact, Professor Guttag already talked about that, in 814 00:43:26,990 --> 00:43:30,290 some languages lists take a time linear with the 815 00:43:30,290 --> 00:43:31,120 length to get to it. 816 00:43:31,120 --> 00:43:33,880 So we're to assume we can get to any piece of data, any 817 00:43:33,880 --> 00:43:36,430 instruction in constant time, and the second assumption 818 00:43:36,430 --> 00:43:39,200 we're going to make is that the basic primitive steps take 819 00:43:39,200 --> 00:43:42,090 constant time, same amount of time to compute. 820 00:43:42,090 --> 00:43:44,410 Again, not completely true, but it's a good model, so 821 00:43:44,410 --> 00:43:47,960 arithmetic operations, comparisons, things of that 822 00:43:47,960 --> 00:43:49,830 sort, we're all going to assume are basically in that 823 00:43:49,830 --> 00:43:52,580 in that particular model. 824 00:43:52,580 --> 00:43:52,870 OK. 825 00:43:52,870 --> 00:43:54,650 Having done that, then, there are three things that we're 826 00:43:54,650 --> 00:43:56,210 going to look at. 827 00:43:56,210 --> 00:43:57,900 As I said, what we want to do is, we want to count the 828 00:43:57,900 --> 00:44:01,000 number of basic steps it takes to compute a computation as a 829 00:44:01,000 --> 00:44:02,070 function of input size. 830 00:44:02,070 --> 00:44:04,550 And the question is, what do we want to count? 831 00:44:04,550 --> 00:44:10,720 Now, one possibility is to do best case. 832 00:44:10,720 --> 00:44:13,140 Over all possible inputs to this function, what's the 833 00:44:13,140 --> 00:44:14,200 fastest it runs? 834 00:44:14,200 --> 00:44:19,590 The fewest, so the minimum, if you like. 835 00:44:19,590 --> 00:44:21,220 It's nice, but not particularly helpful. 836 00:44:21,220 --> 00:44:27,930 The other obvious one to do would be worst case. 837 00:44:27,930 --> 00:44:30,310 Again, over all possible inputs to this function, 838 00:44:30,310 --> 00:44:32,780 what's the most number of steps it takes to do the 839 00:44:32,780 --> 00:44:34,470 computation? 840 00:44:34,470 --> 00:44:38,050 And the third possibility, is to do the expected case. 841 00:44:38,050 --> 00:44:43,430 The average. 842 00:44:43,430 --> 00:44:46,420 I'm going to think of it that way. 843 00:44:46,420 --> 00:44:49,680 In general, people focus on worst case. 844 00:44:49,680 --> 00:44:50,430 For a couple of reasons. 845 00:44:50,430 --> 00:44:53,930 In some ways, this would be nicer, do expected cases, it's 846 00:44:53,930 --> 00:44:56,320 going to tell you on average how much you expect to take, 847 00:44:56,320 --> 00:44:58,690 but it tends to be hard to compute, because to compute 848 00:44:58,690 --> 00:45:02,220 that, you have to know a distribution on input. 849 00:45:02,220 --> 00:45:04,420 How likely are all the inputs, are they all equally likely, 850 00:45:04,420 --> 00:45:05,710 or are they going to depend on other things? 851 00:45:05,710 --> 00:45:07,370 And that may depend on the user, so you can't 852 00:45:07,370 --> 00:45:08,940 kind of get at that. 853 00:45:08,940 --> 00:45:12,470 We're, as a consequence, going to focus on worst case. 854 00:45:12,470 --> 00:45:13,940 This is handy for a couple of reasons. 855 00:45:13,940 --> 00:45:16,590 One, it means there are no surprises. 856 00:45:16,590 --> 00:45:17,630 All right? 857 00:45:17,630 --> 00:45:19,740 If you run it, you have a sense of the upper bound, 858 00:45:19,740 --> 00:45:21,330 about how much time it's going to take to do this 859 00:45:21,330 --> 00:45:23,070 computation, so you're not going to get surprised by 860 00:45:23,070 --> 00:45:25,080 something showing up. 861 00:45:25,080 --> 00:45:28,030 The second one is, a lot of the time, the worst case is 862 00:45:28,030 --> 00:45:29,950 the one that happens. 863 00:45:29,950 --> 00:45:31,990 Professor Guttag used an example of looking in the 864 00:45:31,990 --> 00:45:33,030 dictionary for something. 865 00:45:33,030 --> 00:45:35,710 Now, imagine that dictionary actually has something that's 866 00:45:35,710 --> 00:45:38,010 a linear search to go through it, as opposed to the hashing 867 00:45:38,010 --> 00:45:40,300 he did, so it's a list, for example. 868 00:45:40,300 --> 00:45:42,380 If it's in there, you'll find it perhaps very quickly. 869 00:45:42,380 --> 00:45:44,550 If it's not there, you've got to go through everything to 870 00:45:44,550 --> 00:45:45,440 say it's not there. 871 00:45:45,440 --> 00:45:47,900 And so the worst case often is the one that shows up, 872 00:45:47,900 --> 00:45:50,480 especially in things like search. 873 00:45:50,480 --> 00:45:55,160 So, as a consequence, we're going to stick with the worst 874 00:45:55,160 --> 00:45:57,160 case analysis. 875 00:45:57,160 --> 00:45:59,640 Now, I've got two minutes left. 876 00:45:59,640 --> 00:46:01,750 I was going to start showing you some examples, but I 877 00:46:01,750 --> 00:46:04,363 think, rather than doing that, I'm going to stop here, I'm 878 00:46:04,363 --> 00:46:06,190 going to give you two minutes back of time, but I want to 879 00:46:06,190 --> 00:46:09,630 just point out to you that we are going to have fun next 880 00:46:09,630 --> 00:46:14,190 week, because I'm going to show you what in the world 881 00:46:14,190 --> 00:46:16,960 that has to do with efficiency. 882 00:46:16,960 --> 00:46:19,560 So with that, we'll see you next time.