如何检查列表列表中的所有元素是否都相同(除了一个[Prolog])

时间:2019-05-25 17:33:16

标签: prolog

除了1个由(X,Y)参数化的元素外,我想检查数组的元素是否小于0。 我尝试使用maplist,但无法保持相等。 我尝试过的另一个选择是:

verifyMatrix(X,Y,M) :-
   verifyMatrix(X,Y,0,M).

verifyMatrix(,,_,[]) :-
   !. 
verifyMatrix(X,Y,I,[M|Ms]):-
   rowVerify(0,M),
   Ni is I,
   verifyMatrix(X,Y,Ni,Ms). 
verifyMatrix(X,Y,X,[M|Ms]):-
   rowVerify(Y,M),
   I is X,
   verifyMatrix(-1,-1,I,Ms).

rowVerify(,,[]) :- !. 
rowVerify(Ec,I,[R|Rs]):-
   ((R < 0) ; (Ec is I)),
   Ni is I,
   rowVerify(Ec,Ni,Rs).

rowVerify(Ec,R):-
   rowVerify(Ec,0,R).

2 个答案:

答案 0 :(得分:2)

使用nth1/3(如果希望从0开始索引,则使用nth0/3)来枚举大于ou等于零的矩阵元素:

?- Matrix =[[-1,-2,-3],[-4,-5,+6],[-7,-8,-9]], nth1(R,Matrix,Row), nth1(C,Row,Element), Element>=0.
Matrix = [[-1, -2, -3], [-4, -5, 6], [-7, -8, -9]],
R = 2,
Row = [-4, -5, 6],
C = 3,
Element = 6 ;
false.    

然后,使用findall/3验证该元素是否唯一并位于给定位置:

?- Matrix =[[-1,-2,-3],[-4,-5,+6],[-7,-8,-9]], 
findall(R-C, (nth1(R,Matrix,Row), 
nth1(C,Row,Element), Element>=0),[I-J]).
Matrix = [[-1, -2, -3], [-4, -5, 6], [-7, -8, -9]],
I = 2,
J = 3.

因此,我们可以将谓词less_than_zero_except/3定义为:

less_than_zero_except(I, J, Matrix) :-
    findall(R-C, (nth1(R,Matrix,Row), nth1(C,Row,Element), Element>=0), [I-J]).

此谓词可用于验证特定位置或查找该位置:

?- less_than_zero_except(2,3,[[-1,-2,-3],[-4,-5,+6],[-7,-8,-9]]).
true.

?- less_than_zero_except(I,J,[[-1,-2,-3],[-4,-5,+6],[-7,-8,-9]]).
I = 2,
J = 3.

?- less_than_zero_except(I,J,[[-1,-2,-3],[-4,-5,+6],[-7,-8,+9]]).
false.

?- less_than_zero_except(I,J,[[-1,-2,-3],[-4,-5,-6],[-7,-8,-9]]).
false.

答案 1 :(得分:1)

通过尝试同时解决所有问题,您在这里使事情变得太难了。让我们首先编写一个谓词,以验证列表(“ ”)中的所有元素都小于零,我们稍后将担心该特殊元素。我们可以通过以下方式进行验证:

less_zero(L) :-
    maplist(>(0), L).

我们还可以使用forall/2 [swi-doc]检查除给定索引以外的所有元素是否都符合条件:

less_zero_except(L, J) :-
    forall((nth0(I, L, V), dif(I, J)), V < 0).

例如:

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

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

我们可以生成一个谓词,以检查行索引是否与给定的相同,并将其相应地路由到less_zero/1less_zero_except/2,例如:

verify_row(Row, I, I, ColJ) :-
    less_zero_except(Row, ColJ).
verify_row(Row, I, J, _) :-
    dif(I, J),
    less_zero(Row).

现在我们也可以在矩阵级别使用forall/2

verifyMatrix(RowI, ColJ, Matrix) :-
    forall(nth0(I, Matrix, Row), verify_row(Row, I, RowI, ColJ)).

一个多向谓词

以上内容不是双向的:我们不能在此处传递矩阵,然后让Prolog确定非负值的坐标(假设存在该值)。但是,我们可以通过使用clpfd library [swi-doc]来实现这一点:

:- use_module(library(clpfd)).

validate_cell(V, I, J, I, J) :-
    V #>= 0.
validate_cell(V, _, _, _, _) :-
    V #< 0.

现在,我们可以迭代这些值,例如:

validate_row([], _, _, _, _).
validate_row([C|T], RowI, ColJ, I, J) :-
    validate_cell(C, RowI, ColJ, I, J),
    J1 is J+1,
    validate_row(T, RowI, ColJ, I, J1).

然后我们可以验证矩阵:

validate_matrix([], _, _, _).
validate_matrix([Row|T], RowI, ColJ, I) :-
    validate_row(Row, RowI, ColJ, I, 0),
    I1 is I+1,
    validate_matrix(T, RowI, ColJ, I1).

然后我们可以根据validate_matrix/3来定义validate_matrix/4

validate_matrix(ColI, RowJ, Matrix) :-
    validate_matrix(Matrix, ColI, RowJ, 0).

我们现在可以生成满足给定约束的矩阵,并找出非负元素的坐标,并验证给定坐标对的矩阵:

?- validate_matrix(I, J, M).
M = [] ;
M = [[]] ;
M = [[], []] ;
M = [[], [], []] ;
M = [[], [], [], []] ;
M = [[], [], [], [], []] ;
M = [[], [], [], [], [], []] ;
M = [[], [], [], [], [], [], []] ;
M = [[], [], [], [], [], [], [], []] .

?- validate_matrix(I, J, [R1, R2, R3]).
R1 = R2, R2 = R3, R3 = [] ;
I = 2,
J = 0,
R1 = R2, R2 = [],
R3 = [_5416],
_5416 in 0..sup ;
I = 2,
J = 0,
R1 = R2, R2 = [],
R3 = [_5672, _5678],
_5672 in 0..sup,
_5678 in inf.. -1 ;
I = 2,
J = 0,
R1 = R2, R2 = [],
R3 = [_5916, _5922, _5928],
_5916 in 0..sup,
_5922 in inf.. -1,
_5928 in inf.. -1.

?- validate_matrix(I, J, [[1, -1], [-2, -3]]).
I = J, J = 0 ;
false.

?- validate_matrix(I, J, [[-1, -1], [-2, 3]]).
I = J, J = 1 ;
false.

?- validate_matrix(I, J, [[-1, 1], [-2, 3]]).
false.

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

?- validate_matrix(1, 1, [[-1, -1], [-2, 3]]).
true ;
false.