如何将列表[5,4,2,8,3,1,6,9,5]划分为多个子列表,这些子列表将按破坏序列的值进行拆分?
例如,列表[5,4,2,8,3,1,6,9,5]
会产生像[5], [4], [2,8], [3], [1,6,9], [5] or [[5], [4], [2,8], [3], [1,6,9], [5]]
这样的子列表的列表(没关系)。
关于此的任何想法或建议如何解决此问题?
谢谢。
答案 0 :(得分:2)
在我看来,这似乎是DCG的问题,所以这是一个DCG解决方案:
ascending([X|Xs]) -->
[X],
ascending(X, Xs).
ascending(X, [Y|Xs]) -->
[Y],
{ X =< Y },
{ ! },
ascending(Y, Xs).
ascending(_X, []) -->
[].
可以与phrase/3
一起使用,以获取排序的前缀和其余元素:
?- phrase(ascending(Asc), [1,2,3,4,5], Rest).
Asc = [1, 2, 3, 4, 5],
Rest = [].
?- phrase(ascending(Asc), [1,2,3,4,5,2,3,4,5], Rest).
Asc = [1, 2, 3, 4, 5],
Rest = [2, 3, 4, 5].
?- phrase(ascending(Asc), [1,2,3,4,5,2,3,4,5], Rest), phrase(ascending(Asc2), Rest, Final).
Asc = [1, 2, 3, 4, 5],
Rest = Asc2, Asc2 = [2, 3, 4, 5],
Final = [].
主要谓词是:
sorted_sublists([], []).
sorted_sublists(List, [Prefix|Remaining]) :-
phrase(ascending(Prefix), List, Rest),
sorted_sublists(Rest, Remaining).
但是,ascending//2
中的剪切有点难看。 DCG中的否定有点乏味,但可以使其受约束:
:- use_module(library(clpfd)).
ascending(X, [Y|Xs]) -->
{ X #=< Y },
[Y],
ascending(Y, Xs).
ascending(X, []) -->
{ X #=< Y },
\+ [Y].
我认为这很好。有某种方法可以做类似但不一定有约束的事情吗?本质上,一种写DCG的方式“匹配空列表或不满足某些谓词P
的非空列表”?
答案 1 :(得分:1)
非常棘手,但是可以使用DCG来完成:
sub([A,B|T]) --> [[A]], {A > B},sub([B|T]); {A =< B, phrase(sub_1([A,B|T], S), R, [])}, [R], sub(S).
sub([A]) --> [[A]].
sub([]) --> [].
sub_1([A,B|T], S) --> [A], {A =< B}, sub_1([B|T], S);[A], {A > B, S = [B|T]}.
sub_1([A], []) --> [A].
结果:
?- phrase(sub([5,4,2,8,3,1,6,9,5] ), A, []).
A = [[5], [4], [2, 8], [3], [1, 6, 9], [5]] ;
false
。
答案 2 :(得分:0)
您只是想提出一项策略,但是我真的无法提出一个好的策略。我希望其他人能比我的方法更好。
我真的对我的解决方案不满意,因为感觉像是一个问题,这个简单的问题应该得到一个简单的解决方案,而我的解决方案不是很简单。实际上,我觉得这样的事情应该起作用:
sorted_sublists([], []).
sorted_sublists(L, [Prefix|Remaining]) :-
append(Prefix, Suffix, L),
sort(Prefix, Prefix),
sorted_sublists(Suffix, Remaining).
这对我来说似乎是合理的说明:给我一个前缀L,如果已经对它进行了排序,则将其放在结果列表中,然后继续查找剩余的内容。但是,这不起作用,因为Prefix可以是空列表,但是如果您这样修复它:
sorted_sublists([], []).
sorted_sublists(L, [Prefix|Remaining]) :-
append(Prefix, Suffix, L),
Prefix=[_|_],
sort(Prefix, Prefix),
sorted_sublists(Suffix, Remaining).
它仍然不起作用,因为您得到了很多解决方案,而其中的 last 是您真正想要的解决方案:
[debug] ?- sorted_sublists([1,2,3,1,2,1,1], Sublists).
Sublists = [[1], [2], [3], [1], [2], [1], [1]] ;
Sublists = [[1], [2], [3], [1, 2], [1], [1]] ;
Sublists = [[1], [2, 3], [1], [2], [1], [1]] ;
Sublists = [[1], [2, 3], [1, 2], [1], [1]] ;
Sublists = [[1, 2], [3], [1], [2], [1], [1]] ;
Sublists = [[1, 2], [3], [1, 2], [1], [1]] ;
Sublists = [[1, 2, 3], [1], [2], [1], [1]] ;
Sublists = [[1, 2, 3], [1, 2], [1], [1]] ;
false.
仍然,好像是朝正确方向运动。如果我们有一个可以剥离第一个排序前缀的谓词呢?如果有,我们可以跳过append/3
和错误的解决方案。因此,让我们专注于编写该谓词。我想到了这个:
sorted_prefix([Last], [Last], []).
sorted_prefix([X,Y|Ys], Prefix, Suffix) :-
(X < Y ->
sorted_prefix([Y|Ys], Prefix0, Suffix),
Prefix = [X|Prefix0]
;
Prefix = [X], Suffix = [Y|Ys]
).
因此,基本情况是列表中只有一个元素。那是一个排序的前缀。
归纳式案例比较棘手。这样的想法是,如果前两个项目按顺序排列,那么我想重述第二个项目以及其余列表,然后将结果放在该结果的前面。换句话说,如果L的排序前缀为R并且X小于L的第一项,则[X | L]的排序前缀为[X | R]。如果不是这种情况,我们将在另一种情况下结束,即如果X大于L的第一个元素,则[X | L]的排序前缀仅为[X]。在这种情况下,我们还必须计算出后缀,即L。
最后的sorted_sublists/2
变得更简单:
sorted_sublists([], []).
sorted_sublists(L, [Prefix|Remaining]) :-
sorted_prefix(L, Prefix, Suffix),
sorted_sublists(Suffix, Remaining).
这只是一次递归剥离一个排序的前缀。