Reputation: 103
I'm currently working through the 99 Prolog problems list http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/ and am on question 18. It states:
Given two indices,
I
andK
, the slice is the list containing the elements between theI
'th andK
'th element of the original list (both limits included). Start counting the elements with1
.Example query:
?- slice([a,b,c,d,e,f,g,h,i,k],3,7,L).
Expected result:L = [c,d,e,f,g]
I've looked at the given solution, but my question was whether anyone could figure out why my solution was wrong? This is my code:
chop([H|_],_,End,End,[H]).
chop([_|L],Start,End,Count,Out) :-
(Count < Start),
N is Count + 1,
chop(L,Start,End,N,Out).
chop([H|L],Start,End,Count,[H|Out]) :-
(Count >= Start; Count < End),
N is Count + 1,
chop(L,Start,End,N,Out).
slice(L,Start,End,Out) :-
(Start =< End),
Count is 1,
chop(L,Start,End,Count,Out).
My train of thought was: if the element at iteration 'Count' is between the two given limits then add to the list, if not then move on. As an example output, for the call:
?- slice([a,b,c,d,e],2,3,X).
I get the output:
X = [b,c] ? ;
X = [b,c] ? ;
X = [a,b,c] ? ;
X = [a,b,c] ? ;
And for the call:
?- slice([a,b,c,d,e],3,3,X).
X = [c] ? ;
X = [b,c] ? ;
X = [a,c] ? ;
X = [a,b,c] ? ;
The first given list is correct but then it all goes wrong; I've tried using trace but it's boggling my mind.
Upvotes: 1
Views: 198
Reputation: 18726
We define slice/4
based on append/3
and length/2
, as defined by the Prolog Prologue:
slice(AsBsCs,P,Q,Bs) :-
append(AsBs,_Cs,AsBsCs),
append(As , Bs,AsBs ),
length([_|As],P),
length( AsBs ,Q).
Sample query as given by the OP:
?- slice([a,b,c,d,e,f,g,h,i,k],3,7,Xs).
Xs = [c,d,e,f,g] ;
false.
Let's generalize above query like this:
?- slice([a,b,c,d,e,f,g,h,i,k],P,7,Xs). P = 1, Xs = [a,b,c,d,e,f,g] ; P = 2, Xs = [b,c,d,e,f,g] ; P = 3, Xs = [c,d,e,f,g] ; P = 4, Xs = [d,e,f,g] ; P = 5, Xs = [e,f,g] ; P = 6, Xs = [f,g] ; P = 7, Xs = [g] ; P = 8, Xs = [] ; false.
How about generalizing a different way?
?- slice([a,b,c,d,e,f,g,h,i,k],3,Q,Xs). ; Q = 2, Xs = [] ; Q = 3, Xs = [c] ; Q = 4, Xs = [c,d] ; Q = 5, Xs = [c,d,e] ; Q = 6, Xs = [c,d,e,f] ; Q = 7, Xs = [c,d,e,f,g] ; Q = 8, Xs = [c,d,e,f,g,h] ; Q = 9, Xs = [c,d,e,f,g,h,i] ; Q = 10, Xs = [c,d,e,f,g,h,i,k] ; false.
Last, we run a query which is a generalization of both:
?- slice([a,b,c,d,e,f,g,h,i,k],P,Q,Xs). P = 1, Q = 0, Xs = [] ; P = 1, Q = 1, Xs = [a] ; P = 2, Q = 1, Xs = [] ; P = 1, Q = 2, Xs = [a,b] ; P = 2, Q = 2, Xs = [b] ; P = 3, Q = 2, Xs = [] ; P = 1, Q = 3, Xs = [a,b,c] ; P = 2, Q = 3, Xs = [b,c] ; P = 3, Q = 3, Xs = [c] ; P = 4, Q = 3, Xs = [] ; P = 1, Q = 4, Xs = [a,b,c,d] ; P = 2, Q = 4, Xs = [b,c,d] ; P = 3, Q = 4, Xs = [c,d] ; P = 4, Q = 4, Xs = [d] ; P = 5, Q = 4, Xs = [] ; P = 1, Q = 5, Xs = [a,b,c,d,e] ; P = 2, Q = 5, Xs = [b,c,d,e] ; P = 3, Q = 5, Xs = [c,d,e] ; P = 4, Q = 5, Xs = [d,e] ; P = 5, Q = 5, Xs = [e] ; P = 6, Q = 5, Xs = [] ; P = 1, Q = 6, Xs = [a,b,c,d,e,f] ; P = 2, Q = 6, Xs = [b,c,d,e,f] ; P = 3, Q = 6, Xs = [c,d,e,f] ; P = 4, Q = 6, Xs = [d,e,f] ; P = 5, Q = 6, Xs = [e,f] ; P = 6, Q = 6, Xs = [f] ; P = 7, Q = 6, Xs = [] ; P = 1, Q = 7, Xs = [a,b,c,d,e,f,g] ; P = 2, Q = 7, Xs = [b,c,d,e,f,g] ; P = 3, Q = 7, Xs = [c,d,e,f,g] ; P = 4, Q = 7, Xs = [d,e,f,g] ; P = 5, Q = 7, Xs = [e,f,g] ; P = 6, Q = 7, Xs = [f,g] ; P = 7, Q = 7, Xs = [g] ; P = 8, Q = 7, Xs = [] ; P = 1, Q = 8, Xs = [a,b,c,d,e,f,g,h] ; P = 2, Q = 8, Xs = [b,c,d,e,f,g,h] ; P = 3, Q = 8, Xs = [c,d,e,f,g,h] ; P = 4, Q = 8, Xs = [d,e,f,g,h] ; P = 5, Q = 8, Xs = [e,f,g,h] ; P = 6, Q = 8, Xs = [f,g,h] ; P = 7, Q = 8, Xs = [g,h] ; P = 8, Q = 8, Xs = [h] ; P = 9, Q = 8, Xs = [] ; P = 1, Q = 9, Xs = [a,b,c,d,e,f,g,h,i] ; P = 2, Q = 9, Xs = [b,c,d,e,f,g,h,i] ; P = 3, Q = 9, Xs = [c,d,e,f,g,h,i] ; P = 4, Q = 9, Xs = [d,e,f,g,h,i] ; P = 5, Q = 9, Xs = [e,f,g,h,i] ; P = 6, Q = 9, Xs = [f,g,h,i] ; P = 7, Q = 9, Xs = [g,h,i] ; P = 8, Q = 9, Xs = [h,i] ; P = 9, Q = 9, Xs = [i] ; P = 10, Q = 9, Xs = [] ; P = 1, Q = 10, Xs = [a,b,c,d,e,f,g,h,i,k] ; P = 2, Q = 10, Xs = [b,c,d,e,f,g,h,i,k] ; P = 3, Q = 10, Xs = [c,d,e,f,g,h,i,k] ; P = 4, Q = 10, Xs = [d,e,f,g,h,i,k] ; P = 5, Q = 10, Xs = [e,f,g,h,i,k] ; P = 6, Q = 10, Xs = [f,g,h,i,k] ; P = 7, Q = 10, Xs = [g,h,i,k] ; P = 8, Q = 10, Xs = [h,i,k] ; P = 9, Q = 10, Xs = [i,k] ; P = 10, Q = 10, Xs = [k] ; P = 11, Q = 10, Xs = [] ; false.
Upvotes: 2
Reputation: 697
the problem you have is that your rules are not mutually exclusive everything that matches with your second rule
chop([_|L],Start,End,Count,Out) :-
will also match with your third rule
chop([H|L],Start,End,Count,[H|Out]) :-
Meaning that once you have found a working answer, and try to find more, every successful branching into the second rule will result in a second answer following the third branch. (hence the additional prepended letter)
you could solve this by adding a cut in at the end of the second rule
chop([_|L],Start,End,Count,Out) :-
(Count < Start),
N is Count + 1,
chop(L,Start,End,N,Out),
!.
Upvotes: 0