开发者

Prolog: Doubling the value of each element in a list of lists and returning a single list

开发者 https://www.devze.com 2023-01-18 03:59 出处:网络
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.

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!

0

精彩评论

暂无评论...
验证码 换一张
取 消