python的约束库constraint解决《2018刑侦科题目》
Github地址:https://github.com/ZJW9633/hello-word/blob/master/Xingzhenke
题目分析:
10道题互相关联,耦合性强,暴力求解需4^10种可能,本人使用python的约束库constraint设置约束进行解决。
python代码:
1 #-*- coding:utf-8 -*- 2 # 《2018刑侦科推理试题》非穷举的 Python 解法 3 # 需要先安装约束解决库 `pip install python-constraint` 4 # author:jinwei 5 # date:2018/04/1 6 7 from constraint import * 8 from time import time 9 problem = Problem() 10 11 # a1 - a10 表示第一题到第十题的答案变量,答案使用“1”表示“A”, “2”表示“B”,以此类推 12 vars = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10"] 13 problem.addVariables(vars, [1, 2, 3, 4]) 14 15 #第 1 题 16 #略 17 #第 2 题 18 def a2_func(a2, a5): 19 return (a2 == 1 and a5 == 3) or (a2 == 2 and a5 == 4) or (a2 == 3 or a5 == 1) or (a2 == 4 or a5 == 2) 20 problem.addConstraint(a2_func, ["a2", "a5"]) 21 22 #第 3 题 23 def a3_func(a2, a3, a4,a6): 24 return (a3 == 1 and a6 == a2 == a4 != a3) or (a3 == 2 and a3 == a2 == a4 != a6) \ 25 or (a3 == 3 and a3 == a6 == a4 != a2) or (a3 == 4 and a3 == a6 == a2 != a4) 26 problem.addConstraint(a3_func, ['a2','a3','a4','a6']) 27 28 29 #第 4 题 30 def a4_func(a1, a2, a4, a5, a6, a7, a9, a10): 31 return (a4 == 1 and a1 == a5) or (a4 == 2 and a2 == a7) or (a4 == 3 and a1 == a9) or (a4 == 4 and a6 == a10) 32 problem.addConstraint(a4_func, ['a1','a2','a4','a5','a6','a7','a9','a10']) 33 34 #第 5 题 35 def a5_func( a4, a5, a7, a8, a9): 36 return (a5 == a8 == 1) or (a5 == a4 == 2) or (a5 == a9 == 3) or (a5 == a7 == 4) 37 problem.addConstraint(a5_func, ['a4','a5','a7','a8','a9']) 38 39 #第 6 题 40 def a6_func(a1, a2, a3, a4, a5, a6 ,a8, a9, a10): 41 return (a6 == 1 and a2 == a4 == a8) or (a6 == 2 and a1 == a6 == a8) \ 42 or (a6 == 3 and a3 == a10 == a8) or (a6 == 4 and a5 == a9 == a8) 43 problem.addConstraint(a6_func, ['a1','a2','a3','a4','a5','a6','a8','a9','a10']) 44 45 #第 7 题 46 def a7_func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10): 47 all_answers = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10] 48 counter = [0, 0, 0, 0] 49 for a in all_answers: 50 counter[a - 1] += 1 51 imin = counter.index(min(counter)) + 1 52 n = len(set(counter)) 53 # 这题为“此10题种被选中的选项最少的为,ABCD选择,说明 ABCD 的数量个不相同” 54 return n == 4 and ((a7 == 1 and imin == 3) or (a7 == 2 and imin == 2) or (a7 == 3 and imin == 1) or (a7 == 4 and imin == 4)) 55 problem.addConstraint(a7_func, vars) 56 57 #第 8 题 58 def a8_func(a8, a7, a5, a2, a10, a1): 59 adj = lambda x: abs(a1 - x) != 1 60 return (a8 == 1 and adj(a7)) or (a8 == 2 and adj(a5)) or (a8 == 3 and adj(a2)) or (a8 == 4 and adj(a10)) 61 problem.addConstraint(a8_func, ["a8", "a7", "a5", "a2", "a10", "a1"]) 62 63 #第 9 题 64 def a9_func(a1, a2, a5, a6, a9, a10): 65 cond1 = a1 == a6 66 cond = lambda x: cond1 != (x == a5) 67 return (a9 == 1 and cond(a6)) or (a9 == 2 and cond(a10)) or (a9 == 3 and cond(a2)) or (a9 == 4 and cond(a9)) 68 problem.addConstraint(a9_func, ["a1", "a2", "a5", "a6", "a9", "a10"]) 69 70 #第 10 题 71 def a10_func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10): 72 all_answers = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10] 73 counter = [0, 0, 0, 0] 74 for a in all_answers: 75 counter[a - 1] += 1 76 v = abs(max(counter) - min(counter)) 77 return (a10 == 1 and v == 3) or (a10 == 2 and v == 2) or (a10 == 3 and v == 4) or (a10 == 4 and v == 1) 78 problem.addConstraint(a10_func, vars) 79 80 81 # 约束设置完毕,开始求解 82 start_time=time() 83 solutions = problem.getSolutions() 84 elsap_time=time()-start_time 85 print("解决时间:{0}s".format(elsap_time)) 86 print("答案组数:{0}".format(len(solutions))) 87 88 chars = ['A', 'B', 'C', 'D'] 89 90 for si in range(0, len(solutions)): 91 print("\n---------- 第 {0} 组结果 ----------".format(si + 1)) 92 s = solutions[si] 93 for i in range(1, 11): 94 key = "a" + str(i) 95 answer = chars[s[key] - 1] 96 print("{0}".format( answer),end='')
代码结果:
解决时间:0.5780596733093262s 答案组数:1 ---------- 第 1 组结果 ---------- BCACACDABA Process finished with exit code 0
总结:
出现的问题:在进行约束条件的时,将传入所有参数a1~a10,并且将vars传入constraint中,增加了不必要的计算,大大降低了效率。
改进前运行所需时间:
改进:重新编写约束函数,只传入必要的参数,提高效率
改进后的运行时间:0.5s