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

Prolog 序言:将列表列表中每个元素的值加倍并返回单个列表,prolog,clpfd,dcg,Prolog,Clpfd,Dcg,我需要编写一组子句,这些子句接受一组整数列表,并返回一个包含所有元素的列表 例如: ?- double([[1,2],[3]], X). Yes X = [2,4,6] ?- mega_append([[1,2],[3]], X). Yes X = [1,2,3] 我有一组名为mega_append的子句,它们从列表中返回单个列表 例如: ?- double([[1,2],[3]], X). Yes X = [2,4,6] ?- mega_append([[1,2],[3]], X). Y

我需要编写一组子句,这些子句接受一组整数列表,并返回一个包含所有元素的列表

例如:

?- double([[1,2],[3]], X).
Yes
X = [2,4,6]
?- mega_append([[1,2],[3]], X).
Yes
X = [1,2,3]
我有一组名为mega_append的子句,它们从列表中返回单个列表

例如:

?- double([[1,2],[3]], X).
Yes
X = [2,4,6]
?- mega_append([[1,2],[3]], X).
Yes
X = [1,2,3]
以下是我的进展(m_a是mega_append的缩写):

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


当只有一个值(例如:
double([[1]],X)
)时,它可以工作。有人能洞察我做错了什么吗?我的逻辑或代码不正确吗?

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

要解决这个问题,您可以首先使用mega_append来展平列表,然后使用辅助谓词来处理展平的列表。 也就是说,双人床的外观如下所示:

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

double([])     --> [].
double([D|Ds]) --> {DD #= D*2}, [DD], double(Ds).
编辑: 这里有一种只使用一个子句的方法,因为您希望看到一个子句。 我建议使用辅助谓词

double([],[]).
double([[]],[]).
double(List,[H1|T1]) :-
    mega_append(List,[H2|T2]),
    H1 is 2 * H2,
    double([T2], T1).
使用,我们定义双精度//1,如下所示:

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

double([])     --> [].
double([D|Ds]) --> {DD #= D*2}, [DD], double(Ds).
让我们使用, ,和非终结符
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. :-使用_模块(库(应用))。 -短语(foldl(double,[[1,2],[3]]),Xs)。 Xs=[2,4,6]。 -短语(foldl(double,[A,B],[C]],[2,4,6])。 A=1,B=2,C=3。 想要更多使用
短语/[2,3]
的示例吗?
阅读SICStus序言页

如果mega_append获得一个列表而不是列表列表,会发生什么?例?-mega_-append([2,3],X)。谢谢。我用那种方法就可以弄明白了。不过,我仍然相信,有一种方法可以做到这一点,那就是只使用一组子句。通常有一个
flatten/2
过程,它完成了您的
MUA/2
所做的事情。确实有。我已经用一个例子编辑了我的文章,但是imo使用辅助谓词比那个例子要好。(可能有一种我看不到的好方法。)@rvirding:它不一样。如果在原始代码中用flatte替换m_a,您会说它是有效的。也就是说,平坦(L1,L2),L1=L2,当L1是平坦的。你提到
flatte/2
是件好事,因为这绝对是值得了解的事情。同时,这是一个家庭作业,我怀疑
mega_append
是作为
flatten
的一个不太强大的版本精心设计的,特别是为了防止OP的第一次尝试。即使使用
flatten
我也会创建一个谓词来解决展平列表的问题,然后在更一般的情况下解决它使用该版本。你知道,问题分解。起初,我还试图将所有内容都放在一个谓词中,但有时最好将问题分解。