如何在 Prolog 中编写一个对列表进行操作的函数

How to program in Prolog a function that does operations on lists

如何在Prolog中编写包含n个a和n个b的程序,这里需要注意的是列表中a和b的数量必须相等,而且列表必须始终从头开始以 a 结束,以 b 结束,否则为假。示例:[a,b]true[a,a,a,b,b,b]true[a,a,a,a]false[a,a,a,b,b] 也是 false .

这是我尝试做的事情:

langageB([b]).
langageB([b| S]):- langageB(S).

language([]).

langage([a,b]).
langage([a | S]):- langage(S).
langage([a| S]):- langageB(S).

但它并没有像我想要的那样工作。

使用DCG表示法,所需的语言可以定义为:

langage --> [a,b].
langage --> [a], langage, [b]. % For each a at the beginning of the list 
                               % there must be a corresponding b at the end

langage(List) :- phrase(langage, List).

示例:

?- langage([a,a,a,b,b,b]).
true .

?- langage([a,a,b,b,b]).
false.

?- langage(L).
L = [a, b] ;
L = [a, a, b, b] ;
L = [a, a, a, b, b, b] ;
L = [a, a, a, a, b, b, b, b] .

如果你想看看如何直接使用差异列表定义谓词,你可以列出谓词的子句langage/2:

?- listing(langage).

langage([a, b|A], A).

langage([a|A], B) :-
    langage(A, C),
    C=[b|B].

因此,另一种解决方案是:

langage(List) :-
  langage(List, []).

langage([a, b|A], A).

langage([a|A], B) :-
    langage(A, C),
    C = [b|B].

假设例如[a, b, a, b] 是可接受的列表:

go :-
    findnsols(20, ABs, ab_list(ABs), ABsLst), !,
    writeln(ABsLst).


ab_list(ABsWrapped) :-
    length(ABs, Len),
    ab_list_(Len, 0, [], ABs),
    append([[a], ABs, [b]], ABsWrapped).


ab_list_(0, 0, ABs, ABs) :- !.

ab_list_(CharsToAdd, Bal, SoFar, ABs) :-
    succ(CharsToAdd0, CharsToAdd),
    add_char(Char, Inc),
    Bal1 is Bal + Inc,
    % Ensure that the balance can be zero for the complete list
    CharsToAdd0 >= abs(Bal1),
    ab_list_(CharsToAdd0, Bal1, [Char|SoFar], ABs).

add_char(b, -1).
add_char(a, 1).

结果:

?- time(go).
[[a,b],[a,a,b,b],[a,b,a,b],[a,a,a,b,b,b],[a,a,b,a,b,b],[a,b,a,a,b,b],[a,a,b,b,a,b],[a,b,a,b,a,b],[a,b,b,a,a,b],[a,a,a,a,b,b,b,b],[a,a,a,b,a,b,b,b],[a,a,b,a,a,b,b,b],[a,b,a,a,a,b,b,b],[a,a,a,b,b,a,b,b],[a,a,b,a,b,a,b,b],[a,b,a,a,b,a,b,b],[a,a,b,b,a,a,b,b],[a,b,a,b,a,a,b,b],[a,b,b,a,a,a,b,b],[a,a,a,b,b,b,a,b]]
    % 935 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 1419728 Lips)

原文:这是一个(非常低效的)解决方案,作为 swi-prolog 中的一行:

length(As, 2), same_length(As, Bs), maplist(=(a), As), maplist(=(b), Bs), append([As, Bs], ABs), distinct(ABsPerm, permutation(ABs, ABsPerm)), append([[a], ABsPerm, [b]], Final).
langage --> [a], ( [] | langage ) , [b].

?- phrase(langage, Xs).
   Xs = "ab"
;  Xs = "aabb"
;  Xs = "aaabbb"
;  Xs = "aaaabbbb"
;  Xs = "aaaaabbbbb"
;  ...