PROLOG:检查第一个列表是否包含比第二个列表少3倍的每个元素

时间:2011-11-23 11:50:41

标签: prolog

我需要检查第二个列表中的每个元素是否比第一个列表中的相同元素多3倍。我的函数一直都返回false,我不知道我错了什么。

以下是代码:

fourth(_,[ ]).
fourth(A,[HF|TF]) :-
    intersection(A, HF, NewA),
    intersection(TF, HF, NewB),
    append(HF, NewB, NewT),
    append(NewA, NewA, NewAA),
    append(NewA, NewAA, NewAAA),
    length(NewAAA) == length(NewT),
    select(HF, TF, NewTF),
    fourth(A, NewTF).

示例:

?- fourth([1,2,3], [1,1,1]).
true.

?- fourth([1,2,3], [1,1,1,1]).
false.

?- fourth([1,2,3], [1,1]).
false.

?- fourth([1,2,2,3], [1,1,2,2,1,2,2,2,2]).
true.

4 个答案:

答案 0 :(得分:3)

我会让自己成为select/3谓词:select(X,From,Left),然后对于第一个列表中的每个elt,我会在第二个列表上使用相同的第一个参数调用它三次,逐步将其向前传递在没有Left3三次出现的情况下,给我一个最终X;我会为第一个列表中的每个元素执行 。然后,如果我成功并最终得到一个空列表,这意味着它从第一个列表中每个elt正好有三次。

答案 1 :(得分:2)

您的代码似乎不必要地复杂化。它还包含您使用HF而不是列表[HF]的错误。

那么你想要实现的逻辑是什么?:

  1. 从第二个列表中取下一个元素(留下尾部)
  2. 检查它是否在第一个列表中,如果是,则将其删除(否则失败)
  3. 从第二个列表的尾部删除它两次
  4. 这给出了:

    fourth(_,[ ]).
    fourth(A,[HF|TF]) :-
         once(select(HF, A, AR)), % using once/1 to avoid choicepoints
         once(select(HF, TF, TF1)),
         once(select(HF, TF1, TFR)),
         fourth(AR, TFR).
    

答案 2 :(得分:1)

以下是您的代码,其中包含有关失败原因的建议:

fourth(_,[]).
fourth(A,[HF|TF]) :-
    intersection(A, HF, NewA),
    intersection(TF, HF, NewB),

您想要使用 intersection / 3 ,原因有两个:

1)它不会仅过滤A中的HF。

2)如果用元素调用它会失败,所以至少要使用[HF] HF

相反,使用 include / 3 :include(=(HF),A,NewA)。有关详细信息,请参阅SWI-pl doc。

    append(HF, NewB, NewT),
    append(NewA, NewA, NewAA),
    append(NewA, NewAA, NewAAA),

使用 append / 2 会更好,特别是对于您的NewAAA列表。

    length(NewAAA) == length(NewT),

你无法比较这样的长度。首先,长度/ 1 不存在 内置的swi-pl谓词。相反,直接比较列表或使用 长度/ 2 两次,然后比较结果。

    select(HF, TF, NewTF),
    fourth(A, NewTF).

只有在TF中删除一次HT才会导致算法失败。你需要 删除TF中所有出现的HT,例如减去/ 3 ......

如果你想要一个尊重你原创作品的工作解决方案,我会加上它,所以请随意提问,但因为它被标记为家庭作业,我会先让你那些工作线索......

答案 3 :(得分:0)

%阻止我们的"块世界" % %b3 %b4 b7 %b1 b5 b8 %b2 b6 b9 %==============

%Block Stacking 上(B1,B2)。 上(B3,B4)。 上(B4,B5)。 上(B5,B6)。 上(B7,B8)。 上(B8,B9)。

%堆叠顺序 左(B2,B6)。 左(B6,B9)。

%概括"以上" 上方(上方,下方): - 开(上方,下方)。 以上(上方,下方): - on(Above,AnyBlock),上方(AnyBlock,Below)。

如果X是任何块Y左边的块,则

%isLeft(X,Y)解析为true。 %isLeft / 2只是调用leftOf / 2后跟一个cut(!)来保证 %只生成一个结果。 % %例如:isleft(b1,b7)生成true %isleft(b2,b6)生成true %isleft(b4,b5)产生错误。 %isleft(b9,b3)产生错误。

isLeft(X,Y): - leftOf(X,Y),! %在下面显示leftOf的实现。实施将涉及一个 %极少数情况(如上面的上述谓词),但只能使用 %提供左上方谓词。