【问题标题】:Permutations including all members in Prolog包括 Prolog 中所有成员的排列
【发布时间】:2016-07-07 21:14:23
【问题描述】:

扩展这个问题Can be this lisp function be implemented recursively?,如果列表表示如下,是否可以在Prolog中拥有所有组合:

items1(1, 2, 3).
items2(4, 5).

我可以通过以下格式的数据得到答案:

items1(1).
items1(2).
items1(3).

items2(4).
items2(5).

?- findall((A,B), (items1(A), items2(B)), L).
L = [ (1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)].

我检查了来自http://www.swi-prolog.org/pldoc/man?predicate=permutation/2 的排列谓词,但这是出于不同的目的。

【问题讨论】:

    标签: list prolog


    【解决方案1】:

    您似乎已经通过规范化数据库很好地解决了您的问题。将列表[I_1, I_2, ..., I_n] 表示为事实items(I_1, I_2, ..., I_n). 很不方便。列表适用于(可能是有序的)具有 0 个或更多元素的集合;事实通常用于具有预设列数的表,每行一个事实。而这两种表示:

    1. [a, b, c](列表)和
    2. item(a). item(b). item(c).(事实表)

    其实很相似。选择一个或另一个取决于您希望如何使用它,并且在您的程序中从一个转换为另一个非常容易(并且很常见)。例如,当您定义了 (2) 时,?- member(X, [a, b, c]).?- item(X). 大致相同。 the question you linked 的 Prolog 列表版本将是:

    combo(L1, L2, X-Y) :-
        member(X, L1),
        member(Y, L2).
    

    然后:

    ?- combo([1,2,3], [4,5], R).
    R = 1-4 ;
    R = 1-5 ;
    R = 2-4 ;
    R = 2-5 ;
    R = 3-4 ;
    R = 3-5.
    

    items([a, b, c]). 有点不方便(但仍然没有必要),所以你有一个参数,所有项目的列表。然后,你可以这样做:

    ?- items(Is),
       member(X, Is).
    

    如果你真的有 items(a, b, c). 之类的东西,并且你知道你正好有三个项目,你仍然可以这样做:

    ?- items(A, B, C),
       member(X, [A, B, C]).
    

    如果您在编译时不知道items 的数量,则需要在运行时检查程序。如果您的程序看起来像您的问题:

    items1(1, 2, 3).
    items2(4, 5).
    

    然后你可以例如这样做:

    ?- current_predicate(items1/N), % figure out the arity of items1
       length(Is, N),               % make a list of that length
       Fact =.. [items1|Is],        % create a callable term
       Fact,                        % call the term to instantiate Is
       member(X, Is).               % enumerate the list
    

    如你所见,相当迂回。

    还有一条评论:在 Prolog 中使用(A,B) 作为“元组”是不寻常的。对于一对,你通常会写A-B,如果你不知道你有多少元素,它通常只是一个列表,例如[A,B|Rest]。请参阅this answer 及其下方的 cmets 了解更多详情。

    【讨论】:

    • 很好的答案。谢谢。
    • @rnso 我仍然对 Lisp 版本如此迂回感到有点惊讶。必须有更简单的方法来做到这一点......
    • 像你这样有经验的人可以评论 Prolog vs Lisp。你之前已经发过这个帖子了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 2012-02-20
    • 2019-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    相关资源
    最近更新 更多