{"id":2575,"date":"2017-05-04T19:05:29","date_gmt":"2017-05-04T23:05:29","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=2575"},"modified":"2019-11-01T17:10:05","modified_gmt":"2019-11-01T21:10:05","slug":"the-eight-queens-problem-generating-all-solutions","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2017\/05\/04\/the-eight-queens-problem-generating-all-solutions\/","title":{"rendered":"The Eight Queens Problem &#8211; Generating All Solutions"},"content":{"rendered":"<div class=\"content\"><p>On <a href=\"https:\/\/blogs.mathworks.com\/steve\/2017\/04\/20\/the-eight-queens-problem\/\">April 20<\/a>, I wrote about an algorithm for solving the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Eight_queens_puzzle\">Eight Queens Problem<\/a>. In this problem, the task is to place eight queens on a chessboard so that none of the queens is attacking any other queen. Here is one solution.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/sample-solution-8.png\" alt=\"\"> <\/p><p>After I published that post, I became curious to see what others might have submitted about this problem on the File Exchange. A little searching brought me to <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/5961-magnify\">this submission<\/a> by uu tii. When I looked at the submission, I was surprised to how little code it contained. This is it:<\/p><pre>function M = eightqueens()\r\nN=8;\r\nT=N-2;\r\nrows=1:N;\r\ncols=perms(rows);\r\nS=size(cols,1);\r\nM=zeros(N,N,S);\r\nlinearInd = sub2ind(size(M), repmat(rows',1,S), cols', repmat(1:S,N,1));\r\nM(linearInd) = 1;\r\ndv=arrayfun(@(k)max([arrayfun(@(x)sum(diag(M(:,:,k),x)),-T:T),arrayfun(@(x)sum(diag(rot90(M(:,:,k)),x)),-T:T)]),1:S);\r\nM(:,:,dv&gt;1)=[];<\/pre><p>When I ran it, it returned an 8x8x92 array. The size caught my eye because there are exactly 92 solutions to the Eight Queens Problem (including rotations and flips).<\/p><pre class=\"codeinput\">M = eightqueens;\r\nwhos <span class=\"string\">M<\/span>\r\n<\/pre><pre class=\"codeoutput\">  Name      Size              Bytes  Class     Attributes\r\n\r\n  M         8x8x92            47104  double              \r\n\r\n<\/pre><p>Let's peek at one of the planes of <tt>M<\/tt>.<\/p><pre class=\"codeinput\">M(:,:,45)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n     0     0     0     0     1     0     0     0\r\n     1     0     0     0     0     0     0     0\r\n     0     0     0     0     0     0     0     1\r\n     0     0     0     1     0     0     0     0\r\n     0     1     0     0     0     0     0     0\r\n     0     0     0     0     0     0     1     0\r\n     0     0     1     0     0     0     0     0\r\n     0     0     0     0     0     1     0     0\r\n\r\n<\/pre><p>Indeed, that is a solution. So, what's going on in this small chunk of code? Well, as I see it, this code has three conceptual chunks. The first chunk, consisting of eight lines, is the longest. Let's run it.<\/p><pre class=\"codeinput\">N=8;\r\nT=N-2;\r\nrows=1:N;\r\ncols=perms(rows);\r\nS=size(cols,1);\r\nM=zeros(N,N,S);\r\nlinearInd = sub2ind(size(M), repmat(rows',1,S), cols', repmat(1:S,N,1));\r\nM(linearInd) = 1;\r\n\r\nwhos <span class=\"string\">M<\/span>\r\n<\/pre><pre class=\"codeoutput\">  Name      Size                    Bytes  Class     Attributes\r\n\r\n  M         8x8x40320            20643840  double              \r\n\r\n<\/pre><p>This seems to be a collection of 40320 boards. There aren't that many solutions, so the collection must contain many boards that aren't valid solutions. For example:<\/p><pre class=\"codeinput\">M(:,:,45)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n     0     0     0     0     0     0     0     1\r\n     0     0     0     0     0     0     1     0\r\n     0     0     0     0     0     1     0     0\r\n     0     0     0     1     0     0     0     0\r\n     1     0     0     0     0     0     0     0\r\n     0     0     1     0     0     0     0     0\r\n     0     0     0     0     1     0     0     0\r\n     0     1     0     0     0     0     0     0\r\n\r\n<\/pre><p>There are four queens lined up on the main antidiagonal, so this board is not a solution.<\/p><p>This set of boards has been constructed by making the observation that any solution must have exactly one queen on each row and exactly one queen on each column. The array <tt>M<\/tt> contains every board that has this property. All the computational magic here is in the line <tt>cols=perms(rows)<\/tt>. The rest of this chunk is some indexing computations to initialize and fill in the array <tt>M<\/tt> with queens at the locations given by <tt>rows<\/tt> and <tt>cols<\/tt>.<\/p><p>The second chunk is this line:<\/p><pre class=\"codeinput\">dv=arrayfun(@(k)max([arrayfun(@(x)sum(diag(M(:,:,k),x)),-T:T),arrayfun(@(x)sum(diag(rot90(M(:,:,k)),x)),-T:T)]),1:S);\r\n<\/pre><p>Wow, there's a lot going on there. I would summarize it this way: For every board <tt>k<\/tt> in M, sum every diagonal and every antidiagonal and take the maximum of those sums. The idea is that <tt>M<\/tt> was constructed so that every board has exactly one queen on each row and exactly one queen on each column, so you really only have to check the diagonals of a board to determine whether it is a solution. Let's look at <tt>dv<\/tt> for the 45th board, which I displayed above.<\/p><pre class=\"codeinput\">dv(45)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n     4\r\n\r\n<\/pre><p>Remember my comment above that board 45 has 4 queens lined up on the main antidiagonal? That's why <tt>dv(45)<\/tt> is 4.<\/p><p>The last conceptual chunk is eliminate all the boards in the <tt>M<\/tt> that are not solutions. We do that by eliminating all boards for which <tt>dv &gt; 1<\/tt>.<\/p><pre class=\"codeinput\">M(:,:,dv&gt;1)=[];\r\n\r\nwhos <span class=\"string\">M<\/span>\r\n<\/pre><pre class=\"codeoutput\">  Name      Size              Bytes  Class     Attributes\r\n\r\n  M         8x8x92            47104  double              \r\n\r\n<\/pre><p>And there it is. That's a very clever use of <tt>perms<\/tt> and indexing and <tt>arrayfun<\/tt> to generate all possible solutions. Thanks, uu tii.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_30c4a092094740f9883ca25d539b666a() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='30c4a092094740f9883ca25d539b666a ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 30c4a092094740f9883ca25d539b666a';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2017 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_30c4a092094740f9883ca25d539b666a()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2017a<br><\/p><\/div><!--\r\n30c4a092094740f9883ca25d539b666a ##### SOURCE BEGIN #####\r\n%%\r\n% On <https:\/\/blogs.mathworks.com\/steve\/2017\/04\/20\/the-eight-queens-problem\/ April 20>, I wrote about an algorithm for solving the <https:\/\/en.wikipedia.org\/wiki\/Eight_queens_puzzle\r\n% Eight Queens\r\n% Problem>. In this problem, the task is to place eight queens on a\r\n% chessboard so that none of the queens is attacking any other queen. Here\r\n% is one solution.\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/steve\/files\/sample-solution-8.png>>\r\n%\r\n% After I published that post, I became curious to see what others might\r\n% have submitted about this problem on the File Exchange. A little\r\n% searching brought me to\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/5961-magnify\r\n% this submission> by uu tii. When I looked at the submission, I was\r\n% surprised to how little code it contained. This is it:\r\n%\r\n%  function M = eightqueens()\r\n%  N=8;\r\n%  T=N-2;\r\n%  rows=1:N;\r\n%  cols=perms(rows);\r\n%  S=size(cols,1);\r\n%  M=zeros(N,N,S);\r\n%  linearInd = sub2ind(size(M), repmat(rows',1,S), cols', repmat(1:S,N,1));\r\n%  M(linearInd) = 1;\r\n%  dv=arrayfun(@(k)max([arrayfun(@(x)sum(diag(M(:,:,k),x)),-T:T),arrayfun(@(x)sum(diag(rot90(M(:,:,k)),x)),-T:T)]),1:S);\r\n%  M(:,:,dv>1)=[];\r\n%\r\n% When I ran it, it returned an 8x8x92 array. The size caught my eye\r\n% because there are exactly 92 solutions to the Eight Queens Problem\r\n% (including rotations and flips).\r\n\r\nM = eightqueens;\r\nwhos M\r\n\r\n%%\r\n% Let's peek at one of the planes of |M|.\r\n\r\nM(:,:,45)\r\n\r\n%%\r\n% Indeed, that is a solution. So, what's going on in this small chunk of\r\n% code? Well, as I see it, this code has three conceptual chunks. The first\r\n% chunk, consisting of eight lines, is the longest. Let's run it.\r\n\r\nN=8;\r\nT=N-2;\r\nrows=1:N;\r\ncols=perms(rows);\r\nS=size(cols,1);\r\nM=zeros(N,N,S);\r\nlinearInd = sub2ind(size(M), repmat(rows',1,S), cols', repmat(1:S,N,1));\r\nM(linearInd) = 1;\r\n\r\nwhos M\r\n\r\n%%\r\n% This seems to be a collection of 40320 boards. There aren't that many\r\n% solutions, so the collection must contain many boards that aren't valid\r\n% solutions. For example:\r\n\r\nM(:,:,45)\r\n\r\n%%\r\n% There are four queens lined up on the main antidiagonal, so this board is\r\n% not a solution.\r\n%\r\n% This set of boards has been constructed by making the observation that\r\n% any solution must have exactly one queen on each row and exactly one\r\n% queen on each column. The array |M| contains every board that has this\r\n% property. All the computational magic here is in the line\r\n% |cols=perms(rows)|. The rest of this chunk is some indexing computations\r\n% to initialize and fill in the array |M| with queens at the locations\r\n% given by |rows| and |cols|.\r\n%\r\n% The second chunk is this line:\r\n\r\ndv=arrayfun(@(k)max([arrayfun(@(x)sum(diag(M(:,:,k),x)),-T:T),arrayfun(@(x)sum(diag(rot90(M(:,:,k)),x)),-T:T)]),1:S);\r\n\r\n%%\r\n% Wow, there's a lot going on there. I would summarize it this way: For\r\n% every board |k| in M, sum every diagonal and every antidiagonal and take\r\n% the maximum of those sums. The idea is that |M| was constructed so that\r\n% every board has exactly one queen on each row and exactly one queen on\r\n% each column, so you really only have to check the diagonals of a board to\r\n% determine whether it is a solution. Let's look at |dv| for the 45th\r\n% board, which I displayed above.\r\n\r\ndv(45)\r\n\r\n%%\r\n% Remember my comment above that board 45 has 4 queens lined up on the\r\n% main antidiagonal? That's why |dv(45)| is 4.\r\n%\r\n% The last conceptual chunk is eliminate all the boards in the |M| that are\r\n% not solutions. We do that by eliminating all boards for which |dv > 1|.\r\n\r\nM(:,:,dv>1)=[];\r\n\r\nwhos M\r\n\r\n%%\r\n% And there it is. That's a very clever use of |perms| and indexing and\r\n% |arrayfun| to generate all possible solutions. Thanks, uu tii.\r\n##### SOURCE END ##### 30c4a092094740f9883ca25d539b666a\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/sample-solution-8.png\" onError=\"this.style.display ='none';\" \/><\/div><p>On April 20, I wrote about an algorithm for solving the Eight Queens Problem. In this problem, the task is to place eight queens on a chessboard so that none of the queens is attacking any other... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2017\/05\/04\/the-eight-queens-problem-generating-all-solutions\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[601,911,122,1191,116,526,190,468,126,306,130],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/2575"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/comments?post=2575"}],"version-history":[{"count":2,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/2575\/revisions"}],"predecessor-version":[{"id":2577,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/2575\/revisions\/2577"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=2575"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=2575"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=2575"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}