如何检查列表中的哪些项目满足特定条件?
How to check which items on the list meet certain condition?
如何制作一个名为 busLineLonger 的函数,该函数至少接收两个参数来决定公交线路是否更长?
*/This is how it works*/
* busStops(number_of_the_bus,number_of_stops)*/
/*?- busLineLonger([busStops(1,7),busStops(2,4),busStops(3,6)],5,WHICH).
* WHICH = [1,3].
只使用比较级的东西,比如@> <@ /==@。
对不起我的英语
编辑...
到目前为止我想到了这样的事情
busLineLonger([busStops(A,B)|R],N,[_|_]):-
N@>B,
busLineLonger(R,N,A).
您的代码中需要修复的一些问题:
- 第三个参数是
[_|_]
,也就是说结果是自由变量……没有意义。您需要两种情况:一种是 B
大于 N
并且您包括了结果;另一个 B
小于或等于 N
,并且您不包括该结果。
- 缺少基本案例。总线列表为空时的结果是什么?
可能的解决方案:
busLineLonger([],_,[]).
busLineLonger([busStops(A,B)|R],N,[A|S]) :- B>N, busLineLonger(R,N,S).
busLineLonger([busStops(_,B)|R],N,S) :- B=<N, busLineLonger(R,N,S).
?- busLineLonger([busStops(1,7),busStops(2,4),busStops(3,6)],5,WHICH).
WHICH = [1, 3]
以下是使用 meta-predicates 的方法,
reified test predicates,
和 lambda expressions.
:- use_module(library(lambda)).
首先,我们像这样定义具体化的测试谓词(>)/3
:
>(X,Y,Truth) :- (X > Y -> Truth=true ; Truth=false).
接下来,我们定义三个 busLineLonger/3
的不同实现(命名为busLineLonger1/3
、busLineLonger2/3
和busLineLonger3/3
)以下元谓词的术语:maplist/3
、tfilter/3
、tfiltermap/4
和 tchoose/3
。当然,最后我们只需要一个---但这不应该阻止我们探索我们拥有的各种选择!
#1:基于tfilter/3
and maplist/3
执行两个单独的步骤:
1. Select 个关注事项。
2. 将这些项目投影到感兴趣的数据。
busLineLonger1(Ls0,N,IDs) :-
tfilter(\busStops(_,L)^(L>N), Ls0,Ls1),
maplist(\busStops(Id,_)^Id^true, Ls1, IDs).
#2:基于tfiltermap/4
在这里,我们使用与之前完全相同的 lambda 表达式,但我们通过
他们 both 到元谓词 tfiltermap/4
。这样做可以帮助减少
节省一些资源。
busLineLonger2(Ls,N,IDs) :-
tfiltermap(\busStops(_,L)^(L>N), \busStops(Id,_)^Id^true, Ls,IDs).
tfiltermap/4
的实现方式如下:
:- meta_predicate tfiltermap(2,2,?,?).
tfiltermap(Filter_2,Map_2,Xs,Ys) :-
list_tfilter_map_list(Xs,Filter_2,Map_2,Ys).
:- meta_predicate list_tfilter_map_list(?,2,2,?).
list_tfilter_map_list([],_,_,[]).
list_tfilter_map_list([X|Xs],Filter_2,Map_2,Ys1) :-
if_(call(Filter_2,X), (call(Map_2,X,Y),Ys1=[Y|Ys0]), Ys1=Ys0),
list_tfilter_map_list(Xs,Filter_2,Map_2,Ys0).
#3:基于tchoose/3
这里我们不使用两个单独的lambda表达式,而是使用一个组合的。
busLineLonger3(Ls,N,IDs) :-
tchoose(\busStops(Id,L)^Id^(L>N), Ls,IDs).
tchoose/3
的实现方式如下:
:- meta_predicate tchoose(3,?,?).
tchoose(P_3,Xs,Ys) :-
list_tchoose_list(Xs,P_3,Ys).
:- meta_predicate list_tchoose_list(?,3,?).
list_tchoose_list([],_,[]).
list_tchoose_list([X|Xs],P_3,Ys1) :-
if_(call(P_3,X,Y), Ys1=[Y|Ys0], Ys1=Ys0),
list_tchoose_list(Xs,P_3,Ys0).
让我们看看他们的行动!
?- Xs = [busStops(1,7),busStops(2,4),busStops(3,6)], busLineLonger1(Xs,5,Zs).
Xs = [busStops(1, 7), busStops(2, 4), busStops(3, 6)],
Zs = [1, 3].
?- Xs = [busStops(1,7),busStops(2,4),busStops(3,6)], busLineLonger2(Xs,5,Zs).
Xs = [busStops(1, 7), busStops(2, 4), busStops(3, 6)],
Zs = [1, 3].
?- Xs = [busStops(1,7),busStops(2,4),busStops(3,6)], busLineLonger3(Xs,5,Zs).
Xs = [busStops(1, 7), busStops(2, 4), busStops(3, 6)],
Zs = [1, 3].
完成!
那么...底线是什么?
- 许多元谓词都是通用的,可以用在很多类似于这里的情况中。
- 实施这些元谓词是一次性的工作,可以迅速分期偿还。
- 许多元谓词处理 "recursive part",使您能够专注于实际工作。
- 通常,对于元谓词(与常规谓词一样),"there's more than one way to do things"。
- 根据具体情况,使用特定的元谓词可能比使用另一个更好,反之亦然。
- 对于这个问题,我认为实现#3(使用
tchoose/3
的那个)是最好的。
如何制作一个名为 busLineLonger 的函数,该函数至少接收两个参数来决定公交线路是否更长?
*/This is how it works*/
* busStops(number_of_the_bus,number_of_stops)*/
/*?- busLineLonger([busStops(1,7),busStops(2,4),busStops(3,6)],5,WHICH).
* WHICH = [1,3].
只使用比较级的东西,比如@> <@ /==@。 对不起我的英语
编辑... 到目前为止我想到了这样的事情
busLineLonger([busStops(A,B)|R],N,[_|_]):-
N@>B,
busLineLonger(R,N,A).
您的代码中需要修复的一些问题:
- 第三个参数是
[_|_]
,也就是说结果是自由变量……没有意义。您需要两种情况:一种是B
大于N
并且您包括了结果;另一个B
小于或等于N
,并且您不包括该结果。 - 缺少基本案例。总线列表为空时的结果是什么?
可能的解决方案:
busLineLonger([],_,[]).
busLineLonger([busStops(A,B)|R],N,[A|S]) :- B>N, busLineLonger(R,N,S).
busLineLonger([busStops(_,B)|R],N,S) :- B=<N, busLineLonger(R,N,S).
?- busLineLonger([busStops(1,7),busStops(2,4),busStops(3,6)],5,WHICH).
WHICH = [1, 3]
以下是使用 meta-predicates 的方法, reified test predicates, 和 lambda expressions.
:- use_module(library(lambda)).
首先,我们像这样定义具体化的测试谓词(>)/3
:
>(X,Y,Truth) :- (X > Y -> Truth=true ; Truth=false).
接下来,我们定义三个 busLineLonger/3
的不同实现(命名为busLineLonger1/3
、busLineLonger2/3
和busLineLonger3/3
)以下元谓词的术语:maplist/3
、tfilter/3
、tfiltermap/4
和 tchoose/3
。当然,最后我们只需要一个---但这不应该阻止我们探索我们拥有的各种选择!
#1:基于tfilter/3
and maplist/3
执行两个单独的步骤: 1. Select 个关注事项。 2. 将这些项目投影到感兴趣的数据。
busLineLonger1(Ls0,N,IDs) :-
tfilter(\busStops(_,L)^(L>N), Ls0,Ls1),
maplist(\busStops(Id,_)^Id^true, Ls1, IDs).
#2:基于tfiltermap/4
在这里,我们使用与之前完全相同的 lambda 表达式,但我们通过
他们 both 到元谓词 tfiltermap/4
。这样做可以帮助减少
节省一些资源。
busLineLonger2(Ls,N,IDs) :-
tfiltermap(\busStops(_,L)^(L>N), \busStops(Id,_)^Id^true, Ls,IDs).
tfiltermap/4
的实现方式如下:
:- meta_predicate tfiltermap(2,2,?,?).
tfiltermap(Filter_2,Map_2,Xs,Ys) :-
list_tfilter_map_list(Xs,Filter_2,Map_2,Ys).
:- meta_predicate list_tfilter_map_list(?,2,2,?).
list_tfilter_map_list([],_,_,[]).
list_tfilter_map_list([X|Xs],Filter_2,Map_2,Ys1) :-
if_(call(Filter_2,X), (call(Map_2,X,Y),Ys1=[Y|Ys0]), Ys1=Ys0),
list_tfilter_map_list(Xs,Filter_2,Map_2,Ys0).
#3:基于tchoose/3
这里我们不使用两个单独的lambda表达式,而是使用一个组合的。
busLineLonger3(Ls,N,IDs) :-
tchoose(\busStops(Id,L)^Id^(L>N), Ls,IDs).
tchoose/3
的实现方式如下:
:- meta_predicate tchoose(3,?,?).
tchoose(P_3,Xs,Ys) :-
list_tchoose_list(Xs,P_3,Ys).
:- meta_predicate list_tchoose_list(?,3,?).
list_tchoose_list([],_,[]).
list_tchoose_list([X|Xs],P_3,Ys1) :-
if_(call(P_3,X,Y), Ys1=[Y|Ys0], Ys1=Ys0),
list_tchoose_list(Xs,P_3,Ys0).
让我们看看他们的行动!
?- Xs = [busStops(1,7),busStops(2,4),busStops(3,6)], busLineLonger1(Xs,5,Zs).
Xs = [busStops(1, 7), busStops(2, 4), busStops(3, 6)],
Zs = [1, 3].
?- Xs = [busStops(1,7),busStops(2,4),busStops(3,6)], busLineLonger2(Xs,5,Zs).
Xs = [busStops(1, 7), busStops(2, 4), busStops(3, 6)],
Zs = [1, 3].
?- Xs = [busStops(1,7),busStops(2,4),busStops(3,6)], busLineLonger3(Xs,5,Zs).
Xs = [busStops(1, 7), busStops(2, 4), busStops(3, 6)],
Zs = [1, 3].
完成!
那么...底线是什么?
- 许多元谓词都是通用的,可以用在很多类似于这里的情况中。
- 实施这些元谓词是一次性的工作,可以迅速分期偿还。
- 许多元谓词处理 "recursive part",使您能够专注于实际工作。
- 通常,对于元谓词(与常规谓词一样),"there's more than one way to do things"。
- 根据具体情况,使用特定的元谓词可能比使用另一个更好,反之亦然。
- 对于这个问题,我认为实现#3(使用
tchoose/3
的那个)是最好的。