3

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

例如,我有这个字符串列表,我希望能够从这些字符串之一返回单个字符('。''o','*')。我正在处理的程序将其视为行和列。这是我的数据库中的一个事实,如下所示:

matrix(["...o....",
        ".******.",
        "...o....",
        ".*...*..",
        "..o..*..",
        ".....*..",
        ".o...*..",
        "....o..o"].

我有谓词:

get(Row,Col,TheChar) :- 

它采用行号和列号(索引从 1 开始)并返回该特定行和列的条目 (TheEntry)。

我有一种感觉,我的谓词头可能没有正确构建,但我真的更专注于如何逐个字符地遍历列表中的每个字符串而不递归并返回它。

我是 prolog 的新手,对此我有很大的困难。

任何帮助将不胜感激!

谢谢!

4

2 回答 2

3

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

get(Row,Col,TheChar) :-    
   matrix(M),
   nth(Row,M,RowList),
   nth(Col,RowList,TheChar).

请注意,TheChar 统一为字符代码,例如

| ?- get(1,4,X).
X = 111

如果您想查看字符,例如可以使用原子代码,例如

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

希望这可以帮助。

于 2011-10-27T07:53:13.810 回答
1

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

单元格(X,Y,Cell):-矩阵(行),矩阵=..[矩阵|行],arg(X,矩阵,列),行=..[行|列],arg(Y,行,细胞) 。

动态构建术语的使用=..可能暗示您的矩阵表示不是最好的。您可能会考虑矩阵的不同表示。

假设具有固定长度行的“标准”矩阵,您可以表示矩阵

A B C D
E F G H
I J K L

以几种不同的方式:

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

    "ABCDEFGHIJKL"
    

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

    ( RowLength * RowOffset ) + ColOffset
    

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

  • 复合词是另一种选择:

    matrix( rows( row('A','B','C','D') ,
                  row('E','F','G','H') ,
                  row('I','J','K','L')
                )
          ).
    

    查找仍然很简单:

    cell(X,Y,Matrix,Value) :- arg(X,Matrix,Row) , arg(Y,Matrix,Cell) 。

  • 第三种选择可能是使用数据库更直接地表示您的矩阵,使用数据库谓词asserta, assertz, retract, retractall, recorda, recordz, recorded, erase。您可以构建一个事实结构,例如在数据库中,如下所示:

    matrix( Matrix_Name ).
    
    matrix_cell( Matrix_Name , RowNumber , ColumnNumber , Value ).
    

    这具有允许稀疏(不需要表示空单元格)和锯齿状(行的长度可以变化)表示的优点。

  • 如果您的序言允许,另一种选择(最后的手段,您可能会说)是跳出程序语言,并以更像...矩阵的方式表示矩阵。我必须这样做一次:一旦数据模型超过一定大小,我们就会遇到内存和 CPU 的巨大性能问题。我们的解决方案是将所需的关系表示为一个巨大的位数组,这在 C 中是微不足道的(而在 Prolog 中则不然)。

我相信您也可以想出其他表示矩阵的方法。

TMTOWTDI(Tim-Toady 或“There's More Than One Way To Do It”)正如 Perl 社区中所说的那样。

于 2011-10-27T17:27:12.457 回答