0

I want to delete a given element X from the list in Prolog. Such that delete(X,L) deletes the first instance (from the head) of integer X from list L.

The predicate should be of the form delete(X,List). I don't know how to do it.

For example:

delete(5,[2,3,4,5,6,7,8,9]).
Should return the list with 5 removed from it
List=[2,3,4,6,7,8,9]

Any help is much appreciated. Thank you

Archy89
  • 11
  • 3
  • Start with writing a predicate that checks whether the element exists in the list and that unifies an "output variable" with the rest of the list after that element: `lookfor(Item,List,RestOfListBeyondItem)` first. Then post that. – David Tonhofer Apr 30 '20 at 17:15
  • 1
    **exclude(=(5), [1,2,3,4,5,6], L).** works fine ! In Prolog, a predicate never "returns" à list, or anything else, the outpout must be an argument of the predicate So , – joel76 Apr 30 '20 at 18:36

2 Answers2

0

as I mentioned in the coments, that question has already been answered in the site.

I wrote a similar approach that you may find useful

delete(_, [], []):- !.
delete(X, [X|L1], L2):- !, delete(X,L1,L2).
delete(X, [H|L1], [H|L2]):- !,delete(X,L1,L2).

Feel free to askme any question about the implementation, cheers!

xeitor
  • 368
  • 4
  • 15
0

Keep Calm and Avoid Red Cuts

Better with green cuts then. And test cases are always mandatory.


deleted(X, [H|L1], [H|L2]) :- X\=H, !, deleted(X,L1,L2).
deleted(X, [X|L1],    L2)  :-       !, deleted(X,L1,L2).
deleted(_, [], []).

:- begin_tests(deleted).

test(empty)           :- deleted(1,[],[]).
test(not_exists)      :- deleted(1,[2,3,4,5,6],R), R = [2,3,4,5,6].
test(exists_once)     :- deleted(1,[2,1,4,5,6],R), R = [2,4,5,6].
test(exists_once_end) :- deleted(1,[2,3,4,5,1],R), R = [2,3,4,5].
test(exists_multi)    :- deleted(1,[2,1,4,1,6],R), R = [2,4,6].
test(exists_only)     :- deleted(1,[1,1,1,1,1],R), R = [].

:- end_tests(deleted).

rt :- run_tests(deleted).
?- rt.
% PL-Unit: deleted ...... done
% All 6 tests passed
true.

Sadly this doesn't run in "reverse"

?- deleted(1,X,[2,3]).

blows the stack sky-high ... instead returning an infinite series of possible X, like [1,2,3] etc.

What does one need to change to make it behave? (I think it's not directly evident and may demand another approach).

Addendum: Green cuts removed

Yep, it still works (although having cuts is essential to keep the machine from getting bogged down in keeping avenues open that we know (as programmers who prove theorems in our head as we write code) are useless:

deleted(X, [H|L1], [H|L2]) :- X\=H, deleted(X,L1,L2).
deleted(X, [X|L1],    L2)  :-       deleted(X,L1,L2).
deleted(_, [], []).

:- begin_tests(deleted_nondeterministic).

test(empty,           all(RR = [[]]))          :- deleted(1,[],RR).
test(not_exists,      all(RR = [[2,3,4,5,6]])) :- deleted(1,[2,3,4,5,6],RR).
test(exists_once,     all(RR = [[2,4,5,6]]))   :- deleted(1,[2,1,4,5,6],RR).
test(exists_once_end, all(RR = [[2,3,4,5]]))   :- deleted(1,[2,3,4,5,1],RR).
test(exists_multi,    all(RR = [[2,4,6]]))     :- deleted(1,[2,1,4,1,6],RR).
test(exists_only,     all(RR = [[]]))          :- deleted(1,[1,1,1,1,1],RR).

:- end_tests(deleted_nondeterministic).

rt :- run_tests(deleted_nondeterministic).
David Tonhofer
  • 14,559
  • 5
  • 55
  • 51
  • I was a bit beset by doubts, so I added the cut-less version too. The solutions become non-deterministic, but are still the same. Phew! Prolog should have an annotation to disable cuts within a clause or predicate. – David Tonhofer May 01 '20 at 08:05
  • @repeat I don't want to go there at this point in time. – David Tonhofer May 01 '20 at 09:20
  • @repeat Of course not. In fact that query is seriously underspecified and a proper LP system would reject it with "unknown". – David Tonhofer May 01 '20 at 10:24
  • I do not agree. If some query is too general for your code to handle, then your code should detect it and properly raise an `instantiation_error`. Don't shift the blame, fix your code. It's broken. – repeat May 01 '20 at 12:20
  • @repeat Agree with the `dif/2`, but I disagree completely with this cut being "red". Also, I appreciate the sentiment, but ... why bomb-proof a a triple-liner (in a language that is non-bomb-proof by design and where most predicates would conk out if fuzzed) for a barely specified homework problem? Sure, I could `maplist(nonvar,L)` but does it help the original poster? Come on. – David Tonhofer May 01 '20 at 15:54
  • I didn't mean to be harsh. You are right, in this particular case, the cuts are indeed green. I was a bitt confused about why you lost valid solutions. However, `maplist(nonvar)` doesn't help here, as it is causes failure in cases that logically should succeed. Bottom line: switch to dif, remove the cuts, so I can swing my downvote to an up... – repeat May 01 '20 at 16:25