我思考了很久,但仍然搞不清楚。 是否有可能编写一个脚本,使用回溯算法生成这种格式的列表:
[a]
[a,b]
[a,b,a]
[a,b,a,b]
...
我已经制作了一个每次生成两个元素的脚本,但是当我尝试制作一个能够交替生成"a"、"b"的脚本时,我的头开始疼了。
以下是每次生成两个元素的脚本:
ab([a]).
ab([b,a|T]):-ab([a|T]).
ab([a,b|T]):-ab([b|T]).
在描述列表时,始终考虑使用DCG符号。
这使得聚焦您想要描述的本质变得非常方便,而不需要那么多额外的变量和参数。
例如,请考虑:
abs --> [a], abs_rest。
abs_rest --> []。 abs_rest --> [b],([] | abs)。
示例查询和答案:
?- phrase(abs, ABs)。 ABs = [a]; ABs = [a,b]; ABs = [a,b,a]; ABs = [a,b,a,b]; ABs = [a,b,a,b,a]; ABs = [a,b,a,b,a,b]。
有关此方便形式的更多信息,请参见dcg!
我同意@mat的观点,对于这种类型的问题,应尽可能使用dcg。
以下是另一组规则。
abs --> [a].
abs --> [a,b].
abs --> [a,b], abs.
?- phrase(abs, Ls).
Ls = [a] ;
Ls = [a, b] ;
Ls = [a, b, a] ;
Ls = [a, b, a, b] ;
Ls = [a, b, a, b, a] ;
Ls = [a, b, a, b, a, b] ;
Ls = [a, b, a, b, a, b, a] ;
Ls = [a, b, a, b, a, b, a, b] ;
Ls = [a, b, a, b, a, b, a, b, a]
abs2 --> [].
abs2 --> [a].
abs2 --> [a,b], abs2.
?- phrase(abs2, Ls).
Ls = [] ;
Ls = [a] ;
Ls = [a, b] ;
Ls = [a, b, a] ;
Ls = [a, b, a, b] ;
Ls = [a, b, a, b, a] ;
Ls = [a, b, a, b, a, b] ;
Ls = [a, b, a, b, a, b, a] ;
Ls = [a, b, a, b, a, b, a, b]
这是在SWI-Prolog中使用确定性子句语法的练习之一。
如果您不想使用DCG,那么我同意@mat的建议,建议您使用listing/1
来查看标准Prolog语法中的DCG。
listing(abs).
abs([a|A], A).
abs([a, b|A], A).
abs([a, b|A], B) :-
abs(A, B).
listing(abs2).
abs2(A, A).
abs2([a|A], A).
abs2([a, b|A], B) :-
abs2(A, B).
abs(X,[]).
X = [a] ;
X = [a, b] ;
X = [a, b, a] ;
X = [a, b, a, b] ;
X = [a, b, a, b, a] ;
X = [a, b, a, b, a, b] ;
X = [a, b, a, b, a, b, a]
abs2(X,[]).
X = [] ;
X = [a] ;
X = [a, b] ;
X = [a, b, a] ;
X = [a, b, a, b] ;
X = [a, b, a, b, a] ;
X = [a, b, a, b, a, b]
?- ab([b,a]).
true
ab([b,a|T]) :-
ab([a|T]).
ab
序列以a
开头,其余部分必须是ba
序列,其中ba
序列再次根据ab
序列进行定义:ab([a]).
ab([a|Xs]) :-
ba(Xs).
ba([b]).
ba([b|Xs]) :-
ab(Xs).
或者,你可以把abs
看作一个状态机,当最后一个元素是b
时产生a
,反之亦然。如果我们引入一个额外的参数来追踪历史记录,我们就得到了:
abs(a,[a]).
abs(b,[b]).
abs(a,[a|Xs]) :-
abs(b,Xs).
abs(b,[b|Xs]) :-
abs(a,Xs).
ab
序列,其最后一个元素是a
。ab(Xs) :-
abs(a,Xs).
玩得开心 :)
?- listing(abs//0), listing(abs_rest//0).
你可以将其输出结果交给你的教师,知道有一个更好的解决方案,但你可能不被允许使用,因为为什么要使用适当的形式化语言,当有一种更复杂的表达方式呢? - matlisting/1
使您的Prolog系统输出您也可以使用的低级代码。在内部,您的系统将DCG编译为普通的Prolog,并且您可以使用listing/1
检查生成的代码(如果您的系统提供它)。 - mat