如何编写无cut的DCG以接受l0k形式(l为k的反转)的字符串?
问题分析
你的DCG当前会生成错误结果,核心原因是递归规则s --> a(X), s, a(X)允许嵌套包含0的对称结构,导致最终字符串出现多个0,不符合你要求的**恰好一个0分隔l和k**的需求(l是k的反转,整个字符串结构为l ++ [0] ++ reverse(l))。
修复后的DCG实现
不需要使用cut,只需重新设计DCG,明确只匹配中间一个0,两边为对称序列:
% 主规则:匹配 l ++ [0] ++ reverse(l) s --> seq(L), [0], seq_rev(L). % 匹配由{1,2,3}组成的任意序列L(包括空序列) seq([]) --> []. seq([X|Xs]) --> a(X), seq(Xs). % 匹配序列L的反转 seq_rev([]) --> []. seq_rev([X|Xs]) --> seq_rev(Xs), a(X). % 匹配单个字母表字符 a(1) --> [1]. a(2) --> [2]. a(3) --> [3].
效果验证
执行查询:
?- s([1,2,3,3,2,1,0|L], []).
只会得到唯一正确结果:
L = [1, 2, 3, 3, 2, 1].
代码说明
seq(L)负责匹配左侧的字符串l,生成列表L;seq_rev(L)负责匹配右侧的reverse(l),通过递归反转的方式保证与L对称;- 主规则
s严格限定中间只有一个0,从根本上避免了原代码中嵌套生成多个0的问题。
内容的提问来源于stack exchange,提问作者vinicio
相关产品推荐
相关产品推荐

