s(Count) --> a(Count), b(Count), c(Count).
a(0) --> [].
a(succ(Count)) --> [a], a(Count).
b(0) --> [].
b(succ(succ(Count))) --> [b], b(Count).
c(0) --> [].
c(succ(succ(succ(Count)))) --> [c], c(Count).
很容易创建一个像a^n b^n c^n这样的语言,对每个规则使用succ(0),但是当涉及到改变a b和c的每个块的n时,它就不起作用了。
发布于 2018-12-03 15:31:07
看看你的条款,比如:
c(0) --> [].
c(succ(succ(succ(Count)))) --> [c], c(Count).
请注意,您只匹配两个大小写-零个或三个字符,但是一个或两个字符呢?不过,修改c
以考虑每个可接受的长度似乎是个死胡同,在您控制所有c
和b
的地方(即在s
中)指定您需要的a
和b
的数量要容易得多。
s(succ(succ(Count))) --> a(succ(succ(Count))), b(succ(Count)), c(Count).
这自然会转化为您的规范:对于至少两个的N
,接受N
a
s、N-1
b
s和N-2
c
s。
现在,剩下的就很容易了:
a(0) --> [].
a(succ(Count)) --> [a], a(Count).
b(0) --> [].
b(succ(Count)) --> [b], b(Count).
c(0) --> [].
c(succ(Count)) --> [c], c(Count).
当然,您可以将它们替换为泛型子句char(Char, Count)
(作为练习向左)。
?- phrase(s(succ(succ(succ(0)))), X).
X = [a, a, a, b, b, c].
发布于 2018-12-04 07:57:59
除了@firefrorefiddle的回答之外,我还想注意三件事。首先,当使用Peano数时,更习惯于使用函数s/1来表示后继变量,并使用单个字母(如X)来表示变量,从而获得较小的项:
s(X) succ(Count)
s(s(X)) succ(succ(Count))
s(s(s(X))) succ(succ(succ(Count)))
s(s(s(s(X)))) succ(succ(succ(succ(Count))))
. .
. .
. .
其次,为了进一步提高可读性,最好为DCG选择一个不同的名称,可能类似于language//1而不是s//1。第三,您可以定义一个更通用的DCG,让您指定元素及其在列表中出现的次数,而不是为a
、b
和c
编写相同的DCG规则。把所有这些放在一起,你的DCG可能看起来像这样:
language(s(s(X))) -->
element_frequency(a,s(s(X))),
element_frequency(b,s(X)),
element_frequency(c,X).
element_frequency(_E,0) -->
[].
element_frequency(E,s(X)) -->
[E],
element_frequency(E,X).
在上面的代码语言中,//1对应于你的代码中的s//1,而element_frequency//2是a//1,b//1和c//1的替代。如果你查询这个DCG,你会发现它仍然产生与@firefrorefiddle的帖子中相同的答案,例如:
?- phrase(language(s(s(s(0)))),L).
L = [a,a,a,b,b,c]
发布于 2018-12-03 14:50:16
DCG的[]随时匹配。让我们把a,b,c规则颠倒过来。
s(Count) --> a(Count), b(Count), c(Count).
a(succ(Count)) --> [a], a(Count).
a(0) --> [].
b(succ(succ(Count))) --> [b], b(Count).
b(0) --> [].
c(succ(succ(succ(Count)))) --> [c], c(Count).
c(0) --> [].
:- s(N,[a,a,a,a,a,a,b,b,b,c,c],[]),writeln(N).
:- halt.
https://stackoverflow.com/questions/53588615
复制相似问题