楼主: l6397
5332 16

[问答] 怎样计算扑克牌24点 [推广有奖]

11
邓贵大 发表于 2014-1-13 01:14:16
(A_B)_(C_D)、
((A_B)_C)_D、
(A_(B_C))_D
A_((B_C)_D)
A_(B_(C_D))
NO ONE LESS
MY brute-force solution, no tricks played
  1. data _null_;
  2.         array op[4] $1. _temporary_ ('+','-','*','/');
  3.         do i=1 to 4;
  4.         do j=1 to 4;
  5.         do k=1 to 4;
  6.                 slno = i-1 + 4*(j-1) + 16*(k-1);
  7.                 call symputx('A' || cats(slno), '(a' || op[i] || 'b)' || op[j] || '(c' || op[k] || 'd)');
  8.                 call symputx('AA' || cats(slno), 'cats("(", a, "' || op[i] || '", b, ")' || op[j] || '(", c, "' || op[k] || '", d, ")")');
  9.                 slno = slno + 64;
  10.                 call symputx('A' || cats(slno), '((a' || op[i] || 'b)' || op[j] || 'c)' || op[k] || 'd');
  11.                 call symputx('AA' || cats(slno), 'cats("((", a, "' || op[i] || '", b, ")' || op[j] || '", c, ")' || op[k] || '", d)');
  12.                 slno = slno + 64;
  13.                 call symputx('A' || cats(slno), '(a' || op[i] || '(b' || op[j] || 'c))' || op[k] || 'd');
  14.                 call symputx('AA' || cats(slno), 'cats("(", a, "' || op[i] || '(", b, ")' || op[j] || '", c, "))' || op[k] || '", d)');
  15.                 slno = slno + 64;
  16.                 call symputx('A' || cats(slno), 'a' || op[i] || '((b' || op[j] || 'c)' || op[k] || 'd)');
  17.                 call symputx('AA' || cats(slno), 'cats(a, "' || op[i] || '((", b, "' || op[j] || '", c, ")' || op[k] || '", d, ")")');
  18.                 slno = slno + 64;
  19.                 call symputx('A' || cats(slno), 'a' || op[i] || '(b' || op[j] || '(c' || op[k] || 'd))');
  20.                 call symputx('AA' || cats(slno), 'cats(a, "' || op[i] || '(", b, "' || op[j] || '(", c, "' || op[k] || '", d, "))")');
  21.         end;
  22.         end;
  23.         end;
  24.         stop;
  25. run;
  26. %put _USER_;
  27. %macro doit();
  28. %local i;
  29. data a;
  30.         do a=1 to 13;
  31.         do b=1 to 13;
  32.         do c=1 to 13;
  33.         do d=1 to 13;
  34.                 solved='N';
  35.                 length answer $ 15;
  36.                 %do i=0 %to 319;
  37.                         if round(&&A&i, 1e-10) = 24 then do;
  38.                                 solved='Y';
  39.                                 answer = &&AA&i;
  40.                                 output;
  41.                                 continue;
  42.                         end;
  43.                 %end;
  44.                 answer= ' ';
  45.                 output;
  46.         end;
  47.         end;
  48.         end;
  49.         end;
  50.         stop;
  51. run;
  52. %mend;
  53. %doit;

  54. data b;
  55.         set a;
  56.         call sortn(a,b,c,d);
  57. run;
  58. proc sort data=b;
  59.         by a b c d solved;
  60. data c;
  61.         set b;
  62.         by a b c d;
  63.         if last.d;
  64. run;
  65. proc freq data=c;
  66.         tables solved;
  67. run;
复制代码
感谢神:创造了有千种变化的24点游戏娱乐人类
又感谢神:让24点的各种变化能在很短的时间里列举出来
已有 3 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
webgu + 100 + 100 + 5 + 5 + 5 大开眼界。
pobel + 5 + 5 + 5 精彩帖子
jingju11 + 5 + 5 + 5 真是精彩啊。

总评分: 经验 + 100  论坛币 + 100  学术水平 + 15  热心指数 + 15  信用等级 + 15   查看全部评分

Be still, my soul: the hour is hastening on
When we shall be forever with the Lord.
When disappointment, grief and fear are gone,
Sorrow forgot, love's purest joys restored.

12
zhengbo8 发表于 2014-1-13 01:53:39
邓贵大 发表于 2014-1-13 01:14
(A_B)_(C_D)、
((A_B)_C)_D、
(A_(B_C))_D
好方法。我做出正解了。

13
zhengbo8 发表于 2014-1-13 01:58:33
从扑克中任意抽出四张(数字表示为1-13),用加、减、乘、除的方法使结果成为24,每张牌只能用一次。 一副牌(52张)中,任意抽取4张可有1820种不同组合。
即不考虑顺序、以及花色,有1820个组合。其中,458个是无解的。即有1820-458=1362个。

这下数目对了,1362个。不用考虑各种表达式组合,枚举的,要是优化一下效率,就更好了。

  1. data a;
  2.         length expr $ 16;
  3.         do x1= 1 to 13;
  4.                 do x2=1 to 13;
  5.                         expr=cats('(',x1,'+',x2,')');value=x1+x2;output;
  6.                         expr=cats('(',x1,'-',x2,')');value=x1-x2;output;
  7.                         expr=cats('(',x2,'-',x1,')');value=x2-x1;output;
  8.                         expr=cats('(',x1,'*',x2,')');value=x1*x2;output;
  9.                         expr=cats('(',x1,'/',x2,')');value=x1/x2;output;
  10.                         expr=cats('(',x2,'/',x1,')');value=x2/x1;output;
  11.                 end;
  12.         end;
  13. run;

  14. data a_result(drop=rc expr1 value1 value);
  15.         retain x1-x4 expr;
  16.         if _N_=0 then set a;
  17.         declare hash h1 (dataset: 'a') ;
  18.         declare hiter iter('h1');
  19.         h1.defineKey('expr');
  20.         h1.defineData(all:'yes');
  21.         h1.defineDone() ;
  22.         set a(rename=(x1=x3 x2=x4 value=value1 expr=expr1));
  23.         rc = iter.first();
  24.         do while(rc=0);
  25.             select;
  26.                 when(abs((value*value1)-24)<=0.001) do;
  27.                         expr=cats(expr,'*',expr1);output;
  28.                 end;
  29.                 when((value+value1)=24) do;
  30.                         expr=cats(expr,'+',expr1);output;
  31.                 end;
  32.                 when(value1<>0 and abs((value/value1)-24)<=0.001) do;
  33.                         expr=cats(expr,'/',expr1);output;
  34.                 end;
  35.                 when((value-value1)=24) do;
  36.                         expr=cats(expr,'-',expr1);output;
  37.                 end;
  38.                 otherwise;
  39.             end;
  40.            rc=iter.next();
  41.         end;      
  42. run ;


  43. data b;
  44.         retain x1-x3 expr value;
  45.         length expr $ 16;
  46.         set a(rename=(expr=temp value=val));
  47.         do x3=1 to 13;
  48.                 expr=cats('(',temp,'+',x3,')');value=val+x3;output;
  49.                 expr=cats('(',temp,'-',x3,')');value=val-x3;output;
  50.                 expr=cats('(',x3,'-',temp,')');value=x3-val;output;        
  51.                 expr=cats('(',temp,'*',x3,')');value=val*x3;output;
  52.                 expr=cats('(',temp,'/',x3,')');value=val/x3;output;
  53.                 if (val ne 0) then do;
  54.                         expr=cats('(',x3,'/',temp,')');value=x3/val;
  55.                         output;
  56.                 end;
  57.         end;
  58.         drop temp val;
  59. run;

  60. data b_result;
  61.         retain x1-x4 expr;
  62.         length expr $ 16;
  63.         set b(rename=(expr=temp));
  64.         do x4=1 to 13;
  65.                 if abs(value+x4-24)<=0.001 then do;expr=cats(temp,"+",x4);output;end;
  66.                 if abs(value-x4-24)<=0.001 then do;expr=cats(temp,"-",x4);output;end;
  67.                 if abs(x4-value-24)<=0.001 then do;expr=cats(x4,"-",temp);output;end;
  68.                 if abs(value*x4-24)<=0.001 then do;expr=cats(temp,"*",x4);output;end;
  69.                 if abs(value/x4-24)<=0.001 then do;expr=cats(temp,"/",x4);output;end;
  70.                 if ((value ne 0) and abs(x4/value-24)<=0.001) then do;
  71.                         expr=cats(x4,"/",temp);output;
  72.                 end;
  73.         end;
  74.         drop temp value;
  75. run;

  76. data result;
  77.         set a_result b_result;
  78.         call sortn(x1,x2,x3,x4);
  79. run;

  80. proc datasets library=work;
  81.         save result/mt=data;
  82. quit;

  83. proc sort data=result nodupkey;by x1-x4;run;
复制代码


已有 1 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
webgu + 100 + 100 + 5 + 5 + 5 兄弟,别说你是医学院出来的。

总评分: 经验 + 100  论坛币 + 100  学术水平 + 5  热心指数 + 5  信用等级 + 5   查看全部评分

14
wsyxh 发表于 2014-1-13 15:33:43
zhengbo8 发表于 2014-1-13 01:58
从扑克中任意抽出四张(数字表示为1-13),用加、减、乘、除的方法使结果成为24,每张牌只能用一次。 一副 ...
高人,学习中……
如果把乘方、开方运算也考虑进去,六种基本运算就齐了,一定更有趣。

15
jingju11 发表于 2014-1-15 13:34:07
看到两位的程序,才知道sas的潜能和两位无与伦比的才能。前者可以挖掘,后者却是学习不到的。
京剧
已有 1 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
webgu + 100 + 100 + 3 + 3 + 3 都是如此博大精深啊。

总评分: 经验 + 100  论坛币 + 100  学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

16
邓贵大 发表于 2014-3-26 05:01:26
Verified all claims in http://zh.wikipedia.org/zh/24%E7%82%B9
  1. %macro btree(out, x, len1, len2);
  2.         %local n i;
  3.         %let n = %length(&x);
  4.         
  5.         %if &n=1 %then %do;
  6.                 data &out;
  7.                         length tree $ &len1 expr $ &len2;
  8.                         tree = "&x";
  9.                         expr = "cats(&x)";
  10.                 run;
  11.         %end;
  12.         %else %do i=1 %to %eval(&n-1);
  13.                 %local Ltmp&i Rtmp&i tmp&i;
  14.                 data;stop;run;        %let Ltmp&i = %substr(&syslast,6);
  15.                 data;stop;run;        %let Rtmp&i = %substr(&syslast,6);
  16.                 data;stop;run;        %let tmp&i = %substr(&syslast,6);
  17.                 proc datasets nolist;
  18.                         delete &&tmp&i &&Ltmp&i &&Rtmp&i;
  19.                 quit;
  20.                 %btree(&&Ltmp&i, %substr(&x,1,&i), &len1, &len2);
  21.                 %btree(&&Rtmp&i, %substr(&x,%eval(&i+1)), &len1, &len2);
  22.                 data &&tmp&i;
  23.                         do until(eof);
  24.                                 set &&Ltmp&i(keep=tree expr rename=(tree=Ltree expr=Lexpr)) end=eof;
  25.                                 do _n_=1 to nobs;
  26.                                         set &&Rtmp&i(keep=tree expr rename=(tree=Rtree expr=Rexpr)) nobs=nobs point=_n_;
  27.                                         length tree $ &len1 expr $ &len2;
  28.                                         %if &i>1 and &n-&i>1 %then %do;
  29.                                                 tree = cats('(', Ltree, ')#(', Rtree, ')');
  30.                                                 expr = cats('cats(''('',', Lexpr, ','')#('',', Rexpr, ','')'')');
  31.                                         %end;
  32.                                         %else %if &i>1 %then %do;
  33.                                                 tree = cats('(', Ltree, ')#', Rtree);
  34.                                                 expr = cats('cats(''('',', Lexpr, ','')#'',', Rexpr, ')');
  35.                                         %end;
  36.                                         %else %if &n-&i>1 %then %do;
  37.                                                 tree = cats(Ltree, '#(', Rtree, ')');
  38.                                                 *expr = cats('cats(', Lexpr, ',''#('',', Rexpr, ','')'')');
  39.                                         %end;
  40.                                         %else %do;
  41.                                                 tree = cats(Ltree, '#', Rtree);
  42.                                                 expr = cats('cats(', Lexpr, ',''#'',', Rexpr, ')');
  43.                                         %end;
  44.                                         output;
  45.                                 end;
  46.                         end;
  47.                         stop;
  48.                         keep tree expr;
  49.                 run;
  50.                 proc append base=&out data=&&tmp&i force;
  51.                 proc datasets nolist;
  52.                         delete &&tmp&i &&Ltmp&i &&Rtmp&i;
  53.                 quit;
  54.         %end;
  55. %mend;

  56. %macro doit(out=c, cards=, trees=, batchsize=128);
  57. %local i j n nobs batch k;
  58. %let n = %length(&cards);

  59. data yyy;
  60.         array op[0:3] $1. _temporary_ ('+','-','*','/');
  61.         set &trees;
  62.         array _A[%eval(&n-1)] _temporary_;

  63.         _start = 1;
  64.         do i=1 to %eval(&n-1);
  65.                 _A[i] = findc(tree, '#', _start);
  66.                 _start = _A[i] + 1;
  67.         end;
  68.         
  69.         do i=0 to 4**%eval(&n-1)-1;
  70.                 do j=1 to %eval(&n-1);
  71.                         base = 4**(j-1);
  72.                         k = mod(floor(i/base),4);
  73.                         substr(tree, _A[j], 1) = op[k];
  74.                 end;
  75.                 _order=ranuni(0);
  76.                 output;
  77.         end;
  78.         keep _order tree;
  79. run;
  80. proc sort data=yyy;        *check in random order, unnecessary;
  81.         by _order;
  82. data _null_;
  83.         set yyy end=eof nobs=nobs;
  84.         call symputx(cats('A', _n_-1), tree, 'L');
  85.         if eof then call symputx('upto', nobs-1, 'L');
  86. run;

  87. %let batch = %sysevalf((&upto+1)/&batchsize, ceil);

  88. data base;
  89. %do j=1 %to &n;
  90.         do %substr(&cards,&j,1)=1 to 13;
  91. %end;
  92.                 output;
  93. %do j=1 %to &n;
  94.         end;
  95. %end;
  96.         stop;
  97. run;

  98. %do k=1 %to &batch;
  99. data a&k;
  100.         do until(eof);
  101.                 set base end=eof;
  102.                 %do i=%eval(&batchsize*(&k-1)) %to %sysfunc(min(&batchsize*&k-1, &upto));
  103.                         if round(&&A&i, 1e-10) = 24 then do;
  104.                                 key = &i;
  105.                                 output;
  106.                                 continue;
  107.                         end;                        
  108.                 %end;
  109.         end;
  110.         stop;
  111. run;

  112. data _null_;
  113.         if 0 then set a&k nobs=nobs;
  114.         call symputx('nobs', nobs);
  115.         stop;
  116. run;
  117. %if &nobs>0 %then %do;
  118.         data _a&k;
  119.                 set a&k;
  120.                 array _x[&n];
  121.                 %do j=1 %to &n;
  122.                         _x[&j] = %substr(&cards,&j,1);
  123.                 %end;
  124.                 call sortn(of _x[*]);
  125.                 keep _x1-_x&n;
  126.         proc sort data=_a&k nodupkey;
  127.                 by _x1-_x&n;
  128.         data base;
  129.                 if _n_=1 then do;
  130.                         if 0 then set _a&k;
  131.                         declare hash _ht(dataset:"_A&k", hashexp:16);
  132.                         _ht.definekey('_x1' %do j=2 %to &n; ,"_x&j" %end;);
  133.                         _ht.definedone();
  134.                 end;
  135.                 set base;
  136.                 array _x[&n];
  137.                 %do j=1 %to &n;
  138.                         _x[&j] = %substr(&cards,&j,1);
  139.                 %end;
  140.                 call sortn(of _x[*]);
  141.                 if _ht.find() ne 0 then output;
  142.                 drop _x1-_x&n;
  143.         run;
  144. %end;
  145. %end;
  146. data b;
  147.         set %do k=1 %to &batch; a&k %end; base(in=in2);
  148.         array _x[*] %do j=1 %to &n; %substr(&cards,&j,1) %end;;
  149.         if in2 then solved='N'; else solved='Y';
  150.         length answer $ %eval(5*&n-5);
  151.         if solved='Y' then do;
  152.                 answer = symget("A" || cats(key));
  153.                 %do j=1 %to &n;
  154.                         answer=tranwrd(answer, "%substr(&cards,&j,1)", trim(cats(%substr(&cards,&j,1))));
  155.                 %end;
  156.         end;
  157.         call sortn(of _x[*]);
  158. run;
  159. proc sort data=b;
  160.         by %do j=1 %to &n; %substr(&cards,&j,1) %end; solved;
  161. data _b;
  162.         set b;
  163.         by %do j=1 %to &n; %substr(&cards,&j,1) %end;;
  164.         if last.%substr(&cards, &n, 1);
  165. run;
  166. data _b;
  167.         set _b;
  168.         array _x[*] %do j=1 %to &n; %substr(&cards,&j,1) %end;;
  169.         obs = _n_;
  170.         do _n_=1 to dim(_x);
  171.                 _y = _x[_n_];
  172.                 _name_ = vname(_x[_n_]);
  173.                 output;
  174.         end;
  175.         keep obs _name_ _y solved answer;
  176. proc sql;
  177. create table _c as
  178.         select obs, _y from _b
  179.                 group by 1,2 having count(*)>4;
  180. quit;

  181. proc sql;
  182.         delete from _b where obs in (select obs from _c);
  183. quit;
  184. proc transpose data=_b out=&out(drop=_name_ obs);
  185.         by obs solved answer;
  186.         id _name_;
  187.         var _y;
  188. run;
  189. %mend;


  190. title1 '4 Cards';
  191. options nonotes;
  192. %btree(xxx4, abcd, 11, 100);
  193. options notes errors=0;
  194. proc print data=xxx4;
  195.         var tree;
  196. run;
  197. %doit(out=c, cards=abcd, trees=xxx4);

  198. proc freq data=c;
  199.         tables solved;
  200. run;
  201. proc print data=c;
  202.         where solved='Y';
  203. run;

  204. title1 '5 Cards';
  205. options nonotes;
  206. %btree(xxx5, abcde, 15, 150);
  207. options notes errors=0;
  208. proc print data=xxx5;
  209.         var tree;
  210. run;
  211. %doit(out=c, cards=abcde, trees=xxx5);

  212. proc freq data=c;
  213.         tables solved;
  214. run;
  215. proc print data=c;
  216.         where solved='Y';
  217. run;

  218. title1 '6 Cards';
  219. options nonotes;
  220. %btree(xxx6, abcdef, 19, 200);
  221. options notes errors=0;
  222. proc print data=xxx6;
  223.         var tree;
  224. run;
  225. %doit(out=c, cards=abcdef, trees=xxx6);

  226. proc freq data=c;
  227.         tables solved;
  228. run;
  229. proc print data=c;
  230.         where solved='Y';
  231. run;

  232. title1 '7 Cards';
  233. options nonotes;
  234. %btree(xxx7, abcdefg, 23, 300);
  235. options notes errors=0;
  236. proc print data=xxx7;
  237.         var tree;
  238. run;
  239. %doit(out=c, cards=abcdefg, trees=xxx7, batchsize=16);

  240. proc freq data=c;
  241.         tables solved;
  242. run;
  243. proc print data=c;
  244.         where solved='Y';
  245. run;
复制代码
My code won't work for >7 cards. Only He the Lord has no limits. Hallelujah!
Be still, my soul: the hour is hastening on
When we shall be forever with the Lord.
When disappointment, grief and fear are gone,
Sorrow forgot, love's purest joys restored.

17
lwhzbyz 发表于 2014-3-26 15:30:24
现在手上的电脑运行不了SAS真是捉急啊。。。。。

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-25 07:24