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

发布于 2024-12-12 07:10:29 字数 560 浏览 0 评论 0原文

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

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

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

我有谓词:

get(Row,Col,TheChar) :- 

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

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

我是序言新手,在这方面遇到了很大的困难。

任何帮助将不胜感激!

谢谢你!

I am having trouble figuring out how to access a single character from a list of strings without using recursion, but instead backtracking.

For example I have this list of Strings and I want to be able to return a single character from one of these strings ('.' 'o', '*'). The program I am working on is treating it as rows and columns. It is a fact in my database that looks like this:

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

I have the predicate:

get(Row,Col,TheChar) :- 

that takes a row and column number (with index starting at 1) and returns the entry (TheEntry) at that specific row and column.

I have a feeling my predicate head might not be build correctly but I'm really more focused on just how to go through each String in the list character by character without recursion and returning that.

I am new to prolog and am having major difficulty with this.

Any help at all would be greatly appreciated!

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

和影子一齐双人舞 2024-12-19 07:10:29

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 = *

希望这会有所帮助。

An implementation of get/3 might look like this:

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

Note that TheChar is unified to a character code e.g.

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

If you want to get see the character you can for instance use atom codes, e.g.

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

Hope this helps.

生来就爱笑 2024-12-19 07:10:29

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

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

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

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

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

用几种不同的方式表示该矩阵:

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

    <前><代码>“ABCDEFGHIJKL”

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

    ( 行长度 * 行偏移 ) + ColOffset
    

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

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

    矩阵(行(行('A','B','C','D'),
                  行('E','F','G','H') ,
                  行('I','J','K','L')
                )
          )。
    

    查找仍然很简单:

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

  • 第三种选择可能是使用数据库更直接地表示矩阵,使用数据库谓词 assertaassertzretract 、 <代码>retractall、recordarecordz记录擦除。您可以构建事实结构,例如在数据库中按照以下方式构建事实结构:

    矩阵( Matrix_Name )。
    
    矩阵单元(矩阵名称、行号、列号、值)。
    

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

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

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

TMTOWTDI(Tim-Toady 或“有不止一种方法可以做到这一点”)正如 Perl 社区中所说的那样。

using your matrix representation, you could do something like this:

cell(X,Y,Cell) :-
matrix(Rows) ,
Matrix =.. [matrix|Rows] ,
arg(X,Matrix,Cols) ,
Row =.. [row|Cols] ,
arg(Y,Row,Cell)
.

The use of =.. to construct terms on the fly might be a hint that your matrix representation isn't the best. You might consider different representations for your matrix.

Assuming a "standard" matrix with fixed-length rows, you could represent the matrix

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

in a couple of different ways:

  • A single string, if the cell values can be represented as a single character and your prolog supports real strings (rather than string-as-list-of-char-atoms):

    "ABCDEFGHIJKL"
    

    Lookup is simple and zero-relative (e.g., the first row and the first column are both numbered 0):

    ( RowLength * RowOffset ) + ColOffset
    

    gives you the index to the appropriate character in the atom. Retrieval consists of a simple substring operation. This has the advantages of speed and simplicity.

  • a compound term is another option:

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

    Lookup is still simple:

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

  • A third option might be to use the database to represent your matrix more directly using the database predicates asserta, assertz, retract , retractall , recorda, recordz, recorded, erase. You could build a structure of facts, for instance in the database along the lines of:

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

    This has the advantage of allowing both sparse (empty cells don't need to be represented) and jagged (rows can vary in length) representations.

  • Another option (last resort,you might say) would be to jump out into a procedural language, if your prolog allows that, and represent the matrix in a more...matrix-like manner. I had to do that once: we ran into huge performance problems with both memory and CPU once the data model got past a certain size. Our solution was to represent the needed relation as a ginormous array of bits, which was trivial to do in C (and not so much in Prolog).

I'm sure you can come up with other methods of representing matrices as well.

TMTOWTDI (Tim-Toady or "There's More Than One Way To Do It") as they say in the Perl community.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文