prolog - How to check which items on the list meet certain condition? -
how make function called buslinelonger, receives @ least 2 parameters decide if bus line longer or not?
*/this how works*/ * busstops(number_of_the_bus,number_of_stops)*/ /*?- buslinelonger([busstops(1,7),busstops(2,4),busstops(3,6)],5,which). * = [1,3].
using comparative things, @> <@ /==@. sorry english
edit... far i've think of this
buslinelonger([busstops(a,b)|r],n,[_|_]):- n@>b, buslinelonger(r,n,a).
here's how using meta-predicates, reified test predicates, , lambda expressions.
:- use_module(library(lambda)).
first, define reified test predicate (>)/3
this:
>(x,y,truth) :- (x > y -> truth=true ; truth=false).
next, define three different implementations of buslinelonger/3
(named buslinelonger1/3
, buslinelonger2/3
, , buslinelonger3/3
) in terms of following meta-predicates: maplist/3
, tfilter/3
, tfiltermap/4
, , tchoose/3
. of course, in end need one---but shouldn't keep exploring various options have!
#1: based on tfilter/3
, maplist/3
do 2 separate steps: 1. select items of concern. 2. project items data of interest.
buslinelonger1(ls0,n,ids) :- tfilter(\busstops(_,l)^(l>n), ls0,ls1), maplist(\busstops(id,_)^id^true, ls1, ids).
#2: based on tfiltermap/4
here, use same lambda expressions before, pass them both meta-predicate tfiltermap/4
. doing can reduce save resources.
buslinelonger2(ls,n,ids) :- tfiltermap(\busstops(_,l)^(l>n), \busstops(id,_)^id^true, ls,ids).
here's how tfiltermap/4
can implemented:
:- 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: based on tchoose/3
here not use 2 separate lambda expressions, combined one.
buslinelonger3(ls,n,ids) :- tchoose(\busstops(id,l)^id^(l>n), ls,ids).
here's how tchoose/3
can implemented:
:- 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).
let's see them in action!
?- 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].
done!
so... what's the bottom line?
- many meta-predicates versatile , can used in lot of sitations similar 1 here.
- implementing these meta-predicates 1 time effort amortized quickly.
- many meta-predicates handle "recursive part", enables focus on actual work.
- often, meta-predicates (as regular ones), "there's more 1 way things".
- depending on concrete circumstances, using particular meta-predicate may better using one, , vice versa.
- for question, think, implementation #3 (the 1 using
tchoose/3
) best.
Comments
Post a Comment