I am trying to find the index position of the minimum element in a list and print the element at the corresponding index position in another list.

For example:

``````?- min2(X,Y,[a,b,c],[5,3,7]).
X= b
y= 3``````

Code:

``````min2(A,B,[A|_],[B|_]).
min2(A,B,[X|T1],[Y|T2]) :- smallest(W,[Y|T2]),  % using a predicate to find the min element in teh list
B is W,              % setting B to the result of above(i.e the min element)
min2(A,B,T1,T2).     % looking up position corresponding to min element in list1``````

the predicate for finding the min element in the list is:

``````smallest(Head, [Head]).
smallest(Element, [Head|Tail]) :- smallest(E, Tail), E < Head , Element is E.``````

The result I am getting is :

``````X = a,
Y = 5 ;
X = b,
Y = 3 ;
false.``````

It somehow picks the first element also. My base case could be wrong? I tried altering the base case to `min2(A,B,[A|_],[B|_]).` and it breaks.

Please show me where I am going wrong.

Thanks.

2
Contributors
6
Replies
8
Views
7 Years
Discussion Span
Last Post by bharatk

You can not find corresponding element from other list by min2. Use this corresponding relation:

``````corresponding(A, B, [A|_], [B|_]).
corresponding(A, B, [_|C], [_|D]) :-
corresponding(A, B, C, D).``````
``````| ?- corresponding(X, 3, [a, b, c], [5, 3, 6]).

X = b ? a

no
| ?-``````

Did you solve it? With smallest or gprolog min_list, the min2 rule is only one line and very obvious logical statement.

Did you solve it? With smallest or gprolog min_list, the min2 rule is only one line and very obvious logical statement.

I actually found a way to solve it & get exactly what I wanted.

Here I check if B is H2 then A is H1. Here is the code:

``````min2(A,B,[A],[B]).
min2(A,B,[X|T1],[Y|T2]) :- smallest(W,[Y|T2]), B is W, min2(A,B,T1,T2), !.
min2(A,B,[H1|T1],[H2|T2]):- B=:=H2 -> A = H1 ; min2(A,B,T1,T2).``````

My version was this, I kind of like the simplicity especially if you utilice gprolog min_list, it is short and simple

``````corresponding(A, B, [A|_], [B|_]).
corresponding(A, B, [_|C], [_|D]) :- corresponding(A, B, C, D).
min2(A, B, C, D) :- min_list(D, B), corresponding(A, B, C, D).``````

For min_list implementation, as I posted to StackOverflow (don't double post other time), my smallest with cuts as yours was copy from internet:

``````% length 1 is base case, all  minimums are equal, so cuts
smallest([A], A).
% shorten by 1 by dropping bigger or equal
smallest([A, B|C], D) :-
A > B,
smallest([B|C], D), !.
% cut means this is else branch and need not condition
smallest([A, _|C], D) :-
smallest([A|C], D).``````

Your code only returns last occurance of minimum pair, not all pairs.

``````?- min_pair(X,Y,[a,b,c],[5,3,3]).

X = b
Y = 3 ? a

X = c
Y = 3

no
| ?- min2(X,Y,[a,b,c],[5,3,3]).

X = c
Y = 3

yes
| ?-``````

Edited by pyTony: n/a

My version was this, I kind of like the simplicity especially if you utilice gprolog min_list, it is short and simple

``````corresponding(A, B, [A|_], [B|_]).
corresponding(A, B, [_|C], [_|D]) :- corresponding(A, B, C, D).
min2(A, B, C, D) :- min_list(D, B), corresponding(A, B, C, D).``````

For min_list implementation, as I posted to StackOverflow (don't double post other time), my smallest with cuts as yours was copy from internet:

``````% length 1 is base case, all  minimums are equal, so cuts
smallest([A], A).
% shorten by 1 by dropping bigger or equal
smallest([A, B|C], D) :-
A > B,
smallest([B|C], D), !.
% cut means this is else branch and need not condition
smallest([A, _|C], D) :-
smallest([A|C], D).``````

This is elegant & efficient and as you said, the solution I had got didn't find all the pairs.

It does take a while to get used to Prolog's way of doing stuff coming from the imperative world. And sorry for the double posting. I thought I could have more views & discussions by doing so.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.