[英]Recognize A^n B^n language in Prolog with no arithmetics
如何識別沒有算術的Prolog中的A ^ n B ^ n語言以及A!= B的任何A,B?
有了已知的A = a和B = b,我們就可以寫了
% For each 'a' save 'b' in a list, then check
% whether constructed list is equal to the rest of input list
anbn(L) :- anbn(L, []).
anbn(L, L).
anbn([a|L],A) :- anbn(L, [b|A]).
對於任何A和BI都在考慮一個解決方案
anbn(L) :- anbn(L, []).
anbn([H|L],[]) :- anbn(L,[H]). % save an element
anbn([H|L], [H|A]) :- anbn(L, [H,H|A]). % make sure front elements are the same
所以第一個元素都是相同的,但是我沒有看到一個優雅的方法來檢查列表其余部分中的所有元素是否與前面的元素相同和不同。
我可以檢查剩下的是否與存儲的列表一樣長,然后它是否只包含第二個類型的元素,但我相信我的問題過於復雜,並且存在一個簡短的解決方案。
使用明確的子句語法。
s(_, _) --> [].
s(A, B) --> [A], s(A, B), [B].
演示:
?- phrase(s(1, 2), X).
X = [] ;
X = [1, 2] ;
X = [1, 1, 2, 2] ;
X = [1, 1, 1, 2, 2, 2] .
編輯:回到原始解決方案,並堅持下去:
anbn(List) :- List = [] -> true; List = [A|Rest], a(Rest, A, 0).
a([A|Rest], A, N) :- !, a(Rest, A, s(N)).
a([B|Rest], _, N) :- b(Rest, B, N).
b([B|Rest], B, s(N)) :- b(Rest, B, N).
b([], _, 0).
它是迭代的,它不會創建選擇點,很明顯,如果列表的所有元素都是基礎的,它是正確的。
DCG通常在翻譯期間將裸變量重新包裝為短語/ 3。 因此,不僅當A和B是終端時,而且當A和B是任意DCG目標時,可以實現A ^ n B ^ n。
這是代碼:
s(_,_) --> [].
s(A,B) --> A, s(A,B), B.
在這里可以看到由SWI-Prolog完成的翻譯。 正如可以看到裸變量已被轉換為短語/ 3目標:
?- listing.
s(_, _, A, A).
s(A, C, B, F) :-
phrase(A, B, D),
s(A, C, D, E),
phrase(C, E, F).
這是針對終端A和B的示例運行:
?- phrase(s("alfa","beta"),X), atom_codes(Y,X).
X = [],
Y = '' ;
X = [97, 108, 102, 97, 98, 101, 116, 97],
Y = alfabeta ;
X = [97, 108, 102, 97, 97, 108, 102, 97, 98|...],
Y = alfaalfabetabeta ;
X = [97, 108, 102, 97, 97, 108, 102, 97, 97|...],
Y = alfaalfaalfabetabetabeta .
這是一個示例運行,對於一些DCG目標為A和B:
bit --> "0".
bit --> "1".
?- length(L,8), phrase(s(("(",bit),(bit,")")),L), atom_codes(R,L).
L = [40, 48, 40, 48, 48, 41, 48, 41],
R = '(0(00)0)' ;
L = [40, 48, 40, 48, 48, 41, 49, 41],
R = '(0(00)1)' ;
L = [40, 48, 40, 48, 49, 41, 48, 41],
R = '(0(01)0)' ;
Etc..
再見
我認為這比那更簡單:
anbn(L) :- append(As, Bs, L), maplist(ab, As, Bs).
ab(a, b).
編輯:這很容易推廣到任意文字。
anbn(L) :- L = [A|_], append(As, Bs, L), maplist(ab(A), As, Bs).
ab(A, A, B) :- A \== B.
編輯:威爾尼斯注意到它的錯誤后:我的意思是
anbn(L) :- append([A|As], [B|Bs], L), A \= B, maplist(ab(A, B), As, Bs).
ab(A, B, A, B).
anbn( [] ) :- !.
anbn( L ) :- L=[A|_], copy_half( L,L, Z,Z, A,_V). % Z is second half
copy_half( [A|B], [_,_|C], [V|D], Z, A,V) :- !, copy_half( B,C, D,Z, A,V).
copy_half( Z, [], [], Z, A,V) :- A \== V.
相當於
anbn_verboten(L):- L = [] ;
length(L,N), N2 is N div 2, length(X,N2), length(Y,N2), append(X,Y,L),
L=[P|_], Y=[Q|_], P \= Q.`.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.