我目前正在处理99 Prolog问题列表http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/,问题是18。它声明:
给定两个索引
I
和K
,切片是包含原始列表的I
'和K
'元素之间的元素的列表(包括两个限制)。开始使用1
计算元素。示例查询:
?- slice([a,b,c,d,e,f,g,h,i,k],3,7,L).
预期结果:L = [c,d,e,f,g]
我看过给定的解决方案,但我的问题是,是否有人能够找出解决方案错误的原因?这是我的代码:
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).
我的思路是:如果迭代'Count'中的元素在两个给定限制之间,则添加到列表中,如果没有则继续。作为示例输出,用于呼叫:
?- slice([a,b,c,d,e],2,3,X).
我得到了输出:
X = [b,c] ? ;
X = [b,c] ? ;
X = [a,b,c] ? ;
X = [a,b,c] ? ;
致电:
?- slice([a,b,c,d,e],3,3,X).
X = [c] ? ;
X = [b,c] ? ;
X = [a,c] ? ;
X = [a,b,c] ? ;
第一个给定的列表是正确的但是一切都出错了;我尝试过使用痕迹,但令人难以置信。
答案 0 :(得分:2)
我们定义slice/4
基于append/3
和length/2
,由Prolog Prologue定义:
slice(AsBsCs,P,Q,Bs) :-
append(AsBs,_Cs,AsBsCs),
append(As , Bs,AsBs ),
length([_|As],P),
length( AsBs ,Q).
OP给出的示例查询:
?- slice([a,b,c,d,e,f,g,h,i,k],3,7,Xs).
Xs = [c,d,e,f,g] ;
false.
让我们像这样概括上面的查询:
?- 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.
如何推广不同的方式?
?- 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.
最后,我们运行一个查询,它是两者的概括:
?- 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.
答案 1 :(得分:0)
你遇到的问题是你的规则并不相互排斥 与你的第二条规则匹配的一切
chop([_|L],Start,End,Count,Out) :-
也会与您的第三条规则相匹配
chop([H|L],Start,End,Count,[H|Out]) :-
这意味着一旦你找到了一个有效的答案,并试图找到更多,每个成功分支到第二个规则将导致第三个分支后面的第二个答案。 (因此附加的前置字母)
您可以通过在第二条规则末尾添加剪切来解决此问题
chop([_|L],Start,End,Count,Out) :-
(Count < Start),
N is Count + 1,
chop(L,Start,End,N,Out),
!.