1 00:00:06,136 --> 00:00:08,270 SRINI DEVADAS: Good morning, everyone. 2 00:00:08,270 --> 00:00:10,130 Thanks for coming in on a Friday morning, 3 00:00:10,130 --> 00:00:12,680 especially with the long weekend coming up. 4 00:00:12,680 --> 00:00:17,900 We're going to pick up where we left off yesterday. 5 00:00:17,900 --> 00:00:23,810 And so if you recall, we were looking 6 00:00:23,810 --> 00:00:27,710 at an iterative approach to solving the eight queens 7 00:00:27,710 --> 00:00:29,150 problem. 8 00:00:29,150 --> 00:00:32,730 And in case you've forgotten in the, 9 00:00:32,730 --> 00:00:37,600 I guess, intervening 20 hours, the eight queens problem, 10 00:00:37,600 --> 00:00:41,560 which is a specific instance of n queens 11 00:00:41,560 --> 00:00:43,270 is you have a chess board-- 12 00:00:43,270 --> 00:00:45,960 and I won't draw all the squares-- 13 00:00:45,960 --> 00:00:48,200 which is, obviously, an 8 by 8 board. 14 00:00:48,200 --> 00:00:52,530 And you want to place eight queens on this board 15 00:00:52,530 --> 00:00:55,220 such that no two queens attack each other. 16 00:00:55,220 --> 00:00:58,970 And we looked at different data structures to solve this. 17 00:00:58,970 --> 00:01:02,510 The naive data structure would be 18 00:01:02,510 --> 00:01:09,860 to represent the board as a two-dimensional list. 19 00:01:09,860 --> 00:01:13,120 And so you end up having an 8 by 8, 20 00:01:13,120 --> 00:01:15,830 if you have a chessboard for the eight queens problem. 21 00:01:15,830 --> 00:01:19,100 We looked at a 4 by 4 for starters. 22 00:01:19,100 --> 00:01:22,730 And then after that, we looked at compressing 23 00:01:22,730 --> 00:01:29,090 that representation down to a one-dimensional list where 24 00:01:29,090 --> 00:01:31,670 let's say you had a 5 by 5 board because we've 25 00:01:31,670 --> 00:01:33,050 got five entries here. 26 00:01:36,920 --> 00:01:40,670 You exploit the fact that there can be at most one 27 00:01:40,670 --> 00:01:43,670 queen on any given column. 28 00:01:43,670 --> 00:01:46,730 And you say I'm going to represent 29 00:01:46,730 --> 00:01:52,490 the position of that queen using a single number where is from, 30 00:01:52,490 --> 00:01:58,220 in this case 0 through 4, if I have a 5 by 5 board, 31 00:01:58,220 --> 00:02:00,090 and you put that in here. 32 00:02:00,090 --> 00:02:03,260 So a minus 1 would represent this being empty. 33 00:02:03,260 --> 00:02:13,690 A 2 would represent a queen in the second column 34 00:02:13,690 --> 00:02:17,110 in this position over here, et cetera, et cetera. 35 00:02:17,110 --> 00:02:20,920 So with this more compact representation, 36 00:02:20,920 --> 00:02:23,770 it turns out that the conflict check 37 00:02:23,770 --> 00:02:27,140 becomes pretty straightforward. 38 00:02:27,140 --> 00:02:30,820 And if you remember, our conflict check 39 00:02:30,820 --> 00:02:34,360 is incremental in the sense that what you're going to do 40 00:02:34,360 --> 00:02:39,220 is assume that queens have already been placed 41 00:02:39,220 --> 00:02:40,510 in some number of columns. 42 00:02:40,510 --> 00:02:41,680 I mean, it could be zero. 43 00:02:41,680 --> 00:02:43,150 In this case it's 2. 44 00:02:43,150 --> 00:02:45,430 And you're going to try and check 45 00:02:45,430 --> 00:02:47,680 to see when a third queen is placed 46 00:02:47,680 --> 00:02:50,280 on this third column, number two, 47 00:02:50,280 --> 00:02:55,240 whether it conflicts with the existing queens. 48 00:02:55,240 --> 00:02:59,372 But you don't have to worry about the checks associated 49 00:02:59,372 --> 00:03:01,330 with the existing queens because you've already 50 00:03:01,330 --> 00:03:02,560 taken care of that. 51 00:03:02,560 --> 00:03:05,080 So that's the incremental nature of this check. 52 00:03:05,080 --> 00:03:07,570 And I won't go over this code again, 53 00:03:07,570 --> 00:03:13,030 but the check associated with ensuring 54 00:03:13,030 --> 00:03:20,730 that when you place a queen on a given column, 55 00:03:20,730 --> 00:03:21,910 it checks the diagonals. 56 00:03:21,910 --> 00:03:24,250 That's the most interesting part. 57 00:03:24,250 --> 00:03:29,260 And you put a queen here, you need to check this, 58 00:03:29,260 --> 00:03:30,920 and you need to check that. 59 00:03:30,920 --> 00:03:32,950 And in this case, obviously there's a conflict. 60 00:03:32,950 --> 00:03:34,741 And because there are two diagonals, that's 61 00:03:34,741 --> 00:03:37,060 why you have the ABS, the absolute value over there, 62 00:03:37,060 --> 00:03:39,720 and you're exploiting the fact that the diagonal is 63 00:03:39,720 --> 00:03:42,790 a diagonal of a square, and how much you move up 64 00:03:42,790 --> 00:03:45,910 should be how much you move to the right or down, left, 65 00:03:45,910 --> 00:03:47,680 or what have you. 66 00:03:47,680 --> 00:03:51,670 Another check is simply ensuring that when 67 00:03:51,670 --> 00:03:53,670 you look at the particular column 68 00:03:53,670 --> 00:03:58,060 and you see the number current is a particular column, 69 00:03:58,060 --> 00:04:00,220 the number associated with that particular column 70 00:04:00,220 --> 00:04:02,960 shouldn't be repeated in some other column. 71 00:04:02,960 --> 00:04:08,470 Because that would imply that if you saw a 2 and a 2 here, 72 00:04:08,470 --> 00:04:11,770 obviously, that would imply that you 73 00:04:11,770 --> 00:04:16,690 have two queens on the same row, and you can't have that. 74 00:04:16,690 --> 00:04:18,000 So that's the story. 75 00:04:18,000 --> 00:04:23,560 And we decided to use iteration because, at this point in time, 76 00:04:23,560 --> 00:04:25,970 you know nothing else in terms of control flow. 77 00:04:25,970 --> 00:04:29,350 I know that's not the case, but we assume that. 78 00:04:29,350 --> 00:04:32,680 And so you end up having this ugly code 79 00:04:32,680 --> 00:04:39,100 associated with eight nested loops that does 80 00:04:39,100 --> 00:04:43,960 this incremental enumeration. 81 00:04:43,960 --> 00:04:52,960 So board 0 being i implies that you're taking the first column 82 00:04:52,960 --> 00:04:54,820 and you're iterating the positions 83 00:04:54,820 --> 00:04:57,860 of the queen in the rows of the first column, 84 00:04:57,860 --> 00:04:59,240 and so on and so forth. 85 00:04:59,240 --> 00:05:00,670 And if you go ahead and run this, 86 00:05:00,670 --> 00:05:02,950 which we did last time you end up 87 00:05:02,950 --> 00:05:08,470 getting 92 different solutions to the eight queens problem, 88 00:05:08,470 --> 00:05:11,350 and as I mentioned, there's only 12 distinct ones. 89 00:05:11,350 --> 00:05:14,410 So if you take rotation and reflection into account 90 00:05:14,410 --> 00:05:17,540 and each of these is a legitimate solution, 91 00:05:17,540 --> 00:05:20,440 that needs to be translated into the picture 92 00:05:20,440 --> 00:05:24,820 that you see here by essentially taking this data 93 00:05:24,820 --> 00:05:26,480 structure that you see. 94 00:05:26,480 --> 00:05:31,300 7 becomes the queen in the left corner, et cetera. 95 00:05:31,300 --> 00:05:37,840 So we absolutely wouldn't want to publish this code. 96 00:05:37,840 --> 00:05:39,400 I guess, in effect, I'm doing it. 97 00:05:39,400 --> 00:05:45,970 But you would not want to claim authorship of this code 98 00:05:45,970 --> 00:05:50,500 especially if you know about the programming technique that's 99 00:05:50,500 --> 00:05:51,860 called recursion. 100 00:05:51,860 --> 00:05:53,800 So that's really what we're going to do today. 101 00:05:53,800 --> 00:05:56,008 We're going to look at a couple of different puzzles. 102 00:05:56,008 --> 00:05:59,320 We'll finish up with the n queen's puzzle fairly quickly, 103 00:05:59,320 --> 00:06:02,330 and we'll look at how we could use recursion, which 104 00:06:02,330 --> 00:06:05,440 is an algorithm paradigm as well as a programming paradigm 105 00:06:05,440 --> 00:06:08,330 to solve challenging problems. 106 00:06:08,330 --> 00:06:12,010 And there's really two classes, at least, 107 00:06:12,010 --> 00:06:14,170 of recursive algorithms, and you're 108 00:06:14,170 --> 00:06:15,830 going to see both of those today. 109 00:06:15,830 --> 00:06:18,730 The first one is nQueens, and I'll get to the second one 110 00:06:18,730 --> 00:06:21,670 when we get to the second one. 111 00:06:21,670 --> 00:06:27,460 So our goal now is to take that ugly code and make it pretty. 112 00:06:27,460 --> 00:06:30,190 And before I get into that, I want 113 00:06:30,190 --> 00:06:37,150 to show you a simpler example of iteration versus recursion. 114 00:06:37,150 --> 00:06:39,670 And this is about as simple as it 115 00:06:39,670 --> 00:06:41,980 gets while still being interesting 116 00:06:41,980 --> 00:06:43,730 from an algorithmic standpoint. 117 00:06:43,730 --> 00:06:49,990 So the greatest common divisor, Euclid's age-old algorithm 118 00:06:49,990 --> 00:06:52,480 to compute the greatest common divisor. 119 00:06:52,480 --> 00:06:55,300 And you see the two line, three line, 120 00:06:55,300 --> 00:06:57,670 what have you iterative algorithm up 121 00:06:57,670 --> 00:07:02,590 there that corresponds to taking the pair of numbers, obviously, 122 00:07:02,590 --> 00:07:06,700 m and n that you need to compute the greatest 123 00:07:06,700 --> 00:07:08,230 common divisor for. 124 00:07:08,230 --> 00:07:20,320 And all you do is assign m to n and n becomes n mod m. 125 00:07:20,320 --> 00:07:23,950 And I'm not going to explain why this algorithm is correct 126 00:07:23,950 --> 00:07:25,120 or anything like that. 127 00:07:25,120 --> 00:07:26,980 I'm not particularly interested in that. 128 00:07:26,980 --> 00:07:29,290 What I'm much more interested in is 129 00:07:29,290 --> 00:07:34,510 ensuring that you understand that the iterative algorithm is 130 00:07:34,510 --> 00:07:37,990 the same as the recursive one. 131 00:07:37,990 --> 00:07:40,854 The recursive one gets you the correct answer 132 00:07:40,854 --> 00:07:42,520 if you assume the iterative algorithm is 133 00:07:42,520 --> 00:07:44,830 correct and vice versa, and that's 134 00:07:44,830 --> 00:07:46,660 really what this is about. 135 00:07:46,660 --> 00:07:51,530 So we won't argue if Euclid is correct or not. 136 00:07:51,530 --> 00:07:57,440 But the point here is you could have translated-- 137 00:07:57,440 --> 00:07:59,650 well, you did translate this iterative algorithm 138 00:07:59,650 --> 00:08:01,060 into a recursive one. 139 00:08:01,060 --> 00:08:02,920 And there's a couple of things I want 140 00:08:02,920 --> 00:08:06,700 you to keep in mind when you look at recursive code 141 00:08:06,700 --> 00:08:08,860 and certainly when you write recursive code. 142 00:08:08,860 --> 00:08:11,140 And it's much easier pointing this out 143 00:08:11,140 --> 00:08:13,870 in a simple example like this. 144 00:08:13,870 --> 00:08:19,450 So first off, when we say recursion-- 145 00:08:19,450 --> 00:08:22,000 and I should have probably said this a little bit earlier-- 146 00:08:22,000 --> 00:08:26,230 recursion is something calling itself. 147 00:08:26,230 --> 00:08:29,980 So you can say a function, f, calling itself, 148 00:08:29,980 --> 00:08:32,020 that's the simple case. 149 00:08:32,020 --> 00:08:34,480 We also consider if you have f calling 150 00:08:34,480 --> 00:08:42,049 g, which calls f, then that is recursive as well. 151 00:08:42,049 --> 00:08:45,070 And see you can have arbitrary structures that 152 00:08:45,070 --> 00:08:46,920 correspond to nested recursion. 153 00:08:46,920 --> 00:08:51,660 We're really only going to be looking at functions 154 00:08:51,660 --> 00:08:55,390 at least in this lecture, where you have a single function, f, 155 00:08:55,390 --> 00:08:58,210 calling itself, which is exactly the case 156 00:08:58,210 --> 00:09:01,880 for our RGCD, the Recursive GCD that you see here. 157 00:09:01,880 --> 00:09:05,530 You see a call RGCD inside of RGCD, 158 00:09:05,530 --> 00:09:07,270 and you know this function is recursive. 159 00:09:07,270 --> 00:09:09,730 Sometimes you may look at a function 160 00:09:09,730 --> 00:09:15,070 and you don't see that immediate syntactic evidence 161 00:09:15,070 --> 00:09:19,330 that the function is recursive, but it may be recursive 162 00:09:19,330 --> 00:09:23,740 because of nested recursion, f calling 163 00:09:23,740 --> 00:09:26,240 g, more complicated recursion. 164 00:09:26,240 --> 00:09:29,650 So this is clearly a recursive function, RGCD. 165 00:09:29,650 --> 00:09:34,870 And two things that you need to look 166 00:09:34,870 --> 00:09:38,620 for if you want to write correct recursion, I mean this 167 00:09:38,620 --> 00:09:41,300 is not sufficient to write correct recursion, 168 00:09:41,300 --> 00:09:43,450 but necessary. 169 00:09:43,450 --> 00:09:46,930 And in particular, when I say correct recursion, 170 00:09:46,930 --> 00:09:52,220 I want it to be non-terminating, so the problem 171 00:09:52,220 --> 00:09:56,230 with something calling itself is, you think of it as there's 172 00:09:56,230 --> 00:09:59,334 some sort of cycle and you absolutely 173 00:09:59,334 --> 00:10:01,250 need to break out of the cycle, otherwise, you 174 00:10:01,250 --> 00:10:02,770 will be in the cycle forever. 175 00:10:02,770 --> 00:10:05,970 You could call something which calls something, which 176 00:10:05,970 --> 00:10:08,260 calls something that goes on, your program 177 00:10:08,260 --> 00:10:09,807 isn't going to terminate. 178 00:10:09,807 --> 00:10:12,390 So you always want to be careful when you write recursive code 179 00:10:12,390 --> 00:10:14,900 that there's a base case. 180 00:10:14,900 --> 00:10:16,970 There's a termination condition. 181 00:10:16,970 --> 00:10:20,560 So there should be some part of the code 182 00:10:20,560 --> 00:10:25,030 where if certain conditions are satisfied, 183 00:10:25,030 --> 00:10:27,880 you're not making a recursive call. 184 00:10:27,880 --> 00:10:29,920 That is what I would consider the base case. 185 00:10:29,920 --> 00:10:32,770 That really comes from induction and from the mathematics 186 00:10:32,770 --> 00:10:33,820 of recursion. 187 00:10:33,820 --> 00:10:36,190 You want to have a base case and then the recursion 188 00:10:36,190 --> 00:10:38,770 is really the inductive step. 189 00:10:38,770 --> 00:10:41,620 If that doesn't make too much sense, don't worry about it. 190 00:10:41,620 --> 00:10:43,330 You can think of it syntactically. 191 00:10:43,330 --> 00:10:45,490 Look for a path in the code where you 192 00:10:45,490 --> 00:10:48,220 don't see RGCD inside of RGCD. 193 00:10:48,220 --> 00:10:52,180 And you can clearly see that in the if m mod n 194 00:10:52,180 --> 00:10:54,370 equals equals 0, return n. 195 00:10:57,520 --> 00:11:00,310 So you want to have what we call the base 196 00:11:00,310 --> 00:11:07,150 case where a function returns. 197 00:11:10,660 --> 00:11:12,670 That's not enough because you don't quite 198 00:11:12,670 --> 00:11:15,940 know if you're going to get to that base case or not. 199 00:11:15,940 --> 00:11:19,900 You're going to call this function with some arguments, 200 00:11:19,900 --> 00:11:22,780 and you want to get some sense that the arguments are 201 00:11:22,780 --> 00:11:25,666 shrinking as you go. 202 00:11:25,666 --> 00:11:27,415 And it could even be the other way around. 203 00:11:27,415 --> 00:11:30,370 The arguments may increase, and once you 204 00:11:30,370 --> 00:11:34,240 grow beyond a certain threshold, you fire off on the return 205 00:11:34,240 --> 00:11:37,390 without making the recursive call. 206 00:11:37,390 --> 00:11:41,050 So this notion of the arguments becoming smaller 207 00:11:41,050 --> 00:11:46,090 is very common in the case of the algorithmic paradigm 208 00:11:46,090 --> 00:11:47,930 that we'll be following in this class 209 00:11:47,930 --> 00:11:50,200 where we're going to take large problems like a eight 210 00:11:50,200 --> 00:11:53,700 queens or n queens and go to n minus 1 queens 211 00:11:53,700 --> 00:11:55,300 and n minus 2 queens. 212 00:11:55,300 --> 00:11:59,800 And divide and conquer, which is other paradigm that we look at. 213 00:11:59,800 --> 00:12:03,130 As you can see from the name is taking a big problem 214 00:12:03,130 --> 00:12:05,080 and making it smaller. 215 00:12:05,080 --> 00:12:07,030 So really for the most part, you're 216 00:12:07,030 --> 00:12:10,270 going to essentially have a situation where you're 217 00:12:10,270 --> 00:12:19,240 going to say that the arguments to the function 218 00:12:19,240 --> 00:12:25,280 should be smaller in some sense. 219 00:12:25,280 --> 00:12:27,590 And smaller could mean bigger. 220 00:12:27,590 --> 00:12:29,420 I mean, it's just a definitional thing. 221 00:12:29,420 --> 00:12:33,080 I mean, the point is when you get to the base case, 222 00:12:33,080 --> 00:12:35,750 usually you are saying, as you can see in this base case, 223 00:12:35,750 --> 00:12:38,220 you're saying when it comes down to the fact 224 00:12:38,220 --> 00:12:41,660 that a particular condition is satisfied, in this case, 225 00:12:41,660 --> 00:12:43,760 it's the relationship between m and n. 226 00:12:43,760 --> 00:12:45,920 And if that's 0, then we return n. 227 00:12:45,920 --> 00:12:47,630 But in other cases, it just might 228 00:12:47,630 --> 00:12:51,950 be when you get to a one queen problem, you're done. 229 00:12:51,950 --> 00:12:53,390 I mean, you have no choice. 230 00:12:53,390 --> 00:12:55,070 You've got this 1 by 1 board and you've 231 00:12:55,070 --> 00:12:57,500 got to put your queen on it, and obviously, that 232 00:12:57,500 --> 00:13:00,080 might create a conflict, but you're done. 233 00:13:00,080 --> 00:13:01,790 I mean, there's no two things about it 234 00:13:01,790 --> 00:13:03,290 if you have one queen problem. 235 00:13:03,290 --> 00:13:04,960 There's only one step. 236 00:13:04,960 --> 00:13:07,310 You put your queen down. 237 00:13:07,310 --> 00:13:10,250 So that's where we were at with respect to the puzzles 238 00:13:10,250 --> 00:13:12,410 that we're going to be doing in this class 239 00:13:12,410 --> 00:13:15,590 where you're going to shrink things down. 240 00:13:15,590 --> 00:13:20,360 So in that sense, smaller would mean smaller. 241 00:13:20,360 --> 00:13:22,810 It's not necessarily in quotes. 242 00:13:22,810 --> 00:13:23,690 So that makes sense? 243 00:13:23,690 --> 00:13:26,630 Any questions at all about syntax or anything 244 00:13:26,630 --> 00:13:29,940 that you see on the board here? 245 00:13:29,940 --> 00:13:31,110 All right good. 246 00:13:31,110 --> 00:13:40,990 So now, I'm ready to show you what the n queens 247 00:13:40,990 --> 00:13:42,239 code looks like. 248 00:13:42,239 --> 00:13:43,780 One of the other problems, of course, 249 00:13:43,780 --> 00:13:51,440 with the eight queens code is that it only 250 00:13:51,440 --> 00:13:55,820 works for eight queens, and it doesn't work for nine. 251 00:13:55,820 --> 00:14:00,290 And that's annoying, so you'd like 252 00:14:00,290 --> 00:14:05,720 to have a procedure that takes n as an argument and works 253 00:14:05,720 --> 00:14:08,510 for n equals 4, n equals 8. 254 00:14:08,510 --> 00:14:11,030 And eventually, you could run this on n equals 20, 255 00:14:11,030 --> 00:14:12,260 and it will finish. 256 00:14:12,260 --> 00:14:13,350 I'll show you. 257 00:14:13,350 --> 00:14:16,550 But there is an exponential relationship 258 00:14:16,550 --> 00:14:21,330 between run time and n because it's just 259 00:14:21,330 --> 00:14:22,560 a complicated problem. 260 00:14:22,560 --> 00:14:24,090 There's a lot of combinations. 261 00:14:24,090 --> 00:14:27,880 So you do not want to run this code for more than n equals 25. 262 00:14:27,880 --> 00:14:29,810 It hasn't completed. 263 00:14:29,810 --> 00:14:33,590 I think at some point I did an analysis on how long 264 00:14:33,590 --> 00:14:37,009 it would take for n equals 30, and it wasn't 265 00:14:37,009 --> 00:14:38,300 something I wanted to wait for. 266 00:14:38,300 --> 00:14:40,430 I mean, my computer would have gotten old 267 00:14:40,430 --> 00:14:44,720 and died before the program came back. 268 00:14:44,720 --> 00:14:47,360 Which is a reasonable experiment to carry out, 269 00:14:47,360 --> 00:14:49,490 but I like my computer. 270 00:14:49,490 --> 00:14:52,760 I'm kind of annoyed with it because of the new operating 271 00:14:52,760 --> 00:14:55,310 system, but I generally like it. 272 00:14:55,310 --> 00:14:57,710 So you can see that we're going to use 273 00:14:57,710 --> 00:14:59,710 exactly the same framework. 274 00:14:59,710 --> 00:15:04,080 We're going to use the same no conflicts routine. 275 00:15:04,080 --> 00:15:07,460 There's no change there, no change in data structures. 276 00:15:07,460 --> 00:15:10,160 There's no change in really even the incremental strategy 277 00:15:10,160 --> 00:15:11,650 that we're following. 278 00:15:11,650 --> 00:15:13,640 But we can take that intuitive code 279 00:15:13,640 --> 00:15:16,910 and turn it into this pretty code that has about five lines, 280 00:15:16,910 --> 00:15:19,740 or seven lines, what have you. 281 00:15:19,740 --> 00:15:23,060 And so you can see, again, that if you look at that code, 282 00:15:23,060 --> 00:15:24,960 I mean, it's not that much more complicated. 283 00:15:24,960 --> 00:15:26,789 There's more going on in there. 284 00:15:26,789 --> 00:15:29,330 There's more going on because it's a more interesting problem 285 00:15:29,330 --> 00:15:35,780 at some level than GCD, but it has the same characteristics 286 00:15:35,780 --> 00:15:39,650 in terms of having a base case, and it's actually an easy one 287 00:15:39,650 --> 00:15:40,370 to look at. 288 00:15:40,370 --> 00:15:44,270 And it also has a property 2 here 289 00:15:44,270 --> 00:15:46,490 where the argument to the nQueens 290 00:15:46,490 --> 00:15:51,050 is going to be one less than what the caller function has 291 00:15:51,050 --> 00:15:53,780 as its argument because you're going column by column, 292 00:15:53,780 --> 00:15:55,410 and you're taking away. 293 00:15:55,410 --> 00:15:58,760 In this case, you're not necessarily going to a 7 294 00:15:58,760 --> 00:16:00,470 by 7, really. 295 00:16:00,470 --> 00:16:04,280 It's not that you're going from 8 by 8 to 7 by 7. 296 00:16:04,280 --> 00:16:07,340 You're going from 8 by 8 to 7 by 8. 297 00:16:09,920 --> 00:16:11,250 You have one less column. 298 00:16:11,250 --> 00:16:14,990 You still have to work with all the rows. 299 00:16:14,990 --> 00:16:16,830 So that's really what's going on out here. 300 00:16:16,830 --> 00:16:18,600 If current equal size-- 301 00:16:18,600 --> 00:16:22,400 so what's happening is current is actually incrementing. 302 00:16:22,400 --> 00:16:28,820 So you're moving and what is remaining is becoming smaller. 303 00:16:28,820 --> 00:16:31,710 And current starts with-- 304 00:16:31,710 --> 00:16:34,980 so if you look at nQueens here, it 305 00:16:34,980 --> 00:16:39,170 says nQueens, a size, and rQueens, 306 00:16:39,170 --> 00:16:47,120 which is this routine here, it sets current to be 0. 307 00:16:47,120 --> 00:16:50,540 And size is, of course, whatever you give nQueens, 308 00:16:50,540 --> 00:16:53,010 which could be 8 or 20. 309 00:16:53,010 --> 00:17:00,290 And finally, if you look at this part of the code, 310 00:17:00,290 --> 00:17:02,060 you get to the point where you run out 311 00:17:02,060 --> 00:17:04,490 of columns when current equals size. 312 00:17:04,490 --> 00:17:07,730 And at this point, you put all the queens down, 313 00:17:07,730 --> 00:17:10,010 and that things haven't fallen apart-- 314 00:17:10,010 --> 00:17:11,630 you haven't returned false-- 315 00:17:11,630 --> 00:17:14,150 and therefore, you're done. 316 00:17:14,150 --> 00:17:16,880 So when you get to that quote ninth column, 317 00:17:16,880 --> 00:17:19,210 you're off the board, and you're done. 318 00:17:19,210 --> 00:17:21,829 And all of the existing queens, the eight queens 319 00:17:21,829 --> 00:17:23,690 that were put on the board, didn't 320 00:17:23,690 --> 00:17:25,460 conflict with each other. 321 00:17:25,460 --> 00:17:27,140 That's how it works. 322 00:17:27,140 --> 00:17:31,859 And then over here, you've taken your eight loops that 323 00:17:31,859 --> 00:17:34,400 were in the eight queens problem or the for loops in the four 324 00:17:34,400 --> 00:17:37,800 queens problem and you've gone off 325 00:17:37,800 --> 00:17:39,860 and turned it into one loop. 326 00:17:39,860 --> 00:17:41,810 And the reason that works is because rQueens 327 00:17:41,810 --> 00:17:43,430 is calling rQueens out here. 328 00:17:43,430 --> 00:17:46,610 So that's your recursive call. 329 00:17:46,610 --> 00:17:51,080 And then the argument here is current plus 1, 330 00:17:51,080 --> 00:17:53,120 and it's getting closer and closer to size 331 00:17:53,120 --> 00:17:56,150 as you go around, which means that it's effectively 332 00:17:56,150 --> 00:17:57,950 getting smaller. 333 00:17:57,950 --> 00:18:01,160 What you're working with is getting smaller. 334 00:18:01,160 --> 00:18:04,280 So if of look at what happens here, 335 00:18:04,280 --> 00:18:07,610 you can trace the execution of this, 336 00:18:07,610 --> 00:18:09,560 and this is worthwhile doing. 337 00:18:09,560 --> 00:18:13,490 And I'll put this in the notes, and you can look at it for a 4 338 00:18:13,490 --> 00:18:14,360 by 4. 339 00:18:14,360 --> 00:18:18,030 But in general, if you're confused about recursion, 340 00:18:18,030 --> 00:18:20,780 it's absolutely worthwhile to trace 341 00:18:20,780 --> 00:18:24,650 the execution for small arguments 342 00:18:24,650 --> 00:18:27,710 and figure out exactly when things are terminating 343 00:18:27,710 --> 00:18:30,920 and when things are being called recursively. 344 00:18:30,920 --> 00:18:34,325 And this is simply a single call. 345 00:18:39,500 --> 00:18:45,920 It looks like it's a single call, because there's 346 00:18:45,920 --> 00:18:47,750 only one instance of rQueens. 347 00:18:47,750 --> 00:18:51,700 But if you look at the code, how many calls would 348 00:18:51,700 --> 00:18:56,590 I possibly make if I were sitting with an eight queens 349 00:18:56,590 --> 00:19:03,280 problem and I started with size equals 8? 350 00:19:03,280 --> 00:19:06,070 Then in that very first, I invoke rQueens 351 00:19:06,070 --> 00:19:10,130 with current equal 0 and size equals 8. 352 00:19:10,130 --> 00:19:13,360 How many rQueens calls will the first rQueens make? 353 00:19:18,120 --> 00:19:22,130 How many times would potentially make that? 354 00:19:22,130 --> 00:19:26,810 So if I look at the branching here and I say this is rQueens 355 00:19:26,810 --> 00:19:34,610 and this has current equals 0 and size equals 8, 356 00:19:34,610 --> 00:19:39,310 the way you want to think about this from a tracing standpoint 357 00:19:39,310 --> 00:19:41,960 is you're making calls. 358 00:19:41,960 --> 00:19:44,690 rQueens is calling rQueens. 359 00:19:44,690 --> 00:19:48,320 And obviously, there is rQueens in the middle 360 00:19:48,320 --> 00:19:51,360 of that code over there. 361 00:19:51,360 --> 00:19:54,680 And so what is the breadth here in terms 362 00:19:54,680 --> 00:19:56,010 of the number of calls? 363 00:19:58,617 --> 00:19:59,116 Someone? 364 00:20:04,660 --> 00:20:05,600 Trace the code. 365 00:20:05,600 --> 00:20:10,010 So i in range 8, which means 0 through 7, 366 00:20:10,010 --> 00:20:13,480 and then I'm going to go off, and this is the very first one. 367 00:20:13,480 --> 00:20:17,150 So noConflicts is going to constantly return-- 368 00:20:17,150 --> 00:20:18,650 it's the first queen. 369 00:20:18,650 --> 00:20:21,950 So noConflicts is going to constantly return true. 370 00:20:21,950 --> 00:20:24,350 So I'm going to go inside of the if, 371 00:20:24,350 --> 00:20:27,220 and I'm going to make that rQueens call. 372 00:20:27,220 --> 00:20:31,040 So I'm going to have eight different calls associated 373 00:20:31,040 --> 00:20:32,990 with each of the positions that corresponds 374 00:20:32,990 --> 00:20:36,440 to the queen on that first column. 375 00:20:36,440 --> 00:20:40,280 And then each of these could potentially 376 00:20:40,280 --> 00:20:43,890 make eight different calls, potentially I 377 00:20:43,890 --> 00:20:46,640 said because as you get deeper in the recursion, 378 00:20:46,640 --> 00:20:49,820 the noConflicts is going to fire false, 379 00:20:49,820 --> 00:20:51,892 and it may not make the call. 380 00:20:51,892 --> 00:20:53,600 But obviously, the very first one, you're 381 00:20:53,600 --> 00:20:55,320 going to make eight calls. 382 00:20:55,320 --> 00:21:00,670 So recursion is scary from a performance standpoint 383 00:21:00,670 --> 00:21:05,294 to some people and rightly so because things could explode 384 00:21:05,294 --> 00:21:06,710 on you, and this goes back to what 385 00:21:06,710 --> 00:21:10,680 I said about running this with n r size 386 00:21:10,680 --> 00:21:12,630 equals 25 and so on and so forth. 387 00:21:12,630 --> 00:21:14,510 And one of the things that is worth doing 388 00:21:14,510 --> 00:21:23,240 and you have to do this type of analysis in classes like 6.006, 389 00:21:23,240 --> 00:21:25,310 not a lot of this but because we don't 390 00:21:25,310 --> 00:21:27,050 do exponential algorithms. 391 00:21:27,050 --> 00:21:30,020 But you can look at this tree that 392 00:21:30,020 --> 00:21:32,820 is being generated by these recursive calls 393 00:21:32,820 --> 00:21:36,140 and you do want to get some sense of how large this tree is 394 00:21:36,140 --> 00:21:37,300 going to become. 395 00:21:37,300 --> 00:21:39,807 And we're going to look at a different class of algorithms. 396 00:21:39,807 --> 00:21:41,390 Most of algorithms we're going to look 397 00:21:41,390 --> 00:21:45,920 at that are recursive for the rest of this course including 398 00:21:45,920 --> 00:21:49,700 the next one that we'll get to in a few minutes, 399 00:21:49,700 --> 00:21:52,100 aren't as bad as this one in terms 400 00:21:52,100 --> 00:21:54,620 of computational complexity. 401 00:21:54,620 --> 00:21:56,420 But n queens is a hard problem. 402 00:21:56,420 --> 00:22:00,570 It needs exhaustive search, and there's a lot of combinations. 403 00:22:00,570 --> 00:22:02,960 And so it's not an efficient algorithm. 404 00:22:02,960 --> 00:22:05,450 Efficient means polynomial times something 405 00:22:05,450 --> 00:22:09,180 like n square quadratic, n cubed, and so on. 406 00:22:09,180 --> 00:22:11,630 And this is not efficient, and the reason for that 407 00:22:11,630 --> 00:22:14,630 is this explosion in the number of recursive calls. 408 00:22:14,630 --> 00:22:17,990 So it's easy to write five lines of code that takes forever 409 00:22:17,990 --> 00:22:18,830 to run. 410 00:22:18,830 --> 00:22:19,700 It will terminate. 411 00:22:19,700 --> 00:22:21,680 It's not that it had an infinite loop in it, 412 00:22:21,680 --> 00:22:24,500 but the number of combinations explodes on you because 413 00:22:24,500 --> 00:22:32,300 of eight and then eight again for each of these and then-- 414 00:22:32,300 --> 00:22:32,850 and so on. 415 00:22:32,850 --> 00:22:36,980 So you can see that gets pretty large pretty quick. 416 00:22:36,980 --> 00:22:45,800 So this code is something that, as I said, 417 00:22:45,800 --> 00:22:47,990 is essentially the same. 418 00:22:47,990 --> 00:22:51,350 It's sitting there computing nQueens 20. 419 00:22:51,350 --> 00:22:54,590 That's why this is not a problem with my laptop, at least, 420 00:22:54,590 --> 00:22:58,467 as of this moment, I don't think it's a problem with my laptop. 421 00:22:58,467 --> 00:22:59,300 And so there you go. 422 00:22:59,300 --> 00:23:07,140 So nQueens 20 gave you the representation that we chose. 423 00:23:07,140 --> 00:23:09,350 You can try and convince yourself 424 00:23:09,350 --> 00:23:11,780 that this, in fact, is correct. 425 00:23:11,780 --> 00:23:13,410 I haven't. 426 00:23:13,410 --> 00:23:16,790 But that code is so straightforward at this point 427 00:23:16,790 --> 00:23:20,200 that if there is anything wrong with it, 428 00:23:20,200 --> 00:23:22,850 it would be catastrophically wrong. 429 00:23:22,850 --> 00:23:26,680 It would just crash or it wouldn't return anything. 430 00:23:26,680 --> 00:23:28,620 And so that is one solution. 431 00:23:28,620 --> 00:23:29,900 There's many, many solutions. 432 00:23:29,900 --> 00:23:33,710 Unlike the eight queens case, where I ran it to completion 433 00:23:33,710 --> 00:23:36,200 and all the 92 solutions got printed out, 434 00:23:36,200 --> 00:23:38,100 there's millions of solutions here. 435 00:23:38,100 --> 00:23:41,180 So if I just took out a return statement and let it run, 436 00:23:41,180 --> 00:23:44,030 you'll get screen fulls of solutions 437 00:23:44,030 --> 00:23:49,700 to the 20 queens problem because if you did that, there 438 00:23:49,700 --> 00:23:50,990 would be a lot of solutions. 439 00:23:50,990 --> 00:23:52,820 But especially given that we are not 440 00:23:52,820 --> 00:23:56,960 exploiting rotational symmetry and reflections, 441 00:23:56,960 --> 00:23:58,880 there's a lot of solutions. 442 00:23:58,880 --> 00:24:00,230 But that's one of them. 443 00:24:00,230 --> 00:24:02,870 So there you go. 444 00:24:02,870 --> 00:24:03,650 Yeah. 445 00:24:03,650 --> 00:24:04,150 Question. 446 00:24:04,150 --> 00:24:05,770 AUDIENCE: Is there an expression for the number of solutions 447 00:24:05,770 --> 00:24:07,706 you'll get, that depends on n? 448 00:24:07,706 --> 00:24:08,660 SRINI DEVADAS: No. 449 00:24:08,660 --> 00:24:10,161 There's no closed form solution. 450 00:24:10,161 --> 00:24:10,660 No. 451 00:24:13,650 --> 00:24:19,790 The 12 is a concrete number, and 92 and 12 were enumerated. 452 00:24:19,790 --> 00:24:22,991 Now you could obviously write a computer program that counted-- 453 00:24:22,991 --> 00:24:24,740 I mean, you didn't have to print this out. 454 00:24:24,740 --> 00:24:26,780 You could count the number of solutions 455 00:24:26,780 --> 00:24:30,060 to the 20 queens problem, and you can find that out. 456 00:24:30,060 --> 00:24:32,360 But then if you want to do rotations and reflections, 457 00:24:32,360 --> 00:24:34,230 you'd have to start shaving things off. 458 00:24:34,230 --> 00:24:34,970 Yeah, back there. 459 00:24:34,970 --> 00:24:37,345 AUDIENCE: Do you have the run time for the recursive one? 460 00:24:37,345 --> 00:24:38,734 Would that be n to the n? 461 00:24:38,734 --> 00:24:40,010 SRINI DEVADAS: No. 462 00:24:40,010 --> 00:24:41,780 Because you're doing significant pruning. 463 00:24:41,780 --> 00:24:43,200 Great question. 464 00:24:43,200 --> 00:24:49,250 So some of these things get truncated because you end up 465 00:24:49,250 --> 00:24:52,002 doing this, and then this one you 466 00:24:52,002 --> 00:24:53,210 don't have to go any further. 467 00:24:56,240 --> 00:25:00,530 So it's not n to the n simply because you never 468 00:25:00,530 --> 00:25:05,510 have to put down another queen if the first two queens 469 00:25:05,510 --> 00:25:08,850 conflict with each other. 470 00:25:08,850 --> 00:25:11,350 So you likely did, actually, been back 471 00:25:11,350 --> 00:25:14,470 on Thursday about this time yesterday, 472 00:25:14,470 --> 00:25:16,600 we were going over the 4 by 4. 473 00:25:16,600 --> 00:25:19,930 And we didn't even put a queen down. 474 00:25:19,930 --> 00:25:22,760 We went over and we said, oh, this clearly 475 00:25:22,760 --> 00:25:26,710 can't work because there's a queen on this row already. 476 00:25:26,710 --> 00:25:29,680 This clearly can't work because there's a queen one a way. 477 00:25:29,680 --> 00:25:31,600 So there's no reason to go deeper. 478 00:25:31,600 --> 00:25:37,780 You would go n raised to n if you only did the conflict check 479 00:25:37,780 --> 00:25:40,540 after you put n queens down. 480 00:25:40,540 --> 00:25:42,520 And if you put all n queens down, 481 00:25:42,520 --> 00:25:45,070 closed your eyes put n queens down and then ran a conflict 482 00:25:45,070 --> 00:25:47,530 check, and then did that over and over, 483 00:25:47,530 --> 00:25:49,840 over and over, it would be n raised to n. 484 00:25:49,840 --> 00:25:51,620 But that's not what we're doing. 485 00:25:51,620 --> 00:25:56,020 What we're doing is if you look at the code, we are saying if-- 486 00:25:56,020 --> 00:25:58,960 this is an important statement, actually. 487 00:25:58,960 --> 00:26:00,340 Thanks for the question. 488 00:26:00,340 --> 00:26:02,110 That is pruning your search, and that 489 00:26:02,110 --> 00:26:05,914 is making it significantly less than n raised to n. 490 00:26:05,914 --> 00:26:06,580 A nice exercise. 491 00:26:06,580 --> 00:26:09,540 Remember what I said about opportunity for homework, 492 00:26:09,540 --> 00:26:11,070 when I get questions. 493 00:26:11,070 --> 00:26:14,620 A nice exercise is to go to 8 raised to 8 494 00:26:14,620 --> 00:26:19,930 and then go to the eight queens problem 495 00:26:19,930 --> 00:26:21,430 and figure out what that number is 496 00:26:21,430 --> 00:26:23,740 in terms of the number of times you're actually 497 00:26:23,740 --> 00:26:25,270 checking for no conflicts. 498 00:26:25,270 --> 00:26:28,150 So count the number of times, not the number of solutions, 499 00:26:28,150 --> 00:26:31,266 but the number of times noConflicts is being called, 500 00:26:31,266 --> 00:26:33,390 and you'll find that it's significantly less than 8 501 00:26:33,390 --> 00:26:34,954 raised to 8. 502 00:26:34,954 --> 00:26:36,370 Because you're pruning the search. 503 00:26:38,980 --> 00:26:44,230 Technically, it's called pruning the search high up in the tree. 504 00:26:44,230 --> 00:26:47,140 That's the technical term for it. 505 00:26:47,140 --> 00:26:47,840 All right? 506 00:26:47,840 --> 00:26:48,640 Good. 507 00:26:48,640 --> 00:26:49,860 Any other questions? 508 00:26:52,520 --> 00:26:56,200 So we're done with eight queens and nQueens.