Matrix Prolog-从列表列表中获取元素

Matrix Prolog-从列表列表中获取元素,matrix,prolog,row,backtracking,Matrix,Prolog,Row,Backtracking,我很难弄清楚如何在不使用递归而是使用回溯的情况下从字符串列表中访问单个字符 例如,我有这个字符串列表,我希望能够从其中一个字符串(“.”o“,“*”)返回一个字符。我正在编写的程序将其视为行和列。我的数据库中的一个事实如下所示: matrix(["...o....", ".******.", "...o....", ".*...*..", "..o..*..", ".....*..", ".o...*

我很难弄清楚如何在不使用递归而是使用回溯的情况下从字符串列表中访问单个字符

例如,我有这个字符串列表,我希望能够从其中一个字符串(“.”o“,“*”)返回一个字符。我正在编写的程序将其视为行和列。我的数据库中的一个事实如下所示:

matrix(["...o....",
        ".******.",
        "...o....",
        ".*...*..",
        "..o..*..",
        ".....*..",
        ".o...*..",
        "....o..o"].
get(Row,Col,TheChar) :-    
   matrix(M),
   nth(Row,M,RowList),
   nth(Col,RowList,TheChar).
我有一个谓词:

get(Row,Col,TheChar) :- 
它获取一个行和列编号(索引从1开始),并返回该特定行和列的条目(entry)

我有一种感觉,我的谓词头可能无法正确构建,但我更关注的是如何逐个字符地遍历列表中的每个字符串,而无需递归并返回该字符串

我不熟悉prolog,在这方面遇到了很大的困难

任何帮助都将不胜感激


谢谢大家!

get/3的实现可能如下所示:

matrix(["...o....",
        ".******.",
        "...o....",
        ".*...*..",
        "..o..*..",
        ".....*..",
        ".o...*..",
        "....o..o"].
get(Row,Col,TheChar) :-    
   matrix(M),
   nth(Row,M,RowList),
   nth(Col,RowList,TheChar).
请注意,字符统一为字符代码,例如

| ?- get(1,4,X).
X = 111
如果你想看到角色,你可以使用原子代码,例如

| ?- get(4,2,X), atom_codes(CharAtom,[X]).
X = 42
CharAtom = *

希望这有帮助

使用矩阵表示法,可以执行以下操作:

matrix(["...o....",
        ".******.",
        "...o....",
        ".*...*..",
        "..o..*..",
        ".....*..",
        ".o...*..",
        "....o..o"].
get(Row,Col,TheChar) :-    
   matrix(M),
   nth(Row,M,RowList),
   nth(Col,RowList,TheChar).
单元(X,Y,单元):- 矩阵(行), 矩阵=。。[矩阵|行], arg(X,矩阵,Cols), 行=。。[row | Cols], 参数(Y、行、单元格)

使用
=..
动态构造术语可能暗示您的矩阵表示不是最好的。你可以考虑矩阵的不同表示。 假设一个具有固定长度行的“标准”矩阵,您可以表示该矩阵

A B C D
E F G H
I J K L
以两种不同的方式:

  • 单个字符串,如果单元格值可以表示为单个字符,并且prolog支持实字符串(而不是字符串作为字符原子列表):

    查找很简单,并且是零相对的(例如,第一行和第一列的编号均为0):

    为您提供原子中相应字符的索引。检索由一个简单的子字符串操作组成。这具有快速和简单的优点

  • 复合术语是另一种选择:

    matrix( rows( row('A','B','C','D') ,
                  row('E','F','G','H') ,
                  row('I','J','K','L')
                )
          ).
    
    查找仍然很简单:

    单元(X、Y、矩阵、值):- arg(X,矩阵,行), arg(Y,矩阵,单元)

  • 第三种选择可能是使用数据库谓词
    asserta
    assertz
    retract
    retractall
    recorda
    recordz
    recorded
    erase
    。您可以构建事实的结构,例如,在数据库中,沿着以下路线:

    matrix( Matrix_Name ).
    
    matrix_cell( Matrix_Name , RowNumber , ColumnNumber , Value ).
    
    这具有允许稀疏(不需要表示空单元格)和锯齿(行的长度可以不同)表示的优点

  • 另一种选择(你可能会说,最后一种选择)是跳出到一种过程语言中,如果你的prolog允许的话,并以一种更…类似于矩阵的方式表示矩阵。我不得不这样做一次:一旦数据模型超过一定的大小,我们在内存和CPU上都遇到了巨大的性能问题。我们的解决方案是将所需的关系表示为一个巨大的位数组,这在C语言中很容易做到(在Prolog中也不太容易做到)

我相信你也能想出其他表示矩阵的方法


(Tim Toady或Perl社区中的“不止一种方法”)在swi prolog中没有第n个,因此,
get/3
不是真正正确和安全的。有
nth0/3
nth1/3
谓词是有用的。我也会这样做,以及dmalikov(+1)上面建议使用或
nth1/3
,如果它们不在您的实现中,它们很容易实现。您能解释一下您的意思吗“在不递归的情况下逐字符遍历列表中的每个字符串”?如果要在长度不确定的字符串上进行迭代,则在没有某种递归的情况下无法进行。只有知道字符串的长度,才能执行类似于写n子句(如果长度=n)的操作来访问单个字符。