Prolog-将矩阵转换为带索引的列表

时间:2017-11-18 23:29:08

标签: list matrix prolog

我有一个这样的矩阵:

[[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]]

我需要一个列表,当行不是[0,0,0]时保存索引。 所以我的例子中的结果应该是:

[2,3,4,5,7,8]

我在Prolog中编程递归是有问题的,因为我还没弄清楚它是如何工作的。

首先将矩阵转换为向量可能有帮助吗?它的[1,0,0][0,1,0]无关紧要。唯一重要的是它不是[0,0,0]

2 个答案:

答案 0 :(得分:4)

由于您要描述列表,您可以选择使用DCG。它们通常产生非常易读的代码:

matrix_indices(M,I) :-
   phrase(indices(M,0),I).    % the list I is described by the DCG indices//2

indices([],_) -->             % if M is empty
   [].                        % I is empty too
indices([[0,0,0]|Ls],I0) -->  % if the head of M is [0,0,0]
   {I1 is I0+1},              % the current index is calculated but is not in I
   indices(Ls,I1).            % the same holds for the tail
indices([L|Ls],I0) -->        % if the head of the list
   {dif(L,[0,0,0])},          % differs from [0,0,0]
   {I1 is I0+1},              % the current index is calculated              
   [I1],                      % and is in the list I
   indices(Ls,I1).            % the same holds for the tail

请注意,大括号中的目标是正常的Prolog目标。如果使用给定的示例查询此谓词,则可以获得所需的解决方案:

   ?- matrix_indices([[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]],I).
I = [2,3,4,5,7,8] ? ;
no

您也可以在另一个方向使用谓词,但是您必须要求具体长度或前缀目标length(M,_)以防止谓词循环。例如查询...

   ?- length(M,_), matrix_indices(M,[2,3,4,5,7,8]).
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ? ;
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F,[0,0,0]],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ? ;
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F,[0,0,0],[0,0,0]],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ? 
.
.
.

......按预期产生无限多的答案。

答案 1 :(得分:3)

如何使用findall / 3和nth1 / 3来解决:

?- M = [[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]],
   findall(I, (nth1(I,M,E), E\=[0,0,0]), L).
L = [2, 3, 4, 5, 7, 8]