最近网上出了一个比较火的刑侦推理题,王二比较感兴趣,因而抽空作了作。javascript
刚开始,王二写下了以下代码:html
<script> var arr = new Array(10).fill("A"); recursion(); function a1 (){ return true; } function a2 (){ switch(arr[1]) { case "A": return arr[4] === "C" case "B": return arr[4] === "D" case "C": return arr[4] === "A" case "D": return arr[4] === "B" default: return false; } } function a3 (){ switch(arr[2]) { case "A": return arr[5] === arr[1] && arr[5] === arr[3] case "B": return arr[2] === arr[1] && arr[2] === arr[3] case "C": return arr[5] === arr[2] && arr[5] === arr[3] case "D": return arr[5] === arr[1] && arr[5] === arr[2] default: return false; } } function a4 (){ var f1 = arr[0] === arr[4] , f2 = arr[1] === arr[6] , f3 = arr[0] === arr[8] , f4 = arr[5] === arr[9] ; switch(arr[3]) { case "A": return f1 && !f2 && !f3 && !f4 case "B": return !f1 && f2 && !f3 && !f4 case "C": return !f1 && !f2 && f3 && !f4 case "D": return !f1 && !f2 && !f3 && f4 default: return false; } } function a5 (){ switch(arr[4]) { case "A": return arr[7] === "A" case "B": return arr[3] === "B" case "C": return arr[8] === "C" case "D": return arr[6] === "D" default: return false; } } function a6 (){ var f1 = arr[7] === arr[1] && arr[7] === arr[3] , f2 = arr[7] === arr[0] && arr[7] === arr[5] , f3 = arr[7] === arr[2] && arr[7] === arr[9] , f4 = arr[7] === arr[4] && arr[7] === arr[8] ; switch(arr[5]) { case "A": return f1 && !f2 && !f3 && !f4 case "B": return !f1 && f2 && !f3 && !f4 case "C": return !f1 && !f2 && f3 && !f4 case "D": return !f1 && !f2 && !f3 && f4 default: return false; } } function a7 (){ var c1 = arr.filter((i)=>{return i === "A"}).length , c2 = arr.filter((i)=>{return i === "B"}).length , c3 = arr.filter((i)=>{return i === "C"}).length , c4 = arr.filter((i)=>{return i === "D"}).length ; switch(arr[6]) { case "A": return Math.min(c1,c2,c3,c4) === c3 case "B": return Math.min(c1,c2,c3,c4) === c2 case "C": return Math.min(c1,c2,c3,c4) === c1 case "D": return Math.min(c1,c2,c3,c4) === c4 default: return false; } } function a8 (){ switch(arr[7]) { case "A": return Math.abs(arr[0].charCodeAt(0) - arr[6].charCodeAt(0))>=2 case "B": return Math.abs(arr[0].charCodeAt(0) - arr[4].charCodeAt(0))>=2 case "C": return Math.abs(arr[0].charCodeAt(0) - arr[1].charCodeAt(0))>=2 case "D": return Math.abs(arr[0].charCodeAt(0) - arr[9].charCodeAt(0))>=2 default: return false; } } function a9 (){ var flag = arr[0] === arr[5], f1 = (arr[4] === arr[5]) === !flag , f2 = (arr[4] === arr[9]) === !flag , f3 = (arr[4] === arr[1]) === !flag , f4 = (arr[4] === arr[8]) === !flag ; switch(arr[8]) { case "A": return f1 && !f2 && !f3 && !f4 case "B": return !f1 && f2 && !f3 && !f4 case "C": return !f1 && !f2 && f3 && !f4 case "D": return !f1 && !f2 && !f3 && f4 default: return false; } } function a10 (){ var c1 = arr.filter((i)=>{return i === "A"}).length , c2 = arr.filter((i)=>{return i === "B"}).length , c3 = arr.filter((i)=>{return i === "C"}).length , c4 = arr.filter((i)=>{return i === "D"}).length ; switch(arr[9]) { case "A": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 3 case "B": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 2 case "C": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 4 case "D": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 1 default: return false; } } function vali () { return a1() && a2() && a3() && a4() && a5() && a6() && a7() && a8() && a9() && a10() ; } //递归遍历arr的全部排列组合 function recursion (){ if(vali()){ console.log(arr); } for(var x=0 ; x<arr.length ; x++){ switch(arr[x]) { case "A": arr[x] = "B" ; recursion () ; return ; case "B": arr[x] = "C" recursion () ; return ; case "C": arr[x] = "D" ; recursion () ; return ; case "D": if(x===9) return ; arr[x] = "A" ; continue ; default: return ; } } } </script>
复制代码
以上的代码逻辑上没有问题,可是仍是报了个错——栈溢出java
虽然王二也试着用尾递归优化来尝试解决问题,但依然报错数组
后来王二躺床上又寻思怎么才能解决这恶心的报错,而后想到try
catch
能够捕获错误,或许咱们能递归调用 try
catch
来解决这个问题。按照这个思路王二又在代码片断中添加了以下的代码:优化
var flag = true ;
function run () {
try {
if(flag){
flag = false ;
recursion() ;
}
} catch (err) {
flag = true;
run();
}
}
复制代码
意思是若是栈溢出报错,则在 catch
再次调用 run()
方法 ,直到它不报错为止,不报错也就意味着arr
数组全部排列组合的可能性都被遍历完了。网站
执行后,还真他娘的起做用了。ui
完整的代码片断以下所示(能够拷贝下来尝试运行):spa
<script> var arr = new Array(10).fill("A"); var flag = true ; run(); // ["B", "C", "A", "C", "A", "C", "D", "A", "B", "A"] function run () { try { if(flag){ flag = false ; recursion() ; } } catch (err) { flag = true; run(); } } function a1 (){ return true; } function a2 (){ switch(arr[1]) { case "A": return arr[4] === "C" case "B": return arr[4] === "D" case "C": return arr[4] === "A" case "D": return arr[4] === "B" default: return false; } } function a3 (){ switch(arr[2]) { case "A": return arr[5] === arr[1] && arr[5] === arr[3] case "B": return arr[2] === arr[1] && arr[2] === arr[3] case "C": return arr[5] === arr[2] && arr[5] === arr[3] case "D": return arr[5] === arr[1] && arr[5] === arr[2] default: return false; } } function a4 (){ var f1 = arr[0] === arr[4] , f2 = arr[1] === arr[6] , f3 = arr[0] === arr[8] , f4 = arr[5] === arr[9] ; switch(arr[3]) { case "A": return f1 && !f2 && !f3 && !f4 case "B": return !f1 && f2 && !f3 && !f4 case "C": return !f1 && !f2 && f3 && !f4 case "D": return !f1 && !f2 && !f3 && f4 default: return false; } } function a5 (){ switch(arr[4]) { case "A": return arr[7] === "A" case "B": return arr[3] === "B" case "C": return arr[8] === "C" case "D": return arr[6] === "D" default: return false; } } function a6 (){ var f1 = arr[7] === arr[1] && arr[7] === arr[3] , f2 = arr[7] === arr[0] && arr[7] === arr[5] , f3 = arr[7] === arr[2] && arr[7] === arr[9] , f4 = arr[7] === arr[4] && arr[7] === arr[8] ; switch(arr[5]) { case "A": return f1 && !f2 && !f3 && !f4 case "B": return !f1 && f2 && !f3 && !f4 case "C": return !f1 && !f2 && f3 && !f4 case "D": return !f1 && !f2 && !f3 && f4 default: return false; } } function a7 (){ var c1 = arr.filter((i)=>{return i === "A"}).length , c2 = arr.filter((i)=>{return i === "B"}).length , c3 = arr.filter((i)=>{return i === "C"}).length , c4 = arr.filter((i)=>{return i === "D"}).length ; switch(arr[6]) { case "A": return Math.min(c1,c2,c3,c4) === c3 case "B": return Math.min(c1,c2,c3,c4) === c2 case "C": return Math.min(c1,c2,c3,c4) === c1 case "D": return Math.min(c1,c2,c3,c4) === c4 default: return false; } } function a8 (){ switch(arr[7]) { case "A": return Math.abs(arr[0].charCodeAt(0) - arr[6].charCodeAt(0))>=2 case "B": return Math.abs(arr[0].charCodeAt(0) - arr[4].charCodeAt(0))>=2 case "C": return Math.abs(arr[0].charCodeAt(0) - arr[1].charCodeAt(0))>=2 case "D": return Math.abs(arr[0].charCodeAt(0) - arr[9].charCodeAt(0))>=2 default: return false; } } function a9 (){ var flag = arr[0] === arr[5], f1 = (arr[4] === arr[5]) === !flag , f2 = (arr[4] === arr[9]) === !flag , f3 = (arr[4] === arr[1]) === !flag , f4 = (arr[4] === arr[8]) === !flag ; switch(arr[8]) { case "A": return f1 && !f2 && !f3 && !f4 case "B": return !f1 && f2 && !f3 && !f4 case "C": return !f1 && !f2 && f3 && !f4 case "D": return !f1 && !f2 && !f3 && f4 default: return false; } } function a10 (){ var c1 = arr.filter((i)=>{return i === "A"}).length , c2 = arr.filter((i)=>{return i === "B"}).length , c3 = arr.filter((i)=>{return i === "C"}).length , c4 = arr.filter((i)=>{return i === "D"}).length ; switch(arr[9]) { case "A": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 3 case "B": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 2 case "C": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 4 case "D": return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 1 default: return false; } } function vali () { return a1() && a2() && a3() && a4() && a5() && a6() && a7() && a8() && a9() && a10() ; } //递归遍历arr的全部排列组合 function recursion (){ if(vali()){ console.log(arr); } for(var x=0 ; x<arr.length ; x++){ switch(arr[x]) { case "A": arr[x] = "B" ; recursion () ; return ; case "B": arr[x] = "C" recursion () ; return ; case "C": arr[x] = "D" ; recursion () ; return ; case "D": if(x===9) return ; arr[x] = "A" ; continue ; default: return ; } } } </script>
复制代码
这样的写话栈溢出的问题彷佛就比较完美的被解决了。code
2018年04月27日补充:cdn
其实那天晚上王二脑子进水了,其实这里没有必要用到递归调用,现修改代码以下:
var arr = new Array(10).fill("A");
while(recursion(arr)!=='done'){
vali() && console.log(arr)
}
function a1 (){
return true;
}
function a2 (){
switch(arr[1])
{
case "A":
return arr[4] === "C"
case "B":
return arr[4] === "D"
case "C":
return arr[4] === "A"
case "D":
return arr[4] === "B"
default:
return false;
}
}
function a3 (){
switch(arr[2])
{
case "A":
return arr[5] === arr[1] && arr[5] === arr[3]
case "B":
return arr[2] === arr[1] && arr[2] === arr[3]
case "C":
return arr[5] === arr[2] && arr[5] === arr[3]
case "D":
return arr[5] === arr[1] && arr[5] === arr[2]
default:
return false;
}
}
function a4 (){
var f1 = arr[0] === arr[4] ,
f2 = arr[1] === arr[6] ,
f3 = arr[0] === arr[8] ,
f4 = arr[5] === arr[9] ;
switch(arr[3])
{
case "A":
return f1 && !f2 && !f3 && !f4
case "B":
return !f1 && f2 && !f3 && !f4
case "C":
return !f1 && !f2 && f3 && !f4
case "D":
return !f1 && !f2 && !f3 && f4
default:
return false;
}
}
function a5 (){
switch(arr[4])
{
case "A":
return arr[7] === "A"
case "B":
return arr[3] === "B"
case "C":
return arr[8] === "C"
case "D":
return arr[6] === "D"
default:
return false;
}
}
function a6 (){
var f1 = arr[7] === arr[1] && arr[7] === arr[3] ,
f2 = arr[7] === arr[0] && arr[7] === arr[5] ,
f3 = arr[7] === arr[2] && arr[7] === arr[9] ,
f4 = arr[7] === arr[4] && arr[7] === arr[8] ;
switch(arr[5])
{
case "A":
return f1 && !f2 && !f3 && !f4
case "B":
return !f1 && f2 && !f3 && !f4
case "C":
return !f1 && !f2 && f3 && !f4
case "D":
return !f1 && !f2 && !f3 && f4
default:
return false;
}
}
function a7 (){
var c1 = arr.filter((i)=>{return i === "A"}).length ,
c2 = arr.filter((i)=>{return i === "B"}).length ,
c3 = arr.filter((i)=>{return i === "C"}).length ,
c4 = arr.filter((i)=>{return i === "D"}).length ;
switch(arr[6])
{
case "A":
return Math.min(c1,c2,c3,c4) === c3
case "B":
return Math.min(c1,c2,c3,c4) === c2
case "C":
return Math.min(c1,c2,c3,c4) === c1
case "D":
return Math.min(c1,c2,c3,c4) === c4
default:
return false;
}
}
function a8 (){
switch(arr[7])
{
case "A":
return Math.abs(arr[0].charCodeAt(0) - arr[6].charCodeAt(0))>=2
case "B":
return Math.abs(arr[0].charCodeAt(0) - arr[4].charCodeAt(0))>=2
case "C":
return Math.abs(arr[0].charCodeAt(0) - arr[1].charCodeAt(0))>=2
case "D":
return Math.abs(arr[0].charCodeAt(0) - arr[9].charCodeAt(0))>=2
default:
return false;
}
}
function a9 (){
var flag = arr[0] === arr[5],
f1 = (arr[4] === arr[5]) === !flag ,
f2 = (arr[4] === arr[9]) === !flag ,
f3 = (arr[4] === arr[1]) === !flag ,
f4 = (arr[4] === arr[8]) === !flag ;
switch(arr[8])
{
case "A":
return f1 && !f2 && !f3 && !f4
case "B":
return !f1 && f2 && !f3 && !f4
case "C":
return !f1 && !f2 && f3 && !f4
case "D":
return !f1 && !f2 && !f3 && f4
default:
return false;
}
}
function a10 (){
var c1 = arr.filter((i)=>{return i === "A"}).length ,
c2 = arr.filter((i)=>{return i === "B"}).length ,
c3 = arr.filter((i)=>{return i === "C"}).length ,
c4 = arr.filter((i)=>{return i === "D"}).length ;
switch(arr[9])
{
case "A":
return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 3
case "B":
return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 2
case "C":
return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 4
case "D":
return Math.max(c1,c2,c3,c4) - Math.min(c1,c2,c3,c4) === 1
default:
return false;
}
}
function vali () {
return a1() && a2() && a3() && a4() && a5() && a6() && a7() && a8() && a9() && a10() ;
}
function recursion(arr){
for(var x=0 ; x<arr.length ; x++){
switch(arr[x])
{
case "A":
arr[x] = "B" ;
return arr;
case "B":
arr[x] = "C"
return arr;
case "C":
arr[x] = "D" ;
return arr;
case "D":
if(x===9) return 'done';
arr[x] = "A" ;
continue ;
default:
return 'error';
}
}
}
复制代码
如此简单的问题王二那天想的那么复杂,也是醉了。
原文地址:王玉略的我的网站