2018 刑侦科推理试题
网上看到一个有趣(变态)的推理题目,有点意思,如下:
如果用人脑去思考这个题目,有点发疯。但如果借助计算机蛮力去枚举答案,应该比较容易找到答案,主要难点在于把题目问题转化成计算机的逻辑判断。
每题答案的可能是A、B、C、D。把第一题到第十题到答案的可能性排列在一起,我们把所有可能性都列举一遍,这个序列就是如下的一个字母组列了:
AAAAAAAAAA
BAAAAAAAAA
CAAAAAAAAA
DAAAAAAAAA
ABAAAAAAAA
……
CDDDDDDDDD
DDDDDDDDDD
由于每一题只能是A、B、C、D,也就是一题的答案可以用2个二进制 bit 就可以装得下了,我们把它们分别对应到二进制的 00、01、10、11。上面的那个答案组序列就是这样的一个数据了:
00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00
10 00 00 00 00 00 00 00 00 00
11 00 00 00 00 00 00 00 00 00
11 01 00 00 00 00 00 00 00 00
……
01 11 11 11 11 11 11 11 11 11
10 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11
这组二进制数据,对应的数字就是 0 – 2^20 -1 (也就是1048576 – 1 = 1048575)了。通过排列组合可以知道,每题有四个可能,有10个题目,答案可能性个数为4^10,这个结果和上面的2^20是一样的,2^20 等于 4^10。
通过字母列到数字的转化,我们做枚举答案就很方便啦。一个for 循环 枚举 0 到1048575,把它转化成字母列,再对每个题目要求进行测试。每个测试都通过,则为要求的答案了。
下面我们使用python 来求解这个题目。
一、我们需要一个数字到字母序列的函数
稍作思考变得函数:
def number_to_answer(n):
letters = 'ABCD'
answer = ['','','','','','','','','','']
for i in range(0,10):
answer[i] = letters[((n >> (i * 2)) & 3)]
return answer
n>>(i *2) 是由于第i 题的答案在 n 的高位的 i * 2 的位置上,留意上面二进制数列就能方便理解到。
运算“ & 3 ”,即移动位置后和二进制11 做and 操作,清零高位,该值变成0-3 的数字,即为答案的索引了,再通过索引从letters 读取字母,即为对应位置的答案选项了。
该函数返回answer =[x,x,x,x,x,x,x,x,x,x] ,每个x 的范围是 [A,B,C,D]。
answer[i] 表示第i(这里i从0 开始)题的答案。
二、我们需要把每个题目转化成代码逻辑
第一题没有什么要求,自身所有答案都满足,主要是其他题目对自身存在约束,自身的代码如下:
def question0(answer):
return True
这里我们再来拿第二题来做分析转换,第二题题目是:
“第五题的答案是:
A. C , B. D, C. A, D. B”
answer[10] 是一个答案列, 四个选项就是四个条件映射,那么改题要求就是“第五题的答案 等于 条件选项[第二题答案位置]的映射值”,转成逻辑代码如下:
def question1(answer):
condition_map = {
'A' : 'C',
'B' : 'D',
'C' : 'A',
'D' : 'B'
}
return condition_map[answer[1]] == answer[4]
其他的题目做类似的转化即可,十个题目转化后为 question0 到question9 十个函数。
三、编写测试这十个函数的代码
python 是个比较好的语言,函数可赋值给变量,我们做一个函数数组,赋值为上面的十个测试函数,再写一个循环即可很方便做这十个问题的测试,代码如下:
def test_answer(answer):
functions = [
question0,
question1,
question2,
question3,
question4,
question5,
question6,
question7,
question8,
question9
]
for f in functions:
if not f(answer):
return False
return True
在上面的基础上,我们来个遍历 0 到 1048576 – 1 ,把它转化成字母序列,之后放到上面的测试函数来判断,成功即为上面试卷需求的答案了,这个代码逻辑较为简单:
count = 0
for i in range(0,1048576): # 0 - 2 ^ 20
answer = number_to_answer(i)
if test_answer(answer):
count += 1
print(answer)
print("total count " + str(count))
综上,完整代码如下:
#-*- coding: UTF-8 -*-
import os
import sys
'''
十个题目 为 answer[10]
每个答案 A B C D
答案组列可能为:
AAAAAAAAAA
BAAAAAAAAA
CAAAAAAAAA
DAAAAAAAAA
ABAAAAAAAA
……
CDDDDDDDDD
DDDDDDDDDD
00 -> A
01 -> B
10 -> C
11 -> D
00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00
10 00 00 00 00 00 00 00 00 00
11 00 00 00 00 00 00 00 00 00
11 01 00 00 00 00 00 00 00 00
……
01 11 11 11 11 11 11 11 11 11
10 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11
'''
def question0(answer):
return True
def question1(answer):
condition_map = {
'A' : 'C',
'B' : 'D',
'C' : 'A',
'D' : 'B'
}
return condition_map[answer[1]] == answer[4]
def question2(answer):
if answer[2] == 'A':
if (answer[5] == answer[1]) and (answer[1] == answer[3]) and (answer[3] != answer[2]):
return True
if answer[2] == 'B':
if (answer[2] == answer[1]) and (answer[1] == answer[3]) and (answer[3] != answer[5]):
return True
if answer[2] == 'C':
if (answer[2] == answer[5]) and (answer[5] == answer[3]) and (answer[3] != answer[1]):
return True
if answer[2] == 'D':
if (answer[2] == answer[5]) and (answer[5] == answer[1]) and (answer[1] != answer[3]):
return True
return False
def question3(answer):
condition_map = {
'A' : (answer[0] == answer[4]),
'B' : (answer[1] == answer[6]),
'C' : (answer[0] == answer[8]),
'D' : (answer[5] == answer[9])
}
return condition_map[answer[3]]
def question4(answer):
condition_map = {
'A' : answer[7],
'B' : answer[3],
'C' : answer[8],
'D' : answer[6]
}
return condition_map[answer[4]] == answer[4]
def question5(answer):
condition_map = {
'A' : ((answer[7] == answer[1]) and (answer[7] == answer[3])),
'B' : ((answer[7] == answer[0]) and (answer[7] == answer[5])),
'C' : ((answer[7] == answer[2]) and (answer[7] == answer[9])),
'D' : ((answer[7] == answer[4]) and (answer[7] == answer[8]))
}
return condition_map[answer[5]]
def question6(answer):
letters_count = {
'A' : 0,
'B' : 0,
'C' : 0,
'D' : 0
}
for a in answer:
letters_count[a] += 1
min_letter = 'A'
min_count = 10
for key, val in letters_count.items():
if min_count > val:
min_count = val
min_letter = key
condition_map = {
'A' : 'C',
'B' : 'B',
'C' : 'A',
'D' : 'D'
}
return condition_map[answer[6]] == min_letter
def question7(answer):
letters_pos = {
'A' : 1,
'B' : 2,
'C' : 3,
'D' : 4
}
condition_map = {
'A' : answer[6],
'B' : answer[4],
'C' : answer[1],
'D' : answer[9]
}
return (abs(letters_pos[answer[0]] - letters_pos[condition_map[answer[7]]])) > 1
def question8(answer):
condition_map = {
'A' : answer[5],
'B' : answer[9],
'C' : answer[1],
'D' : answer[8]
}
return (answer[0] == answer[5]) != (condition_map[answer[8]] == answer[4])
def question9(answer):
letters_count = {
'A' : 0,
'B' : 0,
'C' : 0,
'D' : 0
}
for a in answer:
letters_count[a] += 1
min_letter = 'A'
min_count = 10
max_letter = 'D'
max_count = 0
for key, val in letters_count.items():
if min_count > val:
min_count = val
min_letter = key
if max_count < val:
max_count = val
max_letter = key
condition_map = {
'A' : 3,
'B' : 2,
'C' : 4,
'D' : 1
}
return condition_map[answer[9]] == (max_count - min_count)
def number_to_answer(n):
letters = 'ABCD'
answer = ['','','','','','','','','','']
for i in range(0,10):
answer[i] = letters[((n >> (i * 2)) & 3)]
return answer
def test_answer(answer):
functions = [
question0,
question1,
question2,
question3,
question4,
question5,
question6,
question7,
question8,
question9
]
for f in functions:
if not f(answer):
return False
return True
if __name__ == "__main__":
count = 0
for i in range(0,1048576): # 0 - 2 ^ 20
answer = number_to_answer(i)
if test_answer(answer):
count += 1
print(answer)
print("total count " + str(count))
通过跑完整代码,得到的结果为:
[‘B’, ‘C’, ‘A’, ‘C’, ‘A’, ‘C’, ‘D’, ‘A’, ‘B’, ‘A’]
total count 1
这个也就是试卷的题目答案了。
(全文完)
(欢迎转载本站文章,但请注明作者和出处 云域 – Yuccn )