Lambda 重复列表

Lambda 重复列表,lambda,prolog,Lambda,Prolog,假设我需要一个谓词rep(?List,?Times,?TList),它是真的,如果List在TList中重复多次(例如,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,?Times,?TList),它是真的,如果List在TList中重复多次(例如,
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).
两个问题:

  • 是不是有一些内置的(我找不到)可以做到这一点
  • 有没有更直接的方法?比如去掉最后一条?这是必要的,因为当时间没有实例化时,我找不到一种表达时间和RemTimes之间关系的方法
  • 一个简单(但可能效率低下)的策略是扫描第二个列表,每次检查第一个列表是否是剩余部分的子列表

    要进行检查,可以使用SWI 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).
    

    您可以使用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 = []).
    
    为了解决Capelical的评论,没有报告rep上的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])循环

    我不知道什么是专门内置的。这里是一个使用/2生成功能的过程


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

    以下内容有意义吗。(我不会处理
    时间
    未定义的情况。)

    其中,
    打开列表/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] ;
    

    rep([a,b],X[a,b,a,b])上给出错误
    并且没有在
    rep(X,2[a,b,a,b])上报告X绑定
    我不确定我是否理解。。。我的SWI Prolog找不到这样的库,也找不到在SWI Prolog网页上记录的库@鲍里斯:我想你应该从乌尔里希的网站得到。好吧,它不在SWI库+1中。您可以使用部分应用程序缩短lambda:
    foldl(Lst+\\\^Y^append(Y,Lst),NL,[],R)
    在时间为负时不起作用(我同意它在上下文中没有任何意义)。rep(L,N,[a,c,a,c])。给出L=[a],N=4。这正是我的目标。我没有意识到我可以用这种方式使用findall。@Boris-注意findall的特殊模式[List | Ls]是
    result
    。这会在列表空闲时强制绑定,这是必需的,因为findall/3会复制分发给它的术语…
    rep([1],1,[1,1 | |])
    loops。这在规范范围内。很明显,在时间未定义的情况下,产生了初始问题。没有它,它就不是一个纯粹的谓词。。。。
    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] ;