如何检查您'我已经在Prolog DCG中消费了

  • 本文关键字:DCG Prolog 何检查 prolog dcg
  • 更新时间 :
  • 英文 :


假设我有这些DCG:

zorbs([H|T]) --> zorb(H), zorbs(T).
zorbs([]) --> [].

zorb(a) --> [1,2].
zorb(b) --> [3].
zorb(c) --> [6,1,2,2].

我可以做到:

?- phrase(zorbs(X), [1,2,3,6,1,2,2]).
X = [a, b, c] .

我也可以";反向";这样做:

phrase(zorbs([a,b,c]), X).
X = [1, 2, 3, 6, 1, 2, 2].

现在,我想做的是找到一个长度小于4的数字列表(例如(;解析";进入,返回其余部分。

因此,例如,给定[a,b,c],它通常与[1, 2, 3, 6, 1, 2, 2]相关,我希望它与[1, 2, 3](其长度小于4(相关,并给出不可能是"0"的余数;反转,";因此CCD_ 4。我真的不知道从哪里开始,因为似乎没有办法对DCG中已经消耗的元素数量进行推理。

这里有一种解决方案:

X in 0..4,
indomain(X),
Q = [_|_],
prefix(Q, [a,b,c]),
length(A, X),
phrase(zorbs(Q), A).

但我认为这是非常低效的,因为我认为它基本上是从无到有的迭代,我想找到具有最大Q的解决方案。

在这种情况下没有直接的方法。所以你的方法本质上是可以做的。也就是说,您列举了所有可能的解决方案,并相应地选择了它们(您没有显示(。

关于最大等的问题包括一些量化,你不能直接用一阶逻辑表达。

然而,有时你可以使用一些技巧。

有时,类似[a,b,c|_]部分列表可能会有所帮助。

?- Xs = [_,_,_,_|_], phrase(zorbs(Xs),[1,2,3,6,1,2,2]).
false.

因此,在这里我们已经证明,没有长度为4或更长的列表对应于该序列。也就是说,我们已经为无限多的列表证明了这一点!

有时,使用phrase/3代替phrase/2可能会有所帮助。比方说,你有一个不解析的数字序列,你想知道它能解析多远:

?- Ys0 = [1,2,3,6,1,2,7], phrase(zorbs(Xs),Ys0,Ys).
Ys0 = [1,2,3,6,1,2,7], Xs = [], Ys = [1,2,3,6,1,2,7]
;  Ys0 = [1,2,3,6,1,2,7], Xs = "a", Ys = [3,6,1,2,7]
;  Ys0 = [1,2,3,6,1,2,7], Xs = "ab", Ys = [6,1,2,7]
;  false.

(这是交换了两个DCG规则(

可以使用:

% Like "between", but counts down instead of up
count_down(High, Low, N) :-
integer(High),
integer(Low),
count_down_(High, Low, N).
count_down_(H, L, N) :-
compare(C, H, L),
count_down_comp_(C, H, L, N).
count_down_comp_('=', _H, L, N) :-
% All equal, final
N = L.
% Accept H as the counting-down value
count_down_comp_('>', H, _L, H).
count_down_comp_('>', H, L, N) :-
H0 is H - 1,
% Decrement H towards L, and loop
count_down_(H0, L, N).

然后从开始

count_down(4, 1, Len), length(Lst, Len), phrase...

另一种方法是使用freeze逐元素限制列表的长度:

max_len_freeze(Lst, MaxLen) :-
compare(C, MaxLen, 0),
max_len_freeze_comp_(C, Lst, MaxLen).
max_len_freeze_comp_('=', [], 0).
max_len_freeze_comp_('>', [_|Lst], MaxLen) :-
succ(MaxLen0, MaxLen),
!,
freeze(Lst, max_len_freeze(Lst, MaxLen0)).
max_len_freeze_comp_('>', [], _).

然后从开始

max_len_freeze(Lst, 4), phrase...

这将首先找到最长的列表(最大长度4(,因为您的DCG是贪婪(即在[]之前匹配[H|T](。

最新更新