使用 Prolog 在列表中找到第二个参数最低的术语
Find the term with the lowest 2nd argument, in a list, with Prolog
我有一个这样的列表:
L = [range(2,3), range(5,6), range(10,9), range(-2,-30), range(-5,-30)]
现在,我需要将术语 range(-5,-30)
作为此列表的第一个元素,因为它是具有最低 Y
的术语,如果有 2 个术语具有最低 [=13] =], 我会选择最低的 X
.
我不知道如何用 Prolog 做,我试过类似的东西:
find_n_make_first([F,S|T]) :-
F =.. [_,Fx,Fy],
S =.. [_,Sx,Sy],
( Sy<Fy ->
find_n_make_first([S,F|T])
; Fy<Sy ->
find_n_make_first([F,S|T])
; Fy = Sy ->
( Sx<Fx ->
find_n_make_first([S,F|T])
; Fx<Sx ->
find_n_make_first([F,S|T])
)
).
但它不起作用。
实际上,您的第一个问题是了解如何使用这样的定义。总是从想象开始,你已经有了一个有效的定义。您将在那里了解到关于关系的最重要部分:在关系中没有隐含的 "return values"。您需要分别定义它们。所以在你的情况下,这将是:
?- list_sortedby2([range(2,3),range(10,9),range(-2,-30),range(-5,-30)], Us).
Us = [range(-5,-30),range(-2,-30),range(2,3),range(10,9)].
只有然后才开始定义它!
:- use_module(library(lambda)).
list_sortedby2(Ts, Us) :-
must_be_ground(Ts),
maplist(\T^(A2+T)^arg(2,T,A2), Ts, A2Ts), % or map1(Ts, A2Ts)
sort(A2Ts, A2Us),
maplist(\ (_+U)^U^true, A2Us, Us). % or map2(A2Us, Us)
must_be_ground(Ss) :-
( ground(Ss) -> true
; throw(error(instantiation_error,_))
).
代替maplist/3
和λ,您还可以手动编写:
map1([], []).
map1([T|Ts], [A2+T|A2Ts]) :-
arg(2, T, A2),
map1(Ts, A2Ts).
map2([], []).
map2([_+U|A2Us], [U|Us]) :-
map2(A2Us, Us).
事后想想,还有别的东西:最好用( T = range(_, A2) )
替换目标arg(2, T, A2)
,因为你只对结构range/2
感兴趣。以这种方式,list_sortedby2([f(1,2)], Us)
失败,这是一种更安全的处理意外情况的方法。 (产生类型错误会更安全,但至少不会成功。)
我有一个这样的列表:
L = [range(2,3), range(5,6), range(10,9), range(-2,-30), range(-5,-30)]
现在,我需要将术语 range(-5,-30)
作为此列表的第一个元素,因为它是具有最低 Y
的术语,如果有 2 个术语具有最低 [=13] =], 我会选择最低的 X
.
我不知道如何用 Prolog 做,我试过类似的东西:
find_n_make_first([F,S|T]) :-
F =.. [_,Fx,Fy],
S =.. [_,Sx,Sy],
( Sy<Fy ->
find_n_make_first([S,F|T])
; Fy<Sy ->
find_n_make_first([F,S|T])
; Fy = Sy ->
( Sx<Fx ->
find_n_make_first([S,F|T])
; Fx<Sx ->
find_n_make_first([F,S|T])
)
).
但它不起作用。
实际上,您的第一个问题是了解如何使用这样的定义。总是从想象开始,你已经有了一个有效的定义。您将在那里了解到关于关系的最重要部分:在关系中没有隐含的 "return values"。您需要分别定义它们。所以在你的情况下,这将是:
?- list_sortedby2([range(2,3),range(10,9),range(-2,-30),range(-5,-30)], Us).
Us = [range(-5,-30),range(-2,-30),range(2,3),range(10,9)].
只有然后才开始定义它!
:- use_module(library(lambda)).
list_sortedby2(Ts, Us) :-
must_be_ground(Ts),
maplist(\T^(A2+T)^arg(2,T,A2), Ts, A2Ts), % or map1(Ts, A2Ts)
sort(A2Ts, A2Us),
maplist(\ (_+U)^U^true, A2Us, Us). % or map2(A2Us, Us)
must_be_ground(Ss) :-
( ground(Ss) -> true
; throw(error(instantiation_error,_))
).
代替maplist/3
和λ,您还可以手动编写:
map1([], []).
map1([T|Ts], [A2+T|A2Ts]) :-
arg(2, T, A2),
map1(Ts, A2Ts).
map2([], []).
map2([_+U|A2Us], [U|Us]) :-
map2(A2Us, Us).
事后想想,还有别的东西:最好用( T = range(_, A2) )
替换目标arg(2, T, A2)
,因为你只对结构range/2
感兴趣。以这种方式,list_sortedby2([f(1,2)], Us)
失败,这是一种更安全的处理意外情况的方法。 (产生类型错误会更安全,但至少不会成功。)