简体   繁体   中英

Deleting first N prime numbers from a list (Prolog)

Basically I want to remove the first N numbers from a list, the function that checks whether a number is prime or not seems to work well but the program itself doesn't

For example for input [2,4,5,7,6,9,11] and N = 3 I should get [4, 6, 9, 11] but I get only [4, 6, 9] .

divisible(X,Y) :- 
    0 is X mod Y, !.
divisible(X,Y) :- 
    X > Y+1, 
    divisible(X, Y+1).

%isPrime function check whether or not the argument is a prime number
isPrime(2) :- true,!.
isPrime(X) :- X < 2,!,false.
isPrime(X) :- not(divisible(X, 2)).

%delFunction (input_list, N, output_list)
delFunction([],_,_).
delFunction(_,0,_).
delFunction([H|T], N, [H|Res]):-
    not(isPrime(H)), !,
    delFunction(T, N, Res).
delFunction([_|T], N, Res):-
    N1 is N-1,
    delFunction(T,N1,Res).

delFunction([2,4,5,7,6,9,11],3,X) -> [4,6,9] (which is not the correct answer)

Honestly, I don't know where I went wrong, the implementation idea seems pretty easy and straight forward, so is the code.

Also, when I run it it stops at [4] and I have to keep on clicking next to get me to the end of the execution (thus the result). Any idea how to fix it? I'm thinking maybe I need some cuts but not sure where.

PS: I'd rather not use built-in functions (if there are any that would help in this scenario)

Fists of all, instead of

delFunction([],_,_).

you should write

delFunction([],_,[]).

because when the input list (the left one) is empty, you have to construct the base for the output list: an empty list; with delFunction([], _, _) you don't unify the output list with the empty list so the result end with an not unified variable.

Second. Instead of

delFunction(_,0,_).

you should write

delFunction(L,0,L).

The problem is the same: when number is zero you can "copy" the input in the output; that is, you can unify they; that is delFunction(L,0,L) . With delFunction(_,0,_) you don't unify and the result ends with a not unified variable.

Third. In the is-prime clause

delFunction([_|T], N, Res):-
    N1 is N-1,
    delFunction(T,N1,Res).

you should check that N is greater than zero

delFunction([_|T], N, Res):-
    N > 0,
    N1 is N-1,
    delFunction(T,N1,Res).

or, if you prefer, you should add a cut ( ! ) in the zero clause

delFunction(L,0,L) :- !.

Just to avoid that Prolog, via backtracking, can give multiple undesired answers.

--- EDIT ---

As Guy Coder, I avoid cuts like a plague; so I propose the following solution to avoid unwanted repetitions.

delFunction([], _, []).

delFunction([H | T], 0, [H | T]).

delFunction([H | T], N, [H | Res]) :-
    N > 0,
    not(isPrime(H)),
    delFunction(T, N, Res).

delFunction([H | T], N, Res):-
    N > 0,
    isPrime(H),
    N1 is N-1,
    delFunction(T, N1, Res).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM