So... What about writing one predicate that deletes the nth element, then one that takes a list of indices and deletes all those?
Deleting the nth is simple:
del([_|T],T,1).
del([Head|Tail],B,N) :-
K is N-1,
del(Tail,C,K),
B = [Head|C].
Since we know that N is not 1 (otherwise the first clause would have been used), we keep the first (see that B=[Head|C]
, we did not throw Head
away!) and do a recursive call to del(Tail,C,K)
to determine C
with the nth removed.
Now, for listdel
, that takes a list of indices:
listdelaux(A,A,[],_).
listdelaux(A,B,Indices,Level) :-
Indices = [N|IndicesTail],
K is N-Level,
del(A,X,K),
L is Level + 1,
listdelaux(X,B,IndicesTail,L).
listdel(A,B,Indices) :- listdelaux(A,B,Indices,0).
The listdelaux
predicate takes four arguments: The original list, the new list, the list of indices, and the level, which in the first call should be zero.
It will remove the first index; then call itself again for the next index, but in the new call it should subtract from the new index to be removed the number of indices already removed:
Removing [2,4]
from [a,b,c,d,e,f]
:
[a,b,c,d,e,f] --> del(.,.,2) --> [a,c,d,e,f]
[a,c,d,e,f] --> del(.,.,3) --> [a,c,e,f]
See that we had to subtract 1 from 4 in the second call.