Prolog:将列表列表中每个元素的值加倍并返回单个列表

时间:2010-09-26 22:33:59

标签: prolog

我需要编写一组带有整数列表列表的子句,并返回一个包含所有元素的单个列表。

例如:

?- double([[1,2],[3]], X).
Yes
X = [2,4,6]

我有一组名为mega_append的子句,它从列表列表中返回单个列表。

例如:

?- mega_append([[1,2],[3]], X).
Yes
X = [1,2,3]

这是我的进步(m_a是mega_append的缩写):

double([],[]).
double(List,[H1|T1]) :-
    m_a(List,[H2|T2]),
    H1 is 2 * H2,
    double(T2, T1).

我会试着解释一下我认为它会起作用。我将第一个列表展平并将其分为头部和尾部(H2和T2)。我将第二个列表拆分为头部和尾部(H1和T1)。我检查以确保H1(加倍值)等于H2(原始值)的2倍。如果是,那么我检查列表的其余部分。最终如果它们都正确匹配,我应该留下两个空列表,它们应该匹配第一个子句并返回yes。

只有一个值时才有效(例如:double([[1]], X))。谁能提供任何有关我做错的见解?我的逻辑或代码不正确吗?

2 个答案:

答案 0 :(得分:2)

您的问题是T2是单个列表,因此递归调用后的List不是列表列表。

要解决此问题,您可以先使用mega_append来压缩列表,然后使用辅助谓词来处理展平列表。 即双重将如下所示:

double([],[]).
double(List,X) :-
    m_a(List,FList),
    double_aux(List, FList).

修改 这是一种只使用一个子句的方法,因为你想看到一个。 我建议使用辅助谓词。

double([],[]).
double([[]],[]).
double(List,[H1|T1]) :-
    mega_append(List,[H2|T2]),
    H1 is 2 * H2,
    double([T2], T1).

答案 1 :(得分:2)

使用,我们定义 nonterminal double//1,如下所示:

:- use_module(library(clpfd)).

double([])     --> [].
double([D|Ds]) --> {DD #= D*2}, [DD], double(Ds).

让我们使用phrase/2运行一些查询, apply:foldl/4和非终结double//1

:- use_module(library(apply)).

?- phrase(foldl(double,[[1,2],[3]]),Xs).
Xs = [2,4,6].

?- phrase(foldl(double,[[A,B],[C]]),[2,4,6]).
A = 1, B = 2, C = 3.

想要使用phrase/[2,3]的更多示例? 阅读this SICStus Prolog manual页面!