我是使用swi Prolog的新手,现在我正在尝试使用Prolog来解决这个逻辑难题http://www.allstarpuzzles.com/logic/00335.html
但是当我试图运行该程序时,该程序似乎停止响应并且Prolog冻结了。看来我在确定每支球队的得分时遇到了问题。 这是我的Prolog代码:
team(dirtydozen).
team(plough).
team(barflyers).
team(threestooges).
team(friends).
pub(maid).
pub(old).
pub(clown).
pub(king).
pub(queen).
score(75).
score(74).
score(73).
score(72).
score(71).
score(70).
score(69).
score(68).
score(67).
score(66).
score(65).
score(64).
score(63).
score(62).
score(61).
score(60).
solve :-
score(Score1),score(Score2),score(Score3),score(Score4),score(Score5),
pub(Pub1),pub(Pub2),pub(Pub3),pub(Pub4),pub(Pub5),
Hasil = [[dirtydozen,Pub1,Score1],
[plough,Pub2,Score2],
[barflyers,Pub3,Score3],
[threestooges,Pub4,Score4],
[friends,Pub5,Score5]],
Score1 is Score2 + 6,
Score1 is Score3 + 9,
\+ member([threestooges,maid,_],Hasil),
member([friends,_,A],Hasil),
member([_,old,B],Hasil),
member([_,clown,C],Hasil),
member([_,king,D],Hasil),
(A-B) is 2*(C-D),
member([_,queen,E],Hasil),
member([threestooges,_,F],Hasil),
F >= E+3.
答案 0 :(得分:1)
几乎是正确的。只有四个问题。 ;-) 首先,这是一个几乎可以工作的版本:
team(dirtydozen).
team(plough).
team(barflyers).
team(threestooges).
team(friends).
pub(maid).
pub(old).
pub(clown).
pub(king).
pub(queen).
score(75).
score(74).
score(73).
score(72).
score(71).
score(70).
score(69).
score(68).
score(67).
score(66).
score(65).
score(64).
score(63).
score(62).
score(61).
score(60).
solve(Hasil) :-
Hasil = [[dirtydozen,Pub1,Score1],
[plough,Pub2,Score2],
[barflyers,Pub3,Score3],
[threestooges,Pub4,Score4],
[friends,Pub5,Score5]],
member([friends,_,A],Hasil),
member([_,old,B],Hasil),
member([_,clown,C],Hasil),
member([_,king,D],Hasil),
member([_,queen,E],Hasil),
member([threestooges,_,F],Hasil),
\+ member([threestooges,maid,_],Hasil),
score(Score2),
Score1 is Score2 + 6,
score(Score3),
Score1 is Score3 + 9,
score(Score1),
score(Score4),
score(Score5),
AB is A-B,
AB is 2*(C-D),
F >= E+3,
pub(Pub1),
pub(Pub2),
pub(Pub3),
pub(Pub4),
pub(Pub5).
几乎,因为它提供了解决方案,并且速度快,并且根据您的规范它们是正确的。但是,有很多因为你没有指定所有的酒吧/团队/分数必须彼此不同,所以例如
[[dirtydozen,old,75],[plough,clown,69],[barflyers,queen,66],
[threestooges,king,75], [friends,old,63]]
是一个解决方案,即使“旧”和“75”在其中两次。如果您使用的是SWI,请从clp_fd包中添加all_different
个调用或手动执行:
A \= B, A \= C, ... B \= C etc.
现在,关于冻结:这只是因为你的条款的次优顺序。首先查看score
和pub
。在solve
谓词的前两行中,这两个谓词的每个可能的排列都分配给Score[N]
和Pub[N]
变量。尝试计算有多少可能的任务!只有这样,您的程序才会检查相关作业是否符合规则。
通过重新排序您的条件,我从一开始就排除了大量的作业。以这些行为例:
score(Score1), score(Score2), Score1 is Score2 + 2,...
这可以这样评价:
Score1 = 75, Score2 = 75, 75 is 75+2?
Score1 = 74, Score2 = 75, 74 is 75+2?
Score1 = 73, Score2 = 75, 73 is 75+2?
Score1 = 72, Score2 = 75, 72 is 75+2?
...
总而言之,必须检查最多225个Score1和Score2的组合,以确定它们是否是正确的分配。
现在让我们考虑重新排序的版本:
score(Score2), Score1 is Score2 + 2, score(Score1),...
评估现在沿着这些方向运行:
Score2 = 75, Score1 = 77, score(77)?
Score2 = 74, Score1 = 76, score(76)?
Score2 = 73, Score1 = 75, score(75)?
我们只有15个有效作业。所以规则是:尝试将这些变量彼此修复,以免让树展开超出必要的范围。修复移动目标!
唯一的另外两个小问题:1)(A-B) is 2*(C-D)
不起作用,因为它指出,评估2*(C-D)
的结果必须不是整数,而是形式{ {1}}。引入一个中间变量来解决。 2)你没有让(A-B)
返回任何有用的东西,所以只说solve
。不知道那是不是你想要的。 ; - )