排列,包括Prolog中的所有成员

时间:2016-07-07 06:11:42

标签: list prolog

在这个问题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的排列谓词,但这是出于不同的目的。

1 个答案:

答案 0 :(得分: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).(事实表)
  3. 实际上非常相似。选择一个或另一个是你想要如何使用它的问题,在程序中从一个转换到另一个是非常容易的(并且很常见)。例如,当您定义了(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的arity,则需要在运行时检查该程序。如果你的程序看起来像你的问题:

    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及其下方的评论。