List 如何以正确的方式实现转置谓词(Prolog)?
我正在制作一个解决难题的程序。但是我需要做一个谓词,返回给定矩阵(列表列表)的转置,我不能使用预定义的。但是,无论我做什么,我都无法让谓词在不超过堆栈限制的情况下反向工作,例如:List 如何以正确的方式实现转置谓词(Prolog)?,list,prolog,List,Prolog,我正在制作一个解决难题的程序。但是我需要做一个谓词,返回给定矩阵(列表列表)的转置,我不能使用预定义的。但是,无论我做什么,我都无法让谓词在不超过堆栈限制的情况下反向工作,例如:trans([[1,2],[3,4]],X)。返回[[1,3],[2,4]]但trans(X,[[1,3],[2,4]])。超过堆栈限制 下面是反式谓词: trans(M,M1):- length(M,L), trans1(0,L,M,R). trans1(N,N,_,[]). trans1(I,N,M
trans([[1,2],[3,4]],X)。
返回[[1,3],[2,4]]
但trans(X,[[1,3],[2,4]])。
超过堆栈限制
下面是反式谓词:
trans(M,M1):-
length(M,L),
trans1(0,L,M,R).
trans1(N,N,_,[]).
trans1(I,N,M,M1):-
I1 is I+1,
column(M,I1,C),
trans1(I1,N,M,M2).
下面是我使用的列谓词:
row([H|_],1,H):-!.
row([_|T],I,X) :-
I1 is I-1,
row(T,I1,X).
column([],_,[]).
column([H|T], I, [R|X]):-
row(H, I, R),
column(T,I,X).
你知道我如何使用trans吗?如果我给出了它的转置,你可以通过查看公开的、免费的(比如啤酒)开源SWI Prolog代码来重新组装谓词。为什么人们不经常这样做对我来说是个谜。这很容易,但我想还是比有人把工作代码扔给你更难 首先,这里是(有点神秘的): 这使用谓词
相同的长度/2
。它在中定义,如下所示:
same_length([], []).
same_length([_|T1], [_|T2]) :-
same_length(T1, T2).
非常直截了当
然后它使用maplist
和foldl
。允许还是不允许?如果没有,您可以将映射列表(长度(L),Ls)重写为:
all_same_length([], L).
all_same_length([X|Xs], L) :-
same_length(X, L),
all_same_length(Xs, L).
愚蠢的代码,不应该手动编写,但很好
然后,您可以将地图列表(相同长度(L),Ls)
替换为所有相同长度(L,Ls)
这就给您留下了foldl(转置,L,Ts,[L | Ls],
。这是“神秘”的一点;这个限定可能是对作者的一种赞美
无论采用哪种方式,这样编写的忽略最后一个参数(结果)的折叠都可以作为循环重新编写,与上面的映射列表没有太大区别。折叠中使用的transpose\u4
在其定义中有一个映射列表,但我已经展示了如何做到这一点
因为这看起来像是家庭作业,我会让你自己解决
作弊代码:如果你深入研究这个库的历史(都在github上!),你可能会非常幸运,找到一个相同转置的pre-foldl实现。很多年前,我写了自己的转置/2,作为我工作的一部分。这是:
% row/columns transposition
%
transpose_col_row([], []).
transpose_col_row([U], B) :- gen(U, B).
transpose_col_row([H|T], R) :- transpose_col_row(T, TC), splash(H, TC, R).
gen([H|T], [[H]|RT]) :- gen(T,RT).
gen([], []).
splash([], [], []).
splash([H|T], [R|K], [[H|R]|U]) :-
splash(T,K,U).
尽管代码没有使用任何复杂的东西,但理解它的功能并不容易,而且,就像您自己的或SWI Prolog库(clpfd)实现一样,它是不“可逆的”
您的代码有许多需要解决的问题(注意:单例警告实际上是错误),但假设您可以确定它们,并获得一个工作的trans(M,T),您可以使用一个简单的“hack”,在检查实例化后交换参数:
trans_rev(M,T) :- var(M) -> trans(T,M) ; trans(M,T).
让我们尝试一下我自己的实现,即
transpose_col_row_rev(M,T) :-
var(M) -> transpose_col_row(T,M) ; transpose_col_row(M,T).
?- transpose_col_row_rev([[1,2]],T).
T = [[1], [2]]
?- transpose_col_row_rev(M,$T).
M = [[1, 2]],
T = [[1], [2]]
transpose_col_row_rev(M,T) :-
var(M) -> transpose_col_row(T,M) ; transpose_col_row(M,T).
?- transpose_col_row_rev([[1,2]],T).
T = [[1], [2]]
?- transpose_col_row_rev(M,$T).
M = [[1, 2]],
T = [[1], [2]]