This is my problem:
Write a procedure
distance(List, Nemptylist, SubList)/3that checks ifSublistis a sublist ofListwith a distance of not more thanNbetween items constraint (Nis implemented asNemptylist– a list ofNanonymous variables). Assume thatListis fully instantiated. Duplicate answers are allowed, as long as their number is finite.For example, for
N= 2 :?- distance( [a,t,d,r,a,n,c,b,c] , [_,_], [a,b,c] ). true ?- distance( [m,a,t,d,r,b,c,t] , [_,_] , [a,b,c] ). false ?- distance([a, t, d, r, a, n, c, b], [_, _], [a, b, c]). false ?- distance([c, c, c, a, c, c, c], [_, _], [a]). true.
I've been sitting for hours, trying to solve this problem and eventually the examples above worked, but then i ran some tests and they failed.
My solution for now is as follows:
distance( L1 , L2 , [X] ) :-
member(X,L1) .
distance( L1 , L2 , [H|T] ) :-
distance(L1,L2,T) ,
append(Y,Z,L2) ,
T=[Hs|Ts] ,
append([H],Y,W) ,
append(W,[Hs],R) ,
sublist(R,L1) .
prefix(X,L) :- append(X, _, L).
suffix(X,L) :- append(_, X, L).
sublist(X,L) :- suffix(S,L) , prefix(X,S) .
when i try to run this test:
distance( [r,a,n,c,b,c],[],X) .
it fails due to run-time exceeded error.
I debugged it for hours and I'm really exhausted. Please help me finish this horrible assignment.
Here is a solution step-by-step starting with an incomplete definition:
distance_tentative(Xs, _Ys, Zs) :-
phrase(( ..., seq(Zs), ... ), Xs).
... --> [] | [_], ... .
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
This solution is too specialized because it describes only substrings but not subsequences. A subsequence is rather:
subseq([]) --> [].
subseq([E|Es]) --> [E], subseq(Es).
subseq(Es) --> [_], subseq(Es).
Now, we want to limit the number of intermediary unrelated elements. That is, we want to limit the application of the last rule to the length of this list argument LN.
subseq_n([], _) --> [].
subseq_n([E|Es], LN) --> [E], subseq_n(Es, LN).
subseq_n(Es, [_|LN]) --> [_], subseq_n(Es, LN).
Maybe the last rule should rather read:
subseq_n(Es, [E|LN]) --> [E], subseq_n(Es, LN).
I suspect some problem in the translation of the problem statement. In any case, now we have:
distance(Xs, Ys, Zs) :-
phrase(( ..., subseq_n(Zs, Ys), ... ), Xs).
There are many redundant answers, but you stated that this is OK.
There is a lot of redundancy that is, ambiguity, between the first ... and the start of the first element of subseq_n//2; similarly, between subseq_n//2 and ... at the end. Further, if Zs is empty, a single answer would suffice. Brief
distance(_Xs, _Ys, []).
distance(Xs, Ys, [Z|Zs]) :-
phrase( ( ..., [Z], rsubseq_n(Zs, Ys), ... ), Xs).
rsubseq_n([], _) --> [].
rsubseq_n([E|Es], Ys) --> [E], rsubseq_n(Es, Ys).
rsubseq_n([E|Es], [_|Ys]) --> [_], rsubseq_n([E|Es], Ys).
Note that the "distance list" is now used only within the subsequence.
This program has very favorable termination properties:
distance(A,B,C)terminates_if b(A).
So only the first argument has to be known to make the predicate terminate.
Edit: Your problem statement has been ambiguous w.r.t. where the distance N applies to:
... with a distance of not more than N between items constraint ...
This can mean a total edit distance of no more than N, or a distance between each consecutive pair. So assuming that the distance between each consecutive pair is meant:
distanceII(_Xs, _Ys, []).
distanceII(Xs, Ys, [Z|Zs]) :-
phrase( ( ..., [Z], rsubseq_d(Zs, Ys), ... ), Xs).
rsubseq_d([], _) --> [].
rsubseq_d([E|Es],Max) -->
maxseq(Max),
[E],
rsubseq_d(Es, Max).
maxseq(_) --> [].
maxseq([_|Es]) --> [_], maxseq(Es).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With