用简单的方式是生成和测试:在这里,你让Prolog的生成置换,但只有在满足特定条件时才接受。例如:
dif3([_]).
dif3([A,B|T]) :-
D is abs(A-B),
D =< 3,
dif3([B|T]).
,然后定义:
perm3(L,R) :-
perm(L,R),
dif3(R).
这种方法不是很有效:它可以是用于置换的指数数量,只有少数是有效的情况下,这会意味着大量的计算工作。例如,如果元素列表是[2,5,7,9]
,它将生成从[2,9,...]
开始的所有排列,而更智能的方法已经可以看出,永远不会生成有效的解决方案。
其他更智能的方法是交错生成并测试。在这里,您只选择takeout3/4
这些有效的候选人号码。您可以定义一个谓词takeout3(L,P,X,T).
其中L
是最初的名单,P
对上号,X
所选号码与T
结果列表:
takeout3([X|T],P,X,T) :-
D is abs(X-P),
D =< 3.
takeout3([H|L],N,X,[H|T]) :-
takeout3(L,N,X,T).
现在我们就可以生成排列如下:
perm3([],[]).
perm3(L,[E|T]) :-
takeout(L,E,R),
perm3(R,E,T).
perm3([],_,[]).
perm3(L,O,[E|T]) :-
takeout3(L,O,E,R),
perm3(R,E,T).
注意我们使用perm3
的两个版本:perm3/2
和perm3/3
,第一个用于生成第一个元素(使用旧的takeout/3
),perm3/3
用于生成使用takeout3/4
的其余排列组合。
这种方法的完整的源代码是:
takeout([X|T],X,T).
takeout([H|L],X,[H|T]) :-
takeout(L,X,T).
takeout3([X|T],P,X,T) :-
D is abs(X-P),
D =< 3.
takeout3([H|L],N,X,[H|T]) :-
takeout3(L,N,X,T).
perm3([],[]).
perm3(L,[E|T]) :-
takeout(L,E,R),
perm3(R,E,T).
perm3([],_,[]).
perm3(L,O,[E|T]) :-
takeout3(L,O,E,R),
perm3(R,E,T).
与swipl
运行它给:
?- perm3([2,7,5],L).
L = [2, 5, 7] ;
L = [7, 5, 2] ;
false.
预期的行为。
你能解释一下你的'perm'的作品,因为你把它相当困难。有更直接的方法来做到这一点... –