permutation / 2 }}; 它们的定义基本相同,但对参数进行了一些运行时类型检查。
下面是如何使用它们:
?- eq_set([1,2,3], [2,3,1]).
true ;
false.
?- eq_set([1,2,3], S).
S = [1, 2, 3] ;
S = [1, 3, 2] ;
S = [2, 1, 3] ;
S = [2, 3, 1] ;
S = [3, 1, 2] ;
S = [3, 2, 1] ;
false.
?- eq_set([1,2,3], [1,2]).
false.
?- eq_set(A, B).
A = B, B = [] ;
A = B, B = [_4480] ;
A = B, B = [_4480, _4492] ;
...
我不确定最后一个查询有多大用处。你可以强制它按“集合”的大小递增的顺序枚举解决方案,像这样:
?- length(S1, _), eq_set(S1, S2), numbervars(S1).
S1 = S2, S2 = [] ;
S1 = S2, S2 = [A] ;
S1 = S2, S2 = [A, B] ;
S1 = [A, B],
S2 = [B, A] ;
S1 = S2, S2 = [A, B, C] ;
S1 = [A, B, C],
S2 = [A, C, B] ;
S1 = [A, B, C],
S2 = [B, A, C] ;
S1 = [A, B, C],
S2 = [B, C, A] ;
S1 = [A, B, C],
S2 = [C, A, B] ;
S1 = [A, B, C],
S2 = [C, B, A] ;
S1 = S2, S2 = [A, B, C, D] .
“不用担心`numbervars`,它只是为集合中的所有自由变量提供可读的名称。请记住,将两个自由变量统一起来会使它们成为同一个变量。”
“这是一个起点,但也许已经足够好了。最明显的遗漏是它没有要求参数是不含重复项的列表。定义这个的一种方法是要求每个元素与所有其他元素都不相同。由于“不同”是可交换的,因此可以像这样定义它:”
is_set([]).
is_set([X|Xs]) :-
all_different(Xs, X),
is_set(Xs).
all_different([], _).
all_different([Y|Ys], X) :-
dif(X, Y),
all_different(Ys, X).
这里使用了 dif/2
,它是一个广泛可用的谓词(但你的 Prolog 是否有它还需确认)。
对于最后一个例子,我们可能会使用 maplist
:
is_set([]).
is_set([X|Xs]) :-
maplist(dif(X), Xs).
is_set(Xs).