Prolog:匹配一个或多个匿名变量

时间:2012-03-19 22:18:53

标签: prolog

[_,[X,_],_]将匹配[d,[X,a],s]之类的列表。有没有办法将它与任何有一个或多个匿名变量的模式相匹配?即。 [[X,a],s]和[[d,a],[p,z],[X,b]]会匹配吗?

我正在尝试编写一个程序来计算列表中的元素,即。 [a,a,a,b,a,b] => [[a,4],[b,2]]但我被卡住了:

listcount(L, N) :-  listcountA(LS, [], N).
listcountA([X|Tail], [? [X, B], ?], N) :- B is B+1, listcountA(Tail, [? [X,B] ?], N).
listcountA([X|Tail], AL, N) :- listcountA(Tail, [[X,0]|AL], N).

感谢。

3 个答案:

答案 0 :(得分:2)

变量匹配 term ,anonimus变量不是异常。列表只是头部和尾部之间的二元关系的语法糖。因此变量可以匹配列表,头部或尾部,但不是未指定的序列。

我希望能帮到你的一些说明:

  

listcount(L,N): - listcountA(LS,[],N)。

在Prolog中,谓词由名称 num.of.arguments标识,所谓的 functor arity 。所以通常带有附加参数的“service”谓词保持相同的名称。

  

listcountA([X | Tail],[?[X,B],?],N): - B是B + 1,listcountA(Tail,[?[X,B]?],N)。< / p>

B是B + 1永远不会成功,你必须使用新变量。并且没有办法在列表中匹配,使用'通配符',就像你似乎做的那样。而是编写一个谓词来查找和更新计数器。

最后一点:通常元素使用二元关系表示,方便一些(任意)运算符。例如,最常用的是破折号。

所以我会写

listcount(L, Counters) :-
    listcount(L, [], Counters).

listcount([X | Tail], Counted, Counters) :-
    update(X, Counted, Updated),
    !, listcount(Tail, Updated, Counters).
listcount([], Counters, Counters).

update(X, [X - C | R], [X - S | R]) :-
    S is C + 1.
update(X, [H | T], [H | R]) :-
    update(X, T, R).
update(X, [], [X - 1]).  % X just inserted

update / 3可以使用一些库谓词简化,“移入内部”递归。例如,使用select / 3:

listcount([X | Tail], Counted, Counters) :-
    ( select(X - C, Counted, Without)
    ->  S is C + 1
    ;   S = 1, Without = Counted
    ),
    listcount(Tail, [X - S | Without], Counters).
listcount([], Counters, Counters).

答案 1 :(得分:1)

我会在这篇文章的前言中说,如果你喜欢这个答案,请考虑给@chac正确答案,因为这个答案是基于他们的答案。

这是一个版本,它还使用累加器并处理输入列表中的变量,为您提供直接要求的输出术语结构:

listcount(L, C) :-
    listcount(L, [], C).
listcount([], PL, PL).
listcount([X|Xs], Acc, L) :-
    select([X0,C], Acc, RAcc), 
    X == X0, !,
    NewC is C + 1,
    listcount(Xs, [[X0, NewC]|RAcc], L).
listcount([X|Xs], Acc, L) :-
    listcount(Xs, [[X, 1]|Acc], L).

请注意listcount/2遵循基于累加器的版本listcount/3,它维护累加器中的计数,并且不假设输入排序或地面输入列表(命名/标记变量将正常工作) )。

答案 2 :(得分:0)

[_,[X,_],_]只匹配有3个元素的列表,第1个和第3个可以是原子或列表,第二个元素必须是长度为2的列表,但我知道你知道。它与2个元素列表不匹配,为了找到元素并将其插入结果列表,最好使用头尾递归。 下面是一个谓词草图,如果复制粘贴,我打赌不会工作;)

% find_and_inc(+element_to_search, +list_to_search, ?result_list)
find_and_inc(E, [], [[E, 1]]);
find_and_inc(E, [[E,C]|T1], [[E,C1]|T2]) :- C1 is C+1;
find_and_inc(E, [[K,C]|T1], [[K,C]|T2]) :- find_and_inc(E, T1, T2).