我试图做到这一点:
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 ).
提前致谢!
答案 0 :(得分:2)
首先,您不需要在基本情况下进行切割。它不必要地修剪解决方案搜索:
replicate([], _, []). % The empty list is the result of replicating any list by []
然后你的递归规则replicate([_|List1], List2, Result)
似乎有一个合理的格式/头。但是你体内存在逻辑问题。如果你要描述逻辑,那就没有意义了。特别是,您在两个不同的地方使用Result
来表达两种不同的含义,这将导致意外失败。谓词只需逻辑思考它的含义:
Result
是List2
复制[_|List1]
,如果SubResult
是List2
复制List1
}和Result
是将SubResult
附加到List2
的结果。
注意使用" subresult" (SubResult
)这里与主要结果(Result
)不同。重要的是这些是不同的变量。
如果你把它写成Prolog,你会得到:
replicate([_|List1], List2, Result) :-
replicate(List1, List2, SubResult),
append(List2, SubResult, Result).
我没有对此进行测试,但基本上应该这样做。作为Prolog学习过程的一部分,您应该尝试并自行解决任何遗留问题。我也没有考虑是否有更有效的解决整体问题的方法,但我只是用你当前的方法来解决你的问题。
<小时/> 另一种方法是使用maplist/2
和append/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).