Prolog possible removal of elements in a list

2019-02-19 09:09发布

问题:

I have been asked to try to search for all possible outcomes of, removing any numbers from any single elements from a list.

For example, if I have a list X = [1,2,3]

remove(X, Y)

My result will be:

Y = [2,3]
Y = [1,1,3]
Y = [1,3]
Y = [1,2,2]
Y = [1,2,1]
Y = [1,2]

For this, I have already written 2 solutions, but I don't really know what is the cons of my solutions. My professor keeps telling me that there is a better way of doing this.

My First approach:

test(S1, S2):-
    length(S1, L),
    M is L -1,
    between(0, M, N),
    remove(S1, S2, N).
remove([H|T], [H2|T2], Heap):-
    (
        Heap>0->
        H2 = H,
        remove(T, T2, Heap-1);
        between(1, H, N),
        H2 is H - N,
        T2 = T
    ).

My Second Approach:

remove1([H|T], [H|TY]):-
    not(T=[]),
    remove1(T, TY).
remove1([H|T], S2):-
    between(1, H, X),
    HY is H - X,
    (   HY = 0-> S2 = T; S2=[HY|T]).

Both of the approaches are giving the same result, but I do really want to know how I can do it better. Would anyone mind giving me some advice please?

回答1:

You have to:

  • select one item (number) from the list
  • replace selected item with a number which is less than the selected item
  • alternatively remove entirely the selected item

For example:

remove([N|Tail], [NX|Tail]):-
  succ(N1, N),
  between(1, N1, NX).
remove([_|Tail], Tail).
remove([N|Tail], [N|NTail]):-
  remove(Tail, NTail).

The first clause selects the first item in the list, and replaces that item with a number which is less than the item.

The second clause removes the item from the list (as shown in your examples when you subtract N to the selected item (N) it does not appear in the second list.

The third clause applies recursion, leaving the head item as-is and applies the procedure to the remaining list.



回答2:

Here's another solution using append/3. I'm thinking @gusbro's answer is more elegant and/or efficient. But it's an alternative:

reduce(L, R) :-
    append(L1, [X|L2], L),
    (   X1 is X - 1,              % some element varies 1 to X-1
        between(1, X1, Y),
        append(L1, [Y|L2], R)
    ;   append(L1, L2, R)         % or the element is just removed
    ).