我从哪里开始这个prolog程序?

时间:2015-02-21 03:31:37

标签: prolog

我花时间正确翻译了 四个人在你面前:一个男魔术师,一个女魔术师,一个巫师和一个女巫。每个人都有一个或多个硬币的袋子。
硬币由青铜,铜,黄铜或锡制成。
哪个袋子包含最少的硬币? 鉴于:

1 - 没有两个相同内容的袋子 2 - 在一个袋子里,不能有两个相同的硬币 3 - 一个袋子可以包含一个,两个或四个硬币 4 - 巫师和男魔术师各有一枚硬币,其他三只都没有 5 - 所有没有黄铜硬币的袋子都含有青铜币 6 - 所有没有锡币的袋子也不含青铜币 使用深度优先搜索创建Prolog程序以找到解决此问题的解决方案
我不知道从哪里开始

coin(bronze).
coin(copper).
coin(brass).
coin(tin).
% 5: All bags without a brass coin contain a bronze coin.
hint_1(B) :- \+ \+ ( memberchk(brass, B) ; memberchk(bronze, B) ).

% 6: All bags without tin coins do not contain a bronze coin either.
hint_2(B) :- \+ ( \+ memberchk(tin, B), memberchk(bronze, B) ).

unique_coin(Us, Bags) :-
        member(U, Us),
        \+ (member(Bag, Bags), memberchk(U, Bag)).
bag(Cs) :-
        % 3: A bag can contain either one, two or four coins
        member(L, [1,2,4]), length(Cs, L),
     % 2: In a bag, there cannot be two of the same coins.
        foldl(ascending_coin, Cs, _, _).

ascending_coin(C, Prev, C) :-
        coin(C),
        Prev @< C..

 %All bags are different
all_dif([]).
all_dif([L|Ls]) :-
        maplist(dif(L), Ls),
        all_dif(Ls).

bags(Bs) :-
        Bs = [MM,FM,Wizard,Witch],
        maplist(bag, Bs),
        % 1: There are no two bags of identical content
        all_dif(Bs),
        % 4: The Wizard and the male magician each have a unique coin.
             unique_coin(Wizard, [MM,FM,Witch]),
        unique_coin(MM, [FM,Wizard,Witch]),
        maplist(hint_1, Bs),
        maplist(hint_2, Bs).

2 个答案:

答案 0 :(得分:1)

这是我尝试解决方案。它似乎有用,但我对这些谜题的练习并不是很好。使用#n的评论表明该行上的代码旨在解决您拼图中的规则n。

编辑:我已经更新了我的代码,以便从您的代码中加入两个更好的创意:

  1. 我定义了not_member/2,因此我可以maplist检查其他列表中的唯一项目。这是普遍性和unique_coin/2之间的折衷。虽然您的unique_coin/2可能只是更好的选择。
  2. 跟着你,我翻译了我的条件(强制执行“如果列表没有铜币......”规则)进入分离。

  3. bag_with_fewest_coins(Answers) :-
        Bags = [A, B, C, D],                                 % there are four bags...
        maplist(coin_bag, Bags),                             % ... of coins
        is_set(Bags),                                        % #1
        member(MemA, A), maplist(not_member(MemA), [B,C,D]), % #4
        member(MemB, B), maplist(not_member(MemB), [A,C,D]), % #4
        predsort(compare_lengths, Bags, [Answer|_]). % Answer is shortest list.
    
    not_member(X, Ys) :-
        \+ member(X, Ys).
    
    %% To be used with predsort/3:
    compare_lengths(Comp, A, B) :-
        length(A, LenA), length(B, LenB),
        compare(Comp, LenA, LenB).         % Per @mat's suggestion in comments.
    
    coin_bag(Bag) :-
        Coins = [bronze, copper, brass, tin],          % types of coins
        member(Len, [1,2,4]), length(Bag, Len),        % #3
        set_subset(Coins, Bag),                        % #2
        (member(brass, Bag) ; member(bronze, Bag)),    % #5
        (member(tin, Bag)   ; \+ member(bronze, Bag)). % #6
    
    % Taken form gusbro's SO answer: http://stackoverflow.com/a/4917016/1187277
    % For the purposes of this predicate, each element of Set is thought of as
    % distinct, qua differentiable entity, regardless of whether it would unify,
    % equate with, or otherwise match another element in Set.
    set_subset([], []).
    set_subset([X|Set], [X|Subset]) :-
        set_subset(Set, Subset).
    set_subset([_|Set], Subset) :-
        set_subset(Set, Subset).
    

    然后,根据@ mat在评论中的建议,我们可以使用set_of/3来确保我们收集所有不同的答案:

    ?- setof(B, bag_with_fewest_coins(B), Answers).
    Answers = [[brass]].
    

    这表明只有一个独特的答案。


    这些提示与之前版本的问题有关。我离开了他们以防将来对某人有帮助

    对规则和事实使用非常具有描述性的名称会很有帮助。 rule没有帮助,因为它告诉我们什么样的规则我们没有描述。在Prolog中,<head> :- <body>.形式的任何内容都是规则,因此我们知道某些内容是基于其语法的规则。这使我们能够将我们的规则命名为描述性内容,例如bag_contents

    你的一些规则对我来说没有多大意义,我认为这是因为你有点误解了Prolog中的表达方式。所以这里有一些关于你的规则的指示:

    我希望你的意思是说这个规则是“M2是列表的第一个元素,它是一个长度为2的列表,或者是一个长度为4的列表”:

    rule(M2,[M2|_]):- length(M2,X), X=2; X = 4.
    

    但它实际上说“M2的长度为X,X = 2,或者X = 4”,这是因为;/2运算符的优先级大于,/2运算符的优先级。因此,您需要使用括号以正确的方式对表达式进行分组,如:length(M2,X), (X=2; X = 4)

    这条规则的第二个分支永远不会成功:

    rule([A|B]):- length(A,Y), Y= 1; Y = 2, Y=4, rule(B).
    

    因为第二部分(在;之后)读取“Y = 2且Y = 4且规则(B)”,但如果Y = 2则为\+ Y = 4,那么它将永远失败。

    因此,我对进一步进展的建议是为您的规则提供描述性的,不同的名称,纠正某些条款中的错误逻辑,并尝试设置可以在最高级别测试规则的情况。

答案 1 :(得分:-1)

尝试http://swish.swi-prolog.org/这会有效..可能有一些问题SWI-Prolog桌面版。桌面veriosn无法检查memberchek和foldl函数的构建。希望这有帮助