检查一个字符串是否包含在一种语言中(Prolog)
Checking if a string is contained in a language (Prolog)
这是 CFG:
S -> T | V
T -> UU
U -> aUb | ab
V -> aVb | aWb
W -> bWa | ba
所以这将接受某种形式的:
{a^n b^n a^m b^m | n,m >= 1} U {a^n b^m a^m b^n | n,m >= 1}
这是我正在使用的代码:
in_lang([]).
in_lang(L) :-
mapS(L), !.
mapS(L) :-
mapT(L) ; mapV(L),!.
mapT(L) :-
append(L1, mapU(L), L), mapU(L1), !.
mapU([a|T]) :-
((append(L1,[b],T), mapU(L1)) ; (T = b)),!.
mapV([a|T]) :-
((append(L1,[b],T), mapV(L1)) ;
(append(L1,[b],T), mapW(L1))),
!.
mapW([b|T]) :-
((append(L1,[a],T), mapW(L1)) ;
(T = a)),
!.
截至目前,以下三个字符串返回 false:
[a,a,b,b,a,b] // this should be true
[a,a,a,b,b,a,a,b,b,b] // this should be true as well
[a,a,a,b,b,a,b,b,b] // this one IS false
任何帮助或见解将不胜感激,我对 Prolog 不太满意,因此自己调试它一直是一个挑战。
在 mapT
的定义中,您试图使用 mapU
的 "return value" 作为 append
的参数。但是 mapU
是谓词,谓词没有 return 值。
相反,人们通常会编写一个带有未绑定变量的谓词,该谓词将绑定到所需的 "return value";在谓词被证明后,现在绑定的变量可以在后续谓词中使用。
只需使用 dcg! And library(double_quotes)
.
:- set_prolog_flag(double_quotes, chars).
s --> t | v.
t --> u, u.
u --> "a",u,"b" | "ab".
v --> "a",v,"b" | "a",w,"b".
w --> "b",w,"a" | "ba".
| ?- use_module(library(double_quotes)).
| ?- length(L,N), phrase(s, L).
L = "abab", N = 4 ? ;
L = "abab", N = 4 ? ;
L = "aabbab", N = 6 ? ;
L = "abaabb", N = 6 ? ;
L = "aababb", N = 6 ? ;
L = "abbaab", N = 6 ? ;
L = "aaabbbab", N = 8 ? ;
L = "aabbaabb", N = 8 ? ;
L = "abaaabbb", N = 8 ? ;
L = "aaababbb", N = 8 ? ...
首先,请注意这段代码没有意义:
... append(L1, mapU(L), L) ...
在 Prolog 中有谓词,没有函数...
一个 CFG 生产规则(非终端)应该 'eat' 一些标记,在 Prolog 中这意味着您至少需要 2 个参数:输入标记列表,以及生产成功后剩下的内容匹配输入的相关部分。
也就是说,append/3 不是必需的:只是模式匹配,由统一运算符 (=)/2
执行
mapS(L1, L) :- mapT(L1,L) ; mapV(L1,L).
mapT(L1, L) :- mapU(L1,L2), mapU(L2,L).
mapU(L1, L) :- L1=[a|L2], mapU(L2,L3), L3=[b|L] ; L1=[a,b|L].
... complete the translation
然后调用它:
?- mapS([a,a,b,b,a,b],R).
R = [] ;
false.
R = []
表示整个序列已经匹配...
这是 CFG:
S -> T | V
T -> UU
U -> aUb | ab
V -> aVb | aWb
W -> bWa | ba
所以这将接受某种形式的:
{a^n b^n a^m b^m | n,m >= 1} U {a^n b^m a^m b^n | n,m >= 1}
这是我正在使用的代码:
in_lang([]).
in_lang(L) :-
mapS(L), !.
mapS(L) :-
mapT(L) ; mapV(L),!.
mapT(L) :-
append(L1, mapU(L), L), mapU(L1), !.
mapU([a|T]) :-
((append(L1,[b],T), mapU(L1)) ; (T = b)),!.
mapV([a|T]) :-
((append(L1,[b],T), mapV(L1)) ;
(append(L1,[b],T), mapW(L1))),
!.
mapW([b|T]) :-
((append(L1,[a],T), mapW(L1)) ;
(T = a)),
!.
截至目前,以下三个字符串返回 false:
[a,a,b,b,a,b] // this should be true
[a,a,a,b,b,a,a,b,b,b] // this should be true as well
[a,a,a,b,b,a,b,b,b] // this one IS false
任何帮助或见解将不胜感激,我对 Prolog 不太满意,因此自己调试它一直是一个挑战。
在 mapT
的定义中,您试图使用 mapU
的 "return value" 作为 append
的参数。但是 mapU
是谓词,谓词没有 return 值。
相反,人们通常会编写一个带有未绑定变量的谓词,该谓词将绑定到所需的 "return value";在谓词被证明后,现在绑定的变量可以在后续谓词中使用。
只需使用 dcg! And library(double_quotes)
.
:- set_prolog_flag(double_quotes, chars).
s --> t | v.
t --> u, u.
u --> "a",u,"b" | "ab".
v --> "a",v,"b" | "a",w,"b".
w --> "b",w,"a" | "ba".
| ?- use_module(library(double_quotes)).
| ?- length(L,N), phrase(s, L).
L = "abab", N = 4 ? ;
L = "abab", N = 4 ? ;
L = "aabbab", N = 6 ? ;
L = "abaabb", N = 6 ? ;
L = "aababb", N = 6 ? ;
L = "abbaab", N = 6 ? ;
L = "aaabbbab", N = 8 ? ;
L = "aabbaabb", N = 8 ? ;
L = "abaaabbb", N = 8 ? ;
L = "aaababbb", N = 8 ? ...
首先,请注意这段代码没有意义:
... append(L1, mapU(L), L) ...
在 Prolog 中有谓词,没有函数...
一个 CFG 生产规则(非终端)应该 'eat' 一些标记,在 Prolog 中这意味着您至少需要 2 个参数:输入标记列表,以及生产成功后剩下的内容匹配输入的相关部分。
也就是说,append/3 不是必需的:只是模式匹配,由统一运算符 (=)/2
执行mapS(L1, L) :- mapT(L1,L) ; mapV(L1,L).
mapT(L1, L) :- mapU(L1,L2), mapU(L2,L).
mapU(L1, L) :- L1=[a|L2], mapU(L2,L3), L3=[b|L] ; L1=[a,b|L].
... complete the translation
然后调用它:
?- mapS([a,a,b,b,a,b],R).
R = [] ;
false.
R = []
表示整个序列已经匹配...