如何访问序言中的列表排列? [英] How to access list permutations in prolog?
问题描述
我想访问列表排列并将其作为参数传递给其他函数.
I want to access list permutation and pass it as argument to other functions.
这是排列代码:
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :-
takeout(X,R,S),
write(S).
perm([X|Y],Z) :-
perm(Y,W),
takeout(X,Z,W).
perm([],[]).
推荐答案
首先,让我们重新定义您的谓词,以免它们执行任何不必要的I/O:
To start with, let's redefine your predicates so they don't do any unnecessary I/O:
takeout(X,[X|R],R).
takeout(X,[F |R],[F|S]) :- takeout(X,R,S).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
现在,您拥有了可以被视为纯"排列函数的功能:
Now you have what could be considered a "pure" permutation function:
?- perm([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 1, 3] ;
X = [2, 3, 1] ;
X = [1, 3, 2] ;
X = [3, 1, 2] ;
X = [3, 2, 1] ;
false.
因此,假设您有一个max_heap函数,该函数接受值列表并生成树.我会让您担心,因此,我们假设它存在并且被称为max_heap/2
,并且进一步假设您有一种方法来显示这个有吸引力的display_heap/1
.要接受"排列并将其作为这些函数的参数发送",您实际上是在数学中说:假设P是X的排列,让我们对其进行max_heap并显示它.或者,假设P是X的排列,H是由X构成的最大堆,让我们显示H:
So, suppose you have a max_heap function that takes a list of values and produces a tree. I'll let you worry about that, so let's just posit that it exists and is called max_heap/2
and let's further posit that you have a way to display this attractively called display_heap/1
. To "take" the permutation and "send" it as a parameter to these functions, you're really saying in math-ese: suppose P is a permutation of X, let's make a max_heap with it and display it. Or, suppose P is a permutation of X, H is a max heap made from X, let's display H:
show_heaps(List) :- perm(List, P), max_heap(P, H), display_heap(H).
这和我的英语句子说的一样:假设P是列表的一个排列,然后H是它的堆表示,然后显示它.从技术上讲,display_heap/1
仍然是一个谓词,对于给定的堆,该谓词可能为true或false.在实践中,这永远是正确的,并且如果您运行此命令,您仍然必须反复打;
来说,给我另一种解决方案,除非您使用失败驱动的循环或诸如findall/3
的额外逻辑谓词来执行此操作.导致找到所有解决方案.
This says the same thing as my English sentence: suppose P is a permutation of the list, then H is a heap representation of it, then display it. Technically, display_heap/1
is still a predicate which could be true or false for a given heap. In practice, it will always be true, and if you run this you'll still have to hit ;
repeatedly to say, give me another solution, unless you use a failure-driven loop or an extralogical predicate like findall/3
to cause all the solutions to be found.
编辑:让我们讨论故障驱动的循环和findall/3
.首先,让我添加一些新的谓词,因为我不知道您在做什么,但这对我们而言无关紧要.
Edit: Let's discuss failure-driven loops and findall/3
. First let me add some new predicates, because I don't know exactly what you're doing, but it doesn't matter for our purposes.
double([X|Xs], [Y|Ys]) :- Y is X*2, double(Xs, Ys).
double([],[]).
showlist(Xs) :- print(Xs).
所以现在我有一个谓词double/2
,它使列表中的值加倍,并且有一个谓词showlist/1
在标准输出上打印该列表.我们可以这样尝试:
So now I have a predicate double/2
which doubles the values in the list and a predicate showlist/1
that prints the list on standard output. We can try it out like so:
?- perm([1,2,3], X), double(X, Y), showlist(Y).
[2,4,6]
X = [1, 2, 3],
Y = [2, 4, 6] ;
[4,2,6]
X = [2, 1, 3],
Y = [4, 2, 6] ;
[4,6,2]
X = [2, 3, 1],
Y = [4, 6, 2] ;
[2,6,4]
X = [1, 3, 2],
Y = [2, 6, 4] ;
[6,2,4]
X = [3, 1, 2],
Y = [6, 2, 4] ;
[6,4,2]
X = [3, 2, 1],
Y = [6, 4, 2] ;
false.
当您键入;
时,您说的是或"?到Prolog.换句话说,您是在说还有什么?"您是在告诉Prolog,实际上,这不是我想要的答案,请尝试找到我更喜欢的另一个答案.您可以通过失败驱动的循环来使此过程正式化:
When you type ;
you're saying, "or?" to Prolog. In other words, you're saying "what else?" You're telling Prolog, in effect, this isn't the answer I want, try and find me another answer I like better. You can formalize this process with a failure-driven loop:
?- perm([1,2,3], X), double(X, Y), showlist(Y), fail.
[2,4,6][4,2,6][4,6,2][2,6,4][6,2,4][6,4,2]
false.
因此,现在您看到每个排列的输出都通过了double/2
,然后Prolog报告为false.这就是这样的意思:
So now you see the output from each permutation having gone through double/2
there, and then Prolog reported false. That's what one means by something like this:
show_all_heaps(List) :- perm(List, X), double(X, Y), showlist(Y), nl, fail.
show_all_heaps(_).
看看它是如何工作的:
?- show_all_heaps([1,2,3]).
[2,4,6]
[4,2,6]
[4,6,2]
[2,6,4]
[6,2,4]
[6,4,2]
true.
另一个选择是使用findall/3
,它看起来更像这样:
The other option is using findall/3
, which looks more like this:
?- findall(Y, (perm([1,2,3], X), double(X, Y)), Ys).
Ys = [[2, 4, 6], [4, 2, 6], [4, 6, 2], [2, 6, 4], [6, 2, 4], [6, 4, 2]].
使用它来解决问题可能超出了您正在从事的任何家庭作业的范围.
Using this to solve your problem is probably beyond the scope of whatever homework it is you're working on though.
这篇关于如何访问序言中的列表排列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!