:-mode best_and_rest(+,-,-). best_and_rest([H|T],Best,Rest):- (foreach(X,T), fromto(H,In1,Out1,Best), fromto([],In2,Out2,Rest) do best(X,In1,Out1,In2,Out2) ). best(X,Y,X,L,[Y|L]):- better(X,Y), !. best(X,Y,Y,L,[X|L]).
If several elements of the list have the same best value, only the first one is selected.
The order of elements in Rest may be quite different from the order in the input list. If that is not acceptable, we must use a different implementation. A rather clever one is given below:
best_and_rest([First|Xs],Best,Rest):- (foreach(X,Xs), fromto(First,BestSoFar,NextBest,Best), fromto(Start,Rest1,Rest2,[]), fromto(Start,Head1,Head2,Gap), fromto(Rest,Tail1,Tail2,Gap) do (better(X,BestSoFar) -> NextBest = X, Tail1 = [BestSoFar|Head1], Tail2 = Rest1, Head2 = Rest2 ; NextBest = BestSoFar, Tail2 = Tail1, Head2 = Head1, Rest1 = [X|Rest2] ) ).