list - 带有列表的 Prolog 基本练习给出了堆栈大小错误
问题描述
我开始学习序言,我被这个问题困住了,如果有人能告诉我我做错了什么以及为什么错了这样我就可以学习,这将非常有帮助。
锻炼
编写一个遵循以下语法的谓词:
supr_bigger(元素,列表,结果)
其中Result是列表List ,但删除了所有大于Elem的元素。
代码
supr_bigger(_,[],[]).
supr_bigger(Elem,[X|Y],R) :- X =< Elem,
insert(X,R,R1),
supr_bigger(Elem,Y,R1).
supr_bigger(Elem,[X|Y],R) :- X > Elem, supr_bigger(Elem,Y,R).
insert(Z,L1,L2) :- choose(Z,L2,L1).
choose(X,[X|L],L).
choose(X,[Y|L1],[Y|L2]) :- choose(X,L1,L2).
当我尝试测试上面的代码时,出现了这个错误:
?- supr_bigger(3,[3,2,5,4,1,2,6],R)。
错误:超出堆栈限制(1,0Gb)
错误:堆栈大小:本地:2Kb,全局:0,9Gb,跟踪:0Kb
错误:堆栈深度:16,最后调用:13%,选择点:11
非常感谢提前。
解决方案
您可以使用谓词trace/1
来找出您的代码有什么问题:
?- trace, supr_bigger(3, [3,2,1,4], R).
Call: (11) supr_bigger(3, [3, 2, 1, 4], _4526) ? creep
Call: (12) 3=<3 ? creep
Exit: (12) 3=<3 ? creep
Call: (12) insert(3, _4526, _5168) ? creep
Call: (13) choose(3, _5210, _4526) ? creep
Exit: (13) choose(3, [3|_4526], _4526) ? creep
Exit: (12) insert(3, _4526, [3|_4526]) ? creep
Call: (12) supr_bigger(3, [2, 1, 4], [3|_4526]) ? creep
Call: (13) 2=<3 ? creep
Exit: (13) 2=<3 ? creep
Call: (13) insert(2, [3|_4526], _5482) ? creep
Call: (14) choose(2, _5524, [3|_4526]) ? creep
Exit: (14) choose(2, [2, 3|_4526], [3|_4526]) ? creep
Exit: (13) insert(2, [3|_4526], [2, 3|_4526]) ? creep
Call: (13) supr_bigger(3, [1, 4], [2, 3|_4526]) ? creep
Call: (14) 1=<3 ? creep
Exit: (14) 1=<3 ? creep
Call: (14) insert(1, [2, 3|_4526], _5796) ? creep
Call: (15) choose(1, _5838, [2, 3|_4526]) ? creep
Exit: (15) choose(1, [1, 2, 3|_4526], [2, 3|_4526]) ? creep
Exit: (14) insert(1, [2, 3|_4526], [1, 2, 3|_4526]) ? creep
Call: (14) supr_bigger(3, [4], [1, 2, 3|_4526]) ? creep
Call: (15) 4=<3 ? creep
Fail: (15) 4=<3 ? creep
Redo: (14) supr_bigger(3, [4], [1, 2, 3|_4526]) ? creep
Call: (15) 4>3 ? creep
Exit: (15) 4>3 ? creep
Call: (15) supr_bigger(3, [], [1, 2, 3|_4526]) ? creep
Fail: (15) supr_bigger(3, [], [1, 2, 3|_4526]) ?
如您所见,当输入列表为空时(调用 15),输出列表实际上包含所有应该选择的元素。但是,在这种情况下不能应用递归定义中的基本子句,因为列表(子句的第三个参数)和(目标的第三个参数)不匹配。supr_bigger/3
[]
[1, 2, 3|_4526]
要解决此问题,您可以将代码修改为:
- 关闭打开列表
[1, 2, 3|_4526]
,将其转换为[1, 2, 3]
. - 添加一个新参数来收集最终结果。
但是,由于您的代码还有许多其他问题,因此最好尝试一种更简单的方法:
supr_bigger(_, [], []).
supr_bigger(B, [X|Xs], [X|Ys]) :- X =< B, supr_bigger(B, Xs, Ys).
supr_bigger(B, [X|Xs], Ys) :- X > B, supr_bigger(B, Xs, Ys).
例子:
?- supr_bigger(3, [3,2,1,4], R).
R = [3, 2, 1] ;
false.
要消除虚假选择点,您可以执行以下操作
supr_bigger(B, L, R) :-
best_supr_bigger(L, B, R).
best_supr_bigger([], _, []).
best_supr_bigger([X|Xs], B, R) :-
( X =< B
-> R = [X|Ys]
; R = Ys ),
best_supr_bigger(Xs, B, Ys).
例子:
?- supr_bigger(3, [3,2,1,4], R).
R = [3, 2, 1].
推荐阅读
- bash - 为什么需要 nohup 并且 disown 本身不起作用?
- mongodb - mongodb 是否可以在 3 个服务器上安装 3 个分片,每个分片都有副本集
- angular - 如何以角度验证formarray?
- javascript - 用户提交日期后自动生成天数
- python - 列表问题中的python列表...将某些索引中具有某些值的元素移动到新列表如果不匹配则创建空列表
- redirect - 控制器中的操作后如何精确重定向页面(grails)
- java - 如何修复“渲染期间引发的异常:android.view.View 无法转换为 android.view.ViewGroup”
- python - 在 CentOS 中将 python 3 设置为默认 python 版本
- ios - 按下 uiAlert 按钮后以编程方式推送到新的 viewController
- r - R. Get_sentiments() 错误 - menu() 不能交互使用?