通过连接原子统一不同长度的列表

时间:2012-12-25 13:34:06

标签: list prolog wildcard matching dcg

考虑以下列表:

  

[我的,名称,是,千斤顶,鲍尔]

我想将其统一为以下模式:

  

[我的,名称,是,名称]

因此变量Name最后的值为'jack baur'。 该变量在这里作为某种通配符工作,并且应该与未知数量的原子/列表成员统一。

重要:

  • 变量/通配符并不总是在最后
  • 可能有多个变量/通配符

目前我有这样的事情:

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).

显然,只有当Name只是一个单词而不是两个单词时,这才有效。

我如何在Prolog中解决这个问题?

2 个答案:

答案 0 :(得分:1)

您需要自定义统一算法,例如:

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).

用法:

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

为了提高效率,此算法仅允许变量出现在L中。我会留下将原子粘贴在一起的问题,因为你似乎已经解决了这个问题。

请注意,当前版本允许变量匹配零原子,但您可以轻松添加约束以禁止它。

答案 1 :(得分:1)

这里有DCG的可能性。我认为这很干净。

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), !.

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

这里的基本生产是列表// 1,匹配任何明确长度的令牌列表。

注意:list(A),list(B),两者 A,B应该避免未绑定。 如果中间有令牌,就像在list(A),[and],list(B),

中一样