斑马问题
题目
5 个不同国家(英国、西班牙、日本、意大利、挪威)且工作各不相同(油漆工、摄影师、外交官、小提琴家、医生)的人分别住在一条街上的 5 所房子里,
每所房子的颜色不同(红色、白色、蓝色、黄色、绿色),每个人都有自己养的不同宠物(狗、蜗牛、斑马、马、狐狸),喜欢喝不同的饮料(矿泉水、牛奶、茶、橘子汁、咖啡)。
根据以下提示,你能告诉我哪所房子里的人养斑马,哪所房子里的人喜欢喝矿泉水吗?
1. 英国人住在红色的房子里
2. 西班牙人养了一条狗
3. 日本人是一个油漆工
4. 意大利人喜欢喝茶
5. 挪威人住在左边的第一个房子里
6. 绿房子在白房子的右边
7. 摄影师养了一只蜗牛
8. 外交官住在黄房子里
9. 中间那个房子的人喜欢喝牛奶
10. 喜欢喝咖啡的人住在绿房子里
11. 挪威人住在蓝色的房子旁边
12. 小提琴家喜欢喝橘子汁
13. 养狐狸的人所住的房子与医生的房子相邻
14. 养马的人所住的房子与外交官的房子相邻
参考资料:[斑马难题-百度百科](https://baike.baidu.com/item/%E6%96%91%E9%A9%AC%E9%9A%BE%E9%A2%98/3709972?fr=aladdin)
代码
from kanren import run, eq, membero, var, conde # kanren一个描述性Python逻辑编程系统
from kanren.core import lall # lall包用于定义规则
import time
def left(q, p, list):
return membero((q, p), zip(list, list[1:]))
def right_of(q, p, list):
return left(p, q, list)
def next_to(q, p, list):
return conde([left(q, p, list)], [right_of(q, p, list)])
class Agent:
"""
推理智能体.
"""
def __init__(self):
"""
智能体初始化.
"""
self.units = var() # 单个unit变量指代一座房子的信息(国家,工作,饮料,宠物,颜色)
# 例如('英国人', '油漆工', '茶', '狗', '红色')即为正确格式,但不是本题答案
# 请基于给定的逻辑提示求解五条正确的答案
self.rules_zebraproblem = None # 用lall包定义逻辑规则
self.solutions = None # 存储结果
def define_rules(self):
"""
定义逻辑规则.
"""
self.rules_zebraproblem = lall(
(eq, (var(), var(), var(), var(), var()), self.units),
# self.units共包含五个unit成员,即每一个unit对应的var都指代一座房子(国家,工作,饮料,宠物,颜色)
# 各个unit房子又包含五个成员属性: (国家,工作,饮料,宠物,颜色)
(membero, ('英国人', var(), var(), var(), '红色'), self.units), # Clue 1
(membero, ('西班牙人', var(), var(), '狗', var()), self.units), # Clue 2
(membero, ('日本人', '油漆工', var(), var(), var()), self.units), # Clue 3
(membero, ('意大利人', var(), '茶', var(), var()), self.units), # Clue 4
(eq, (('挪威人', var(), var(), var(), var()), var(), var(), var(), var()), self.units), # Clue 5
(right_of, (var(), var(), var(), var(), '绿色'), (var(), var(), var(), var(), '白色'),self.units),
# Clue 6
(membero, (var(), '摄影师', var(), '蜗牛', var()), self.units), # Clue 7
(membero, (var(), '外交官', var(), var(), '黄色'), self.units), # Clue 8
(eq, (var(), var(), (var(), var(), '牛奶', var(), var()), var(), var()), self.units), # Clue 9
(membero, (var(), var(), '咖啡', var(), '绿色'), self.units), # Clue 10
(next_to, ('挪威人', var(), var(), var(), var()), (var(), var(), var(), var(), '蓝色'), self.units),
# Clue 11
(membero, (var(), '小提琴家', '橘子汁', var(), var()), self.units), # Clue 12
(next_to, (var(), var(), var(), '狐狸', var()), (var(), '医生', var(), var(), var()), self.units),
# Clue 13
(next_to, (var(), var(), var(), '马', var()), (var(), '外交官', var(), var(), var()), self.units), # Clue 14
(membero, (var(), var(), '矿泉水', var(), var()), self.units), # Clue 15
(membero, (var(), var(), var(), '斑马', var()), self.units), # Clue 16
)
def solve(self):
"""
规则求解器
return: 斑马规则求解器给出的答案,共包含五条匹配信息,解唯一.
"""
self.define_rules()
self.solutions = run(0, self.units, self.rules_zebraproblem)
return self.solutions
if __name__ == '__main__':
agent = Agent()
solutions = agent.solve()
# 提取解释器的输出
output = [house for house in solutions[0] if '斑马' in house][0][4]
print('\n{}房子里的人养斑马'.format(output))
output = [house for house in solutions[0] if '矿泉水' in house][0][4]
print('{}房子里的人喜欢喝矿泉水'.format(output))
# 解释器的输出结果展示
for i in solutions[0]:
print(i)