如何检查两个列表整数之间的差异是否大于或等于2?

时间:2016-02-27 18:14:23

标签: list prolog clpfd

鉴于两个已排序的列表YsX,如何确保Xs中的Y与{{1}中的任何Ys之间的绝对差异至少是两个?

带有预期答案的示例查询:

?- different([1,2,4],[5,6]).   % 5-4 < 2
false
?- different([1,4],[2,6]).     % 2-1 < 2
false
?- different([1,2,6],[4,8]).   % 4-2 >= 2 and 6-4 >= 2 and 8-6 >= 2
true
?- different([],[4]). 
true

我怎样才能得到这个结果?有任何想法吗?谢谢!

修改:这是我现在的代码:

difference([], []).
difference([_|_], []).
difference([], [_|_]).
difference(L1, L2) :-
   L1 = [X1|X2],
   L2 = [Y1|_],
   Dif is X1-Y1,
   (-1>Dif|Dif>1),
   difference(X2, L2).

2 个答案:

答案 0 :(得分:1)

在这个答案中,我们使用来获得两者 通用性最佳(线性)算术复杂度。

diff_to_mdist([], _, _).
diff_to_mdist([_|_], [], _).
diff_to_mdist([X|Xs], [Y|Ys], D) :-
   (  X #=< Y-D,            diff_to_mdist(Xs, [Y|Ys], D)
   ;  X #>  Y-D, X #>= Y+D, diff_to_mdist([X|Xs], Ys, D)
   ).
diff_to_mdist([X0,X1|Xs], [Y0,Y1|Ys], D) :-
   X0 #> Y0-D, X0 #< Y0+D,
   (  X0 #< Y0, X0 #=< Y0-D, X1 #>= Y0+D, diff_to_mdist([X0,X1|Xs], [Y1|Ys], D)
   ;  X0 #> Y0, Y0 #=< X0-D, Y1 #>= X0+D, diff_to_mdist([X1|Xs], [Y0,Y1|Ys], D)
   ).

让我们使用版本1.4.4并运行类似OP建议的查询!

| ?- diff_to_mdist([1,2,4], [5,6], 2).
no
| ?- diff_to_mdist([1,4], [2,6], 2).
no
| ?- diff_to_mdist([1,2,6], [4,8], 2). 
true ? ;
no
| ?- diff_to_mdist([], [4], 2). 
yes

答案 1 :(得分:0)

首先,您可以使您当前的代码更整洁,更容易阅读,如下所示:

different([], []).
different([_|_], []).
different([], [_|_]).
different([X|Xs], [Y|Ys]) :-
    abs(X-Y) >= 2,     % Prolog evaluates arithmetic expressions for compares
    different(Xs, [Y|Ys]).

在这种情况下,你已经完成了我在评论中提到的递归的一个级别,因为它只检查第一个列表中的每个元素而不是第二个元素的第一个元素。它忽略了第二个列表中的所有其他元素。所以你需要进一步分解它。您可以创建一个帮助器谓词,将列表中的每个元素与单个值进行比较。然后让你的主谓词用另一个列表的每个元素调用这个辅助谓词。然后主要谓词如下:

different([], []).
different([], [_|_]).
different([X|Xs], L) :-
    different_element(X, L),
    different(Xs, L).

然后帮助器谓词是:

% This predicate succeeds if the first argument has the desired difference
% to each of the elements of the second argument (a list)
%
different_element(_, []).
different_element(X, [Y|Ys]) :-
    abs(X-Y) >= 2,
    different_element(X, Ys).