magnattic
magnattic

Reputation: 13038

Unifying lists of different length by concatenating atoms

Consider the following list:

[my,name,is,jack,baur]

I want to unify this to the following pattern:

[my,name,is,Name]

So that the variable Name has the value 'jack baur' in the end. The variable is working as some sort of wildcard here and should unify with an unknown number of atoms/list members.

Important:

Currently I have something like this:

rule([my,name,is,Name],[hello,Name]).

% Sentence is a list (e.g. [my,name,is,jack,baur]
answer(Sentence,Response) :-
    rule(Sentence,ResponseList),
    atomic_list_concat(ResponseList,' ',Response).

Obviously this only works when Name is exactly one word, not two.

How would I approach this problem in Prolog?

Upvotes: 2

Views: 185

Answers (2)

CapelliC
CapelliC

Reputation: 60034

here a DCG possibility. It's fairly clean, I think.

list(L) --> {length(L, _)}, L.

rule(R) -->
    [my, name, is], list(Name),
    [and, i, live, in], list(Country),
    {flatten([hello, Name, of, Country],R)}.

rule([hello|Name]) -->
    [my, name, is], list(Name) .

answer(Sentence, Response) :-
    phrase(rule(Response), Sentence), !.

with that

?- answer([my, name, is, bill, the, kid, and, i, live, in, new, york],R).
R = [hello, bill, the, kid, of, new, york].

the essential production here is list//1, that matches any definite length list of tokens.

Beware: list(A),list(B),, with both A, B unbound should be avoided. It's ok instead if there are tokens in between, like in list(A),[and],list(B),

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363817

You need a custom unification algorithm, such as the following:

unify([], []).
unify([X|L], R) :-
    (var(X) ->
        % unify the variable X with some prefix of R
        append(X, Tail, R),
    ;
        R = [X|Tail],
    ),
    unify(L, Tail).

Usage:

1 ?- unify([i, am, a, Profession, and, i, Verb, it],
           [i, am, a, prolog, programmer, and, i, like, it]).
Profession = [prolog, programmer],
Verb = [like].

This algorithm only allows variables to occur in L for the sake of efficiency. I'll leave the problem of pasting atoms together to you, since you seem to have already solved that.

Note that the current version allows variables to match zero atoms, but you can easily add a constraint to disallow that.

Upvotes: 1

Related Questions