【问题标题】:Generate list - geometric progression生成列表 - 几何级数
【发布时间】:2015-07-04 22:34:31
【问题描述】:

我想使用具有 4 个参数的谓词生成几何级数列表 - 将生成级数的列表、此列表的长度、起始元素和级数的乘数。到目前为止我所做的是只有一个 3 参数谓词来生成几何级数而不会停止:

gengeom([X],X,_).
gengeom([H|Tail],H,Q):-X is H*Q,gengeom(Tail,X,Q).

这个查询给了我开始元素 1 和乘数 2 的所有级数:

?-gengeom(L,1,2),write(L),nl,fail.

谁能帮我写出我真正想要的 4 参数谓词(在列表长度变为某个数字后停止生成更多数字)?

【问题讨论】:

    标签: list prolog


    【解决方案1】:

    只需添加一个倒计时参数即可,并将保留代码的良好生成属性:

    gengeom([X],X,_,_).
    gengeom([H|Tail],H,Q,N) :- N>1, M is N-1, X is H*Q, gengeom(Tail,X,Q,M).
    
    ?- gengeom(L,1,2,3).
    L = [1] ;
    L = [1, 2] ;
    L = [1, 2, 4] ;
    false.
    

    当然,您可以使用 findall/3,Prolog 的“列表生成器”变得更紧凑:

    gengeom(L,H,Q,N) :-
        findall(V, (between(H,N,M), V is Q**(M-1)), L).
    

    但是这个 sn-p(类似于 @joel76' 的帖子)将只构建“最终”列表...

    【讨论】:

      【解决方案2】:

      使用 SWI-Prolog,您可以编写:

      :- use_module(library(lambda)).
      
      gengeom(Len, Start, Multiplier, L) :-
          length(L, Len),
          foldl(\X^Y^Z^(X = Y,
                       Z is Y * Multiplier),
                L, Start, _).
      

      例如:

      ?- gengeom(5, 1, 2, L).
      L = [1, 2, 4, 8, 16].
      

      【讨论】:

      • 不错! 2 备注:Multiplier 需要声明为全局。所以foldl(Multiplier+\X^...foldl 目标本身已经可以很好地枚举所有长度。
      • @false。我同意你的第二句话(但 O.P. 想要固定长度),但你能解释一下为什么 Multiplier 需要被声明为全局的吗?
      • is 替换为#= 并使用未实例化的Multiplier 进行查询。
      • 换句话说:(\)/1 中的变量默认是本地的。
      • 好的,对我来说是 gengeom(+, +, +, -) !我没想过概括谓词
      【解决方案3】:

      好吧,正如您所问的,当列表的长度为 1 时,包括您需要更新停止条件为 true 的长度参数,并且一般子句必须在每一步中递减此长度。
      现在gengeom/4 谓词将如下所示:

      gengeom([X], X ,_, 1):- !.
      gengeom([H|Tail], H, Q, N):-N > 0, X is H * Q, N1 is N - 1, gengeom(Tail, X, Q, N1).
      

      这会找到开始 1、乘数 2 和长度 5 的级数

      ?- gengeom(L, 1, 2, 5).
      L = [1, 2, 4, 8, 16]
      

      您可以使用元谓词findall/3找到从长度1到所选长度的所有解决方案:

      findall(L, (member(N, [1,2,3,4,5]), gengeom(L,1,2, N)), R).
      

      这应该是完整的:

      gengeom([X], X ,_, 1):- !.
      gengeom([H|Tail], H, Q, N):-N > 0, X is H * Q, N1 is N - 1, gengeom(Tail, X, Q, N1).
      
      generate(Start, Step, Stop):- findall(L, (numlist(1,Stop, Len), member(N, Len), gengeom(L,Start,Step, N)), R), writeGen(R).
      
      writeGen([]).
      writeGen([H|Tail]):- write(H), nl, writeGen(Tail).
      

      测试

      ?- generate(1, 2, 5).
      [1]
      [1, 2]
      [1, 2, 4]
      [1, 2, 4, 8]
      [1, 2, 4, 8, 16]
      true
      

      【讨论】:

      • 如果你避免过度约束基本情况(见我的帖子)你会得到更好的结果,而不需要引入 findall/3
      猜你喜欢
      • 2016-11-09
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-10
      相关资源
      最近更新 更多