Prolog 列表的排列,其中数字必须改变其在序言中的位置

Prolog 列表的排列,其中数字必须改变其在序言中的位置,prolog,prolog-dif,logical-purity,Prolog,Prolog Dif,Logical Purity,我正在为我的作业解决这个问题 谓词可接受的置换(L,R)应仅在R表示列表L的可接受置换时成功。 例如:[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

我正在为我的作业解决这个问题

谓词可接受的置换(L,R)应仅在R表示列表L的可接受置换时成功。 例如:[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).

请告诉我问题的确切位置,以便我的输出与正确的输出匹配。如果您能告诉我它是如何完成的,我将不胜感激。

问题在于您没有检查输出列表的所有元素是否与输入列表位于不同的位置。您应该添加一个谓词来检查这一点,如下所示:

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:不必创建自己的谓词(在本例中为
不同位置/2
),您可以通过以下方式使用
映射列表/3
\=/2

perm(L,LO):-
    acceptable_permutation(L,LO),
    maplist(\=,L,LO).
改进2:swi prolog提供了计算列表置换的谓词
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

问题在于,您没有检查输出列表的所有元素是否与输入列表位于不同的位置。您应该添加一个谓词来检查这一点,如下所示:

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:不必创建自己的谓词(在本例中为
不同位置/2
),您可以通过以下方式使用
映射列表/3
\=/2

perm(L,LO):-
    acceptable_permutation(L,LO),
    maplist(\=,L,LO).
改进2:swi prolog提供了计算列表置换的谓词
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
1)调用没有固定点的置换。一个有趣的名字!在那之前

2)像这样,我们使用
maplist/3
permutation/2

3)与此不同,我们使用而不是
(\=)/2
来保持逻辑纯度

有助于保持Prolog程序的通用性,在这种情况下还可以提高效率

让我们这样定义
list\u disrange/2

list_derangement(Es, Xs) :- maplist(dif, Es, Xs), % using dif/2 permutation(Es, Xs). 对于相应的接地条件,上述实施具有可比速度:

?- 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. ?时间((find_perm([1,2,3,4,5,6,7,8,9,10,11],u),false))。 %931088992推断,107.816秒107.320 CPU(100%CPU,8675793) 错。 ?时间((列表混乱([1,2,3,4,5,6,7,8,9,10,11],u),假))。 %1368212629推断,98.019秒97.890 CPU(100%CPU,13976991) 错。 1)调用没有固定点的置换。一个有趣的名字!在那之前

2)像这样,我们使用
maplist/3
permutation/2

3)与此不同,我们使用而不是
(\=)/2
来保持逻辑纯度

有助于保持Prolog程序的通用性,在这种情况下还可以提高效率

让我们这样定义
list\u disrange/2

list_derangement(Es, Xs) :- maplist(dif, Es, Xs), % using dif/2 permutation(Es, Xs). 对于相应的接地条件,上述实施具有可比速度:

?- 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. ?时间((find_perm([1,2,3,4,5,6,7,8,9,10,11],u),false))。 %931088992推断,107.816秒107.320 CPU(100%CPU,8675793) 错。 ?时间((列表混乱([1,2,3,4,5,6,7,8,9,10,11],u),假))。 %1368212629推断,98.019秒97.890 CPU(100%CPU,13976991) 错。
非常感谢你的详细解释。我也很感激你为我展示了代码的改进。谢谢。考虑<代码> a= a,FundPurm([a,b],[b,a])。< /C>正确地成功,其泛化<代码> FiffyPrm([a,b],[b,a])。< /> >失败。这就是为什么需要
dif/2
的原因之一。另一个是性能。非常感谢您的详细解释。我也很感激你为我展示了代码的改进。谢谢。考虑<代码> a= a,FundPurm([a,b],[b,a])。< /C>正确地成功,其泛化<代码> FiffyPrm([a,b],[b,a])。< /> >失败。这就是为什么需要
dif/2
的原因之一。另一个是性能。你对
可接受的排列([1,2,2],L)
有什么期望?@假井根据赋值,列表中不应该有重复的数字。无论如何,有人已经回答了我的问题。你对
可接受的排列([1,2,2],L)
有什么期望?@false那么根据作业,列表中不应该有重复的数字。无论如何,有人已经回答了我的问题。非常疯狂的这种疯狂。蒂尔:西班牙语是,意大利语是。显然意大利人赢了。这是一种疾病,不是每一种变异@错。我想,在这个例子中,许多比较都是值得的。我最喜欢的是
maplist(dif,…),置换(…)
vs
permutation(…),maplist(dif,…)
(而不是
permutation(…),maplist(\=),…)
…非常混乱。直到:在西班牙语中,它是,在意大利语中。显然意大利语赢了。这是一个dis-而不是每一个突变!@false。我想在这个例子中很多比较都是值得的。我最喜欢的是
地图列表(dif…),排列(…)
vs
排列(…),地图列表(dif…)
(不是
置换(…),映射列表(\=),…)
。。。