我需要编写一组带有整数列表列表的子句,并返回一个包含所有元素的单个列表。
例如:
?- 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)
)。谁能提供任何有关我做错的见解?我的逻辑或代码不正确吗?
答案 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)
使用clpfd,我们定义dcg 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.