重复列表

时间:2013-01-30 08:40:29

标签: lambda prolog

说我需要一个谓词代表(?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 没有实例化时,我找不到表达 Times RemTimes 之间关系的方法。

4 个答案:

答案 0 :(得分: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绑定(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])循环!

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

我不知道一个专门的内置。这是一个使用length / 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), !.

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

答案 3 :(得分: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] ;