list - SWI-Prolog:当列表为空时如何停止谓词?(包括谓词)
问题描述
course(cmput325).
course(cmput175).
course(cmput201).
course(cmput204).
prerequisite(cmput204, cmput325).
prerequisite(cmput175, cmput201).
prerequisite(cmput175, cmput204).
我需要写一个新的谓词,即
can_take(+L,?C).
定义:
L 是一个学生已经学习过的课程列表。如果 C 也给出了,那么谓词应该检查学生是否拥有 C 的所有必修课程。如果 C 是一个变量,那么通过回溯,谓词应该一次产生学生现在可以学习的一门课程。课程可以按任何顺序排列,但每门课程只能生成一次,并且您不应返回学生已经学习过的任何课程。
例子:
?- findall(C, can_take([cmput175], C), L).
should return
L = [cmput201, cmput204].
这是我的谓词:
can_take(L,C) :- prerequisite(L,C).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
这个谓词没有返回正确的结果,它只是返回了假。我认为这是因为我没有确定 L 为空时的条件,但是,如果我尝试在其中任何一个中添加 L \== [] 。它仍然给了我错误......我应该怎么做才能让这个谓词停止并给我结果?
- - - -更新 - - - -
pre(X,C) :- prerequisite(X,C).
pre(X,C) :- prerequisite(X,Y), pre(Y,C).
pre2(C,L) :- findall(L1,pre(L1,C),L).
required(C,L) :- pre2(C,L1),sort(L1,L).
can_take([],_).
can_take(L,C) :- required(C,L).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
这是我的代码测试:
?- required(cmput325,L).
L = [cmput175, cmput204].
?- required(cmput204,L).
L = [cmput175].
?- can_take([cmput175],X).
X = cmput201 ;
X = cmput204 ;
?- findall(C, can_take([cmput175], C), L).
L = [cmput201, cmput204].
?- can_take([cmput204],cmput325).
false. (this one is OK)
?- can_take([cmput175,cmput204],cmput325).
true ;
false. (this one is OK)
?- can_take([cmput175],cmput204).
true ;
true ;
false.
最后一个不行,因为我不希望它返回两个真实的陈述......所以我想要的是让它在第二行或最后一行返回 true 时停止。对于我的作业,我不允许使用 cut 运算符!,还有其他方法吗?
解决方案
(我会假设你可以再学习一门课程,即使你已经上过课了。至少这是我所知道的规则。)
您可以参加课程,前提是您已经参加了所有必修课程。
Prolog 中没有直接的“全部”。但是你可以用不同的方式来制定这个
您可以参加课程,前提是没有您尚未参加的必修课程。
can_take(Takens, Next) :-
course(Next),
iwhen( ground(Takens),
\+ ( prerequisite(Required, Next), \+ member(Required, Takens) ) ).
这用于iwhen/2
防止Takens
未完全实例化的情况。
请注意,您的示例略有不同:
?- findall(C, can_take([cmput175], C), L).
L = [cmput175, cmput201, cmput204].
% ^^^^^^^^
免责声明
您的问题本质上是非单调的:通过为要求添加更多事实,您正在减少您可能参加的课程数量。作为初学者,宁愿坚持本质上单调的问题。正是在这一方面,Prolog 真正出类拔萃。
推荐阅读
- python - 从 pmdarima 导入 auto_arima 时:错误:无法从“scipy.misc”导入名称“factorial”
- java - toString 错误,无法解析方法 toString()
- database - 为什么自动提交 DDL 命令前后执行的 DML 命令?
- sql - Postgres plpgsql 返回表和值
- python - 如何检查Python中的字符串中是否不存在多个字符串中的任何一个
- redhat-openjdk - JDK 8 Instrumentation API 使 JVM 崩溃
- angular - 测试禁用的锚点在单击时不会更改当前位置
- google-maps - Google Directions API - 没有腿的渲染路线
- node.js - 创建一个 post 表,将 userID 添加到 post 表中,并将 postID 自动添加到 sequlize 中的 image 表中
- wpf - 从类库 (dll) 运行 wpf 应用程序