我正在尝试编写一个prolog程序,用于确定一个列表是否是另一个列表的排列。输入格式为perm(L,M)
,当且仅当列表L
是列表M
的排列时,该格式才为真。
这是我的AI课程,所以我不能只使用gprolog已经提供的漂亮的小permutation
谓词。我们的教授注意到member
谓词可能有用,但我所涉及的任何想法似乎都需要非常棘手且不那么具体的事情(而且我假设有一种方法可以解决这个问题而不会得到太先进了,因为这个课程是prolog的新手。)
无论如何,检查的一种方法应该是L
和M
大小相同,每个L
元素都在M
中,每个{{} 1}}元素在M
中(使用L
!)。但是,对于member
和[2,2,4]
等案例而言,这还不够。
另一种方法可能是确保每个元素的相同数量都在相反的列表中,但我对prolog的印象是任何类型的变量“内存”都是相当困难的业务(事实上,它似乎是示例程序我看到执行排序等等根本就没有真正操纵数据;它们只是'假设'重新排列事物然后告诉你是或否......?)
在精神上,人们可以对两个列表进行排序并并排检查元素,但是,在其他许多方法中,这似乎有点过于面向对象......
任何提示?我最大的麻烦似乎是(如上所述)做“操作”似乎更像是询问关于他们的事实,并希望事情保持足够长的时间以达到你想要的地方。
**更新:gprolog确实提供了[4,4,2]
功能,但它附带了我期待的与声明相关的麻烦,给出了这样的尝试:
delete
在手册中,删除定义如下:“delete(List1,Element,List2)删除List1中所有出现的Element以提供List2。需要严格的术语相等,cf。(==)/ 2”< / p>
执行:
perm([LH|LT], R) :- member(LH,R), delete([LH|LT],LH,R), perm(LT,R).
**更新2:我想我可能已经弄明白了!它有点冗长,但我已经测试了很多例子并且还没有找到一个坏的。如果有人发现重大问题,请指出:
{trace}
| ?- perm([1,2,3],[3,1,2]).
1 1 Call: perm([1,2,3],[3,1,2]) ?
2 2 Call: member(1,[3,1,2]) ?
2 2 Exit: member(1,[3,1,2]) ?
3 2 Call: delete([1,2,3],1,[3,1,2]) ?
3 2 Fail: delete([1,2,3],1,[3,1,2]) ?
2 2 Redo: member(1,[3,1,2]) ?
2 2 Fail: member(1,[3,1,2]) ?
1 1 Fail: perm([1,2,3],[3,1,2]) ?
(1 ms) no
我喜欢切割操作符..
答案 0 :(得分:2)
perm(L, M) :- sort(L, X), sort(M, X).
这使你非常接近并且完全是声明性的(“如果它们具有相同的排序表示,则两个列表是彼此的排列”,但是在Prolog中排序会删除重复项)。但是,对于像perm([1,2], [2,2,2,1])
这样的情况,它会成功,我不确定你是否愿意。它会处理[2,2,4]和[4,4,2],因为它们都排序为[2,4]
。另一个解决方案是这样的:
perm([], []).
perm([L|Ls], M) :- select(L, M, Ms), !, perm(Ls, Ms).
[2,2,4]和[4,4,2]版本不会成功,但[1,2]和[2,2,2,1]会失败。我不确定你想要哪一个,但我认为其中一个或另一个可能是正确的。
答案 1 :(得分:2)
总是很好地定义更一般的谓词并以狭隘的方式使用它:
perm(X,L):- mselect(X,L,[]).
mselect([A|B],L,R):- select(A,L,M), mselect(B,M,R).
mselect([],L,L).
member
不好,因为它保持第二个列表不变。 delete
也不好,因为它删除了多重性。
但您可以使用append
。 :)它也结合了挑选和删除:
perm([A|B],L):- length(L,N), between(0,N,I),length(X,I),
append(X,[A],Y), append(Y,Z,L),
append(X,Z,M), perm(B,M).
perm([],[]).
答案 2 :(得分:1)
通常的模型是归纳。
如果您知道如何构建N-1个元素的所有排列,则可以获得N个元素的所有排列,并将元素插入所有可用位置。
交易的诀窍&#39;正在使用select / 3内置,就像成员一样,&#39; peek&#39;一个元素,但从列表中删除,然后返回&#39;较小的清单。那些动词并不适合Prolog。让我们说select / 3是元素之间的 relation ,包含它的列表,以及缺少它的相同列表。
然后让Prolog做所有的搜索...结果代码真的很小......
答案 3 :(得分:0)
只需对两个列表进行排序并比较结果