按另一个列表的项目数复制列表

时间:2018-05-04 11:02:34

标签: prolog

我试图做到这一点:

times([x, x], [1, 5, 9, 8], Result).

第二个列表由第一个列表中的元素数量复制。

结果是:[1, 5, 9, 8, 1, 5, 9, 8]

我已经尝试了这个但是工作不正常:

times( [ ], _, [ ] ) :- !.
times( [ _ | List1 ], List2, Result ) :-    append( [], List2, Result ),
                                            times( List1, List2, Result ).

提前致谢!

2 个答案:

答案 0 :(得分:2)

首先,您不需要在基本情况下进行切割。它不必要地修剪解决方案搜索:

replicate([], _, []).   % The empty list is the result of replicating any list by []

然后你的递归规则replicate([_|List1], List2, Result)似乎有一个合理的格式/头。但是你体内存在逻辑问题。如果你要描述逻辑,那就没有意义了。特别是,您在两个不同的地方使用Result来表达两种不同的含义,这将导致意外失败。谓词只需逻辑思考它的含义:

  

ResultList2 复制[_|List1],如果 SubResultList2复制List1 }和Result是将SubResult附加到List2的结果。

注意使用" subresult" (SubResult)这里与主要结果(Result)不同。重要的是这些是不同的变量。

如果你把它写成Prolog,你会得到:

replicate([_|List1], List2, Result) :-
    replicate(List1, List2, SubResult),
    append(List2, SubResult, Result).

我没有对此进行测试,但基本上应该这样做。作为Prolog学习过程的一部分,您应该尝试并自行解决任何遗留问题。我也没有考虑是否有更有效的解决整体问题的方法,但我只是用你当前的方法来解决你的问题。

<小时/> 另一种方法是使用maplist/2append/2。您可以使用maplist/3获取列表列表,然后使用append/2获取结果:

replicate(List1, List2, Result) :-
    length(List1, Len),
    length(R1, Len),
    maplist(=(List2), R1),
    append(R1, Result).

<小时/> 稍微考虑一下,可以使用简单的递归列表处理来解决这个问题。在这种情况下,您将以第二个列表中每个元素的头部递归统一结果的头部,然后对第一个列表中的每个元素继续此过程。

replicate(Rep, List, Res) :-
    replicate(Rep, List, List, Res).

replicate([], _, _, []).
replicate([R|Rs], List, [X|Xs], [X|Res]) :-
    replicate([R|Rs], List, Xs, Res).
replicate([R|Rs], List, [], Res) :-
    replicate(Rs, List, List, Res).

答案 1 :(得分:1)

我们可以用第二个列表替换第一个中的每个元素,然后调用append/2(SWI Prolog有一个):

nreplicate( Xs, Ys, Result) :-
  maplist( subst(Ys), Xs, Zs),
  append( Zs, Result ).

subst(Ys, _, Ys).