gpt4 book ai didi

list - Prolog 创建列表列表

转载 作者:行者123 更新时间:2023-12-02 12:56:37 30 4
gpt4 key购买 nike

我在序言中的列表列表中遇到了一些(或很多)问题。

所以我有一个数字列表,比如 [5,6,1,3] 作为输入。
输出应为 [[5,25],[6,36],[1,1],[3,9]]。

我已经有了一个谓词,即 'return 是 2 个项目列表(请记住,我必须更改 get_squared_pa​​ir 函数以获取其他一些相关值):

get_squared_pair(Number, Result) :-
get_squared_value(Number, SquareValue),
Result = [Number, SquareValue].

get_squared_value(Number, Result) :-
Result is Number * Number.

到这里为止,这是非常合乎逻辑的。现在我需要一个谓词,它递归地遍历一个列表,将平方对添加到一个新列表中,然后返回这个列表列表。我现在拥有的是:
return_list([], 0).
return_list([Head | Tail], Result) :-
get_squared_pair(Head, Add),
append(Add,Result),
return_list(Tail, Result).

由于多种原因,这不起作用,主要是因为我似乎无法弄清楚递归实际上如何处理列表,更不用说列表列表了。此外,它目前以错误的顺序运行,这无济于事。

我知道这可能有点含糊,但我试过用谷歌搜索解决这个问题,但似乎无法很好地将我发现的问题转化为我自己的问题。

任何帮助将非常感激!

最佳答案

让我们看看你的 get_squared_pair/2第一的。虽然它可以工作,但可以稍微整理一下,这也有助于理解 Prolog 的工作原理。 Prolog 的主要机制是统一,这与其他语言中的赋值不同。在统一中,Prolog 检查两个术语并尝试通过在其中一个或两个术语中实例化变量以使它们匹配来统一它们。 Prolog中有一些谓词,如is/2用于计算一个参数中的表达式,然后将第一个参数与该结果统一。

那么,你的第一个谓词,你写成:

get_squared_pair(Number, Result) :-
get_squared_value(Number, SquareValue),
Result = [Number, SquareValue].

get_squared_value(Number, Result) :-
Result is Number * Number.

可以通过两种方式简化。首先,您可以合并 get_squared_value/2因为它只是一行并且并不真正需要它自己的谓词。我们将重命名谓词,因此它不是必需的。
square_pair(Number, Square) :-
S is Number * Number, % Square the number
Square = [Number, S]. % Unify Square with the pair

Prolog 可以统一子句头部的术语,因此可以避免多余的统一。所以这就是你所需要的:
square_pair(Number, [Number, Square]) :-
Square is Number * Number.

转到主谓词, return_list/2 .首先,我们将这个谓词重命名为 square_pairs .在对列表进行递归时,最常见的模式是继续减少列表直到它为空,然后一个基本情况处理空列表。您的实现是这样做的,但基本情况有点困惑,因为第二个参数是整数而不是列表:
square_pairs([], 0).

这真的应该是:
square_pairs([], []).

您的主谓词子句没有正确使用 append/2 . append有两种形式在 SWI 序言中: append/2append/3 .您可以在 SWI Prolog 在线文档中查找它们的作用。我可以告诉你,在 Prolog 中,除非通过回溯,否则一旦实例化,就不能更改谓词子句中变量的值。例如,查看以下可能位于谓词子句中的序列:
X = a,    % Unify X with the atom 'a'
X = b, % Unify X with the atom 'b'

在这种情况下,第二个表达式将始终失败,因为 X已经统一了,不能再统一了。但是,如果我有这个:
foo(X),    % Call foo, which unifies X with a value that makes 'foo' succeed
bar(X, Y), % Call bar, which might fail based upon the value of 'X'

在上述情况下,如果 bar(X, Y)失败,那么 Prolog 将回溯到 foo(X)调用并寻找 X 的另一个值这使得 foo(X)成功。如果找到一个,那么它会调用 bar(X, Y)再次使用 X 的新值, 等等。

所以 append(Add, Result)不附加 AddResultResult 产生一个新值.事实上, append with two arguments 表示第二个列表参数是第一个列表的所有元素的串联,假设第一个参数是一个列表列表,那么 append/2 的定义反正不匹配。

在考虑您的递归时,请意识到参数列表彼此之间是一一对应的。结果列表的头部是第一个参数中列表头部的“平方对”。然后,递归地,第二个参数的尾部是第一个参数尾部的平方对列表。你只需要在 Prolog 中表达它。我们也可以使用我上面描述的技术在从句的头部进行统一。
square_pairs([Head | Tail], [SqPair | SqTail]) :-
square_pair(Head, SqPair),
square_pairs(Tail, SqTail).
square_pairs([], []).

现在我们可以做另一个简化,即消除 square_pair/2辅助谓词完全:
square_pairs([Head | Tail], [[Head, SqHead] | SqTail]) :-
SqHead is Head * Head,
square_pairs(Tail, SqTail).
square_pairs([], []).

Prolog 中有一个方便的谓词 maplist它可用于定义在两个列表之间并行运行的关系,这就是我们这里的场景。我们可以带回 square_pair/2谓词和使用 maplist :
square_pairs(Numbers, SquarePairs) :-
maplist(square_pair, Numbers, SquarePairs).

关于list - Prolog 创建列表列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29557841/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com