本帖最后由 delete_007 于 2015-8-25 15:01 编辑
第1章 IF+TEXT+MAX
该思路的主体是IF函数,通过条件判断牌型是否有点(包括X点和牛)进行分支。有点的情况下,计算5张牌的和,并对10取余,进而判断是X点还是牛。无点的情况下,取5张牌的最大值,得出结果X大。 1.1 判断条件 判断是否有三张牌之和为10的倍数。 由于数据源有大于10的牌,所以需要先处理源数据,这里有三种境界: 第一种,按题目要求,大于10的数当作10计算,于是有公式(21字符): 第二种,按需求进行简化,处理数据源的目的是为了判断三张牌之和是否是10的整数倍,那么10和0是等效的,公式如下(20字符): 第三种,延续第二种思路,跳出TEXT,公式如下(16字符):
在IF函数的大框架下,缩短公式长度的有效方法是减少条件判断部分的公式长度。
以整数部分用于计算牌的张数,小数部分对牌的点数求和(82字符):(delete_007) - OR(MMULT(1+A2:E2*(A2:E2<10)%,MOD(INT(COLUMN(A:AE)/2^ROW($1:$5)*2),2))={3;3.1;3.2})
复制代码 MMULT函数计算5张牌的所有组合结果,如下: {1.05,1.05,2.1,1,2.05,2.05,3.1,1,2.05,2.05,3.1,2,3.05,3.05,4.1,1,2.05,2.05,3.1,2,3.05,3.05,4.1,2,3.05,3.05,4.1,3,4.05,4.05,5.1} 组合结果中有整数部分是3,小数部分是0.1的整数倍的结果,此牌型就是“有点”的情况,否则“无点”。
当然也可以将整数部分和小数部分对换,以小数部分表示牌的张数,而整数部分表示牌的点数之和,MOD函数在处理小数时易造成浮点误差,因此用个位表示牌的张数,十位及以上表示牌的点数之和,公式如下(84字符)。(pxiceplay、chunlin1wang、jsxjd) - AND(MOD(MMULT(A2:E2*(A2:E2<10)*10+1,MOD(INT(COLUMN(A:AE)/2^ROW($1:$5)*2),2))-3,100))
复制代码 结果为真表示“无点”,否则“有点”。 使用FIND方法,可以避免浮点误差问题处理小数,得到组合结果之后,当小数部分是“.03”表示三张牌的组合,个位数是0表示牌的点数之和是10的整数倍,因此有公式(82字符):(cmxxccxx、笑眼晴天、cleverzhzhf) - COUNT(FIND(3%,MMULT(A2:E2*(A2:E2<10)+1%,MOD(INT(COLUMN(A:AE)/2^ROW($1:$5)*2),2))))
复制代码 此公式查找组合结果中是否包含0.03字符串,有则表示“有点”,否则“无点”。 FIND函数可以换成SEARCH、MATCH的模糊查找,大体原理相同,不再赘述。
还有一种比较奇特的条件判断思路,不用复杂的组合因子,而采用逆向思维。(笨笨四、满坛皆为吾师) 求三张牌的点数之和,可以转化为五张牌的点数之和,减去任意两张牌的点数,即如下公式: - SUMIF(A2:E2,"<10")-A2:E2*(A2:E2<10)-TRANSPOSE(A2:E2*(A2:E2<10))
复制代码 然后通过个位数判断是否”有点“。个位是0为有”有点“,非0为”无点“。此处需注意,二维数组对角线上的值五牌之和减同一张牌两次,不满足,使用MUNIT函数附加单位矩阵进行处理。最终得到公式(84字符): - AND(RIGHT(SUMIF(A2:E2,"<10")-A2:E2*(A2:E2<10)-TRANSPOSE(A2:E2*(A2:E2<10)))+MUNIT(5))
复制代码公式结果为真表示“无点”,否则“有点”。
|