Prolog - 将列表分为 N 部分
我正在尝试编写一个谓词,将列表分为 N 个部分。 这是我到目前为止所拥有的。
partition(1, List, List).
partition(N, List, [X,Y|Rest]):-
chop(List, X, Y),
member(NextToChop, [X,Y]), %Choose one of the new parts to chop further.
NewN is N-1,
partition(NewN, NextToChop, Rest).
chop(List, _, _):-
length(List, Length),
Length < 2, %You can't chop something that doesn't have at least 2 elements
fail,!.
chop(List, Deel1, Deel2):-
append(Deel1, Deel2, List),
Deel1 \= [],
Deel2 \= [].
这个想法是继续将列表的一部分分成另外两个部分,直到我有 N 部分。 我用这种方法得到了平庸的结果:
?- partition(2, [1,2,3,4], List).
List = [[1], [2, 3, 4], 1] ;
List = [[1], [2, 3, 4], 2, 3, 4] ;
List = [[1, 2], [3, 4], 1, 2] ;
List = [[1, 2], [3, 4], 3, 4] ;
List = [[1, 2, 3], [4], 1, 2, 3] ;
List = [[1, 2, 3], [4], 4] ;
false.
所以我得到了我想要的东西,但我得到了两次,并且还附加了一些其他东西。 当分成三部分时,情况会变得更糟:
?- partition(3, [1,2,3,4], List).
List = [[1], [2, 3, 4], [2], [3, 4], 2] ;
List = [[1], [2, 3, 4], [2], [3, 4], 3, 4] ;
List = [[1], [2, 3, 4], [2, 3], [4], 2, 3] ;
List = [[1], [2, 3, 4], [2, 3], [4], 4] ;
List = [[1, 2], [3, 4], [1], [2], 1] ;
List = [[1, 2], [3, 4], [1], [2], 2] ;
List = [[1, 2], [3, 4], [3], [4], 3] ;
List = [[1, 2], [3, 4], [3], [4], 4] ;
List = [[1, 2, 3], [4], [1], [2, 3], 1] ;
List = [[1, 2, 3], [4], [1], [2, 3], 2, 3] ;
List = [[1, 2, 3], [4], [1, 2], [3], 1, 2] ;
List = [[1, 2, 3], [4], [1, 2], [3], 3] ;
false.
另一个想法是使用前缀,但我不知道这会如何真正起作用。要使用它,我应该能够让 Prolog 知道它需要采用一个不太短也不太长的前缀,所以我不会采用太长的前缀,这样就没有什么可以留给下一个递归步骤了。
有人能指出我正确的方向吗?
需要澄清的是:谓词应该返回将列表分为 N 个部分的所有可能性(不包括空列表)。
I'm trying to write a predicate that divides a list into N parts.
This is what I have so far.
partition(1, List, List).
partition(N, List, [X,Y|Rest]):-
chop(List, X, Y),
member(NextToChop, [X,Y]), %Choose one of the new parts to chop further.
NewN is N-1,
partition(NewN, NextToChop, Rest).
chop(List, _, _):-
length(List, Length),
Length < 2, %You can't chop something that doesn't have at least 2 elements
fail,!.
chop(List, Deel1, Deel2):-
append(Deel1, Deel2, List),
Deel1 \= [],
Deel2 \= [].
The idea is to keep chopping parts of the list into two other parts until I have N pieces.
I have mediocre results with this approach:
?- partition(2, [1,2,3,4], List).
List = [[1], [2, 3, 4], 1] ;
List = [[1], [2, 3, 4], 2, 3, 4] ;
List = [[1, 2], [3, 4], 1, 2] ;
List = [[1, 2], [3, 4], 3, 4] ;
List = [[1, 2, 3], [4], 1, 2, 3] ;
List = [[1, 2, 3], [4], 4] ;
false.
So I get what I want, but I get it two times and there are some other things attached.
When dividing into 3 parts things get worse:
?- partition(3, [1,2,3,4], List).
List = [[1], [2, 3, 4], [2], [3, 4], 2] ;
List = [[1], [2, 3, 4], [2], [3, 4], 3, 4] ;
List = [[1], [2, 3, 4], [2, 3], [4], 2, 3] ;
List = [[1], [2, 3, 4], [2, 3], [4], 4] ;
List = [[1, 2], [3, 4], [1], [2], 1] ;
List = [[1, 2], [3, 4], [1], [2], 2] ;
List = [[1, 2], [3, 4], [3], [4], 3] ;
List = [[1, 2], [3, 4], [3], [4], 4] ;
List = [[1, 2, 3], [4], [1], [2, 3], 1] ;
List = [[1, 2, 3], [4], [1], [2, 3], 2, 3] ;
List = [[1, 2, 3], [4], [1, 2], [3], 1, 2] ;
List = [[1, 2, 3], [4], [1, 2], [3], 3] ;
false.
Another idea is using prefix but I don't know how that would really work. To use that I should be able to let Prolog know that it needs to take a prefix that's not too short and not too long either, so I don't take a prefix that's too long so there's nothing left for a next recursion step.
Can anyone point me in the right direction?
Little clarification: the predicate should return all posibilities of dividing the list in N parts (not including empty lists).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当描述涉及列表的关系时,DCG 通常非常有用。考虑:
示例查询:
When describing relations that involve lists, DCGs are often very useful. Consider:
Sample query:
这是我用来实现该功能的基本方法(使用
append/2
和length/2
):现在,这并不完全符合您的期望:它允许使用
[]
。解决这个问题的一个想法是使用
maplist
调用预先格式化结果列表:使用
copy_term/2
,maplist/2
调用看起来就像:使用
functor/3
(归功于@false),它看起来像:使用 lambda.pl 你可以写:
因为 '\' 已经执行了术语复制(感谢@false)。
唯一剩下的是
append/2
调用:另一个想法是使用
forall/2
过滤(可能更容易获得,但复杂性更差):等等。 。
Here is the basic way I'd use to implement that (using
append/2
andlength/2
) :Now, that doesn't totally complies to your expectations : it allows for
[]
.One idea to fix that is to use a
maplist
call to format the Resulting list beforehand :using
copy_term/2
, themaplist/2
call looks like :using
functor/3
(credits to @false), it would look like :using lambda.pl you could write :
since the '\' already performs a term copy (thanks @false).
The only thing left is the
append/2
call:Another idea would be to use
forall/2
filtering (maybe simpler to get, but worse in complexity) :etc...