首页 > 解决方案 > 如何从 Prolog 中的矩阵中获取值?

问题描述

我是Prolog的初学者,所以我仍然对如何在Prolog中形成递归函数感到困惑。

假设我有一个矩阵:

S: 
[ 5   6 
  3   4 ] 

在 prolog 中表示为:S = [ [5,6], [3,4]]。

我正在尝试编写一个递归函数来获取单元格值,这样 cell_values (Cells, Matrix, Values) 将返回单元格列表中的值列表。

示例:cell_values ([[0,0], [0,1]], S, Values) --> Values = [5, 6]。其中 S 是上面的矩阵。

我正在考虑使用 nth0 来获取价值。这是我迄今为止的工作。

:- use_module(library(clpfd)).

cell_values([], [], []).
cell_values([X|T], S, Values) :- 
    nth0(X, S, Row),
    nth0(T, Row, Values).

不知道如何解决这个问题。你能为我指出正确的方向吗?

标签: prolog

解决方案


这里的谓词存在一些问题:

  1. 您使用SandT作为行号和列号,但S它是列表的头部,在T这里是尾部。由于索引列表是列表列表,这意味着S将是一个列表和T一个列表列表;
  2. 您不使用递归来生成值列表,因此如果我们修复上述问题,那么它仍然 - 最多 - 会产生一个特定的值;和
  3. 基本谓词过于严格,因为它假定矩阵(第二个参数)应该为空。这是没有意义的,因为通常矩阵将在没有任何更改的情况下传递。无论矩阵如何,如果索引列表为空,则值列表也是如此。

显式递归

所以如果我们重写谓词,有两个规则:

  1. 基本情况:如果索引列表为空,那么无论矩阵如何,值列表也为空:

    cell_values([], _, []).
    
  2. 在递归 cass 中,我们将第一个列表与 匹配,行号也是[[R, C] | T]如此,列是要处理的剩余列表的列表,因此我们执行问题中演示的 ,但使用and和单元格值被添加到结果列表中,然后在递归调用中使用以获取更多元素:RCTnth0/3RCV[V|VT]VT

    cell_values([[R, C]| T], M, [V|VT]) :-
        nth0(R, M, Row),
        nth0(C, Row, V),
        cell_values(T, M, VT).
    

或者把这些放在一起:

cell_values([], _, []).
cell_values([[R, C]| T], M, [V|VT]) :-
    nth0(R, M, Row),
    nth0(C, Row, V),
    cell_values(T, M, VT).

maplist/3

处理列表是一件相当常见的事情,所以我们可能有兴趣使用maplist/3,并编写一个只处理单个子列表的谓词,例如:

cell_value(M, [R, C], V) :-
    nth0(R, M, Row),
    nth0(C, Row, V).

然后我们可以像这样定义谓词cell_values

cell_values(Ixs, M, Vs) :-
    maplist(cell_value(M), Ixs, Vs).

推荐阅读