1

[_, [ X , _ ],_] 将匹配像 [d, [X,a], s] 这样的列表。有没有办法将它与任何有一个或多个匿名变量的模式相匹配?IE。[[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).

谢谢。

4

3 回答 3

2

一个变量匹配一个term,anonimus 变量也不例外。列表只是头尾之间二元关系的语法糖。所以一个变量可以匹配列表、头部或尾部,但不能匹配未指定的序列。

我希望对您有所帮助的一些注意事项:

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

在 Prolog 中,谓词由 namenum.of.arguments 标识,即所谓的functorarity。所以通常带有附加参数的“服务”谓词保持相同的名称。

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

B is 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).
于 2012-03-19T23:49:08.143 回答
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它维护累加器中的计数,并且不假设输入排序或地面输入列表(命名/标记变量可以正常工作)。

于 2012-03-20T01:31:18.163 回答
0

[_, [X, _], _] 将仅匹配具有 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).
于 2012-03-19T22:53:26.767 回答