一份逻辑推理题的程序求解(纯属自娱自乐)
闲来无聊,看到 QQ空间上转载了一份变态推理题的,至少表示我看了十多分钟无处下手,认识的人中有大神居然真的做出来了。。。我不知道他是们那么做的,不过作为编程爱好者,我第一时间想到的是写个程序把答案找出来(不要吐槽)。于是我就动手了。。。不过,这个简单的还是花了我2个小时。。。
下面,先给大家看一看题目:
这十道题可谓丧心病狂,因为题目答案高度关联,居然出现了多少个A多少个B这样的选项,不做完全卷根本不知道每道题对错。。。我简单分析了一下,也只看出切入点大概在第七八九题和第二题的样子吧,简单的分析就可以大概知道答案整体的A选项数量,然后慢慢推,不过期间貌似也有好几步要靠试才能试出来。。。。
我承认我没有那推理能力,所以我想到了用一个小程序。。。十层循环遍历所有可能方案,然后用十层判断过滤方案,找到正确答案。
我的程序是用python写的,用0 1 2 3 来代表ABCD,每层循环变量的取值就代表了每道题的答案,构建一个当前方案t_result,比如i0 = 1 i1 = 0 就对应着第一题选B第二题选A。遍历十层的效果就是这样,
考虑到可能结果不止一个,我另外定义一个叫final_result的列表来保存所有符合要求的结果。
然后是按照题目要求进行规则判断,即进行十层(实际只有九层)if判断来遍历所有方案,得到符合要求的结果,一旦某一环节不符合就由continue语句跳出当前结果,进入下一轮,一直留到最后的就是正确结果了!
每道题具体分析与对应的代码如下:
1、第一个答案是A的题目是哪个?()
A、1 B、2 C、3 D、4
对第一道题的约束条件,我使用了for循环找到当前方案中第一个答案是A的题目序号,并与第一题答案对应的题目进行比较,选项一致的才能通过进入下一层过滤。由于观察发现ABCD选项答案对应的index序号且与ABCD的表示相等,所以最后的判断可以直接简化为比较答案序号与答案,如:当前方案第一题选A,那么第一道选A的题正好就是第一题,通过。
#规则一:第一个答案是A的结果
index = 0
for each_answer in t_result:
if each_answer == 0:
break
else:
if index < 4:
index+=1
#print '第一个答案是A的题是:',index+1
if not (t_result[index] == index):
#print '不符合第一条'
continue
else:
#规则二:唯一具有两个相同答案的问题:……
2、唯一两个具有连续相同答案的问题是:()
A、5,6 B、6,7 C、7,.8 D、8,9
对于第二题,要求找到唯一两个连续相同答案,所以我另写了一个方法find_same_answer,来得到有连续相同答案的个数。
#寻找有相同答案问题的方法
def find_same_answer(result):
count = 0
for i in range(9):
if result[i] == result[i+1]:
count += 1
return count
只有连续相同答案个数为1,并且它的位置正好出先在当前方案答案对应的位置,才能通过。如:当前方案选B,find_same_answer返回1,而第6,7题结果恰好相等,且方案通过。
#规则二:唯一具有两个连续相同答案的问题:
if not ((find_same_answer(t_result) == 1) and ((t_result[1] == 0 and t_result[4] == t_result[5]) or \
(t_result[1] == 1 and t_result[5] == t_result[6]) or \
(t_result[1] == 2 and t_result[6] == t_result[7]) or \
(t_result[1] == 3 and t_result[7] == t_result[8]))):
#print '不符合第二条'
continue
else:
#规则三:本问题与哪个问题答案相同……
3、本问题答案与那一个问题答案相同?()
A、4 B、9 C、8 D、2
这题相对容易些,只要判断第三题答案是否与选项对应的题目答案相同即可。、
#规则三:本问题与哪个问题答案相同
if not ((t_result[2] == 0 and t_result[2] == t_result[3]) or\
(t_result[2] == 1 and t_result[2] == t_result[8]) or\
(t_result[2] == 2 and t_result[2] == t_result[7]) or\
(t_result[2] == 3 and t_result[2] == t_result[1]) ):
#print '不符合第三条'
continue
else:
#规则四:答案是A的个数……
4、答案是A的问题个数是:()
A、5 B、4 C、3 D、2
为了搞定这道题并方便后面的判断,我又写了一个函数X_count,来计算当前方案中答案为X的题目个数:
#计算答案是X的个数的方法:
def X_count(result,x):
count = 0
for each in result:
if each == x:
count += 1
return count
如果对应的选项答案符合,就可以通过。
#规则四:答案是A的个数
if not ((t_result[3] == 0 and X_count(t_result,0) == 5) or\
(t_result[3] == 1 and X_count(t_result,0) == 4) or\
(t_result[3] == 2 and X_count(t_result,0) == 3) or\
(t_result[3] == 3 and X_count(t_result,0) == 2) ):
#print '不符合第四条'
continue
else:
#规则五:本问题与哪个问题答案相同……
5、本问题答案与那一道题问题答案相同?()
A、1 B、2 C、3 D、4
这道题也好说,只要判断选项是否成立即可
#规则五:本问题与哪个问题答案相同
if not ((t_result[4] == 0 and t_result[4] == t_result[0]) or\
(t_result[4] == 1 and t_result[4] == t_result[1]) or\
(t_result[4] == 2 and t_result[4] == t_result[2]) or\
(t_result[4] == 3 and t_result[4] == t_result[3]) ):
#print '不符合第五条'
continue
else:
#规则六:选A问题个数与选什么的问题个数相同……
6、答案选A的问题个数与答案选胜的的问题个数相等?()
A、无 B、C C、C D、D
借用X_count方法,道题的判断不难实现,遇上一题类似,只不过对于选项A、无,要麻烦一些,确保选A的个数与选BCD的个数都不相同。
#规则六:选A问题个数与选什么的问题个数相同
if not ((t_result[5] == 0 and not((X_count(t_result,0) == X_count(t_result,1)) or\
(X_count(t_result,0) == X_count(t_result,2)) or\
(X_count(t_result,0) == X_count(t_result,3)))) or\
(t_result[5] == 1 and X_count(t_result,0) == X_count(t_result,2)) or\
(t_result[5] == 2 and X_count(t_result,0) == X_count(t_result,2)) or\
(t_result[5] == 1 and X_count(t_result,0) == X_count(t_result,3)) ):
#print '不符合第六条'
continue
else:
#规则七:与下一题相差……
7、按照字母顺序,本题答案与下一题相差()(A与B间,B与A间都差1)
A、3 B、2 C、1 D、0
这道题如果直接按照题目描述,判断条件会很麻烦,还涉及到求绝对值,所以我进行了简单的分析,发现第7题选A的话下一题(第8题)只能选D,选B的话下一题只能选D,选C的话下一题可选A或D,选D的话下一题也只能选D,所以得到这道题的判断条件:
#规则七:与下一题相差
if not ((t_result[6] == 0 and t_result[7] == 3) or\
(t_result[6] == 1 and t_result[7] == 3) or\
(t_result[6] == 2 and (t_result[7] == 3 or t_result[7] == 1))or\
(t_result[6] == 3 and t_result[7] == 3) ):
#print '不符合第七条'
continue
else:
#规则八、九:十道题中元音题数目……
8、十道题中答案为元音的题目数为()
A、0 B、1 C、2 D、3
9、是道题中答案为辅音的题目数为()
A、是合数 B、是质数 C、<= 5 D、是平方数
这两道题虽然看起来很吓人,不过其实如果稍加分析的话,可以排除很多答案,完全可以作为解整份题的突破点。
首先,元音只有A,辅音为BCD。第八题决定了选元音答案(即A)的数只能为0 1 2 3 ,那么第九题中辅音答案(BCD)个数也只能为7 8 9 10,不可能小于等于5,第九题C排除,而这四个数中8 9 10为合数,9又为平方数,所以第九题选D那么A也正确,因此第九题D也排除,又因为第一题就决定了题目中有A选项,所以第八题不选A而辅音数为7 或 8,所以这两道题只剩两种情况可选:辅音数为7,8选D 9选B;或者辅音数为8,8选C 9选A。因此判断条件也就简化了:
#规则八、九:十道题中元音题数目
if not ((t_result[7] == 2 and X_count(t_result,0) == 2) or\
(t_result[7] == 3 and X_count(t_result,0) == 3)):
#print '不符合第八九条'
continue
else:
print '得到了一个结果!'
10、本题答案为()
A、A B、B C、C D、D
这道题明显属于打酱油,答案完全取决于之前的九道题目,不管选什么,只要使得之前的九道题目都合理就好,因此不需要再加判断。
好了,上面我们写了那么多,终于可以遍历并过滤了所有4^10种方案,得到合理的结果,所以我们还差最后一步,那就是打印的显示出最终答案。所以,我有的一些了一个打印函数,把列表里的数字改为祖母选项打印出来:
#打印结果的方法
def print_result(result):
new = []
for each in result:
if each == 0:
new.append('A')
if each == 1:
new.append('B')
if each == 2:
new.append('C')
if each == 3:
new.append('D')
print new
最后调用一下这个方法,并把结果存到final_result列表里:
print '得到了一个结果!'
print_result(t_result)
final_result.append(t_result)
最后可以再打印一下final_result,看看所有结果:
print 'final_result',final_result
Ok,大功告成,完整的程序我附在了附件里,按F5运行,就得到了打印出的结果:
于是,借助计算机,我们费了很少的脑力解出了一份让无数人头疼的逻辑推理题。现在,我们拍着胸脯向周围的小伙伴们说:这十道题有唯一的答案A, C, B, C, A, C, D, D, B, A 了!
乔布斯说过,计算机是人类思想的自行车,学会用计算机是一门很重要的技能,它可以让普通人也有能力做到天才能做的事,甚至完成的更好。所以,下次在生活中遇到令人头疼的难题时,不妨开拓一下思路,想想可不可以用计算机程序来解决,可能就会事半功倍呦!