【问题标题】:Is there a more efficient way to implement those 2 function in swi-prolog?有没有更有效的方法在 swi-prolog 中实现这两个功能?
【发布时间】:2019-06-09 18:15:25
【问题描述】:

有没有更快的方法在 swi-prolog 中实现这两个功能,以节省时间和内存?

insert(Ind,List,Val,NList) :-
    nth0(Ind,List,_,R),
    nth0(Ind,NList,Val,R).

build(X,N,List) :- 
    length(List,N),
    maplist(=(X),List). 

解释:第一个在列表的第 N 个位置插入一个值,第二个构建一个包含 N 个元素的列表,所有元素都等于数字 X

编辑:我想出了一种方法来改进我的程序的插入

insert(Ind,List,NList,R,Elem) :-
    Valb=Val,
    Val is Val+1,
    nth0(Ind,NList,Val,R),
    Elem=Valb.

这应该将列表中的元素替换为其值加 1 ,但还应在加 1 之前返回先前的值(Valb)。我知道代码是错误的,如果不再次使用 nth0,我怎么能使它正确?

【问题讨论】:

  • 两者都是O(n)。就时间复杂度而言,没有。您可以通过同时迭代两个列表来更高效地实现前者。
  • build(a,N,[b|_]) 循环,在更好的实现中可能会失败

标签: prolog


【解决方案1】:

就时间复杂度而言,两者都工作在 O(n) 时间和 O(n) 内存中。您不能在 O(n) 时间内构建包含 n 个元素的列表,并且它至少需要 O(n) 内存.可以懒惰地构建列表,从而推迟创建,但对于一个真正的列表,就时间复杂度而言。

然而,我们可以做的是“合并”两个谓词的逻辑,这样我们就可以在每次递归调用时做更多的事情,例如:

build(X,N,List) :-
    var(N),
    !,
    build_gen_(List, X, N).
build(X, N, List) :-
    integer(N),
    !,
    build_num_(N, List, X).

build_gen_([], _, 0).
build_gen_([X|T], X, N) :-
    build_gen_(T, X, N1),
    N is N1 + 1.

build_num_(0, [], _) :-
    !.
build_num_(N, [X|T], X) :-
    N > 0,
    N1 is N-1,
    build_num_(N1, T, X).

因此,我们基本上构造了一个特殊的谓词,它使用相同的谓词执行两个任务(构建长度为N 的列表,并将所有元素设置为X)。

我将专门研究第一个谓词insert/4 作为练习。

【讨论】:

  • _build2 是什么名字?
  • @WillemVanOnsem 感谢您的回答,请查看我帖子中的编辑
猜你喜欢
  • 2012-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 1970-01-01
  • 2019-06-27
相关资源
最近更新 更多