Prolog:消除查询中的重复

问题描述 投票:0回答:1

我一直在尝试编写一个简单的代码,它会以这种方式表现:

| ?- hasCoppiesOf(X,[a,b,a,b,a,b,a,b]).
X = [a,b] ? ;
X = [a,b,a,b] ? ;
X = [a,b,a,b,a,b,a,b] ? ;

| ?- hasCoppiesOf([a,b,a,b,a,b,a,b], X).    
X = [] ? ;    
X = [a,b,a,b,a,b,a,b] ? ;    
X = [a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b] ? ;    
X = ...

这种愿望导致了下一段代码:

hasCoppiesOf(A,[]).


hasCoppiesOf([H1|T1], [H1|T2]) :-
  append(T1, [H1], X),
  hasCoppiesOf([H1|T1], X, T2).


hasCoppiesOf(A, A, B) :-
  hasCoppiesOf(A, B).

hasCoppiesOf(A, [H1|T1], [H1|T2]) :-
  append(T1, [H1], X),
  hasCoppiesOf(A, X, T2).

它给了我第二个查询所需的内容,但是,第一个查询的结果是:

?- hasCoppiesOf(X,[a,b,a,b,a,b,a,b]).
X = [a, b] ;
X = [a, b] ;
X = [a, b] ;
X = [a, b] ;
X = [a, b] ;
X = [a, b] ;
X = [a, b] ;
X = [a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b] ;
X = [a, b, a, b, a, b] ;
X = [a, b, a, b, a, b] ;
X = [a, b, a, b, a, b] ;
X = [a, b, a, b, a, b] ;
X = [a, b, a, b, a, b] ;

似乎工作正常,但是重复相同的答案使我感到困扰。这可能是一个简单的错误,但是有没有办法使输出更漂亮?老实说,这是个谜,为什么Prolog会将两个相同的数组视为不同的答案。还是我的系统有问题?

编辑:此人在评论中的温柔指导帮助我解决了这个问题。但是,如果这个问题让正在阅读的人想要解决完全相同的问题-代码不能很好地工作,我深表歉意。

prolog swi-prolog
1个回答
0
投票

我认为您只是使谓词变得比需要的复杂,可能只是对它进行了过度思考。给定的解决方案可能会在通过逻辑的多个路径中成功。

如果您考虑这个问题,它会更简单:

hasCoppiesOf([], []).
hasCoppiesOf([_|_], []).
hasCoppiesOf(L, Ls) :-
    append(L, L1s, Ls),
    hasCoppiesOf(L, L1s).

基本情况很简单。递归的情况只是说,如果我可以通过附加LsL来获得Ls,则LL1s的副本,而L1sL的副本。对我来说,这听起来很合逻辑。

这在以下情况下效果很好:

hasCoppiesOf([a,b], L).
L = []
L = [a, b]
L = [a, b, a, b]
L = [a, b, a, b, a, b]
...

hasCoppiesOf(L, [a,b,a,b]).
L = [a, b]
L = [a, b, a, b]

但是,最一般的查询不会终止:hasCoppiesOf(A, B).。这可以通过使用length/2顺序限制长度来解决:

hasCoppiesOf([], []).
hasCoppiesOf([_|_], []).
hasCoppiesOf(L, Ls) :-
    length(Ls, _),
    append(L, L1s, Ls),
    hasCoppiesOf(L, L1s).

现在我们得到:

hasCopiesOf1(A, B).
A = B, B = []
A = [_1252|_1254],
B = []
A = B, B = []
A = B, B = [_1252]
A = [_1252],
B = [_1252, _1252]
A = B, B = [_1252, _1258]
A = [_1252],
B = [_1252, _1252, _1252]
A = B, B = [_1252, _1258, _1264]
A = [_1252],
B = [_1252, _1252, _1252, _1252]
A = [_1252, _1258],
B = [_1252, _1258, _1252, _1258]
...
© www.soinside.com 2019 - 2024. All rights reserved.