我正在尝试为我的任务解决这个问题。
仅当R代表列表L的可接受置换时,谓词acceptable_permutation(L,R)才应成功。 例如:[2,1,3]不是列表[1,2,3]的可接受排列,因为3并未改变其位置。
输出为 假定 ,如下所示:
?- acceptable_permutation([1,2,3],R).
R = [2,3,1] ;
R = [3,1,2] ;
false
?- acceptable_permutation([1,2,3,4],R).
R = [2,1,4,3] ;
R = [2,3,4,1] ;
R = [2,4,1,3] ;
R = [3,1,4,2] ;
R = [3,4,1,2] ;
R = [3,4,2,1] ;
R = [4,1,2,3] ;
R = [4,3,1,2] ;
R = [4,3,2,1] ;
false.
我的代码输出给出:
?- acceptable_permutation([1,2,3],R).
R = [1,2,3] ;
R = [1,3,2] ;
R = [2,1,3] ;
R = [2,3,1] ;
R = [3,1,2] ;
R = [3,2,1] ;
?- acceptable_permutation([1,2,3,4],R).
R = [1,2,3,4] ;
R = [1,2,4,3] ;
R = [1,3,2,4] ;
R = [1,3,4,2] ;
R = [1,4,2,3] ;
R = [1,4,3,2] ;
R = [2,1,3,4] ;
R = [2,1,4,3] ;
R = [2,3,1,4] ;
R = [2,3,4,1] ;
R = [2,4,1,3] ;
R = [2,4,3,1] ;
R = [3,1,2,4] ;
R = [3,1,4,2] ;
R = [3,2,1,4] ;
R = [3,2,4,1] ;
R = [3,4,1,2] ;
R = [3,4,2,1] ;
R = [4,1,2,3] ;
R = [4,1,3,2] ;
R = [4,2,1,3] ;
R = [4,2,3,1] ;
R = [4,3,1,2] ;
R = [4,3,2,1] ;
false.
我的代码如下:
acceptable_permutation(list,list).
del(symbol,list,list).
del(X,[X|L1], L1).
del(X,[Y|L1], [Y|L2]):-
del(X,L1, L2).
acceptable_permutation([] , []).
acceptable_permutation(L, [X|P]):-
del(X, L, L1),
acceptable_permutation(L1, P).
请告诉我问题出在哪里,这样我的输出应与正确的输出匹配。如果您向我展示它是如何完成的,我将不胜感激。
答案 0 :(得分:2)
1)没有固定点的置换称为derangement。好笑的名字!也是这样。
2)像previous answer一样,我们使用maplist/3
和permutation/2
。
3)与此previous answer不同,我们使用prolog-dif而不是(\=)/2
来保持逻辑纯洁。
logical-purity有助于保持Prolog程序的通用性,在这种情况下,还可以提高效率。
让我们像这样定义list_derangement/2
:
list_derangement(Es, Xs) :- maplist(dif, Es, Xs), % using dif/2 permutation(Es, Xs).
请注意,maplist/2
目标现在位于另一个目标之前!
与先前答案中的find_perm/2
相比,这可以加快失败案例的检测速度:
?- time(find_perm([1,2,3,4,5,6,7,8,9,10,11], [_,_,_,_,_,_,_,_,_, _,11])). % 303,403,801 inferences, 37.018 CPU in 37.364 seconds (99% CPU, 8196109 Lips) false. ?- time(list_derangement([1,2,3,4,5,6,7,8,9,10,11], [_,_,_,_,_,_,_,_,_, _,11])). % 15,398 inferences, 0.009 CPU in 0.013 seconds (67% CPU, 1720831 Lips) false.
对于相应的地面术语,上述实现的速度相当:
?- time((find_perm([1,2,3,4,5,6,7,8,9,10,11],_),false)). % 931,088,992 inferences, 107.320 CPU in 107.816 seconds (100% CPU, 8675793 Lips) false. ?- time((list_derangement([1,2,3,4,5,6,7,8,9,10,11],_),false)). % 1,368,212,629 inferences, 97.890 CPU in 98.019 seconds (100% CPU, 13976991 Lips) false.
答案 1 :(得分:0)
问题是您没有检查输出列表的所有元素与输入列表的位置是否不同。您应该添加一个谓词来检查它,就像这样:
perm(L,LO):-
acceptable_permutation(L,LO),
different_place(L,LO).
different_place([A|T0],[B|T1]):-
A \= B,
different_place(T0,T1).
different_place([],[]).
?- perm([1,2,3],R).
R = [2, 3, 1]
R = [3, 1, 2]
false
改进1:您可以通过以下方式将different_place/2
与maplist/3
结合使用,而不是创建自己的谓词(在本例中为\=/2
):
perm(L,LO):-
acceptable_permutation(L,LO),
maplist(\=,L,LO).
改进2:swi序言提供了谓词permutation/2
,该谓词计算列表的排列。因此,您只需三行即可解决您的问题:
find_perm(L,LO):-
permutation(L,LO),
maplist(\=,L,LO).
?- find_perm([1,2,3],L).
L = [2, 3, 1]
L = [3, 1, 2]
false