<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: N-Queens Problem in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651685#M195558</link>
    <description>&lt;P&gt;When n=6 , there are four solutions .&lt;/P&gt;
&lt;P&gt;EDITED.&lt;/P&gt;
&lt;P&gt;EDITED again.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;%let n=6 ;


data have;
 do i=1 to &amp;amp;n;
   do j=1 to &amp;amp;n;
      output;
   end;
 end;
run;
 
data want(keep=path);
 set have(obs=&amp;amp;n);
if _n_=1 then do;
  array row{%eval(&amp;amp;n*&amp;amp;n)} _temporary_;
  array col{%eval(&amp;amp;n*&amp;amp;n)} _temporary_;
  array flag{%eval(&amp;amp;n*&amp;amp;n)} _temporary_;

  length path _path  $ 400 temp $ 20;
  declare hash pa(ordered:'y');
  declare hiter hi_path('pa');
  pa.definekey('n');
  pa.definedata('n','path');
  pa.definedone();
end;

count=1;n=1;path=catx(' ',i,j);pa.add();
do while(hi_path.next()=0);
 if n ne 1 then pa.remove(key:_n);_n=n;

  idx=0;
  do i=1 to &amp;amp;n;
   do j=1 to &amp;amp;n;
     idx+1;row{idx}=i;col{idx}=j;flag{idx}=0;
   end;
  end;

  do k=1 to countw(path,'|');
   temp=scan(path,k,'|');
   first=input(scan(temp,1),best.);
   second=input(scan(temp,-1),best.);
   /*Remove - | / \ nodes*/
   do idx=1 to &amp;amp;n*&amp;amp;n;
     if first=row{idx} or second=col{idx} or 
        abs(first-row{idx})=abs(second-col{idx}) then flag{idx}=1;
   end;
  end;

  _path=path;   
   do idx=1 to &amp;amp;n*&amp;amp;n;
     if row{idx}=k and flag{idx}=0 then do;
       count+1;n=count;
	   path=catx('|',path,catx(' ',row{idx},col{idx}));
       pa.add(); 	
       if countw(path,'|')=&amp;amp;n then output;
       path=_path;
     end;
   end;
end;
pa.clear();	
run; 

data temp;
 set want;
 array var{&amp;amp;n} $ 20;
 do k=1 to &amp;amp;n;
   var{k}=scan(path,k,'|');
 end;
 keep var1-var&amp;amp;n ;
run;

data _null_;
 set temp end=last;
 call execute(catt("data solution_",_n_,";array var{&amp;amp;n};do i=1 to &amp;amp;n;do j=1 to &amp;amp;n;
 if findw('",catx('|',of var1-var&amp;amp;n),"',catx(' ',i,j),'|') then var{j}=1;else var{j}=0;end;
 output;end;drop i j;run;"));
run;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sat, 30 May 2020 12:28:01 GMT</pubDate>
    <dc:creator>Ksharp</dc:creator>
    <dc:date>2020-05-30T12:28:01Z</dc:date>
    <item>
      <title>N-Queens Problem</title>
      <link>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651109#M195318</link>
      <description />
      <pubDate>Fri, 29 May 2020 06:56:04 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651109#M195318</guid>
      <dc:creator>skjhzzang</dc:creator>
      <dc:date>2020-05-29T06:56:04Z</dc:date>
    </item>
    <item>
      <title>Re: N-Queens Problem</title>
      <link>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651118#M195322</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/300764"&gt;@skjhzzang&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Please have a look at the following resource, which tries to solve the N-Queens problems using several programming &amp;nbsp;languages: &lt;A href="https://rosettacode.org/wiki/N-queens_problem#SAS" target="_blank" rel="noopener"&gt;https://rosettacode.org/wiki/N-queens_problem#SAS&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;You can easily put the '8' in a macrovariable inside a macro-program.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Hope this helps,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Best,&lt;/P&gt;</description>
      <pubDate>Wed, 27 May 2020 15:44:07 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651118#M195322</guid>
      <dc:creator>ed_sas_member</dc:creator>
      <dc:date>2020-05-27T15:44:07Z</dc:date>
    </item>
    <item>
      <title>Re: N-Queens Problem</title>
      <link>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651163#M195333</link>
      <description>&lt;P&gt;'Pure' macro is really not the environment for typical recursion and fundamental computation.&amp;nbsp; Regardless, it's not impossible.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Example:&lt;/P&gt;
&lt;PRE&gt;%* translated to SAS macro - Richard DeVenezia
%* Based on code at https://www.geeksforgeeks.org/n-queen-problem-backtracking-3/;
%* contributed by Princi Singh ;

%macro logBoard(N);
  %* requires: macro symbols BOARD_1_1 to BOARD_&amp;lt;N&amp;gt;_&amp;lt;N&amp;gt; to exist in callers scope;
  %local i j row;

  %put NOTE: ------------- &amp;amp;=N;

  %do i = 1 %to &amp;amp;N;
    %let row = ;
    %do j = 1 %to &amp;amp;N;
      %let row = &amp;amp;row &amp;amp;&amp;amp;BOARD_&amp;amp;I._&amp;amp;J.;
    %end; 
    %put NOTE: &amp;amp;row;
  %end;

  %put NOTE: -------------;
%mend;

%macro isSafePlace(row, col, N);
  %* requires: macro symbols BOARD_1_1 to BOARD_&amp;lt;N&amp;gt;_&amp;lt;N&amp;gt; to exist in callers scope;
  %local i j index;
  %do j = 1 %to &amp;amp;col;
    %if &amp;amp;&amp;amp;BOARD_&amp;amp;ROW._&amp;amp;J. %then %do;
      0 /* not safe */
      %return;
    %end;
  %end;

  %let i = &amp;amp;row;
  %let j = &amp;amp;col;
  %do index = 1 %to &amp;amp;N;
    %if &amp;amp;&amp;amp;BOARD_&amp;amp;I._&amp;amp;J. %then %do;
      0 /* not safe */
      %return;
    %end;
    
    %let i = %eval(&amp;amp;i-1); %if &amp;amp;i &amp;lt; 1 %then %goto leave1;
    %let j = %eval(&amp;amp;j-1); %if &amp;amp;j &amp;lt; 1 %then %goto leave1;
  %end;
%leave1:

  %let i = &amp;amp;row;
  %let j = &amp;amp;col;
  %do index = 1 %to &amp;amp;N;
    %if &amp;amp;&amp;amp;BOARD_&amp;amp;I._&amp;amp;J. %then %do;
      0 /* not safe */
      %return;
    %end;
    
    %let i = %eval(&amp;amp;i+1); %if &amp;amp;i &amp;gt; &amp;amp;N %then %goto leave2;
    %let j = %eval(&amp;amp;j-1); %if &amp;amp;j &amp;lt;  1 %then %goto leave2;
  %end;
%leave2: 

  1 /* is safe */
%mend;

%macro queensRecursion(col, N);
  %local i j;
  %if &amp;amp;col &amp;gt; &amp;amp;N %then %do; 
    1  /* solution found */
    %return;
  %end;

  %do i = 1 %to &amp;amp;N;
    %if %isSafePlace(&amp;amp;i, &amp;amp;col, &amp;amp;N) %then %do;
      %let BOARD_&amp;amp;I._&amp;amp;COL. = 1;

      %if %queensRecursion(%eval(&amp;amp;col+1), &amp;amp;N) %then %do;
        1
        %return;
      %end;

      /* backtrack */
      %let BOARD_&amp;amp;I._&amp;amp;COL. = 0;
    %end;
  %end;

  0 /* could not be placed safely */
%mend;


%macro queens(N);
  %local i j;
  %do i = 1 %to &amp;amp;N;
  %do j = 1 %to &amp;amp;N;
    %local BOARD_&amp;amp;I._&amp;amp;J;
    %let BOARD_&amp;amp;I._&amp;amp;J = 0;
  %end;
  %end;
  
  %if not %queensRecursion(1, &amp;amp;N) %then %do;
    %put WARNING: No Queens solution found for &amp;amp;=N;
    %return;
  %end;

  %logBoard(&amp;amp;N)
%mend;

options mprint nomlogic nosymbolgen;

%queens(6)&lt;/PRE&gt;
&lt;P&gt;Log&lt;/P&gt;
&lt;PRE&gt;758  %queens(6)
      ------------- N=6
NOTE: 0 0 0 1 0 0
NOTE: 1 0 0 0 0 0
NOTE: 0 0 0 0 1 0
NOTE: 0 1 0 0 0 0
NOTE: 0 0 0 0 0 1
NOTE: 0 0 1 0 0 0
      -------------
&lt;/PRE&gt;</description>
      <pubDate>Wed, 27 May 2020 17:59:46 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651163#M195333</guid>
      <dc:creator>RichardDeVen</dc:creator>
      <dc:date>2020-05-27T17:59:46Z</dc:date>
    </item>
    <item>
      <title>Re: N-Queens Problem</title>
      <link>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651685#M195558</link>
      <description>&lt;P&gt;When n=6 , there are four solutions .&lt;/P&gt;
&lt;P&gt;EDITED.&lt;/P&gt;
&lt;P&gt;EDITED again.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;%let n=6 ;


data have;
 do i=1 to &amp;amp;n;
   do j=1 to &amp;amp;n;
      output;
   end;
 end;
run;
 
data want(keep=path);
 set have(obs=&amp;amp;n);
if _n_=1 then do;
  array row{%eval(&amp;amp;n*&amp;amp;n)} _temporary_;
  array col{%eval(&amp;amp;n*&amp;amp;n)} _temporary_;
  array flag{%eval(&amp;amp;n*&amp;amp;n)} _temporary_;

  length path _path  $ 400 temp $ 20;
  declare hash pa(ordered:'y');
  declare hiter hi_path('pa');
  pa.definekey('n');
  pa.definedata('n','path');
  pa.definedone();
end;

count=1;n=1;path=catx(' ',i,j);pa.add();
do while(hi_path.next()=0);
 if n ne 1 then pa.remove(key:_n);_n=n;

  idx=0;
  do i=1 to &amp;amp;n;
   do j=1 to &amp;amp;n;
     idx+1;row{idx}=i;col{idx}=j;flag{idx}=0;
   end;
  end;

  do k=1 to countw(path,'|');
   temp=scan(path,k,'|');
   first=input(scan(temp,1),best.);
   second=input(scan(temp,-1),best.);
   /*Remove - | / \ nodes*/
   do idx=1 to &amp;amp;n*&amp;amp;n;
     if first=row{idx} or second=col{idx} or 
        abs(first-row{idx})=abs(second-col{idx}) then flag{idx}=1;
   end;
  end;

  _path=path;   
   do idx=1 to &amp;amp;n*&amp;amp;n;
     if row{idx}=k and flag{idx}=0 then do;
       count+1;n=count;
	   path=catx('|',path,catx(' ',row{idx},col{idx}));
       pa.add(); 	
       if countw(path,'|')=&amp;amp;n then output;
       path=_path;
     end;
   end;
end;
pa.clear();	
run; 

data temp;
 set want;
 array var{&amp;amp;n} $ 20;
 do k=1 to &amp;amp;n;
   var{k}=scan(path,k,'|');
 end;
 keep var1-var&amp;amp;n ;
run;

data _null_;
 set temp end=last;
 call execute(catt("data solution_",_n_,";array var{&amp;amp;n};do i=1 to &amp;amp;n;do j=1 to &amp;amp;n;
 if findw('",catx('|',of var1-var&amp;amp;n),"',catx(' ',i,j),'|') then var{j}=1;else var{j}=0;end;
 output;end;drop i j;run;"));
run;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 30 May 2020 12:28:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651685#M195558</guid>
      <dc:creator>Ksharp</dc:creator>
      <dc:date>2020-05-30T12:28:01Z</dc:date>
    </item>
    <item>
      <title>Re: N-Queens Problem</title>
      <link>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651693#M195560</link>
      <description>&lt;P&gt;Better using PROC OPTMODEL .and calling&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/1636"&gt;@RobPratt&lt;/a&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 29 May 2020 11:49:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651693#M195560</guid>
      <dc:creator>Ksharp</dc:creator>
      <dc:date>2020-05-29T11:49:26Z</dc:date>
    </item>
    <item>
      <title>Re: N-Queens Problem</title>
      <link>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651763#M195573</link>
      <description>&lt;P&gt;Please see &lt;A href="https://go.documentation.sas.com/?docsetId=ormpug&amp;amp;docsetTarget=ormpug_clpsolver_gettingstarted02.htm&amp;amp;docsetVersion=15.1&amp;amp;locale=en" target="_self"&gt;this documentation example&lt;/A&gt; for the constraint programming solver in PROC OPTMODEL.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can change the value of n to whatever you want.&amp;nbsp; If you want to find all solutions, use the FINDALLSOLNS in the SOLVE statement.&lt;/P&gt;</description>
      <pubDate>Fri, 29 May 2020 15:29:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/N-Queens-Problem/m-p/651763#M195573</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2020-05-29T15:29:23Z</dc:date>
    </item>
  </channel>
</rss>

