Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excluding all occurrences of the minimum number in a list

Tags:

list

prolog

As a Prolog newbie, I try to define a predicate filter_min/2 which takes two lists to determine if the second list is the same as the first, but with all occurrences of the minimum number removed.

Sample queries with expected results:

?- filter_min([3,2,7,8], N).
N = [3,7,8].

?- filter_min([3,2,7,8], [3,7,8]).
true.

I tried but I always get the same result: false. I don't know what the problem is. I need help!

Here is my code:

filter_min(X,Y) :-
    X == [],
    write("ERROR: List parameter is empty!"),
    !;
    min_list(X,Z),
    filter(X,Y,Z).

filter([],[],0).
filter([H1|T1],[H2|T2],Z) :-
    \+ number(H1),
    write("ERROR: List parameter contains a non-number element"),
    !;
    H1 \= Z -> H2 is H1, filter(T1,T2,Z);
    filter(T1,T2,Z).
like image 278
G_cy Avatar asked Jul 29 '15 02:07

G_cy


People also ask

How to remove all occurrences of an element from a list?

The remove () method removes the first occurrence of the provided element from the list and returns true if the element is found in the list. In order to remove all occurrences of an element from the list, we can repeatedly call the remove () method until it returns false. This approach is not recommended as it is very inefficient.

How to find the minimum and maximum number in a list?

2: Python Program to find the Minimum and Maximum Number in a List with their position using for loop and if statement. Allow user to enter the length of the list. Next, iterate the for loop and add the number in the list. Iterate for loop with list and use if statement to find the min and max number and their position in the list.

How to find the smallest and largest number in a list?

Allow user to enter the length of the list. Next, iterate the for loop and add the number in the list. Use python sort method to find the smallest and largest number from the list. Print the results. Allow user to enter the length of the list. Next, iterate the for loop and add the number in the list.

What is the input list and the item to be removed?

Explanation : The input list is [1, 1, 2, 3, 4, 5, 1, 2] and the item to be removed is 1. In this article, we shall see how to execute this task in 3 ways : The list comprehension can be used to perform this task in which we just check for a match and reconstruct the list without the target element.


2 Answers

There are a couple of problems with your code:

  • filter([],[],0). will not unify when working with any list that does not have 0 as its minimum value, which is not what you want. You want it to unify regardless of the minimum value to end your recursion.
  • The way you wrote filter([H1|T1],[H2|T2],Z) and its body will make it so that the two lists always have the same number of elements, when in fact the second one should have at least one less.

A correct implementation of filter/3 would be the following:

filter([],[],_).
filter([H1|T1],L2,Z):-
    \+ number(H1),
    write("ERROR: List parameter contains a non-number element"),
    !;
    H1 \= Z -> filter(T1,T2,Z), L2 = [H1|T2];
    filter(T1,L2,Z).
like image 94
Fatalize Avatar answered Oct 22 '22 16:10

Fatalize


A bounty was offered...

... for a pure solution that terminates for (certain) cases where neither the length of the first nor of the second argument is known.

Here's a candidate implementation handling integer values, built on clpfd:

:- use_module(library(clpfd)).

filter_min(Xs,Ys) :-
   filter_min_picked_gt(Xs,_,false,Ys).

filter_min_picked_gt([]    ,_,true  ,[]).
filter_min_picked_gt([Z|Xs],M,Picked,[Z|Zs]) :-
   Z #> M,
   filter_min_picked_gt(Xs,M,Picked,Zs).
filter_min_picked_gt([M|Xs],M,_,Zs) :-
   filter_min_picked_gt(Xs,M,true,Zs).

Some sample queries:

?- filter_min([3,2,7,8],[3,7,8]).
true ; false.                        % correct, but leaves choicepoint

?- filter_min([3,2,7,8],Zs).
Zs = [3,7,8] ; false.                % correct, but leaves choicepoint

Now, some queries terminate even though both list lengths are unknown:

?- filter_min([2,1|_],[1|_]).
false.                               % terminates

?- filter_min([1,2|_],[3,2|_]).
false.                               % terminates

Note that the implementation doesn't always finitely fail (terminate) in cases that are logically false:

?- filter_min([1,2|_],[2,1|_]).      % does _not_ terminate
like image 45
repeat Avatar answered Oct 22 '22 16:10

repeat