2018 刑侦科推理试题

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

这个也就是试卷的题目答案了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注