首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

python大破2018年刑侦科推理试题

昨天晚上,一个朋友给我发了一张图,据说是江苏网警微博出的题目,叫“2018年刑侦科试题”。当时已经很晚了,所以今天早上才解决这道题目。

试卷如图所示:

如果你没有接触过数理逻辑中的布尔代数,对真命题、假命题、恒真式等概念不了解,对题目可能会感到云里雾里。这道题目,我以前就见过类似的,不知道这一次是不是又把那道题目搬了出来,还是江苏网警仿造的一道题目。记得当时,我觉得这道题目很难,我没有做出来。但是,今天不一样了,我有计算机,我有python(2017年世界上最受欢迎的语言)。

科普一下真命题和假命题。一般的,在数学中把用语言、符号或式子表达的,可以判断真假的陈述句叫做命题。命题真值只能取两个值:真或假。真对应判断正确,假对应判断错误。任何命题的真值都是唯一的,称真值为真的命题为真命题。例如“15是5的倍数”,就是真命题。而“2010年是闰年”,则是假命题。在程序里,真命题的值是True,假命题的值为False。

再讲几个运算符:not,and和or。

not就是取反运算符,真的反面就是假,也就是说 not True == False(在python语言里,=被用来赋值,==则被用来判断是否相等)。同样地,not False == True。

and是与运算符。A and B如果是真的话,要求A和B都是真。比如"15能被5整除“并且”15能被3整除“,这个命题就是真命题。如果我们记命题 ”15能被5整除“为A,记命题B”15能被3整除“为B,那么就有 A and B == True。如果A和B中间有一个是假命题,则A and B == False。

or是或运算符。A or B如果是真的话,只要A和B中有一个是真即可。比如"15能被5整除“或者”15能被2整除“,这个命题就是真命题。

搞清这些概念之后(如果还是不太清楚,可以查阅一下相关数学书),我们再回过头来看这张试卷。

很显然,这张试卷是浑然一体的,题目之间有着千丝万缕的联系,你单做一道题是不行的。如果你第二题选了A,那么根据第二题的题意,第五题你必须选C,否则就矛盾了。因此,你需要找到的答案就是有顺序的十个字母(都在ABCD之中),并且这十个字母必须满足题目中给出的十个逻辑关系。

对于普通人来说,常规的方法就是先尝试正常分析解答,如果解答不出来就可能去”撞大运“——随便填几个答案,看看有没有矛盾,有矛盾的话进行修改,直到获得一个没有矛盾的答案。

其实,这也是我的思路,我也要随机产生答案去碰运气。但是,不同的是,我要利用计算机,产生上百万个答案去试探。由于现代计算机速度很快,不需要很长时间,就能尝试出正确答案(本题答案最多有4^10=1048576个)。

对于每一个生成的答案,都要对其中的十个选项逐一进行测试,看看是否满足要求。我们把每个答案保存在一个数组(数组变量名叫answer)里,由于python里面的数组下标从0开始,为了阅读方便,我们使用一个长度为11的数组,将答案存放在数组第二项到第十一项里。这样answer[1]就是数组的第二项,但同时也是答案的第一项。我们先构造几个函数,对数组的那些项分别进行处理,并根据判断结果返回True或False。

先看第一题,很显然这一题不管答案是什么,都是对的,因为这一题就好比说的是“我是我”。

python是脚本语言,大部分的语句阅读起来很直白。为了测试第二题的选项,我们定义一个函数judge2(a)。这里的a是输入值,在后面的主程序里面,可以用答案数组answer取代a。程序语言里的函数,跟初中学的函数一样,除了自变量(相当于输入值),还有因变量(也就是输出值)。只不过,程序的函数输出值可能超过一个。在这里,我们就把输出值限制为True和False,用以标明第二题的答案是否满足题目要求。函数如下:

def judge2(a):

if a[2] == 1:

if a[5] == 3:

return True

else:

return False

elif a[2] == 2:

if a[5] == 4:

return True

else:

return False

elif a[2] == 3:

if a[5] == 1:

return True

else:

return False

elif a[2] == 4:

if a[5] == 2:

return True

else:

return False

‍上面函数里的if就是假如的意思。if a[2] == 1,意思就是如果第二题答案是A的话,后面紧接一个if a[5] == 3,意思就是如果第五题答案是C的话。后面的return True就是要让该函数返回真值,表明第二题答案满足要求。else:否则的意思。return False就是说,如果第五题答案不是C,则返回错误值,表明第二题答案不满足要求。elif a[2] == 2,则判断当第二题答案是B时,是否产生矛盾。

第二个函数写完后,我们再依法炮制第三题至第十题的函数,代码如下:

def judge3(a):

if a[3] == 1:

if a[3] != a[6] and a[3] != a[2] and a[3] != a[4]:

return True

else:

return False

elif a[3] == 2:

if a[6] != a[3] and a[6] != a[2] and a[3] != a[4]:

return True

else:

return False

elif a[3] == 3:

if a[2] != a[3] and a[2] != a[6] and a[3] != a[4]:

return True

else:

return False

elif a[3] == 4:

if a[4] != a[3] and a[4] != a[6] and a[4] != a[2]:

return True

else:

return False

def judge4(a):

if a[4] == 1:

if a[1] == a[5]:

return True

else:

return False

elif a[4] == 2:

if a[2] == a[7]:

return True

else:

return False

elif a[4] == 3:

if a[1] == a[9]:

return True

else:

return False

elif a[4] == 4:

if a[6] == a[10]:

return True

else:

return False

def judge5(a):

if a[5] == 1:

if a[5] == a[8]:

return True

else:

return False

elif a[5] == 2:

if a[5] == a[4]:

return True

else:

return False

elif a[5] == 3:

if a[5] == a[9]:

return True

else:

return False

elif a[5] == 4:

if a[5] == a[7]:

return True

else:

return False

def judge6(a):

if a[6] == 1:

if a[8] == a[2] and a[8] == a[4]:

return True

else:

return False

elif a[6] == 2:

if a[8] == a[1] and a[8] == a[6]:

return True

else:

return False

elif a[6] == 3:

if a[8] == a[3] and a[8] == a[10]:

return True

else:

return False

elif a[6] == 4:

if a[8] == a[5] and a[8] == a[9]:

return True

else:

return False

def judge7(a):

count1 = 0

count2 = 0

count3 = 0

count4 = 0

for i in range(1,11):

if a[i] == 1:

count1 += 1

elif a[i] == 2:

count2 += 1

elif a[i] == 3:

count3 += 1

elif a[i] == 4:

count4 += 1

smallest = min(count1,count2,count3,count4)

if a[7] == 1:

if count3 == smallest:

return True

else:

return False

elif a[7] == 2:

if count2 == smallest:

return True

else:

return False

elif a[7] == 3:

if count1 == smallest:

return True

else:

return False

elif a[7] == 4:

if count4 == smallest:

return True

else:

return False

def judge8(a):

if a[8] == 1:

if abs(a[1] - a[7]) != 1:

return True

else:

return False

elif a[8] == 2:

if abs(a[1] - a[5]) != 1:

return True

else:

return False

elif a[8] == 3:

if abs(a[1] - a[2]) != 1:

return True

else:

return False

elif a[8] == 4:

if abs(a[1] - a[10]) != 1:

return True

else:

return False

def judge9(a):

if a[9] == 1:

if (not (a[1] == a[6])) == (a[6] == a[5]):

return True

else:

return False

elif a[9] == 2:

if (not (a[1] == a[6])) == (a[10] == a[5]):

return True

else:

return False

elif a[9] == 3:

if (not (a[1] == a[6])) == (a[2] == a[5]):

return True

else:

return False

elif a[9] == 4:

if (not (a[1] == a[6])) == (a[9] == a[5]):

return True

else:

return False

def judge10(a):

count1 = 0

count2 = 0

count3 = 0

count4 = 0

for i in range(1,11):

if a[i] == 1:

count1 += 1

elif a[i] == 2:

count2 += 1

elif a[i] == 3:

count3 += 1

elif a[i] == 4:

count4 += 1

smallest = min(count1,count2,count3,count4)

biggest = max(count1,count2,count3,count4)

diff = biggest - smallest

if a[10] == 1:

if diff == 3:

return True

else:

return False

elif a[10] == 2:

if diff == 2:

return True

else:

return False

elif a[10] == 3:

if diff == 4:

return True

else:

return False

elif a[10] == 4:

if diff == 1:

return True

else:

return False

上述函数,阅读起来难度不大,需要说明几个函数。abs是绝对值函数,在第八题中出现过,用来判断答案选项是否相邻。由于我们用1234来代替ABCD,因此,只要两个选项相邻,它们的绝对值之差就是1。min函数为求最小值函数,例如min(1,2,3)= 1。相对的,max函数则是求最大值函数。

好了,下面编写主函数。由于我们需要使用随机函数,所以在程序里加入这样一句话:

import random

‍这样就加载了random模块,可以使用random自带的各种函数。

def main():

found = False

while (found == False):

answer = []

for i in range(11):

answer.append(random.randrange(1,5))

if (judge2(answer) == True) and (judge3(answer) == True) and (judge4(answer) == True)\

and (judge5(answer) == True) and (judge6(answer) == True) and (judge7(answer) == True)\

and (judge8(answer) == True) and (judge9(answer) == True) and (judge10(answer) == True):

print(answer[1:11])

found = True

‍我们首先设置一个标识found,用来标识是否找到了正确答案,将其初始值设置为假(False)。while语句则是一个循环,如果没有找到的话,也就是说found == False,我们就不断循环。

随后,我们定义一个空数组answer,再用随机函数random.randrange(1,5)随机生成1-4之间的整数(也就是各个题目的答案)。使用for语句(这也是一个循环体)调用11次,生成11个选项(我们只需要用到后面10个)。

下面,我们将生成的答案,代入上面编写的9个函数里,进行检验。如果九个函数都满足条件(都返回True),我们的程序就结束了,并打印结果:print(answer[1:11]),同时把found标识为True,结束循环。由于答案总是存在的,所以循环一定会结束,这个方法跟暴力破解法差不多。只不过,使用暴力破解的话,需要对每一个可能的答案都进行测试,这样就需要写十重循环,看起来很繁琐。对于只需要找出一个答案的题目来说,使用随机法也足够了。

最后,我们再加上一句,完成程序:

main( )

这个语句调用主函数,主函数再调用相应的子函数,开始计算。由于现在计算机一秒钟可以进行十亿次计算,运算起来还是很快的。虽然python写的程序速度不如其他语言写的程序,但是等待了几秒后,还是出来了答案:

最后一行的[2,3,1,3,1,3,4,1,2,1]即是算出的结果,对应答案为BCACACDABA。

整图如下:

仔细查看整图,你可以体会出题人满满的恶意。为了应对未来的恶意挑战,你是不是应该感觉买本python书学起来呢。另外,我在网上查了查,有人提供了一份手写的答案,好几页,估计没几个人能看懂。还是用计算机解决重复劳动更安逸。

PS:最近有三个省市的小学课本已经加入了python课程,python编程席卷全国,也只是迟早的事。赶紧学吧,这样可以给孩子辅导作业。不学的话,小心被小学生鄙视噢。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180303G0W3UJ00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券