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
我也会创建一个谓词来解决展平列表的问题,然后在更一般的情况下解决它使用该版本。你知道,问题分解。起初,我还试图将所有内容都放在一个谓词中,但有时最好将问题分解。