minimum in list of lists in prolog

送分小仙女□ 提交于 2021-01-03 22:32:32

问题


hello i have a list like this:

[[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]]

list of lists... i want to find the minimum number on inner list in this case i want to return D=2 and L=[a,b,d]

i tried this code:

minway([[N|L]],N,L).
minway([[M|L1]|L2],D,_):- M<D, minway(L2,M,L1).
minway([[M|_]|L2],D,L):- M>=D, minway(L2,D,L).

but i got error:

</2: Arguments are not sufficiently instantiated
   Exception: (8) minway([[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]], _G7777, _G7778) ? 
   creep

for this run sentence:

minway([[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]],D,L).

the result need to be:

D=2.
L=[a,b,d].

where my problem? and how to fix it?

tnx a lot


回答1:


First, switch to a better data representation: Instead of [Key,Value], use Key-Value!

Then, define minway_/3 based on iwhen/2, ground/1, keysort/2, and member/2, like so:

minway_(Lss, N, Ls) :-
   iwhen(ground(Lss), (keysort(Lss,Ess), Ess = [N-_|_], member(N-Ls, Ess))).

Sample query using SICStus Prolog 4.5.0:

| ?- minway_([3-[a,b,c,d],2-[a,b,d],5-[d,e,f],2-[x,t,y]], N, Ls).
N = 2, Ls = [a,b,d] ? ;
N = 2, Ls = [x,t,y] ? ;
no



回答2:


There are a couple of fundamental issues.

One is in your problem lies in your representation of a list. Your predicates seem to assume that, for example, [3, [a,b,c]] is represented as [3 | [a,b,c]] but it is not. The list [3 | [a,b,c]] is the list with 3 as the head, and [a,b,c] as the rest of the list or the tail. In other words, [3 | [a,b,c]] is [3, a, b, c].

And, so, your base case would be:

minway([[N,L]], N, L).

The second issue is in your other predicate clauses. There's no starting point for D. In other words, it's never given a value to start with, so you get an instantiation error. You cannot compare N > D if one of the variables doesn't have a value.

When doing a minimum or maximum from scratch, a common approach is to start by assuming the first element is the candidate result, and then replace it if you find a better one on each step of the recursion. It also means you need to carry with you the last candidate at each recursive call, so that adds extra arguments:

minway([[N,L]|T], D, R) :-
    minway(T, N, L, D, R).

minway([], D, R, D, R).            % At the end, so D, R is the answer
minway([[N,L]|T], Dm, Rm, D, R) :-
    (   N < Dm
    ->  minway(T, N, L, D, R)      % N, L are new candidates if N < Dm
    ;   minway(T, N, Dm, Rm, D, R) % Dm, Rm are still best candidate
    ).

In Prolog, you can simplify this a little since Prolog has a more general term comparison operator, @<, @>, etc, which is smart about comparing more complex terms. For example, [2, [d,e,f]] @< [3, [a,b,c]] is true since 2 < 3 is true. We can then write:

minway([H|T], D, R) :-
    minway(T, H, D, R).

minway([], [D, R], D, R).
minway([H|T], M, D, R) :-
    (   H @< M
    ->  minway(T, H, D, R)
    ;   minway(T, M, D, R)
    ).



回答3:


You can do this by using the minimum predicate. Findall can be very helpful.

min([X],X).
min([H|T],Min):-
    min(T,TMin),
    H>TMin,
    Min is TMin.
min([H|T],Min):-
    min(T,TMin),
    H=<TMin,
    Min is H.

minway(List,D,L):-
    findall(Value,member([Value,_],List),VList),
    min(VList,Min),
    D=Min,
    findall(EList,member([Min,EList],List),L).

?-minway([[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]],D,L).
D = 2,
L = [[a, b, d]]



回答4:


Try library(aggregate):

?- aggregate_all(min(X,Y), 
       member([X,Y], [[3,[a,b,c,d]],
                      [2,[a,b,d]],
                      [5,[d,e,f]]]), 
       min(D,L)).
D = 2,
L = [a, b, d].

See also here:

Aggregation operators on backtrackable predicates
https://www.swi-prolog.org/pldoc/man?section=aggregate



来源:https://stackoverflow.com/questions/34699220/minimum-in-list-of-lists-in-prolog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!