码迷,mamicode.com
首页 > 其他好文 > 详细

趣味集算:算二十四

时间:2018-08-02 11:26:22      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:查看   .com   func   UNC   完成后   更新   还需   body   循环调用   

算24点,是一种常见的智力游戏。它可以使用抽去大小王的扑克牌来玩,随便抽出4张牌,要求通过加、减、乘、除等四则运算,并使用所有的这4个数,将结果算为24。在玩这个游戏时,扑克牌中的JQK记为11,12和13。

用集算器,可以比较方便地编写程序,根据随便给定的4个数,计算出游戏的解答,如下面的24points.dfx:


ABCD
1=arg1[+,-,*,/][][]
2=to(0,255).([~\64+1, ~%64\16+1,~%16\4+1,~%4+1])=A2.select(~.id().count()==4)

3=to(0,63).([~\16+1, ~%16\4+1,~%4+1])=A3.select(~.eq([1,2,3]))=A3.(~.(B1(~)))
4=B2.(~.(A1(~)))=A4.id()

5for B4for B3for C3>func(A8,A5,B5,C5)
6=C1.id(~)for A6if round(eval(B6),3) ==24>D1=D1|B6
7if D1.len()==0>D1=”No answer.”

8func

=A8.(~)
9
=B8.(~)for B9>B9.(~=~-if(#>#C9 && ~>C9,1,0))
10
for B9=D8(B10)/C8(#B10)/ D8(B10+1)>D8.delete(B10)
11

if #B10==3>C1=C1&C10
12

else>D8(B10)=”(“/C10/”)”
13return D1


其中,arg1用参数输入使用的4张牌上的数,参数也可在A1中查看:

技术分享图片

下面,详细分析一下这段代码。

计算使用的4个数在A1中给出,这里用的四张牌是8,3,8,3。首先,在算24点时,应该尝试4张牌的所有顺序。所以,先在A2中,利用一个4位的4进制数,来列出4张牌的可重复排列情况。在B2中,仅选出不重复排列的情况如下:

技术分享图片

在计算时,4个数中间共需要插入3个四则运算符号,每个符号都可以从加减乘除中4选1。在A3中循环一个3位的4进制数,列出所有情况如下:

技术分享图片

在计算时,不同的计算顺序会影响结果,可以通过添加括号来调整计算顺序。3个运算符号,说明计算可以分为3个位置执行,添加括号即是决定这3个位置的执行顺序。在B3中,从A3的结果中选择了同时包含1,2,3的组合,即为所有可能的执行顺序如下:

技术分享图片

由于选出的4张牌中,有可能出现重复的数,为了避免因此造成的多余循环,在A4中把所有的牌面排列顺序列出,并在B4中去掉了可能出现的重复的排列情况。对于A1中给出的[8,3,8,3],B4中列出排列结果如下:

技术分享图片

在第5行的程序中,对于每种数的排列,循环每一种符号选择,并循环所有的计算顺序,调用A8中的子程序计算。

调用A8中的子程序时,数值序列、符号序列和计算顺序序列,分别填到A8,B8,C8中,并在D8中准备计算使用的表达式。单步计算完成后,原有的总计算步数就少了1步,还需要在第9行中相应调整计算顺序序列。在B10中执行循环,每计算一步,都将两个数或表达式用计算符号连接起来,同时在D8中删除1个占位。在第11行执行判断,对于最后一步计算,将把获得的表达式添加到序列C1中。如果是中间步骤,则会在新生成的表达式中添加括号,以保证计算顺序,并将这部分表达式更新到D8中。

这样,当第5行代码中循环调用子程序完毕,就在C1中得到了所有可能出现的表达式。其中会有一些重复的情况,因此在A6中用id()函数去掉重复的表达式。C1和A6中的表达式序列如下:

技术分享图片

在B6中循环A6中的各个表达式,判断结果是否等于24,判断时只需用eval函数计算表达式的结果即可,考虑到双精度数的计算误差,结果保留3位小数。如果结果等于24,说明当前个表达式可以满足条件,在D6中,将其存储到D1中。

在所有的情况都循环完毕后,在A7中,如果发现D1中未填入任何表达式,则说明无解。

计算完成后,就可以在D1中查看结果如下:

技术分享图片

如果需要修改使用的4张牌,则可在计算前修改网格参数arg1,如修改为[7,3,3,7]:

技术分享图片

计算后,D1中查看到的结果如下:

技术分享图片

可以在另一段程序中,通过调用24points.dfx,计算出所有4张扑克牌组合的结果:


ABC
1=file(“d:/file/24points.dfx”)=create(Num1,Num2,Num3,Num4,Answer)
213=A2*A2=B2*A2
3=to(0,A2*C2-1).([~\C2+1, ~%C2\B2 +1,~%B2\A2+1,~%A2+1])=A3.(~.sort()).id()>B3.run((a=~,B1.insert(0,a(1),a(2),a(3),a(4),call(A1,a))))
4=file(“d:/file/24points.txt”)>A4.export@t(B1)

在这段代码中,A3中列出4张扑克牌的所有组合:

技术分享图片

由于同样的4张牌只是打乱顺序,它们的解答是相同的,所以在B3中将A3中的组合排序整理,并去掉重复的情况,以便减少运算次数:

技术分享图片

在C3中,针对B3中的每一种情况,调用24points.dfx来计算结果,并将结果记录在B1的表中,计算结束后,B1中得到的结果如下:

技术分享图片

在第4行,把计算得到的结果记录在文件中,集算器支持多种格式的文件,为了便于查看,这里选择存储到文本文件24points.txt中,存储结果如下:

技术分享图片


趣味集算:算二十四

标签:查看   .com   func   UNC   完成后   更新   还需   body   循环调用   

原文地址:http://blog.51cto.com/12749034/2153500

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!