Fork me on GitHub

JS解出最近比较火的刑侦推理题

晚上闲着无聊,来做一做最近比较火的刑侦推理题

最近网上出了一个比较火的刑侦推理题,王二比较感兴趣,于是抽空做了做。

一、推理题如下

Alt text

二、遇到的问题

刚开始,王二写下了如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<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>

以上的代码逻辑上没有问题,但是还是报了个错——栈溢出

Alt text

虽然王二也试着用尾递归优化来尝试解决问题,但依然报错

三、解决方法

后来王二躺床上又寻思怎么才能解决这恶心的报错,然后想到try catch 可以捕获错误,或许我们能递归调用 try catch 来解决这个问题。按照这个思路王二又在代码片段中添加了如下的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
var flag = true ;

function run () {
try {
if(flag){
flag = false ;
recursion() ;
}
} catch (err) {
flag = true;
run();
}
}

意思是如果栈溢出报错,则在 catch 再次调用 run() 方法 ,直到它不报错为止,不报错也就意味着arr数组所有排列组合的可能性都被遍历完了。

执行后,还真他娘的起作用了。

完整的代码片段如下所示(可以拷贝下来尝试运行):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
<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>

这样的写话栈溢出的问题似乎就比较完美的被解决了。


2018年04月27日补充:

其实那天晚上王二脑子进水了,其实这里没有必要用到递归调用,现修改代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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';
}
}
}

如此简单的问题王二那天想的那么复杂,也是醉了。

-------------本文结束感谢您的阅读-------------