split(0).
split(M,List) :-
M > 0,
MM is floor(M / 10),
Z is M mod 10,
append(List,[Z],SubList),
nl,
print(SubList),
split(MM,SubList).
答案 0 :(得分:2)
这可能是一个简单的错字:你的split/1
事实有一个,而你的归纳案例有两个。修改您的第一行:
split(0,[]).
你应该以相反的方式使用append/3
:
append(SubList,[Z],List),
所以谓词就像:
split(0,[]).
split(M,List) :-
M > 0,
MM is floor(M / 10),
Z is M mod 10,
append(SubList,[Z],List),
split(MM,SubList).
将解决问题部分:它将返回一个正确的答案。但随后陷入无限循环。原因是您在append/3
和List
未实例化的情况下致电SubList
,所以就像:
append(A,[3],B).
将其运行到运行时环境中会生成:
?- append(A,[3],B).
A = [],
B = [3] ;
A = [_G218718],
B = [_G218718, 3] ;
A = [_G218718, _G218724],
B = [_G218718, _G218724, 3] ;
A = [_G218718, _G218724, _G218730],
B = [_G218718, _G218724, _G218730, 3] ;
A = [_G218718, _G218724, _G218730, _G218736],
B = [_G218718, _G218724, _G218730, _G218736, 3] ;
A = [_G218718, _G218724, _G218730, _G218736, _G218742],
B = [_G218718, _G218724, _G218730, _G218736, _G218742, 3];
(等)
因此,append/3
谓词成功的列表数量无限,所有这些列表都会失败,因为最终您使用split/2
调用0
需要一个空列表,并且事实并非如此。
将append/3
与一个元素一起使用通常效率不高:每次插入会导致 O(n)时间复杂度,因此对于此问题,您的split/2
谓词将会在O(n 2 )中运行。解决方案是使用累加器:通过递归调用更新的变量。在这种情况下,您的第一个谓词将split/2
与split/3
相关联:带累加器的版本。
split(A,B) :-
split(A,[],B).
现在split/3
的归纳案例再次是A == 0
的归纳案例。在这种情况下,我们将累加器视为最终结果:
split(0,B,B).
归纳案例意味着我们寻找数字,将其添加到累加器的头部,然后递归传递:
split(M,Acc,Res) :-
M > 0,
MM is floor(M / 10),
Z is M mod 10,
split(MM,[Z|Acc],Res).
所以把它们放在一起,我们的版本有以下代码:
split(A,B) :-
split(A,[],B).
split(0,B,B).
split(M,Acc,Res) :-
M > 0,
MM is floor(M / 10),
Z is M mod 10,
split(MM,[Z|Acc],Res).