Prolog program that removes every nth item from a list

Could you help me solve the following?

Enter a ternary predicate delete_nththat removes every nth element from the list.

Run Examples:

?‐ delete_nth([a,b,c,d,e,f],2,L).
L = [a, c, e] ;
false
?‐ delete_nth([a,b,c,d,e,f],1,L).
L = [] ;
false
?‐ delete_nth([a,b,c,d,e,f],0,L).
false

I tried this:

listnum([],0).
listnum([_|L],N) :-
   listnum(L,N1),
   N is N1+1.

delete_nth([],_,_).
delete_nth([X|L],C,L1) :- 
   listnum(L,S),
   Num is S+1,
   (  C>0
   -> Y is round(Num/C),Y=0
   -> delete_nth(L,C,L1)
   ;  delete_nth(L,C,[X|L1])
   ).
+4
source share
5 answers

My slightly extravagant option:

delete_nth(L, N, R) :-
    N > 0, % Added to conform "?‐ delete_nth([a,b,c,d,e,f],0,L). false"
    ( N1 is N - 1, length(Begin, N1), append(Begin, [_|Rest], L) ->
        delete_nth(Rest, N, RestNew), append(Begin, RestNew, R)
    ;
        R = L
    ).
+4
source

Let me use ! For the sake of universality and tons of other good reasons:

:- use_module(library(clpfd)).

delete_nth/3Based on if_/3and, we determine (#>=)/3:

delete_nth(Xs,N,Ys) :-
   N #> 0,
   every_tmp_nth_deleted(Xs,0,N,Ys).

every_tmp_nth_deleted([]    ,_ ,_,[] ).     % internal auxiliary predicate
every_tmp_nth_deleted([X|Xs],N0,N,Ys0) :-
   N1 is N0+1,
   if_(N1 #>= N,
       (N2 =  0, Ys0 =    Ys ),
       (N2 = N1, Ys0 = [X|Ys])),
   every_tmp_nth_deleted(Xs,N2,N,Ys).

Request example:

? - delete_nth ([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 2 , Ys).
Ys = [1,3,5,7,9,11,13,15]% succeeds deterministically

, - ?

?- delete_nth([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],N,Ys).
  N  =  1     , Ys = []
; N  =  2     , Ys = [1,  3,  5,  7,  9,   11,   13,   15]
; N  =  3     , Ys = [1,2,  4,5,  7,8,  10,11,   13,14   ]
; N  =  4     , Ys = [1,2,3,  5,6,7,  9,10,11,   13,14,15]
; N  =  5     , Ys = [1,2,3,4,  6,7,8,9,   11,12,13,14   ]
; N  =  6     , Ys = [1,2,3,4,5,  7,8,9,10,11,   13,14,15]
; N  =  7     , Ys = [1,2,3,4,5,6,  8,9,10,11,12,13,   15]
; N  =  8     , Ys = [1,2,3,4,5,6,7,  9,10,11,12,13,14,15]
; N  =  9     , Ys = [1,2,3,4,5,6,7,8,  10,11,12,13,14,15]
; N  = 10     , Ys = [1,2,3,4,5,6,7,8,9,   11,12,13,14,15]
; N  = 11     , Ys = [1,2,3,4,5,6,7,8,9,10,   12,13,14,15]
; N  = 12     , Ys = [1,2,3,4,5,6,7,8,9,10,11,   13,14,15]
; N  = 13     , Ys = [1,2,3,4,5,6,7,8,9,10,11,12,   14,15]
; N  = 14     , Ys = [1,2,3,4,5,6,7,8,9,10,11,12,13,   15]
; N  = 15     , Ys = [1,2,3,4,5,6,7,8,9,10,11,12,13,14   ]
; N in 16..sup, Ys = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].
+3

,, , @CapelliC, N = 0.

, , . N- , N , . -, :

, , . :

delete_nth([X|L], C, L1):-
    listnum(L, S),
    Num is S+1,
    C>0 -> Y is round(Num/C),
    Y=0 -> delete_nth(L, C, L1)
    ; delete_nth(L, C, [X|L1]).

, ,

( C>0 -> ( Y is round(Num/C), 
           Y=0 -> delete_nth(L, C, L1) )
; delete_nth(L, C, [X|L1])
).

C>0 -> Y is round(Num/C), 
( Y=0 -> delete_nth(L, C, L1)
; delete_nth(L, C, [X|L1])
).

, , ; ? , ...

!

, , , . , " , ".

: n- N 1. , N, , . 1, N. , , " Kept, N - List?" . , , N 1, , List, : " Count?" 1, N.

, , , , 4- , 3- " ", .. , .

delete_nth(List, N, Kept) :-
    N > 0,                                  %% Will fail if N < 0.
    delete_nth(List, N, N, Kept), !.        %% The first N will be our our counter, the second our target value. I cut because there only one way to generate `Kept` and we don't need alternate solutions.

delete_nth([], _, _, []).                   %% An empty list has nothing to delete.
delete_nth([_|Xs], 1, N, Kept) :-           %% When counter reaches 1, the head is discarded.
    delete_nth(Xs, N, N, Kept).             %% Reset the counter to N.
delete_nth([X|Xs], Counter, N, [X|Kept]) :- %% Keep X if counter is still counting down.
    NextCount is Counter - 1,               %% Decrement the counter.
    delete_nth(Xs, NextCount, N, Kept).     %% Keep deleting elements from Xs...
+2

, (+1). , ditto ?‐ delete_nth([a,b,c,d,e,f],0,L)..

delete_nth(L,C,R) :-
    delete_nth(L,C,1,R).

delete_nth([],_,_,[]).
delete_nth([_|T],C,C,T1) :- !, delete_nth(T,C,1,T1).
delete_nth([H|T],N,C,[H|T1]) :- C<N, C1 is C+1, delete_nth(T,N,C1,T1).

1 ?- delete_nth([a,b,c,d,e,f],2,L).
L = [a, c, e].

2 ?- delete_nth([a,b,c,d,e,f],1,L).
L = [].

3 ?- delete_nth([a,b,c,d,e,f],0,L).
false.

(?) : , , -, ( ";", false ). .

Interesting - IMHO - one liner option:

delete_nth(L,C,R) :- findall(E, (nth1(I,L,E),I mod C =\= 0), R).

but C == 0 must be excluded to avoid

ERROR: mod/2: Arithmetic: evaluation error: `zero_divisor'
+2
source

Another approach, following the initial impulse of @ user3598120, to calculate unwanted Nth elements and inspired the playfulness of @Sergey Dymchenko. It uses exclude/3to remove all elements in an index based on 1, which is a multiple of N

delete_nth(List, N, Kept) :-
    N > 0, 
    exclude(index_multiple_of(N, List), List, Kept).

index_multiple_of(N, List, Element) :-
    nth1(Index, List, Element),
    0 is Index mod N.
+1
source

Source: https://habr.com/ru/post/1539078/


All Articles