题解 | #24点游戏算法#
24点游戏算法
https://www.nowcoder.com/practice/fbc417f314f745b1978fc751a54ac8cb
// 其实就是4个数字有4!=24种排列组合,两种计算逻辑(16+144=160种计算方式),最终极限情况下需要24*160=3840种结果都计算出来,才能知道是否能得到24点。
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// Write your code here
// 组装四种计算结果
function fn(x, y) {
return [x + y, x - y, x / y, x * y];
}
// 组装六种计算结果
function fn2(x, y) {
return [x + y, x - y, x / y, x * y, y - x, y / x];
}
while ((line = await readline())) {
// line = "2 9 9 5";
let [a, b, c, d] = line.split(" ").map((item) => parseInt(item));
let result = [];
// 4个数字 24种顺序组合
let arry = [
[a, b, c, d],
[a, b, d, c],
[a, c, d, b],
[a, c, b, d],
[a, d, c, b],
[a, d, b, c],
[b, a, c, d],
[b, a, d, c],
[b, c, d, a],
[b, c, a, d],
[b, d, c, a],
[b, d, a, c],
[c, a, b, d],
[c, a, d, b],
[c, b, d, a],
[c, b, a, d],
[c, d, b, a],
[c, d, a, b],
[d, a, b, c],
[d, a, c, b],
[d, b, c, a],
[d, b, a, c],
[d, c, b, a],
[d, c, a, b],
];
let flag = false;
// 遍历,计算每一种数字组合
arry.forEach((item) => {
if (flag) {
return false;
}
let [x1, x2, x3, x4] = item;
// 计算第一种情况
// 逻辑为:x1,x2,计算,x3,x4,计算,计算
// 解释:先拿x1和x2 得到res1(四种计算结果),再用x3,x4 得到res2(四种计算结果 )
// x-y和y-x 两种计算方式,在遍历过程中,会出现x,y 和y,x两种顺序,无需重复计算多次
// 得到res1 和res2 两个结果集,交叉得到16个结果,如果包含24 ,设置状态,及时跳出后续的循环
let res1 = fn(x1, x2);
let res2 = fn(x3, x4);
res1.forEach((val1) => {
if (flag) {
return false;
}
res2.forEach((val2) => {
if (flag) {
return false;
}
let tempArry = fn(val1, val2);
if (tempArry.includes(24)) {
// console.log(true, x1, x2, x3, x4, val1, val2, 'case1'); // 调试
console.log(true);
flag = true; // 如果包含24,修改状态
}
});
});
if (flag) {
return false;
}
// 计算第2种情况 这时候需要考虑一个问题(x1+x2)/x3 和 x3/(x1+x2) ,x1*x2-x3 和 x3-x1*x2 是不同的计算方式,不会因为数据顺序变化,而重复,需要额外交换计算一次。
// 逻辑为:x1,x2,计算,x3,计算,x4,计算
// 解释:
// step1:先拿x1和x2 得到res3(x1和x2会因为数据交换产生被减被除,所以只考虑加减乘除,4个结果),
// step2:res3和x3交叉得到res4 (4*6 24个结果,此时需要考虑被除 被减)
// step3:res4和x4交叉得到res5 (24*6 144个结果,此时需要考虑被除 被减),如果结果里包含24 ,设置状态,及时跳出后续的循环
let res3 = fn(x1, x2);
res3.forEach((val3) => {
if (flag) {
return false;
}
let res4 = fn2(val3, x3);
res4.forEach((val4) => {
if (flag) {
return false;
}
let res5 = fn2(val4, x4);
if (res5.includes(24)) {
// console.log(true, x1, x2, x3, x4, val3, val4, 'case2'); // 调试
console.log(true); // 如果包含24,修改状态
flag = true;
}
});
});
if (flag) {
return false;
}
});
if (!flag) {
console.log(false);
}
}
})();
