【问题标题】:Trivia Champions logic puzzle on SWI PrologSWI Prolog 上的 Trivia Champions 逻辑谜题
【发布时间】:2013-04-04 10:53:39
【问题描述】:

我是使用 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.

【问题讨论】:

    标签: prolog


    【解决方案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]]
    

    是一个解决方案,即使“old”和“75”在其中两次。如果您使用的是 SWI,则从 clp_fd 包中添加 all_different 调用或手动进行:

    A \= B, A \= C, ... B \= C etc.
    

    现在,关于冻结:这只是因为您的子句排序不理想。先看看scores 和pubs。在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? 
    ...
    

    总而言之,必须检查 Score1 和 Score2 的多达 225 个组合,以确定它们是否是正确的分配。

    现在让我们考虑重新排序的版本:

    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) 的结果必须不是整数,而是(A-B) 形式的术语。引入一个中间变量来解析。 2)你没有让solve返回任何有用的东西,所以它只说true。不知道这是不是你想要的。 ;-)

    【讨论】:

    • 非常感谢您的解释,现在终于可以使用了。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-01
    • 2019-05-11
    相关资源
    最近更新 更多