阅读权限 255 威望 0 级论坛币 88 个 通用积分 2.1142 学术水平 182 点 热心指数 178 点 信用等级 166 点 经验 9462 点 帖子 296 精华 0 在线时间 335 小时 注册时间 2009-6-17 最后登录 2014-9-20
16 楼
邓贵大
发表于 2014-3-26 05:01:26
Verified all claims in
http://zh.wikipedia.org/zh/24%E7%82%B9 %macro btree(out, x, len1, len2);
%local n i;
%let n = %length(&x);
%if &n=1 %then %do;
data &out;
length tree $ &len1 expr $ &len2;
tree = "&x";
expr = "cats(&x)";
run;
%end;
%else %do i=1 %to %eval(&n-1);
%local Ltmp&i Rtmp&i tmp&i;
data;stop;run; %let Ltmp&i = %substr(&syslast,6);
data;stop;run; %let Rtmp&i = %substr(&syslast,6);
data;stop;run; %let tmp&i = %substr(&syslast,6);
proc datasets nolist;
delete &&tmp&i &&Ltmp&i &&Rtmp&i;
quit;
%btree(&&Ltmp&i, %substr(&x,1,&i), &len1, &len2);
%btree(&&Rtmp&i, %substr(&x,%eval(&i+1)), &len1, &len2);
data &&tmp&i;
do until(eof);
set &&Ltmp&i(keep=tree expr rename=(tree=Ltree expr=Lexpr)) end=eof;
do _n_=1 to nobs;
set &&Rtmp&i(keep=tree expr rename=(tree=Rtree expr=Rexpr)) nobs=nobs point=_n_;
length tree $ &len1 expr $ &len2;
%if &i>1 and &n-&i>1 %then %do;
tree = cats('(', Ltree, ')#(', Rtree, ')');
expr = cats('cats(''('',', Lexpr, ','')#('',', Rexpr, ','')'')');
%end;
%else %if &i>1 %then %do;
tree = cats('(', Ltree, ')#', Rtree);
expr = cats('cats(''('',', Lexpr, ','')#'',', Rexpr, ')');
%end;
%else %if &n-&i>1 %then %do;
tree = cats(Ltree, '#(', Rtree, ')');
*expr = cats('cats(', Lexpr, ',''#('',', Rexpr, ','')'')');
%end;
%else %do;
tree = cats(Ltree, '#', Rtree);
expr = cats('cats(', Lexpr, ',''#'',', Rexpr, ')');
%end;
output;
end;
end;
stop;
keep tree expr;
run;
proc append base=&out data=&&tmp&i force;
proc datasets nolist;
delete &&tmp&i &&Ltmp&i &&Rtmp&i;
quit;
%end;
%mend;
%macro doit(out=c, cards=, trees=, batchsize=128);
%local i j n nobs batch k;
%let n = %length(&cards);
data yyy;
array op[0:3] $1. _temporary_ ('+','-','*','/');
set &trees;
array _A[%eval(&n-1)] _temporary_;
_start = 1;
do i=1 to %eval(&n-1);
_A[i] = findc(tree, '#', _start);
_start = _A[i] + 1;
end;
do i=0 to 4**%eval(&n-1)-1;
do j=1 to %eval(&n-1);
base = 4**(j-1);
k = mod(floor(i/base),4);
substr(tree, _A[j], 1) = op[k];
end;
_order=ranuni(0);
output;
end;
keep _order tree;
run;
proc sort data=yyy; *check in random order, unnecessary;
by _order;
data _null_;
set yyy end=eof nobs=nobs;
call symputx(cats('A', _n_-1), tree, 'L');
if eof then call symputx('upto', nobs-1, 'L');
run;
%let batch = %sysevalf((&upto+1)/&batchsize, ceil);
data base;
%do j=1 %to &n;
do %substr(&cards,&j,1)=1 to 13;
%end;
output;
%do j=1 %to &n;
end;
%end;
stop;
run;
%do k=1 %to &batch;
data a&k;
do until(eof);
set base end=eof;
%do i=%eval(&batchsize*(&k-1)) %to %sysfunc(min(&batchsize*&k-1, &upto));
if round(&&A&i, 1e-10) = 24 then do;
key = &i;
output;
continue;
end;
%end;
end;
stop;
run;
data _null_;
if 0 then set a&k nobs=nobs;
call symputx('nobs', nobs);
stop;
run;
%if &nobs>0 %then %do;
data _a&k;
set a&k;
array _x[&n];
%do j=1 %to &n;
_x[&j] = %substr(&cards,&j,1);
%end;
call sortn(of _x[*]);
keep _x1-_x&n;
proc sort data=_a&k nodupkey;
by _x1-_x&n;
data base;
if _n_=1 then do;
if 0 then set _a&k;
declare hash _ht(dataset:"_A&k", hashexp:16);
_ht.definekey('_x1' %do j=2 %to &n; ,"_x&j" %end;);
_ht.definedone();
end;
set base;
array _x[&n];
%do j=1 %to &n;
_x[&j] = %substr(&cards,&j,1);
%end;
call sortn(of _x[*]);
if _ht.find() ne 0 then output;
drop _x1-_x&n;
run;
%end;
%end;
data b;
set %do k=1 %to &batch; a&k %end; base(in=in2);
array _x[*] %do j=1 %to &n; %substr(&cards,&j,1) %end;;
if in2 then solved='N'; else solved='Y';
length answer $ %eval(5*&n-5);
if solved='Y' then do;
answer = symget("A" || cats(key));
%do j=1 %to &n;
answer=tranwrd(answer, "%substr(&cards,&j,1)", trim(cats(%substr(&cards,&j,1))));
%end;
end;
call sortn(of _x[*]);
run;
proc sort data=b;
by %do j=1 %to &n; %substr(&cards,&j,1) %end; solved;
data _b;
set b;
by %do j=1 %to &n; %substr(&cards,&j,1) %end;;
if last.%substr(&cards, &n, 1);
run;
data _b;
set _b;
array _x[*] %do j=1 %to &n; %substr(&cards,&j,1) %end;;
obs = _n_;
do _n_=1 to dim(_x);
_y = _x[_n_];
_name_ = vname(_x[_n_]);
output;
end;
keep obs _name_ _y solved answer;
proc sql;
create table _c as
select obs, _y from _b
group by 1,2 having count(*)>4;
quit;
proc sql;
delete from _b where obs in (select obs from _c);
quit;
proc transpose data=_b out=&out(drop=_name_ obs);
by obs solved answer;
id _name_;
var _y;
run;
%mend;
title1 '4 Cards';
options nonotes;
%btree(xxx4, abcd, 11, 100);
options notes errors=0;
proc print data=xxx4;
var tree;
run;
%doit(out=c, cards=abcd, trees=xxx4);
proc freq data=c;
tables solved;
run;
proc print data=c;
where solved='Y';
run;
title1 '5 Cards';
options nonotes;
%btree(xxx5, abcde, 15, 150);
options notes errors=0;
proc print data=xxx5;
var tree;
run;
%doit(out=c, cards=abcde, trees=xxx5);
proc freq data=c;
tables solved;
run;
proc print data=c;
where solved='Y';
run;
title1 '6 Cards';
options nonotes;
%btree(xxx6, abcdef, 19, 200);
options notes errors=0;
proc print data=xxx6;
var tree;
run;
%doit(out=c, cards=abcdef, trees=xxx6);
proc freq data=c;
tables solved;
run;
proc print data=c;
where solved='Y';
run;
title1 '7 Cards';
options nonotes;
%btree(xxx7, abcdefg, 23, 300);
options notes errors=0;
proc print data=xxx7;
var tree;
run;
%doit(out=c, cards=abcdefg, trees=xxx7, batchsize=16);
proc freq data=c;
tables solved;
run;
proc print data=c;
where solved='Y';
run; 复制代码 My code won't work for >7 cards. Only He the Lord has no limits. Hallelujah!