简体   繁体   English

在没有算术的情况下识别Prolog中的A ^ n B ^ n语言

[英]Recognize A^n B^n language in Prolog with no arithmetics

How to recognize A^n B^n language in Prolog without arithmetics and for any A, B where A != B? 如何识别没有算术的Prolog中的A ^ n B ^ n语言以及A!= B的任何A,B?

With known A = a and B = b we could write 有了已知的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]).

For any A and BI was thinking of a solution starting with 对于任何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

so that the first elements are all the same, but than I don't see an elegant way of checking whether all elements in the rest of the list are the same and different than the elemenets in the front. 所以第一个元素都是相同的,但是我没有看到一个优雅的方法来检查列表其余部分中的所有元素是否与前面的元素相同和不同。

I could check whether the rest is as long as the stored list and then whether it only consists of the second type elements but I believe I'm overcomplicating the problem and there exists a short and simple solution. 我可以检查剩下的是否与存储的列表一样长,然后它是否只包含第二个类型的元素,但我相信我的问题过于复杂,并且存在一个简短的解决方案。

Use a definite clause grammar. 使用明确的子句语法。

s(_, _) --> [].
s(A, B) --> [A], s(A, B), [B].

Demo: 演示:

?- phrase(s(1, 2), X).
X = [] ;
X = [1, 2] ;
X = [1, 1, 2, 2] ;
X = [1, 1, 1, 2, 2, 2] .

Edit: back to the original solution, and sticking to it: 编辑:回到原始解决方案,并坚持下去:

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).

It is iterative, it does not create choice-points, it is obvious, and it is correct, if all elements of the list are ground. 它是迭代的,它不会创建选择点,很明显,如果列表的所有元素都是基础的,它是正确的。

It is common for DCGs that naked variables are rewrapped as phrase/3 during translation. DCG通常在翻译期间将裸变量重新包装为短语/ 3。 So that one can implement A^n B^n not only for when A and B are terminals, but also when A and B are arbitrary DCGs goals. 因此,不仅当A和B是终端时,而且当A和B是任意DCG目标时,可以实现A ^ n B ^ n。

Here is the code for that: 这是代码:

 s(_,_) --> [].
 s(A,B) --> A, s(A,B), B.

Here one sees the translation that is done by SWI-Prolog. 在这里可以看到由SWI-Prolog完成的翻译。 As one can see the naked variables have been converted to phrase/3 goals: 正如可以看到裸变量已被转换为短语/ 3目标:

 ?- listing.
 s(_, _, A, A).
 s(A, C, B, F) :-
    phrase(A, B, D),
    s(A, C, D, E),
    phrase(C, E, F).

Here is a sample run, for terminals A and B: 这是针对终端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 .

Here is a sample run, for some DCG goals as A and B: 这是一个示例运行,对于一些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..

Bye 再见

I think it's simpler than that: 我认为这比那更简单:

anbn(L) :- append(As, Bs, L), maplist(ab, As, Bs).
ab(a, b).

EDIT: This is easily generalized to arbitrary literals. 编辑:这很容易推广到任意文字。

anbn(L) :- L = [A|_], append(As, Bs, L), maplist(ab(A), As, Bs).
ab(A, A, B) :- A \== B.

EDIT: after Will Ness noting that's bugged: what I meant was 编辑:威尔尼斯注意到它的错误后:我的意思是

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.

Equivalent to 相当于

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM