List 减少谓词调用
我有一个谓词:List 减少谓词调用,list,prolog,List,Prolog,我有一个谓词: check_matrix([[_, E2, E3], [E4, E5, E6], [E7, E8, E9]]) :- E5 = E9, is_valid([E4, E5, E6]), is_valid([E7, E8, R9]), is_valid([E2, E5, E8]), is_valid([E3, E6, E9]). 它检查我的2 x 2矩阵是否有效,左上角的单元
check_matrix([[_, E2, E3],
[E4, E5, E6],
[E7, E8, E9]]) :-
E5 = E9,
is_valid([E4, E5, E6]),
is_valid([E7, E8, R9]),
is_valid([E2, E5, E8]),
is_valid([E3, E6, E9]).
它检查我的2 x 2矩阵是否有效,左上角的单元格,
被完全忽略。E2
、E3
、E4
和E7
单元格只是2 x 2矩阵的标题
这是一个更好的方法,我可以Is\u valid()
,这样我就不需要调用Is\u valid()
4次。如果矩阵变大,例如5x5,则该谓词需要调用is\u valid()
10次。这对Prolog正常吗?还是他们的方式更优雅
我想用另一个谓词创建一个嵌套列表,其中包含我要传递给is\u valid()
的所有可能列表,并在每个列表上调用该谓词,然后将结果传递回check\u matrix()
。我觉得他们的方式一定更优雅。如有任何建议,将不胜感激
更新
E5=E9
只是一个对角线检查器,它检查矩阵的对角线是否相同,如果不相同,则谓词失败 如果要避免这种硬编码谓词,可以尝试递归:
您可以检查每个列表(第一个列表除外)中的是否有效,以便您可以编写:
check_matrix([H|T]) :- is_valid_each_list(T),....
is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
is_vqlid_each_list(T).
请注意,限制length(L,3)
表示元素是长度为3的列表(或任何参数K,如果愿意,只需添加另一个参数)
现在检查E2、E5、E8(位于同一位置的元素)
:
因此,完整的通用解决方案:
check_matrix([H|T]) :- is_valid_each_list(T), is_valid_pos([H|T]).
is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
is_vqlid_each_list(T).
is_valid_pos(L):-length(L,3), is_valid_pos(L,1).
is_valid_pos(_,4).
is_valid_pos(L,K):- findall(X,(member(L1,L),nth0(K,L1,X)),L2),
is_valid(L2),K1 is K+1, is_valid_pos(L,K1).
如果要避免这种硬编码谓词,可以尝试递归: 您可以检查每个列表(第一个列表除外)中的
是否有效,以便您可以编写:
check_matrix([H|T]) :- is_valid_each_list(T),....
is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
is_vqlid_each_list(T).
请注意,限制length(L,3)
表示元素是长度为3的列表(或任何参数K,如果愿意,只需添加另一个参数)
现在检查E2、E5、E8(位于同一位置的元素)
:
因此,完整的通用解决方案:
check_matrix([H|T]) :- is_valid_each_list(T), is_valid_pos([H|T]).
is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
is_vqlid_each_list(T).
is_valid_pos(L):-length(L,3), is_valid_pos(L,1).
is_valid_pos(_,4).
is_valid_pos(L,K):- findall(X,(member(L1,L),nth0(K,L1,X)),L2),
is_valid(L2),K1 is K+1, is_valid_pos(L,K1).
Prolog有一些库,如
library(apply)
,它们提供高阶谓词:传递另一个谓词的谓词
这里似乎适用的高阶谓词是。谓词将谓词(:Goal
)和列表(?list
)作为参数,并对?list
的元素应用:Goal
,直到谓词失败或列表耗尽。您可以将它与在列表上迭代的命令式语言中的函数进行比较,并检查谓词是否适用于列表的所有成员。比如Python中的all(…)
因此,我们可以使用以下方法检查除第一行以外的所有行:
但是,我们也必须检查除第一列以外的所有列。因此我们可以使用谓词。它有两个参数,第二个参数是第一个参数的转置。因此:
?- transpose([[1, 2, 3],
| [4, 5, 6],
| [7, 8, 9]],X).
X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]].
因此,我们可以转置矩阵,然后再次使用maplist/2
检查矩阵M
转置的除第一行以外的所有行。现在我们可以实现如下谓词:
:- use_module(library(apply)).
:- use_module(library(clpfd)).
check_matrix(M) :-
M = [_|MT],
maplist(is_valid,MT),
transpose(M,[_|TT]),
maplist(is_valid,TT).
编辑:
如果您想检查除第一个对角线元素以外的所有元素是否都存在,我建议定义两个附加谓词:
检查列表中的所有元素是否相同;及all_same/1
构造对角线元素列表的diagonal/2
全部相同/1
可以实现为:
all_same([]).
all_same([_]).
all_same([H,H|T]) :-
all_same([H|T]).
和对角线/2
可通过以下方式获得:
diagonal(M,L) :-
diagonal(M,0,L).
diagonal([],_,[]).
diagonal([R|RT],I,[D|DT]) :-
nth0(I,R,D),
I1 is I+1,
diagonal(RT,I1,DT).
现在我们可以检查对角线,如下所示:
check_matrix(M) :-
M = [_|MT],
maplist(is_valid,MT),
transpose(M,[_|TT]),
maplist(is_valid,TT),
diagonal(M,[_|DT]),
all_same(DT).
检查矩阵(M):-
M=[[u124; MT],
地图列表(是否有效,MT),
转置(M,[[u124; TT]),
地图列表(是否有效,TT),
对角线(M,[| DT]),
all_same(DT)。
Prolog有一些库,如library(apply)
,它们提供高阶谓词:传递另一个谓词的谓词
这里似乎适用的高阶谓词是。谓词将谓词(:Goal
)和列表(?list
)作为参数,并对?list
的元素应用:Goal
,直到谓词失败或列表耗尽。您可以将它与在列表上迭代的命令式语言中的函数进行比较,并检查谓词是否适用于列表的所有成员。比如Python中的all(…)
因此,我们可以使用以下方法检查除第一行以外的所有行:
但是,我们也必须检查除第一列以外的所有列。因此我们可以使用谓词。它有两个参数,第二个参数是第一个参数的转置。因此:
?- transpose([[1, 2, 3],
| [4, 5, 6],
| [7, 8, 9]],X).
X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]].
因此,我们可以转置矩阵,然后再次使用maplist/2
检查矩阵M
转置的除第一行以外的所有行。现在我们可以实现如下谓词:
:- use_module(library(apply)).
:- use_module(library(clpfd)).
check_matrix(M) :-
M = [_|MT],
maplist(is_valid,MT),
transpose(M,[_|TT]),
maplist(is_valid,TT).
编辑:
如果您想检查除第一个对角线元素以外的所有元素是否都存在,我建议定义两个附加谓词:
检查列表中的所有元素是否相同;及all_same/1
构造对角线元素列表的diagonal/2
全部相同/1
可以实现为:
all_same([]).
all_same([_]).
all_same([H,H|T]) :-
all_same([H|T]).
和对角线/2
可通过以下方式获得:
diagonal(M,L) :-
diagonal(M,0,L).
diagonal([],_,[]).
diagonal([R|RT],I,[D|DT]) :-
nth0(I,R,D),
I1 is I+1,
diagonal(RT,I1,DT).
现在我们可以检查对角线,如下所示:
check_matrix(M) :-
M = [_|MT],
maplist(is_valid,MT),
transpose(M,[_|TT]),
maplist(is_valid,TT),
diagonal(M,[_|DT]),
all_same(DT).
检查矩阵(M):-
M=[[u124; MT],
地图列表(是否有效,MT),
转置(M,[[u124; TT]),
地图列表(是否有效,TT),
对角线(M,[| DT]),
都一样(DT)。