热点 其他

2018年刑侦推理试题解答

金色葡萄 发表于  2018-03-05 16:46

2018年刑侦推理试题:

此题一出,吓退了一大批原本还对刑侦专业跃跃欲试的各路英雄好汉。这组题目应该如何入手呢?还是先给答案,再来细说解题思路好了。

答案

解题思路

以此题为例,做一个简单的python小教程。

提取"第x题的答案"

首先,观察到题目中经常出现的说法是:“第x题的答案”怎样怎样,那么常用的一个过程就是要提取第x题的答案。

在python中可以使用的一个数据结构叫作列表list。列表是使用[ ]括起来的一些元素,要提取其中的内容,用列表名[序号]就可以提取了。比如

In [1]:

sample=[0.1, 1.2, 2.3, 3.4, 4.5] # “#”号后面的部分是注释,不会进入计算,我后面会在程序中使用注释说明
sample[2] # 注意python的计数是从第0项开始的,所以第2项是2.3而不是1.2

Out[1]:

2.3

如果用数字0、1、2、3来表示ABCD的话,就可以把所有的答案放进一个列表里。提取某一题的答案,就是提取列表中的第几项。注意python的列表是从第0项开始计数的,为了读题中不引起混淆, 我将列表的第0项设定成空项.

In [2]:

# 举例,假设第1题到第5题的答案分别是AABDC,用0、1、2、3来表示ABCD
sample_answer=[_, 0, 0, 1, 3, 2]
# 提取第3题的答案
sample_answer[3]

Out[2]:

1

第1题

这道题的答案是:

  • A.A
  • B.B
  • C.C
  • D.D

题目中没有给出限定,所以暂时先不管它。

第2题

第5题的答案是:

  • A.C
  • B.D
  • C.A
  • D.B

在第2题里,如何描述A->C,B->D,C->A,D->B的映射关系呢?可以用一个python数据结构,叫作字典。字典是用{ }括起来的一组元素,每一个元素里有一个key:value的数据对,表示从key到value的映射。

要表示A->C,B->D,C->A,D->B的映射关系,可以建立一个字典:

In [3]:

a2_dict={0:2,# A.C
             1:3,# B.D
             2:0,# C.A
             3:2}# D.B
a2_dict[1] # 字典内容的提取,是使用字典名[key],就可以提取出value

Out[3]:

3

用0,1,2,3代表ABCD

  • 如果第二题选A,那么就是说第5题的答案是C,也就是a2_dict[0]的值2
  • 如果第二题选B,那么就是说第5题的答案是D,也就是a2_dict[1]的值3
  • 如果第二题选C,那么就是说第5题的答案是A,也就是a2_dict[2]的值0
  • 如果第二题选D,那么就是说第5题的答案是B,也就是a2_dict[3]的值2

假定我们已经知道了所有的答案,放在answer这个列表里,那么第2题的答案是answer[2],第5题的答案是answer[5],那么第2题的答案所对应的值就是a2_dict[ answer[2] ],判断第2题是不是做对了, 就要看

a2_dict[ answer[2] ]==answer[5]

是真还是假。

我将这个判断过程写成一个“函数”,这个函数负责看第2题是否做对了。Python的函数定义是用

def 函数名(参数表):
     空4格写函数内容
     return 返回结果

In [4]:

def test2(answer):
     a2_dict={0:2,# A.C
                  1:3,# B.D
                  2:0,# C.A
                  3:2}# D.B
     return a2_dict[ answer[2] ]==answer[5]

In [5]:

# 一般写好一个函数,应当测试一下是否写对了。
print(test2([_,1,2,3,4,5])) # 应当为假
print(test2([_,1,0,3,4,2])) # 应当为真,假定第2题的答案是0,对应第5题的答案是2

False True

第3题

以下选项中哪一题的答案与其他三项不同:

  • A. 第3题
  • B. 第6题
  • C. 第2题
  • D. 第4题

当然我们可以去一个一个比对,但python中对列表有一个简单的判断命令叫in,如果元素在这个列表中,那么in命令就返回真,否则为假。

如果把第3题、第6题、第2题、第4题的答案放在一个列表中,那么有

a3_list=[ answer[3], answer[6], answer[2], answer[4] ]

  • 如果选A,那么就看answer[3] in [ answer[6], answer[2], answer[4] ]是否为假
  • 如果选B,那么就看answer[6] in [ answer[3], answer[2], answer[4] ]是否为假
  • 如果选C,那么就看answer[2] in [ answer[3], answer[6], answer[4] ]是否为假
  • 如果选D,那么就看answer[4] in [ answer[3], answer[6], answer[2] ]是否为假

为了产生一个没有某一项的列表,我们可以将列表中的某一项pop出去,剩下的a3_list。所以:

In [6]:

def test3(answer):
     a3_list=[answer[3], answer[6], answer[2], answer[4]]
     # 先提取出来要检查的项
     refer=a3_list[ answer[3] ]
     # 在把这一项从列表里pop掉
     a3_list.pop( answer[3] )

     # 看看要检查的项是否在剩下的列表中
     return not(refer in a3_list )

In [7]:

print(test3([_,1,2,3,4,5,6])) # 应当是真
print(test3([_,1,0,0,0,5,0])) # 应当是假

True False

第4题

以下选项中哪两题的答案相同:

  • A. 第1,5题
  • B. 第2,7题
  • C. 第1,9题
  • D. 第6,10题

这道题其实和第2题的思路一样,建立一个映射关系的字典,

a4_dict={0:[1,5],
             1:[2,7],
             2:[1,9],
             3:[6,10]}

然后验证题目中所说的东西即可。

  • 如果选A,那么看a4_dict[0]中的两项[1, 5],
    • 其中1是a4_dict[0]这个列表的第0项,第1题的答案就是answer[ a4_dict[0][0] ]
    • 其中5是a4_dict[0]这个列表的第1项,第5题的答案就是answer[ a4_dict[0][1] ]
  • 如果选B, 那么看a4_dict[1]中的两项[2, 7],
    • 其中2是a4_dict[0]这个列表的第0项,第2题的答案就是answer[ a4_dict[0][0] ]
    • 其中7是a4_dict[0]这个列表的第1项,第7题的答案就是answer[ a4_dict[0][1] ]

In [8]:

def test4(answer):
     a4_dict={0:[1,5],
                  1:[2,7],
                  2:[1,9],
                  3:[6,10]}
     return answer[ a4_dict[ answer[4] ][0]] == answer[ a4_dict[ answer[4] ][1]]

In [9]:

print( test4([_,1,2,3,0,5,6,7]) ) # 应当为假
print( test4([_,1,2,3,0,1,6,7]) ) # 应当为真

False True

第5题

以下选项中哪一题的答案与本题相同

  • A. 第8题
  • B. 第4题
  • C. 第9题
  • D. 第7题

想必已经越来越熟练了,先建立一个映射关系字典:

a5_dict={0:8,
             1:4,
             2:9,
             3:7}

本题的答案当然就是answer[5],

  • 如果选A,那么就是看第8题的答案,也就是answer[ a5_dict[0] ]
  • 如果选B,那么就是看第4题的答案,也就是answer[ a5_dict[1] ]

In [10]:

def test5(answer):
     a5_dict={0:8,
                  1:4,
                  2:9,
                  3:7}
     return answer[5] == answer[ a5_dict[ answer[5] ] ]

In [11]:

print(test5([_,1,2,3,4,0,6,7,0])) # 应当为真, 第5题的答案与第8题都是A print(test5([_,1,2,3,4,1,6,7,0])) # 应当为假, 第5题的答案选的是B, 但与第4题的答案不同

True False

第6题

以下选项中哪两题的答案与第8题相同

  • A. 第[2,4]题
  • B. 第[1,6]题
  • C. 第[3,10]题
  • D. 第[5,9]题

出题人已经开始重复自己了,这道题和第4题区别不大。

建立一个映射字典:

a6_dict={0:[2,4],
             1:[1,6],
             2:[3,10],
             3:[5,9]}

第8题的答案当然是answer[8],

  • 如果选A,那么answer[8]应当等于a6_dict[0]中的第2、4题的答案,
    • 其中2是a6_dict[0][0],第2题的答案也就是answer[a6_dict[0][0]]
    • 其中4是a6_dict[0][1],第4题的答案也就是answer[a6_dict[0][1]]

In [12]:

def test6(answer):
     a6_dict={0:[2,4],
                  1:[1,6],
                  2:[3,10],
                  3:[5,9]}
     return (answer[8] == answer[a6_dict[ answer[6] ][0]] == answer[a6_dict[ answer[6] ][1]] )

In [13]:

print(test6([_,1,0,3,0,5,0,7,0])) # 应当为真,第6题选了A,第8题的答案是A,第2、4题也选的是A print(test6([_,1,0,3,0,5,1,7,2])) # 应当为假,第6题选了B,第8题的答案是C,第1、6题选的不是C

True False

第7题

此十道题中,被选中次数最少的选项字母为:

  • A. C
  • B. B
  • C. A
  • D. D

先建立个映射字典:

a7_dict={0:2,
             1:1,
             2:0,
             3:3}

这道题开始有新花样了,“选中次数最少的字母”,那就要统计一下每个字母都被选中了多少次。

列表里有个.count(value)方法,可以统计出value在列表中出现了多少次。所以:

  • 字母A在答案中出现的次数=answer.count(0)
  • 字母B在答案中出现的次数=answer.count(1)
  • 字母C在答案中出现的次数=answer.count(2)
  • 字母D在答案中出现的次数=answer.count(3)

最少,可以用min(列表)来表示,那么各个字母出现次数中最少的数量就是:

min( [answer.count(0),answer.count(1),answer.count(2),answer.count(3) ] )

In [14]:

def test7(answer):
     a7_dict={0:2,
                  1:1,
                  2:0,
                  3:3}
     return answer.count(a7_dict[answer[7]]) == min( [answer.count(0),answer.count(1),answer.count(2),answer.count(3) ] )

In [15]:

print(test7(["",1,2,3,4,5,6,0,8,9,10])) # 应当为真,这里面所有的字母都只出现了1次 print(test7(["",1,2,3,4,5,6,1,8,9,10])) # 应当为假,1出现了两次,比其他都多

True False

第8题

以下选项中,哪一题的答案与第1题的答案在字母中不相邻:

  • A. 第7题
  • B. 第5题
  • C. 第2题
  • D. 第10题

先建个映射关系:

a8_dict={0:7,
             1:5,
             2:2,
             3:10}

这道题说的是字母不相邻,我们已经用数字0123表示字母ABCD了,那么相邻,就是相差为±1,或者是减完以后平方=1。Python用**表示平方, 用!=来表示不等于

第一题的答案是answer[1],

  • 如果选A,那么有(answer[1]-answer[7])**2 !=1
  • 如果选B,那么有(answer[1]-answer[5])**2 !=1

In [16]:

def test8(answer):
     a8_dict={0:7,
                  1:5,
                  2:2,
                  3:10}
     return (answer[1]-answer[ a8_dict[answer[8]] ])**2 !=1

In [17]:

print(test8([_,1,2,3,4,5,6,7,0])) #应当为真,第8题选了A,第1题的答案是1,与第7题的答案7不相邻 print(test8([_,4,2,3,4,5,6,7,1])) #应当为假,第8题选了B,第1题的答案是4,与第5题的答案5相邻

True False

第9题

已知“第1题与第6题的答案相同”与“第x题与第5题的答案相同”的真假性相反,那么X为:

  • A. 第6题
  • B. 第10题
  • C. 第2题
  • D. 第9题

建立映射关系:

a9_dict={0:6,
             1:10,
             2:2,
             3:9}

“第1题与第6题的答案相同”,这句话的逻辑值是answer[1]==answer[6]

真假性相反用not表示

  • 如果选A,那么X=6,第6题与第5题的答案相同的逻辑值是answer[6]==answer[5],那么not(answer[6]==answer[5])==(answer[1]==answer[6])
  • 如果选B,那么X=10,第10题与第5题的答案相同的逻辑值是answer[10]==answer[5],那么not(answer[10]==answer[5])==(answer[1]==answer[6])

In [18]:

def test9(answer):
     a9_dict={0:6,
                  1:10,
                  2:2,
                  3:9}
     return not(answer[a9_dict[answer[9]]]==answer[5])==(answer[1]==answer[6])

In [19]:

print(test9([_,1,2,3,4,5,6,7,8,0,10])) # 应当为假,第9题选了A,第1题与第6题不同,那么第6题应该和第5题相同才是真假性相反, 这里不满足
print(test9([_,1,2,3,4,6,6,7,8,0,10])) # 应当为真,第9题选了A,第1题与第6题不同,那么第6题应该和第5题相同才是真假性相反

False True

第10题

在此10道题中,ABCD四个字母出现此处最多与最少者的差为:

  • A.3
  • B.2
  • C.4
  • D.1

我们已经胜利在望,发现出题人也没有太多花招了。这题和前面第7题很相似,只是第7题计算了最少,这里要计算最多了.

既然最少可以用min(列表)来表示,那么各个字母出现次数中最少的数量为: min( [answer.count(0),answer.count(1),answer.count(2),answer.count(3) ] )

最多当然用max(列表)来表示,于是各个字母出现次数中最多的数量为: max( [answer.count(0),answer.count(1),answer.count(2),answer.count(3) ] )

建立映射关系:

a10_dict={0:3,
               1:2,
               2:4,
               3:1}

In [20]:

def test10(answer):
     a10_dict={0:3,
                    1:2,
                    2:4,
                    3:1}
     answer_count_list=[answer.count(0),answer.count(1),answer.count(2),answer.count(3) ]
     diff= max( answer_count_list ) - min( answer_count_list )
     return a10_dict[answer[10]]==diff

In [21]:

print(test10(["",1,2,3,4,5,6,7,8,9,0])) #应当为假,第10题选了A,最大最小要相差3,但每个字母只出现了一次, 最大最小相差是0
print(test10(["",1,1,1,4,5,6,7,8,9,0])) #应当为真,第10题选了A,最大最小要相差3,选1出现了3次,选2、3都没有,最大最小相差是3

False True

穷举

现在已经把上面10道题的判定函数都写好了。要求解的答案,就是要令上述10道题的判别函数都返回为真。

10道单选题,每道题可能有4种答案,一共的可能性是

410=1048576

看起来也不大,所以就穷举好了。最简单的方式就是for循环。虽然也还有其他生成穷举序列的方法,但本着“想到解法就先实现出来看看”的敏捷开发思路,先用for循环吧。

所谓for循环,就是让一个变量依次取得列表中的所有值

In [22]:

choice=[0,1,2,3]
test1=True
answer=[]
for a1 in choice:
     for a2 in choice:
          for a3 in choice:
               for a4 in choice:
                    for a5 in choice:
                         for a6 in choice:
                              for a7 in choice:
                                   for a8 in choice:
                                        for a9 in choice:
                                             for a10 in choice:
                                                  answer=["",a1,a2,a3,a4,a5,a6,a7,a8,a9,a10]
                                                  if (True==
                                                      test1==
                                                      test2(answer)==
                                                      test3(answer)==
                                                      test4(answer)==
                                                      test5(answer)==
                                                      test6(answer)==
                                                      test7(answer)==
                                                      test8(answer)==
                                                      test9(answer)==
                                                      test10(answer)):
                                                      print(answer)
print("That's all")

['', 1, 2, 0, 2, 0, 2, 3, 0, 1, 0]
That's all

转载自金色葡萄个人主页,已获得授权。(编辑:Steed

热门评论

  • 2018-03-05 17:46 毛骡 金属材料学博士

    尼玛看了半天,结果是个穷举。

    (╯‵□′)╯︵┻━┻

    用个有点技术含量的嘛,递归怎么样。

    [19] 评论
  • 2018-03-05 18:09 combok

    人工解题思路:以第九题作突破点,

    设情况1为真,前真后假。。。。。。

    设情况2为真,前假后真。。。。。。

    其实答案很好推

    [10] 评论
  • 2018-03-05 17:50 AI油泳的鹰 勘查技术与工程专业,编程爱好者

    这排版,是mathematica终端和python代码的混排么

    [3] 评论

显示所有评论

全部评论(33)
  • 1楼
    2018-03-05 17:46 毛骡 金属材料学博士

    尼玛看了半天,结果是个穷举。

    (╯‵□′)╯︵┻━┻

    用个有点技术含量的嘛,递归怎么样。

    [19] 评论
  • 2楼
    2018-03-05 17:50 AI油泳的鹰 勘查技术与工程专业,编程爱好者

    这排版,是mathematica终端和python代码的混排么

    [3] 评论
  • 3楼
    2018-03-05 18:09 combok

    人工解题思路:以第九题作突破点,

    设情况1为真,前真后假。。。。。。

    设情况2为真,前假后真。。。。。。

    其实答案很好推

    [10] 评论
  • 4楼
    2018-03-05 19:12 combok

    解:设题9前真后假

    →1=6 (6 10 2 9 )中三个=5

    由于2无法=5

    →9=c,5=c=6 10 9

    由6=c→1=c 2=a

    如果前面的都为真,那么4答案不止一个

    所以9不是前真后假

    宗上总推导得出 题9前假后真

    再解:由题9前假后真得出

    →1不等于6, 6 10 2 9中只有一个等于5

    由于2不可能等于5, 9不可能等于5

    所以得出6 10其中一个等于5即是6不等于10 题4答案不可能为d

    上班中,下班待续

    [1] 评论
  • 5楼
    2018-03-05 21:10 壳啊壳啊壳啊壳

    结论一 5不等于9

    结论二 1不等于6

    结论三 2等于6

    然后就都出来了

    都是反证不成立

    乍一看9显眼,但其实第5、6、9题一起看最快得出结论一

    [0] 评论
  • 6楼
    2018-03-06 02:12 combok
    引用@壳啊壳啊壳啊壳 的话:结论一 5不等于9结论二 1不等于6结论三 2等于6然后就都出来了都是反证不成立乍一看9显眼,但其实第5、6、9题一起看最快得出结论一

    你的结论1其实还是需要建立在判断了9真假性这基础。除了9其他都是确定的已知条件

    题9前真后假直接推导5=9=c(虽然后段推导会证明这方向不成立)光从5 6 9无法推进

    真假性相反意思是存在2种情况呢

    [0] 评论
  • 7楼
    2018-03-06 09:57 壳啊壳啊壳啊壳
    引用@combok 的话:你的结论1其实还是需要建立在判断了9真假性这基础。除了9其他都是确定的已知条件题9前真后假直接推导5=9=c(虽然后段推导会证明这方向不成立)光从5 6 9无法推进真假性相反意思是存在2种情况呢

    嗯嗯,殊途同归。我的意思是因为5、6、9显眼,所以如果假设5=9=C,则2=A,那么9的真假也就知道了,我是感觉快一点,本质当然都一样啦

    [0] 评论
  • 8楼
    2018-03-06 11:37 后石器时代
    引用@毛骡 的话:尼玛看了半天,结果是个穷举。(╯‵□′)╯︵┻━┻用个有点技术含量的嘛,递归怎么样。

    编程的就用穷举,这才是编程的真谛,让硬件出力,人不出力

    [0] 评论
  • 9楼
    2018-03-06 15:16 天降龙虾

    柯南:阿笠博士,能不能给俺造个会编程的机器小哀?????

    [1] 评论
  • 10楼
    2018-03-06 16:03 汉尼拔wang

    还以为是逻辑训练的文章,结果是编程~~

    [0] 评论
  • 11楼
    2018-03-06 16:33 毛骡 金属材料学博士
    引用@后石器时代 的话:编程的就用穷举,这才是编程的真谛,让硬件出力,人不出力

    AI也是编程出来的,但是不是穷举……穷举不出来。

    [0] 评论
  • 12楼
    2018-03-07 10:35 Big.D 果壳实验室主任

    就想知道这个题怎么出出来的……

    [2] 评论
  • 13楼
    2018-03-07 12:25 金色葡萄 眼科学博士
    引用@AI油泳的鹰 的话:这排版,是mathematica终端和python代码的混排么

    用jupyter写, 然后nikola生成静态网页. 用来在github上写blog非常方便. 推荐一下

    [0] 评论
  • 14楼
    2018-03-07 12:27 金色葡萄 眼科学博士
    引用@毛骡 的话:尼玛看了半天,结果是个穷举。(╯‵□′)╯︵┻━┻用个有点技术含量的嘛,递归怎么样。

    有人用整数线性规划来做, 我也打算试试把真值判断写成softmax然后再反向传递

    [0] 评论
  • 15楼
    2018-03-07 12:38 金色葡萄 眼科学博士

    现在真是疏于打理啊, 一长串绿果果的头像.

    [2] 评论
  • 16楼
    2018-03-08 13:48 后石器时代
    引用@毛骡 的话:AI也是编程出来的,但是不是穷举……穷举不出来。

    AI的也用的穷举方式,只是不全部穷举,是有一定深度的,当穷举到一定数量后就停止了,当然了穷举也是有优先顺序的。

    [0] 评论
  • 17楼
    2018-03-09 21:24 第一步

    有多少人工就有多少智能啊

    [0] 评论
  • 18楼
    2018-03-10 09:11 岳雪狐狸

    我是花了2个小时,一个一个推算,最后发现错了3个??????算了反正我不考刑侦科(30来了怎么考),直接看答案,额,懂了。

    [1] 评论
  • 19楼
    2018-03-10 11:56 兴国儒生

    我看过网上有人也用C写了个程序,建议大家也看看。

    [0] 评论
  • 20楼
    2018-03-10 12:44 echooool

    求c语言的答案

    [0] 评论
  • 21楼
    2018-03-10 13:31 Forever丶Coke星星

    看得头疼。。。

    [0] 评论
  • 22楼
    2018-03-11 02:00 blue小李小子

    第2题跟第3题是因果点,能很快排除第二题的A选项,BD选项也不能排除,所以说人工智能何时才能理清因果关系呢,很关键

    [0] 评论
  • 23楼
    2018-03-11 13:13 Proton

    一长串 for 和 if 看着真蛋疼……………………

    请改成这样


    import itertools

    tests = [test2, test3, test4, test5, test6, test7, test8, test9, test10]

    for answer in itertools.product([''], *[range(4)] * 10):

    if all(t(answer) for t in tests):

    print(answer)

    [2] 评论
  • 24楼
    2018-03-12 16:10 纳斯卡_22898

    表示想用C++试试。

    [0] 评论
  • 25楼
    2018-03-13 16:32 秦蛋

    mathematica大法好

    虽然有部分竟然看不懂

    这套题用形式逻辑也可以做出来

    [0] 评论
  • 26楼
    2018-03-14 17:36 右京样一

    竟然上首页了……

    感觉金葡君再一次表现出了一贯的对静态、孤立、暴力求解的崇尚。

    [1] 评论
  • 27楼
    2018-03-16 01:54 简尚风拾
    引用文章内容:104857

    这是编程辅导课吗??

    [0] 评论
  • 28楼
    2018-03-16 12:21 实力开~

    厉害了

    [0] 评论
  • 29楼
    2018-03-16 16:36 kakawox

    人工穷举:5题分别取值a.b.c.d计算,当5=a时有唯一解,5=b.c.d时均出现矛盾

    [0] 评论
  • 30楼
    2018-03-18 01:02 沃尔夫-拉叶104

    先存着,等天亮了把这个分享给大佬

    [0] 评论

显示所有评论

你的评论

登录 发表评论

金色葡萄
金色葡萄 眼科学博士

作者的其他文章

更多科研事,扫码早知道

关于我们 加入果壳 媒体报道 帮助中心 果壳活动 免责声明 联系我们 移动版 移动应用

©果壳网    京ICP证100430号    京网文[2015] 0609-239号    新出发京零字东150005号     京公网安备11010502007133号

违法和不良信息举报邮箱:jubao@guokr.com    举报电话:13691127034    网上有害信息举报专区    儿童色情信息举报专区