How to write a prolog program to print between a given range? - prolog

How can I write a a program in prolog to print even and odd numbers between a range?
Sample output:
Enter first number:2
Enter Second number:15
Even numbers:
2
4
6
8
10
12
14
Odd numbers:
1
3
5
7
9
11
13
15

Here's one way to do it:
odds_and_evens( H , H , [H] , [] ) :- % if lo and hi have converged,
0 =\= H rem 2 % and it's odd
. % then park it with the odds and succeed.
odds_and_evens( H , H , [] , [H] ) :- % if lo and hi have conveged,
0 =:= H rem 2 % and it's even
. % then park it with the evens and succeed.
odds_and_evens( L , H, [L|Odds] , Evens ) :- % else... park lo with the odds
L < H, % - if lo is less than hi
0 =\= L rem 2, % - and lo is odd
L1 is L+1, % - increment lo
odds_and_evens(L1, H, Odds, Evens ) % - and recurse down
. %
odds_and_evens( L , H, Odds , [H|Evens] ) :- % else... park lo with the evens
L < H, % - if lo is less than hi
0 =:= L rem 2, % - and lo is even
L1 is L+1, % - incement lo
odds_and_evens(L1, H, Odds, Evens ) % - and recurse down
. % Easy!
But... Prolog has an in-built between/3 that generates a range of integers. And findall/3 finds all the solutions to a query as a list. So one could also — and more succinctly and declaratively! — say:
odds_and_evens( L , H , Odds , Evens ) :-
findall( X , odds( L , H , X ) , Odds ),
findall( X , evens( L , H , X ) , Evens )
.
odds( L , H , N ) :- between(L,H,N), 0 =\= N rem 2 .
evens( L , H , N ) :- between(L,H,N), 0 =:= N rem 2 .
Once you have odds_and_evens/4 defined, you can than do this:
print_odds_and_evens( Lo, Hi ) :-
odds_and_evens(Lo,Hi,Odds,Evens),
write_to_console('Odd Numbers', Odds ),
write_to_console('Even Numbers', Evens )
.
write_to_console(Label, Ns ) :-
write(Label), writeln(':'),
write_to_console(Ns)
,
write_to_console([]) .
write_to_console([N|Ns]) :- writeln(N), write_to_console(Ns).
If that's too much recursion for you, you could also say (cribbing odds/3 and evens/3 from above):
print_odds_and_evens(Lo,Hi) :-
writeln('Odd Numbers:'),
odd(Lo,Hi,N),
writeln(N),
fail
.
print_odds_and_evens(Lo,Hi) :-
writeln('Even Numbers:'),
even(Lo,Hi,N),
writeln(N),
fail
.
print_odds_and_evens(_,_).
odd( L , H , N ) :- between(L,H,N), 0 =\= N rem 2 .
even( L , H , N ) :- between(L,H,N), 0 =:= N rem 2 .

Here is an answer based on SWI-Prolog partition/4.
example_1(Odd,Even) :-
numlist(1,15,List),
partition(is_even,List,Even,Odd).
is_even(N) :-
0 is N mod 2.
Example run
?- example_1(Odd,Even).
Odd = [1, 3, 5, 7, 9, 11, 13, 15],
Even = [2, 4, 6, 8, 10, 12, 14].
Here is a variation that puts the support predicate into a Lambda.
example_2(Odd,Even) :-
numlist(1,15,List),
partition([N]>>(0 is N mod 2),List,Even,Odd).
Example run
?- example_2(Odd,Even).
Odd = [1, 3, 5, 7, 9, 11, 13, 15],
Even = [2, 4, 6, 8, 10, 12, 14].
For answers to the other part of your multi-part question about entering the starting and ending values I would suggest using read_string/5.
See:
How to get user console input into a Prolog list (Answer)
Prolog: How to read data from console and store into database. (Answer)
Other Answers

Here is a solution that only uses Prolog ISO standard built-in predicates. It's also a fast solution as it avoid meta-predicates and appending lists:
print_even_odd(Lower, Upper) :-
even_odd(Lower, Upper, Even, Odd),
write('Even: '), write(Even), nl,
write('Odd: '), write(Odd), nl.
even_odd(Lower, Upper, Even, Odd) :-
Lower =< Upper,
( Lower mod 2 =:= 0 ->
even_odd_lists(Lower, Upper, Even, Odd)
; even_odd_lists(Lower, Upper, Odd, Even)
).
even_odd_lists(Upper, Upper, [Upper], []) :-
!.
even_odd_lists(N, Upper, [N| Even], Odd) :-
M is N + 1,
even_odd_lists(M, Upper, Odd, Even).
Sample calls:
| ?- print_even_odd(1, 24).
Even: [2,4,6,8,10,12,14,16,18,20,22,24]
Odd: [1,3,5,7,9,11,13,15,17,19,21,23]
yes
| ?- print_even_odd(2, 24).
Even: [2,4,6,8,10,12,14,16,18,20,22,24]
Odd: [3,5,7,9,11,13,15,17,19,21,23]
yes
| ?- print_even_odd(1, 35).
Even: [2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34]
Odd: [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35]
yes

There are several possible solutions. Here a, naive, without using higher order predicates:
print_even_odd(Lower,Upper,[],[]):-
Lower > Upper, !.
print_even_odd(Lower,Upper,Lodd,Leven):-
Res is Lower mod 2,
( Res =:= 0 ->
Leven = [Lower | LE1], LO1 = Lodd ;
Lodd = [Lower | LO1], LE1 = Leven
),
L1 is Lower + 1,
print_even_odd(L1,Upper,LO1,LE1).
?- print_even_odd(1,15,LE,LO).
LE = [1, 3, 5, 7, 9, 11, 13, 15],
LO = [2, 4, 6, 8, 10, 12, 14]
You can write more compact solutions using higher order predicates as sugggested in the comments.

Here is another possible solution:
% range(+Start, +Stop, +Step, -List)
range(Start, Stop, Step, List) :-
( Start > Stop
-> List = []
; List = [Start|Rest],
Next is Start + Step,
range(Next, Stop, Step, Rest) ).
% even_odd_lists(+Lower, +Upper, -EList, -OList)
even_odd_lists(Lower, Upper, EList, OList) :-
FirstEven is Lower + Lower mod 2,
FirstOdd is Lower + (Lower-1) mod 2,
range(FirstEven, Upper, 2, EList),
range(FirstOdd, Upper, 2, OList).
Some sample queries are:
?- range(1, 10, 3, R).
R = [1, 4, 7, 10].
?- range(1, 10, 2, R).
R = [1, 3, 5, 7, 9].
?- range(2, 10, 2, R).
R = [2, 4, 6, 8, 10].
?- even_odd_lists(1, 15, LE, LO).
LE = [2, 4, 6, 8, 10, 12, 14],
LO = [1, 3, 5, 7, 9, 11, 13, 15].
?- even_odd_lists(2, 15, LE, LO).
LE = [2, 4, 6, 8, 10, 12, 14],
LO = [3, 5, 7, 9, 11, 13, 15].

Related

What is the simple way to find the max length of a list in prolog?

I'm new to learn the Prolog, I have a list, which looks like -> [[6, 7, 8,9], [6, 7, 8, 9], [6, 7, 8, 9], [7, 8, 9], [7, 8, 9],[5,6,7]], I want to find the all max length lists in the list, In this case, it should return [[6,7,8,9],[6,7,8,9],[6,7,8,9]]
my code
maxlist([A],A).
maxlist([A,B|Rest],Max):-
maxlist([B|Rest],Maxrest),
max(A,Maxrest,Max).
max(A,B,A):-
length(A,N1),
length(B,N2),
N1>N2.
max(A,B,B):-
length(A,N1),
length(B,N2),
N2>N1.
I could only find the one, I don't know how I find all, please don’t solve this predicate in complicate way or use complicates functor, it’s hard to understand for me.
Another possible solution is:
maxlist(ListOfLists, Answer) :-
maxlist(ListOfLists, -inf, [], Answer).
maxlist([], _, Answer, Answer).
maxlist([List|Lists], Max, Acc, Answer) :-
length(List, N),
( N = Max -> maxlist(Lists, Max, [List|Acc], Answer)
; N > Max -> maxlist(Lists, N, [List], Answer)
; maxlist(Lists, Max, Acc, Answer) ).
Examples:
?- maxlist([[6,7,8,9], [6,7,8,9], [6,7,8,9], [7,8,9], [7,8,9], [5,6,7]], M).
M = [[6, 7, 8, 9], [6, 7, 8, 9], [6, 7, 8, 9]].
?- maxlist([[1,2,3],[4,5,6,7,8,9],[0]], M).
M = [[4, 5, 6, 7, 8, 9]].
?- maxlist([[1,2,3], [4,5,6,7], [8], [9,0,1], [2,3,4,5]], M).
M = [[2, 3, 4, 5], [4, 5, 6, 7]].
The big issue with this problem is the repeated iteration of the list and its sublists, is it not?
I would start with a predicate that iterates over your list-of-lists once, prefixing each sublist with its length, and computing the length of the sublist as it goes:
map_lengths( Xs, L, X1 ) :- map_lengths(Xs,0,L,X1) .
map_lengths( [] , M , M , [] ) .
map_lengths( [X|Xs] , T , M , [L:X|Ys] ) :-
length(X,L),
T1 is max(L,T),
map_lengths(Xs,T1,M,Ys)
.
That's one pass over the list and its sublists.
Now that we have that, all we need is a way to extract sublists of a specified length. That's as easy as this:
lists_of_length( _ , [] , [] ) .
lists_of_length( L , [L:X|Xs] , [X|Ys] ) :- !, lists_of_length(L,Xs,Ys) .
lists_of_length( L , [_:_|Xs] , Ys ) :- lists_of_length(L,Xs,Ys) .
That is another single pass of the outer list. We no longer need to iterate over the sublists themselves.
And then, we just wire up the two predicates:
longest( Xs , Ys ) :-
map_lengths( Xs, L, X1 ) ,
lists_of_length(L,X1,Ys)
.
Putting it all together, you get:
https://swish.swi-prolog.org/p/VyUrjJjD.pl
longest( Xs , Ys ) :-
map_lengths( Xs, L, X1 ) ,
lists_of_length(L,X1,Ys)
.
map_lengths( Xs, L, X1 ) :- map_lengths(Xs,0,L,X1) .
map_lengths( [] , M , M , [] ) .
map_lengths( [X|Xs] , T , M , [L:X|Ys] ) :-
length(X,L),
T1 is max(L,T),
map_lengths(Xs,T1,M,Ys)
.
lists_of_length( _ , [] , [] ) .
lists_of_length( L , [L:X|Xs] , [X|Ys] ) :- !, lists_of_length(L,Xs,Ys) .
lists_of_length( L , [_:_|Xs] , Ys ) :- lists_of_length(L,Xs,Ys) .
Overall time and space complexity is O(N).
You can do it traversing the list once and keeping the current maximum length found along with the lists that have that maximum length:
maxlist(L, ML):-
maxlist(L, 0-[], ML).
maxlist([], _-ML, ML).
maxlist([A|L], MaxLen-ML, ML2):-
length(A, Len),
compare(C, Len, MaxLen),
memberchk(C-MaxLen1/ML1, [(<)-MaxLen/ML, (=)-MaxLen/[A|ML], _-Len/[A]]),
maxlist(L, MaxLen1-ML1, ML2).
Sample run:
?- maxlist([[6, 7, 8,9], [6, 7, 8, 9], [6, 7, 8, 9], [7, 8, 9], [7, 8, 9],[5,6,7], [1,2,3,4,5]], ML).
ML = [[1, 2, 3, 4, 5]].
Another alternative:
max_len_lists(LstLists, LstMaxLenFilter) :-
max_len_lists_(LstLists, _LenMax, LstMaxLenFilter),
% No need to check for alternatives
!.
max_len_lists_([], 0, []).
max_len_lists_([H|T], Len, LstMax) :-
length(H, LenH),
% Use recursion to check the rest of the list
max_len_lists_(T, LenT, F),
( LenH = LenT -> Len = LenH, LstMax = [H|F]
; LenH > LenT -> Len = LenH, LstMax = [H]
; Len = LenT, LstMax = F ).

Find all natural divisors of a number (with Prolog)

I want to create a predicate divisors(X,[Y]) which is true if
X>1 and Y is the list of all divisors of X starting with X and going down to 1.
What my code right now looks like:
divisors(1,[1]).
divisors(X,[Y,Z|Ys]) :-
X>0,
Y is X,
Y>Z,
divides(X,[Z|Ys]).
divides(X,[Y,Z|Ys]) :-
Y>Z,
0 is X mod Y,
divides(X,[Z|Ys]).
divides(X,[1]).
But there are several problems with it:
prolog returns an error if asked for the list (e.g. ?-divisors(10,X).)
?- divisors(X,[Y]). Where [Y] is an incomplete list of divisors is true...
Edit by Guy Coder
This answer is by the OP and was posted in a comment below.
Moving here so others can see it.
divisors(X,R) :-
X > 1,
divisors(X,1,[],R).
divisors(X,D,R,R):-
D>X.
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 + 1,
divisors(N,D,R1,R).
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(N,D,R0,R0).
divides(N,D) :-
0 is N mod D.
Op also noted some errors in this version:
It doesn't terminate if I ask a wrong statement like (10,[1,2,3]).
It throws an error if I ask a statement like (X, [10,5,2,1]). (-> Arguments are not sufficiently initialized.)
While the answer by William is nice and probably faster here is answer closer to what you were writing.
divides(N,D) :-
0 is N mod D.
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(N,D,R0,R0) :-
\+ divides(N,D).
divisors(_,0,R,R).
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 - 1,
divisors(N,D,R1,R).
divisors(X,R) :-
X > 1,
divisors(X,X,[],R), !.
Example:
?- between(1,15,N), divisors(N,Rs).
N = 2,
Rs = [1, 2] ;
N = 3,
Rs = [1, 3] ;
N = 4,
Rs = [1, 2, 4] ;
N = 5,
Rs = [1, 5] ;
N = 6,
Rs = [1, 2, 3, 6] ;
N = 7,
Rs = [1, 7] ;
N = 8,
Rs = [1, 2, 4, 8] ;
N = 9,
Rs = [1, 3, 9] ;
N = 10,
Rs = [1, 2, 5, 10] ;
N = 11,
Rs = [1, 11] ;
N = 12,
Rs = [1, 2, 3, 4, 6, 12] ;
N = 13,
Rs = [1, 13] ;
N = 14,
Rs = [1, 2, 7, 14] ;
N = 15,
Rs = [1, 3, 5, 15].
Edit
OP modified their code, see update in question and had some errors.
This version resolves those errors.
divisors(X,R) :-
(
var(X)
->
false
;
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
).
divisors_2(_,[]).
divisors_2(X,[H|T]) :-
divides(X,H),
divisors_2(X,T).
divisors(X,D,R,R):-
D>X.
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 + 1,
divisors(N,D,R1,R).
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(_,_,R0,R0).
divides(N,D) :-
0 is N mod D.
The first error: It doesn't terminate if I ask a wrong statement like divisors(10,[1,2,3]).
is fixed by adding to divisors/2
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
and
divisors_2(_,[]).
divisors_2(X,[H|T]) :-
divides(X,H),
divisors_2(X,T).
which just processes the list of denominators instead of generating a list.
The second error: It throws an error if I ask a statement like divisors(X, [10,5,2,1]). (-> Arguments are not sufficiently initialized.)
is resolved by further adding to divisor/2
divisors(X,R) :-
(
var(X)
->
false
;
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
).
which checks if the first parameter X is a variable and if so just returns false. The other option would be to generate an infinite list of answers. While possible it wasn't requested.
In Prolog, it is quite common to use backtracking and propose multiple solutions to the same query. Instead of constructing a list of dividers, we thus can construct a predicate that unifies the second parameter with all divisors. For example:
divisor(N, D) :-
between(1, N, D),
0 is N mod D.
This then yields:
?- divisor(12, N).
N = 1 ;
N = 2 ;
N = 3 ;
N = 4 ;
N = 6 ;
N = 12.
The above algorithm is an O(n) algorithm: we scan for divisors linear with the value of the item for which we want to obtain the divisors. We can easily improve this to O(√n) by scanning up to √n, and each time yield both the divisor (of course in case it is a divisor), and the co-divisor, like:
emitco(D, _, D).
emitco(D, C, C) :-
dif(D, C).
divisor(N, R) :-
UB is floor(sqrt(N)),
between(1, UB, D),
0 is N mod D,
C is N / D,
emitco(D, C, R).
This still yield the correct answers, but the order is like a convergent alternating sequence:
?- divisor(12, N).
N = 1 ;
N = 12 ;
N = 2 ;
N = 6 ;
N = 3 ;
N = 4.
?- divisor(16, N).
N = 1 ;
N = 16 ;
N = 2 ;
N = 8 ;
N = 4 ;
false.
We can obtain a list of the divisors by using a findall/3 [swi-doc] or setof/3 [swi-doc]. The setof/3 will even sort the divisors, so we can implement divisors/2 in terms of divisor/2:
divisors(N, Ds) :-
setof(D, divisor(N, D), Ds).
For example:
?- divisors(2, N).
N = [1, 2].
?- divisors(3, N).
N = [1, 3].
?- divisors(5, N).
N = [1, 5].
?- divisors(12, N).
N = [1, 2, 3, 4, 6, 12].
?- divisors(15, N).
N = [1, 3, 5, 15].
We can use reverse/2 to reverse that result.

n-queens solution not working in Prolog

I am trying to run following code from N-Queens Problem‍​..How far can we go? to find solutions to n-queens problem:
generate([],_).
generate([H|T],N) :- H in 1..N , generate(T,N).
lenlist(L,N) :- lenlist(L,0,N).
lenlist([],N,N).
lenlist([_|T],P,N) :- P1 is P+1 , lenlist(T,P1,N).
queens(N,L) :-
generate(L,N),lenlist(L,N),
safe(L),!,
labeling([ffc],L).
notattack(X,Xs) :- notattack(X,Xs,1).
notattack(X,[],N).
notattack(X,[Y|Ys],N) :- X #\= Y,
X #\= Y - N,
X #\= Y + N,
N1 is N + 1,
notattack(X,Ys,N1).
safe([]).
safe([F|T]) :- notattack(F,T), safe(T).
I have swi-prolog installed on Debian-9 (stable) Linux and I am running above using command "swipl -f nqueens.pl". On loading, I get an error:
Syntax error: operator expected (probably on 2nd code line)
Where is the problem and how can this be solved? Thanks for your help.
The question actually mentions that it is writting in CLPFD (A Constraint Logic Programming tool over Finite Domains). You have to import this library:
:- use_module(library(clpfd)).
generate([],_).
generate([H|T],N) :- H in 1..N , generate(T,N).
lenlist(L,N) :- lenlist(L,0,N).
lenlist([],N,N).
lenlist([_|T],P,N) :- P1 is P+1 , lenlist(T,P1,N).
queens(N,L) :-
generate(L,N),lenlist(L,N),
safe(L),!,
labeling([ffc],L).
notattack(X,Xs) :- notattack(X,Xs,1).
notattack(X,[],N).
notattack(X,[Y|Ys],N) :- X #\= Y,
X #\= Y - N,
X #\= Y + N,
N1 is N + 1,
notattack(X,Ys,N1).
safe([]).
safe([F|T]) :- notattack(F,T), safe(T).
Then it works, and produces for instance:
?- queens(5,L).
L = [1, 3, 5, 2, 4] ;
L = [1, 4, 2, 5, 3] ;
L = [2, 4, 1, 3, 5] ;
L = [2, 5, 3, 1, 4] ;
L = [3, 1, 4, 2, 5] ;
L = [3, 5, 2, 4, 1] ;
L = [4, 1, 3, 5, 2] ;
L = [4, 2, 5, 3, 1] ;
L = [5, 2, 4, 1, 3] ;
L = [5, 3, 1, 4, 2].
When I look at line 2, as the error message suggests, the most probable cause is the H in 1..N. I would have written that as between(1, H, N). I haven't done anything in Prolog lately, though.
There are several different implementations of Prolog, and they differ in these little details. Try searching for guidelines for writing portable Prolog code.

Form a single list from multiple answers in Prolog

I currently have this piece of code in Prolog
s1(Q,100) :- generate(Q).
generate([X,Y,S,P]) :-
nat(X, 49),
nat(Y, 98),
S is X+Y,
P is X*Y,
S =< 100,
X < Y.
nat(2,_).
nat(X,N) :-
N > 2,
M is N - 1,
nat(Y,M),
X is Y + 1.
It currently generates a list of quadruples, X, Y, S, P such that
1 < X < 49
1 < Y < 98
1 < X < Y
X + Y <= 100
P = X * Y
S = X + Y
This works and creates all possible solutions but with multiple answers (i.e, having to press ; every time to get the next result.)
How can a single list be formed of all these results, for instance,
[[2, 3, 5, 6], [2, 4, 6, 8], ...]
without using any built in predicates such as findall/3?
First, the upper interval bounds you gave for X and Y are both off by one:
1 < X < 49 does not match nat(X,49), 1 < X =< 49 does.
1 < Y < 98 does not match nat(Y,98), 1 < Y =< 98 does.
Let's get it started!
If you want to collect all solutions without using findall/3 (etc), one way is to calculate the Cartesian product (a.k.a. cross-product) of two lists Xs and Ys.
To get Xs and Ys, we can use the builtin predicate numlist/3:
?- numlist(2,49,Xs).
Xs = [2,3,4,/* consecutive integers from 5 to 47 omitted */,48,49].
?- numlist(2,98,Ys).
Ys = [2,3,4,/* consecutive integers from 5 to 96 omitted */,97,98].
To combine every X in Xs with every Y in Ys we use dcg xproduct//3.
For selecting which quadruples to collect, use the grammar rule x_y_maybe_quadruple//2:
x_y_maybe_quadruple(X,Y) -->
( { 1 < X, X < Y, X+Y =< 100 } % if all these conditions are met
-> { P is X * Y },
{ S is X + Y },
[[X,Y,S,P]] % then add single "quadruple"
; [] % else add nothing.
).
Let's put it all together!
?- numlist(2,49,Xs),
numlist(2,98,Ys),
phrase(xproduct(x_y_maybe_quadruple,Xs,Ys),Qss).
Qss = [[2,3,5,6],[2,4,6,8],
/* lots of other quadruples omitted */,
[48,51,99,2448],[48,52,100,2496]].
So... do we actually get all quadruples we would have gotten if we had used findall/3?
?- findall(Qs,generate(Qs),Qss1),
numlist(2,49,Xs),
numlist(2,98,Ys),
phrase(xproduct(x_y_maybe_quadruple,Xs,Ys),Qss2),
Qss1 = Qss2.
Qss1 = Qss2,
Qss2 = [[2, 3, 5, 6], [2, 4, 6, 8], [2|...], [...|...]|...],
Xs = [2, 3, 4, 5, 6, 7, 8, 9, 10|...],
Ys = [2, 3, 4, 5, 6, 7, 8, 9, 10|...].
It works! And not just that: we get exactly the same quadruples in the exact same order!
You need to add a solution to a list if it is not already in the list..if its in the list fail.
so
myfindall(List) :-
my_find(List,[]),
!.
my_find(List,Ac) :-
s1(Q,100),
my_set(Q,Ac,NewAc),
my_find(List,NewAc).
my_find(Ac,Ac).
my_set(X,[],[X]) :-
!.
my_set(H,[H|_],_) :-
!,
fail.
my_set(X,[H|T],L) :-
my_set(X,T,Rtn),
L = [H|Rtn].

Issue in Prolog Programming

Hello I am new in Prolog and trying to write small program in Prolog in order to learn it....
I have written a program to remove the positional element mean remove(List,2,Ans) will remove all the elements of position 2,4,6,8.... from the list... below is my logic
remove(L,N,Ans):-
length(L,LEN),
T1 is 1 mod N,
add(L,N,[],LEN,T1,Res).
add(L,N,Ans,0,T,Ans).
add([H|T],N,Ans,LEN,0,Res):-
LEN1 is LEN-1,
T1 is 1 mod N,
add(T,N,Ans,LEN1,T1,Res).
add([H|T],N,Ans,LEN,T,Res):-
T =\= 0, LEN =\= 0,
LEN1 is LEN-1,
T1 is T1+1,
T2 is T1 mod N,
append([H],Ans,Result),
add(T,N,Result,LEN1,T2,Res).
but every time I run it is failing when finding add. below is the trace of the program that is have for a particular instance
[trace] ?- remove([1,2,3,4,5,6,7,8],2,X).
Call: (6) remove([1, 2, 3, 4, 5, 6, 7, 8], 2, _G2941) ? creep
Call: (7) length([1, 2, 3, 4, 5, 6, 7, 8], _G3039) ? creep
Exit: (7) length([1, 2, 3, 4, 5, 6, 7, 8], 8) ? creep
Call: (7) _G3041 is 1 mod 2 ? creep
Exit: (7) 1 is 1 mod 2 ? creep
Call: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep
Fail: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep
Fail: (6) remove([1, 2, 3, 4, 5, 6, 7, 8], 2, _G2941) ? creep
false.
Does anyone know where the problem is?
Hope you can find your way in your code. I think the better way to learn a language is actually debugging it... lurker' comment already put you on the right track. But I want to show how using builtins can change your perspective (this is of course true for any language, not just Prolog).
remove(L,N,Ans) :- findall(E, (nth1(I,L,E), I mod N =\= 0), Ans).
?- remove([1,2,3,4,5,6,7,8],2,X).
X = [1, 3, 5, 7].
edit when you
Call: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep
no rule can be matched, specifically T cannot be a list and the number 1
add([H|T],N,Ans,LEN,T,Res):-
that said, I'm not sure how you should correct the code...
A common prolog idiom is the use of a "helper" predicate that actually does the work and carries
one or more additional arguments that maintain state. In this case, we need a counter to track
our position within the source list.
remove( Xs , N , Ys ) :-
remove( Xs , 1 , N , Ys ). % Note the additional argument (our counter) initialized to 1
remove( [] , _ , _ , [] ) . % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , [X|Ys] ) :- % otherwise,
P mod N =\= 0 , % - if the current position is NOT a multiple of N,
P1 is P+1 , % - we increment the position,
remove(Xs,P1,N,Ys) % - and recurse down, adding the head of the list
. % to the result.
remove( [_|Xs] , P , N , Ys ) :- % otherwise,
P mod N =:= 0 , % - if the current position is a multiple of N,
P1 is P1+1 , % - increment the position,
remove(Xs,P1,N1,Ys) % - and recurse down, discarding the head of the list
. % Easy!
You might note some repetitive code. In the spirit of keeping things DRY, we can refactor it thusly:
remove( [] , _ , _ , [] ) . % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , Ys ) :- % otherwise,
keep_or_discard(X,P,N,Ys,Y1) , % - decided whether to keep or discard the current list head
P1 is P+1 , % - increment the counter
remove( Xs , P1 , N , Y1 ) % - and recurse down.
.
keep_or_discard( _ , P , N , Ys , Ys ) :- % if P is a multiple of N
P mod N =:= 0 , % - discard X,
! . % - and eliminate the choice point.
keep_or_discard( X , _ , _ , Ys , [X|Ys] ) . % otherwise, we keep it.
Some folk dislike the use of the cut to explicitly eliminate choice points, so alternatively, we can do the refactoring via the use of prolog's implication/if-then-else operator:
remove( [] , _ , _ , [] ) . % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , Ys ) :- % otherwise,
( P mod N =:= 0 % - if P is a multiple of N,
-> Y1 = Ys % - then we discard the list head
; [X|Y1] = Ys % - otherwise, we add it to the result list
) , % - and then ...
P1 is P+1 , % - increment the counter
remove( Xs , P1 , N , Y1 ) % - and recurse down.
.
Whether either of these refactorings is clearer, or easier to understand than the original is, of course, a personal choice.

Resources