3

假设我需要一个谓词 rep( ?List , ?Times , ?TList ),如果List在TList中重复Times次,则该谓词为真(例如,)。只要实例化了两个参数,它就应该起作用。这是一个有点工作的版本:rep([a,c],2,[a,c,a,c])

rep(_,0,[]).
rep(List,1,List).
rep(List,Times,TList) :- integer(Times), Times>1,
    succ(RemTimes,Times), append(List,RemList,TList),
    rep(List,RemTimes,RemList).
rep(List,Times,TList) :- var(Times),
    append(List,RemList,TList),
    rep(List,RemTimes,RemList), !,
    succ(RemTimes,Times).

两个问题:

  1. 是不是有一些内置的(我找不到)可以做到这一点?
  2. 有没有更直接的方法来做到这一点?就像摆脱最后一个子句一样?这是必要的,因为当Times没有实例化时,我找不到表达TimesRemTimes之间关系的方法。
4

4 回答 4

1

你使用 SWI-Prolog,所以你可以这样做:

:- use_module(library(lambda)).

rep(Lst, N, R) :-
    (   numlist(1,N, NL)
    ->  foldl(\_X^Y^Z^append(Y, Lst, Z), NL, [], R)
    ;   R = []).

为了解决 CapelliC 的评论,不报告 X 绑定到 rep(X,2,[a,b,a,b]) 你必须写

foldl(Lst +\_X^Y^Z^append(Y, Lst, Z), NL, [], R)

[编辑] 谢谢@false!有趣的是

rep(Lst, N, R) :-
    (   nonvar(N)
    ->  length(NL, N),
        foldl(Lst +\_^Y^append(Y, Lst), NL, [], R)
    ;   foldl(Lst +\_^Y^append(Y, Lst), NL, [], R),
        length(NL, N)),
    !.

但不幸的是,它与 rep([a,b], N, [a,c,a,c]) 循环!

于 2013-01-30T09:43:19.617 回答
0

一个简单(但可能效率低下)的策略是扫描第二个列表并每次检查第一个是否是其余部分的子列表。

要进行检查,您可以使用prefix/2SWI-Prolog 中的运算符。

sublist_count(L, R, Times) :-
    sublist_count(L, R, 0, Times).
sublist_count(L, [], Times, Times).
sublist_count(L, [R | Tail], Times, End) :-
    prefix(L, [R | Tail]), !,
    NewTimes is Times + 1,
    sublist_count(L, Tail, NewTimes, End).
sublist_count(L, [R | Tail], Times, End) :-
    sublist_count(L, Tail, Times, End).
于 2013-01-30T09:40:23.757 回答
0

我不知道一个专门的内置。这是一个使用长度/2的生成能力的过程

rep(List, Times, TList) :-
    ( var(Times) ; Times > 0 ),  % after joel76' comment...
    ( var(List) ; is_list(List) ), % after false' comment...
    ( var(TList) ; is_list(TList) ), % idem...
    length(List, LA), LA > 0,
    length(TList, LT), LT > 0,
    Times is LT / LA,
    findall(List, between(1, Times, _), [List|Ls]),
    append([List|Ls], TList), !.

当任何列表空闲时,最终剪切避免循环。

于 2013-01-30T09:55:02.553 回答
0

以下是否有意义。(我不处理Times未定义的情况。)

rep(List, Times, TList) :-
    length(List, ListLen),
    PrefixLen is ListLen * Times,
    open_list(List, OpenList, OpenList),
    length(TList, PrefixLen),
    append(TList, _, OpenList).

其中open_list/3定义为:

open_list([], X, X).
open_list([H | T1], [H | T2], X) :-
    open_list(T1, T2, X).

这个想法是创建一个无限列表,然后切断所需的前缀。

使用示例:

?- rep([a, c], 2, TList).
TList = [a, c, a, c].

?- rep(List, 2, TList).
List = TList, TList = [] ;
List = [_G886],
TList = [_G886, _G886] ;
List = [_G886, _G889],
TList = [_G886, _G889, _G886, _G889] ;
于 2013-01-31T17:14:33.173 回答