`(ab)*` 的两个 DCG 规则。可以是一个吗?
Two DCG rules for `(ab)*`. Can it be one?
我想生成或测试符合 Perl 正则表达式的字符串 (ab)*
下面的代码运行良好:
生成
?- phrase_acceptable(Text,6).
Text = abababababab ;
false.
测试(或压缩?)
?- phrase_acceptable("ababab",N).
[97,98,97,98,97,98]
N = 3
列举可能性
?- phrase_acceptable(T,N).
T = '',
N = 0 ;
T = ab,
N = 1 ;
T = abab,
N = 2 ;
T = ababab,
N = 3
...
然而,这需要两个子句acceptable//1
,根据N
是否新鲜来选择。这可以避免吗?使用 CLP(FD) 没有帮助,因为在任何情况下都必须检查 N>=0 以避免无限下降。
ff(X) :- var(X). % "freshvar(X)" using 2 letters, which is less annoying
bb(X) :- nonvar(X). % "notfreshvar(X)" using 2 letters, which is less annoying
acceptable(0) --> [].
acceptable(N) --> { bb(N), N>0, succ(Nm,N) }, `ab`, acceptable(Nm).
acceptable(N) --> { ff(N) }, `ab`, acceptable(Nm), { succ(Nm,N) }.
phrase_acceptable(Text,N) :-
bb(Text),!,
atom_codes(Text,Codes),
writeln(Codes),
phrase(acceptable(N),Codes,[]).
phrase_acceptable(Text,N) :-
ff(Text),!,
phrase(acceptable(N),Codes,[]),
atom_codes(Text,Codes).
这个怎么样:
:- use_module(library(clpfd)).
acceptable(0) --> [].
acceptable(N1) --> `ab`, { N #= N1-1, N #>= 0 }, acceptable(N).
phrase_acceptable(Text, N):-
(nonvar(Text) -> atom_codes(Text, Codes) ; true),
N #>= 0,
phrase(acceptable(N), Codes, []),
(var(Text) -> atom_codes(Text, Codes) ; true).
测试用例:
?- phrase_acceptable(ababab,N).
N = 3 ;
false.
?- phrase_acceptable(Text,3).
Text = ababab ;
false.
?- phrase_acceptable(Text,N).
Text = '',
N = 0 ;
Text = ab,
N = 1 ;
Text = abab,
N = 2 ;
Text = ababab,
N = 3 .
我想生成或测试符合 Perl 正则表达式的字符串 (ab)*
下面的代码运行良好:
生成
?- phrase_acceptable(Text,6).
Text = abababababab ;
false.
测试(或压缩?)
?- phrase_acceptable("ababab",N).
[97,98,97,98,97,98]
N = 3
列举可能性
?- phrase_acceptable(T,N).
T = '',
N = 0 ;
T = ab,
N = 1 ;
T = abab,
N = 2 ;
T = ababab,
N = 3
...
然而,这需要两个子句acceptable//1
,根据N
是否新鲜来选择。这可以避免吗?使用 CLP(FD) 没有帮助,因为在任何情况下都必须检查 N>=0 以避免无限下降。
ff(X) :- var(X). % "freshvar(X)" using 2 letters, which is less annoying
bb(X) :- nonvar(X). % "notfreshvar(X)" using 2 letters, which is less annoying
acceptable(0) --> [].
acceptable(N) --> { bb(N), N>0, succ(Nm,N) }, `ab`, acceptable(Nm).
acceptable(N) --> { ff(N) }, `ab`, acceptable(Nm), { succ(Nm,N) }.
phrase_acceptable(Text,N) :-
bb(Text),!,
atom_codes(Text,Codes),
writeln(Codes),
phrase(acceptable(N),Codes,[]).
phrase_acceptable(Text,N) :-
ff(Text),!,
phrase(acceptable(N),Codes,[]),
atom_codes(Text,Codes).
这个怎么样:
:- use_module(library(clpfd)).
acceptable(0) --> [].
acceptable(N1) --> `ab`, { N #= N1-1, N #>= 0 }, acceptable(N).
phrase_acceptable(Text, N):-
(nonvar(Text) -> atom_codes(Text, Codes) ; true),
N #>= 0,
phrase(acceptable(N), Codes, []),
(var(Text) -> atom_codes(Text, Codes) ; true).
测试用例:
?- phrase_acceptable(ababab,N).
N = 3 ;
false.
?- phrase_acceptable(Text,3).
Text = ababab ;
false.
?- phrase_acceptable(Text,N).
Text = '',
N = 0 ;
Text = ab,
N = 1 ;
Text = abab,
N = 2 ;
Text = ababab,
N = 3 .