我有一个谓词,找到正确的解决方案,但接着找到不正确的解决方案。
?- data(D),data_threshold_nonredundantbumps(D,5,Bs),write(D).
[3,6,7,8,2,4,5,6,9,4,7,3]
D = [3, 6, 7, 8, 2, 4, 5, 6, 9|...],
Bs = [bump([11], [7]), bump([8, 9], [6, 9]), bump([2, 3, 4], [6, 7, 8])] ;
[3,6,7,8,2,4,5,6,9,4,7,3]
D = [3, 6, 7, 8, 2, 4, 5, 6, 9|...],
Bs = [bump([8, 9], [6, 9]), bump([2, 3, 4], [6, 7, 8])] ;
[3,6,7,8,2,4,5,6,9,4,7,3]
D = [3, 6, 7, 8, 2, 4, 5, 6, 9|...],
Bs = [bump([8], [6]), bump([2, 3, 4], [6, 7, 8])] ;
[3,6,7,8,2,4,5,6,9,4,7,3]
D = [3, 6, 7, 8, 2, 4, 5, 6, 9|...],
Bs = [bump([9], [9]), bump([2, 3, 4], [6, 7, 8])] ;
[3,6,7,8,2,4,5,6,9,4,7,3]
D = [3, 6, 7, 8, 2, 4, 5, 6, 9|...],
Bs = [bump([11], [7]), bump([2, 3, 4], [6, 7, 8])] ;
[3,6,7,8,2,4,5,6,9,4,7,3]
D = [3, 6, 7, 8, 2, 4, 5, 6, 9|...],
Bs = [bump([2, 3, 4], [6, 7, 8])] ;
等
这个想法是它会找到数据中的所有非冗余颠簸,其中凹凸是data
的连续子列表,高于threshold
,返回{的有序(按大小)列表{ {1}}其中bump / 2的第一个arg是来自数据的标记列表,第二个arg是值列表。所以bump/2s
意味着在数据索引2,3和4高于5时,它们是6,7,8。
如何添加条件以便找不到这些额外的解决方案? - 没有使用bump([2, 3, 4], [6, 7, 8])
。
如果我的代码可以通过其他方式简化,请告诉我。这似乎有点复杂,它正在尝试做什么。
所以:
这是我的代码:
once/1
答案 0 :(得分:7)
我的印象是你稍微过度思考。对于超过阈值的运行数字有一个直接的表达式,可以通过在列表的单个遍历中从头到尾考虑从头到尾的元素来定义。特别是,我们不需要append/3
来执行此操作。
在Prolog中描述列表时,请始终考虑使用 DCG表示法(dcg)。在这种情况下,需要花一点时间来决定如何最好地应用DCG,因为我们正在描述两个列表:
然而,除了一些技巧和扩展之外,DCG基本上只允许我们描述单个列表,而不是同时单独的列表。因此,我们可以使用这种功能强大且可能非常合适的机制,并且必须选择我们要应用的列表主要是。
在下文中,我展示了一个使用DCG来描述 bump / 1 术语列表的解决方案,也就是说,我“专用”该机制来描述上面提到的第一种列表,并使用另一个DCG来描述第二个类型的列表,我从第一个DCG中通过phrase/2
调用。
data_threshold_bumps(Ds, T, Bs) :-
phrase(bumps(Ds, 1, T), Bs).
bumps([], _, _) --> [].
bumps([D|Ds0], I0, T) -->
{ D #> T,
phrase(bump(D, T, Ds0, Ds, I0, I), Bs) },
[bump(Bs)],
bumps(Ds, I, T).
bumps([D|Ds0], I0, T) -->
{ D #=< T,
I #= I0 + 1 },
bumps(Ds0, I, T).
bump(D, T, Ds0, Ds, I0, I) --> [I0-D],
{ I1 #= I0 + 1 },
run(Ds0, Ds, T, I1, I).
run([], [], _, I, I) --> [].
run([D|Ds0], Ds, T, I0, I) --> [I0-D],
{ D #> T,
I1 #= I0 + 1 },
run(Ds0, Ds, T, I1, I).
run([D|Ds0], [D|Ds0], T, I, I) -->
{ D #=< T }.
示例查询和回答:
?- data_threshold_bumps([3,6,7,8,2,4,5,6,9,4,7,3], 5, Bs). Bs = [bump([2-6, 3-7, 4-8]), bump([8-6, 9-9]), bump([11-7])] ; false.
请注意,这不是完全您需要的完全相同的数据表示形式,但将其转换为该数据表示是微不足道的。
以下是一些改进此解决方案的想法,从容易到难度:
if_/3
。bumps//3
和run//5
使用DCG表示法真的有意义吗?在这里使用DCG比常规谓词有什么好处和缺点?顺便说一下,要否定一个(可再生的)CLP(FD)约束,你需要使用(#/\)/2
来表示一个连词。它不与(,)/2
一起使用。
答案 1 :(得分:2)
在以下代码中,您将找到许多以
括起来的部分:- if(false).
...
:- endif.
所有这些部分都得到相同的结果
?- data_threshold_bumps([3,6,7,8,2,4,5,6,9,4,7,3], 5, Bs).
Bs = [bump([11], [7]), bump([8, 9], [6, 9]), bump([2, 3, 4], [6, 7, 8])] ;
false.
代码本身它只是一个模式匹配的应用程序,并且,从最后到第一个,显示了一种可能的方法来重构相同的基本bump / 5谓词以获得更好的可读性(但是,确实,我的首选它是它的最后一个......)
data_threshold_bumps(Es, T, Sorted) :-
bumps(Es, 1, T, Bs),
predsort(by_len, Bs, Sorted).
bumps([], _, _, []).
bumps([E|Es], P, T, Bs) :-
succ(P, Q),
bumps(Es, Q, T, Cs),
bump(E, P, T, Cs, Bs).
by_len(<, bump(Xs,_), bump(Ys,_)) :-
length(Xs, Xl),
length(Ys, Yl), Xl < Yl.
by_len(>, _, _).
:- use_module(library(clpfd)).
bump(E, _, T, Bs, Bs) :- E #=< T.
bump(E, P, T, Cs, Bs) :- E #> T, elem_placed(E, P, Cs, Bs).
elem_placed(E, P, [], [bump([P], [E])]).
elem_placed(E, P, [X|Bs], [Y|Bs]) :-
X = bump([Q|Ps], [F|Es]),
P #= Q-1,
Y = bump([P,Q|Ps], [E,F|Es]).
elem_placed(E, P, [X|Bs], [bump([P],[E]), X|Bs]) :-
X = bump([Q|_Ps], _Es),
P #\= Q-1.
:- if(false).
bump(E, _, T, Bs, Bs) :- E =< T.
bump(E, P, T, Cs, Bs) :- E > T, elem_placed(E, P, Cs, Bs).
% first stored: tail
elem_placed(E, P, [], [bump([P], [E])]).
% extend current
elem_placed(E, P, [X|Bs], [Y|Bs]) :-
X = bump([Q|Ps], [F|Es]),
succ(P, Q),
Y = bump([P,Q|Ps], [E,F|Es]).
% place new
elem_placed(E, P, [X|Bs], [bump([P],[E]), X|Bs]) :-
X = bump([Q|_Ps], _Es),
\+ succ(P, Q).
:- endif.
:- if(false).
bump(E, _, T, Bs, Bs) :- E =< T.
bump(E, P, T, Cs, Bs) :- E > T, enabled(E, P, Cs, Bs).
enabled(E, P, [], [bump([P], [E])]).
enabled(E, P, [bump([Q|Ps], [F|Es])|Bs], [bump([P,Q|Ps], [E,F|Es])|Bs]) :- succ(P, Q).
enabled(E, P, [bump([Q|Ps], [F|Es])|Bs], [bump([P],[E]), bump([Q|Ps],[F|Es])|Bs]) :- \+ succ(P, Q).
:- endif.
:- if(false).
bump(E, _, T, Bs, Bs) :- E =< T.
bump(E, P, T, [], [bump([P], [E])]) :- E > T.
bump(E, P, T, [bump([Q|Ps], [F|Es])|Bs], [bump([P,Q|Ps], [E,F|Es])|Bs]) :- E > T, succ(P, Q).
bump(E, P, T, [bump([Q|Ps], [F|Es])|Bs], [bump([P],[E]), bump([Q|Ps],[F|Es])|Bs]) :- E > T, \+ succ(P, Q).
:- endif.