Prolog问答竞赛谜题程序调试:查询仅返回false求助
问答竞赛谜题Prolog程序调试问题
谜题内容
五支队伍展开了激烈的问答竞赛:
- “失败者队”名不副实,最终位列第四
- “傻瓜队”的专项主题不是电影
- 擅长烹饪主题的队伍排名直接高于“花园帮派队”,而“花园帮派队”排名又直接高于擅长历史主题的队伍
- 只有流行音乐专项的队伍排名高于“大黄采摘队”
- “暴徒队”排名比擅长时事主题的队伍低两位
需要找出各队伍对应的专项主题和最终排名。
正确答案
排名从第一到第五依次为:
- 傻瓜队(流行音乐)
- 大黄采摘队(烹饪)
- 花园帮派队(时事)
- 失败者队(历史)
- 暴徒队(电影)
预期执行查询:
?- quiz_quest(Teams). Teams = [(numbskulls, pop_music), (rhubarb_pickers, cookery), (garden_gang, current_affairs), (losers, history), (heavy_mob, movies)] ; false.
问题现象
编写的Prolog程序执行上述查询时仅返回false,无法得到预期结果,程序代码如下:
quiz_quest(Teams):- Teams = [ % (Name, Subject) -- position in list is rank, first to last (numbskulls, pop_music), (rhubarb_pickers, cookery), (garden_gang, current_affairs), (losers, history), (heavy_mob, movies) ], % "The losers did not quite finish up to their name and finished fourth". append(_, [(losers, history) | _], Teams), % "The numbskulls were not the team who took movies as a special subject". \+ member((numbskulls, movies), Teams), %" The team answering questions on cookery finished directly above the team called the garden gang". % "The garden gang were directly above the team specializing in history". append(_, [(cookery, _), (garden_gang, _), (history, _) | _], Teams), % Only the pop music specialists finished above the Rhubarb Pickers. append(_, [(_, pop_music), (rhubarb_pickers, _) | _], Teams), % The heavy Mob were two positions below the team answering about current affairs. append(_, [(_, current_affairs), (_, _), (heavy_mob, _) | _], Teams).
错误分析与修正
核心错误点
- 直接绑定结果列表:程序开头就把
Teams赋值为预期的答案列表,完全限制了Prolog的回溯求解能力,后续冗余的条件检查反而会导致冲突。应让Teams是一个长度为5、元素为(队伍名, 主题)的变量列表。 - 元素结构颠倒:所有基于
append的条件中,错误地将“主题”放在元组第一位,但定义明确元组是(Name, Subject),比如烹饪队的条件写成(cookery, _),正确应为(_, cookery)。 - 条件表述不准确:
- “失败者队排第四”:原条件仅查找
(losers, history)存在,未限定位置为第四位。 - “傻瓜队主题不是电影”:题目要求使用
dif/2,而非\+member/2。
- “失败者队排第四”:原条件仅查找
修正后的程序
quiz_quest(Teams):- % 定义Teams为5个(队伍名, 主题)的列表,对应排名1到5 length(Teams, 5), % 1. 失败者队位列第四(列表第四个元素) append(FirstThree, [(losers, LoserSubj) | [_]], Teams), length(FirstThree, 3), % 2. 傻瓜队的主题不是电影 member((numbskulls, NumbSubj), Teams), dif(NumbSubj, movies), % 3. 烹饪队直接在花园帮派队上方,花园帮派队直接在历史队上方 append(_, [(CookTeam, cookery), (garden_gang, GardenSubj), (HistTeam, history) | _], Teams), % 4. 只有流行音乐队在大黄采摘队上方 → 大黄采摘队排第二,流行音乐队排第一 Teams = [(_, pop_music), (rhubarb_pickers, RhubSubj) | _], % 5. 暴徒队比时事队低两位 append(_, [(CurrTeam, current_affairs), _, (heavy_mob, MobSubj) | _], Teams), % 结合解答过程中的隐含绑定:失败者队主题是历史,大黄采摘队主题是烹饪 LoserSubj = history, RhubSubj = cookery.
说明
修正后的程序:
- 先声明
Teams长度为5,保留变量的求解空间 - 每个条件严格对应谜题描述,元组结构符合
(队伍名, 主题)的定义 - 使用
dif/2满足题目要求的谓词限制 - 补充解答过程中明确的主题绑定,确保结果唯一
执行修正后的程序,即可得到预期的查询结果。
内容的提问来源于stack exchange,提问作者Ritta Neg-Mfa
相关产品推荐
相关产品推荐

