python逻辑题(以下10道选择题有唯一答案,请编写自定义函数judge遍历答案列表并汇报正确答案)
1.题目、代码及答案演示
-
代码: 逻辑题
-
说明
:个人没用过Jupyter Notebook
,题目也只是为了统计执行时间,就找了一个计时装饰器将遍历并判断逻辑的函数装饰了下,就可以看出运行的粗略时间了(一秒多一点)。 -
题目要求:以下10道选择题有唯一答案,请编写自定义函数judge遍历答案列表并汇报正确答案。可使用内置或第三方数据类型,但judge函数的参数只能有1个。使用Jupyter Notebook的%%time魔术方法统计执行时间,控制在3秒内。
-
答案演示:
2.思路及要点说明
怎么说呢,这题的实现确实不难,甚至枯燥。
但是却让我思考了下人类大脑与借助计算机完成大量重复判断的思维的根本性差异!
为什么这么说呢?
首先,拿到这题,还没看题干,就会先像解决十几年学习生活中的文化课的选择题一样,一道一道地做了起来。
当一题没有思路后,会先放着,坐下一题。
最多看到后面第二三题慢慢发现,这十道题之间不少会有关联性。
而当经过长达一个多小时的人脑判断十道题目的答案后(并得到了正确答案),开始考虑实现的时候,十分想
打自己的脸
!!
站在计算机的角度
,我送入判断函数的那个参数必然是答案,也就是先用嵌套十层的for
循环生成的结果列表。
我先将4^10
个答案列表做出来,再将这些列表放到每一题中去过滤,发现一个答案列表不符合某题答案的过滤一下。每一个包含判断的小题是一个不同形状的过滤网
,层层过滤即可。
真実(しんじつ)はいつもひとつ!
我们就得到了唯一的真相~ B C A C A C D A B A
代码在我仓库,希望使用的人能够遵循开源协议,维护开源社区
最重要的是,能给博客和仓库一个小星星~MUA
下面举一些例子说明,如果还有问题请留评论区。
- 从第三题入手
原因是因为,一下就可以过滤掉极大一部分三题不相同
的答案列表,减轻后面的判断数量;
以下为判断:
def judge_3(res):
'''第三题 判断3624题有三个相同一个不同
第三题选A 3 624
第三题选B 6 324
第三题选C 2 364
第三题选D 4 362
'''
if res[2] == 1:
if res[5] == res[1] == res[3] and res[2] != res[5]:
judge_6(res)
elif res[2] == 2:
if res[2] == res[1] == res[3] and res[5] != res[2]:
judge_6(res)
elif res[2] == 3:
if res[2] == res[5] == res[3] and res[1] != res[2]:
judge_6(res)
elif res[2] == 4:
if res[2] == res[5] == res[1] and res[3] != res[2]:
judge_6(res)
外层的if判断每一题都有,判断当此题分别选ABCD的时候,相关联题目的逻辑;
在最开始,我们将ABCD映射为1234,通过判断过滤后最后的答案再映射回来即可;
当第三题选A,即res[2] == 1
时,这里res
就是生成的所有可能的答案数组;
通过分析,可以将语义转化为逻辑判断代码的有3 2 5 8 6 4 9 10题,那么17俩题起不到作用,没有使用到;
每一题的注释都有简单写判断的逻辑,这里就不做赘述
;
3.优化
3.1.生成答案列表的优化
生成答案列表原本用十层for循环:
for i1 in range(1, 5):
for i2 in range(1, 5):
for i3 in range(1, 5):
for i4 in range(1, 5):
for i5 in range(1, 5):
for i6 in range(1, 5):
for i7 in range(1, 5):
for i8 in range(1, 5):
for i9 in range(1, 5):
for i10 in range(1, 5):
pass
# result_list = [i1, i2, i3, i4, i5, i6, i7, i8, i9, i10]
现在更换成了itertools.product(可迭代对象, repeat=重复次数)
来生成笛卡尔积对象
# 生成映射ABCD的1234的 十次笛卡尔积列表
for item in itertools.product(range(1, 5), repeat=10):
pass
可以看到十层for循环时间在0.1S,而itertools.product(可迭代对象, repeat=重复次数)
时间在0.05s,得到了一倍的提升!
并且优化后每一个迭代对象不需要用list()方法转换为列表(直接用item送入判断函数即可),又省去了0.1S之多!
3.2.各小题判断顺序的更改
将关联选项更多的判断子函数优先放置,效果很小;
调整了几个答题顺序,发现效果不明显,因此这不是耗时的最主要原因
3.3.减少函数调用
接下来调整了函数调用结构,时间控制在了0.3秒内:
几次优化的过程可以从git历史中看到
4.总结
通过这种逻辑题的分析,就能看出,计算机的优势——快速作大量的判断工作,看起来复杂的背后是一个个简单的判断,真相只有一个,只要认真分析,就能发现蛛丝马迹,茅塞顿开
后面优化速度的内容让我好好思考并优化函数调用结构,不知道还有更好的思路么
最终运行时间控制在了0.3
秒内,正确答案只有一个BCACA,CDABA