在Prolog中轻松复制元素:)

use*_*526 4 list prolog duplicates replicate

我正在研究一个更长的问题,我在列表表单中复制了N次元素,我相信使用append是正确的方法.这个小谓词理论上应该是这样的:

?- repl(x,5,L).
L = [x, x, x, x, x] ;
false.
Run Code Online (Sandbox Code Playgroud)

我似乎无法在网上找到任何提示,复制单个元素,但我相信我们需要使用append,但没有递归解决方案.我来自更多的Haskell背景,这个问题会更容易执行.有人可以帮我开始吗?:)

我的目前为止:

repl(E, N, R) :-
    N > 0, append([E], [], R), writeln(R), repl(E, N-1, R), fail.
Run Code Online (Sandbox Code Playgroud)

这给了我:

?- repl(x,5,L).
[x]
[x]
[x]
[x]
[x]
false.
Run Code Online (Sandbox Code Playgroud)

关闭但不完全!

lur*_*ker 11

递归方法是直截了当的,并且可行.我建议把它搞清楚.但这是一个有趣的选择:

repl(X, N, L) :-
    length(L, N),
    maplist(=(X), L).
Run Code Online (Sandbox Code Playgroud)

如果N被实例化,那么length(L, N)将生成一个长度N仅为"空白" 的列表(不关心术语).然后maplist(=(X), L)将统一L变量的每个元素X.

这给出了一个很好的关系方法,并在一般情况下产生了明智的结果:

| ?- repl(X, N, L).

L = []
N = 0 ? ;

L = [X]
N = 1 ? ;

L = [X,X]
N = 2 ? ;
| ?- repl(X, N, [x,x,x]).

N = 3
X = x

yes
...
Run Code Online (Sandbox Code Playgroud)

要想出一个递归的情况,想一想你的基本情况是什么样的(它将是repl一个计数0- 那么列表是什么样的呢?).在递归的情况下,请考虑:

repl(X, N, [X|T]) :- ...
Run Code Online (Sandbox Code Playgroud)

含义:如果...... ,列表[X|T]X重复的元素N.弄清楚是什么?如果你的基本情况是长0,那么你的递归很可能将描述repl长的列表N中的条款repl长的名单N-1.不要忘记在这个递归规则中,以确保N > 0避免回溯无限递归.如果你不需要谓词纯粹是关系的并且假设N是实例化的,那么它可以相当简单.

如果你创建一个简单的递归版本,你可以将它"包装"在这个谓词中,使其适用于变量N:

repl(X, N, L) :-
    length(L, N),
    simple_recursive_repl(X, N, L).

...
Run Code Online (Sandbox Code Playgroud)

因为length/2它是关系型的,所以它比提供给定列表的长度更有用.当NL没有实例化时,它将成为变量列表的生成器,从长度开始0.类型,length(L, N).在序言提示,看看会发生什么.

  • 更深奥,但更便携的非递归变体:`repl(X,N,L): - length(L,N),union(L,[X],[X]). (2认同)