Prolog: Doubling the value of each element in a list of lists and returning a single list
I need write a set of clauses that ta开发者_JAVA技巧ke a list of integer lists and return a single list with all the elements doubled.
For example:
?- double([[1,2],[3]], X).
Yes
X = [2,4,6]
I have a set of clauses called mega_append that return a single list from a list of lists.
For example:
?- mega_append([[1,2],[3]], X).
Yes
X = [1,2,3]
Here is my progress (m_a is short for mega_append):
double([],[]).
double(List,[H1|T1]) :-
m_a(List,[H2|T2]),
H1 is 2 * H2,
double(T2, T1).
I'll try to explain how I thought it would work. I flatten the first list and split it up into a head and a tail (H2 and T2). I split the second list into a head and a tail (H1 and T1). I check to make sure that H1 (the doubled value) is equal to 2 times H2 (the original value). If it is then I check the rest of the list. Eventually if they all match correctly I should be left with two empty lists which should match the first clause and return yes.
It works when there is only a single value (for example: double([[1]], X)
). Can anyone offer any insight into what I am doing wrong? Is my logic or code incorrect?
Your problem is that T2 is a single list so List after the recursive call is not a list of lists.
To solve this you can first use mega_append to flatten the list and then use an auxiliary predicate to work on the flattened list. I.e. the double will look like this:
double([],[]).
double(List,X) :-
m_a(List,FList),
double_aux(List, FList).
Edit: Here is a way to only use one clause since you want to see one. I recommend using an auxiliary predicate.
double([],[]).
double([[]],[]).
double(List,[H1|T1]) :-
mega_append(List,[H2|T2]),
H1 is 2 * H2,
double([T2], T1).
Using clpfd, we define the dcg nonterminal double//1
like this:
:- use_module(library(clpfd)).
double([]) --> [].
double([D|Ds]) --> {DD #= D*2}, [DD], double(Ds).
Let's run some queries—using phrase/2
,
apply:foldl/4
, and nonterminal 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.
Want more examples using phrase/[2,3]
?
Read this SICStus Prolog manual page!
精彩评论