我正在尝试编写谓词rowN/3
,它返回矩阵的 n -th元素(在本例中为行)。
例如:
?- rowN([[1,2],[3,4],[5,6]], 2, R).
R = [3,4];
No
我正在与柜台挣扎。我试图找到一些非常相似的例子,但没有成功。到目前为止,我设法写了这个:
代码:
rowN(L,[],[]).
rowN([],X,[]).
rowN([],[],[].
rowN([H|T],X,R) :-
A==X,
A is A + 1,
rowI(T,A,H).
答案 0 :(得分:4)
这一行没有多大意义:
rowN(L,[],[]).
因为第二个参数是一个整数(如果我理解正确的话),你使用一个列表。几乎所有的论点都是这种情况。此外,您在递归调用中使用RowI
?
解决方案是首先指定第一行(I = 1
)等于矩阵的头部:
rowN([H|_],1,H).
接下来你需要找到一种迭代的方法来枚举你的矩阵。所以标题肯定是这样的形式:
rowN([H|T],I,X) :-
# ...
现在我们假设I
不等于1
(稍后我们将讨论此主题)。在这种情况下,我们需要进一步遍历矩阵,因此我们将采用 tail 并将计数器I
设置为一个。这可以使用:
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
所以我们的谓词是:
rowN([H|_],1,H).
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
现在,如果您使用此谓词,它将给出正确的结果:
?- rowN([[1,2],[3,4],[5,6]], 2, R).
R = [3, 4] ;
false.
问题是为什么谓词不会产生其他结果:在显示第一个结果后,对于rowN([[1,2],[3,4],[5,6]], 2, R) :- rowN([[3,4],[5,6]],1,[3,4]).
,它可能会尝试寻找替代方案。它通过使用第二个子句来实现,但随后最终会用完行并调用rowN([],_,_)
谓词,因为不是子句匹配,它将失败。
这个解决方案并不完美:它不能正确地在所有方向上工作,这在Prolog中通常很难。这就是为什么优秀的Prolog程序员编写库。
nth1/3
您可以在swi-prolog中使用nth1/3
谓词,而不是重新发明轮子。虽然参数是交换的 - 你需要像nth1(2,[[1,2],[3,4],[5,6]],R).
那样调用它 - 它的优势在于它可以在更多的方向上工作,大多数人可以在快速解决方案中出现,它几乎可以确定无错误(因为它有所有使用谓词的Prolog程序都进行了数十亿次测试,其中一些内置程序是用C ++实现的,有时候更快。例如:
?- nth1(2, [[1,2],[3,4],[5,6]], R).
R = [3, 4].
?- nth1(I, [[1,2],[3,4],[5,6]], [5,6]).
I = 3.
?- nth1(I, [[1,2],[3,4],[5,6]], R).
I = 1,
R = [1, 2] ;
I = 2,
R = [3, 4] ;
I = 3,
R = [5, 6].
?- nth1(I,M,[2,3]).
I = 1,
M = [[2, 3]|_G23] ;
I = 2,
M = [_G22, [2, 3]|_G26] ;
I = 3,
M = [_G22, _G25, [2, 3]|_G29] ;
I = 4,
M = [_G22, _G25, _G28, [2, 3]|_G32] .
您可以询问第二行是什么,询问行[5,6]
的位置,通过回答索引I
和行R
的元组使查询更通用并在某处生成一个行[2,3]
的矩阵。