2013-05-07 2 views
3

Comment reconnaître le langage A^n B^n dans Prolog sans arithmétique et pour tout A, B où A! = B?Reconnaissance du langage A^n B^n dans Prolog sans arithmétique

Avec connu A = A et B = b on pourrait écrire

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

Pour tout A et BI Pensais d'une solution en commençant par

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 

de sorte que les premiers éléments sont d'autant même chose, mais je ne vois pas une manière élégante de vérifier si tous les éléments dans le reste de la liste sont les mêmes et différents que les éléments sur le devant.

Je pourrais vérifier si le reste est aussi long que la liste stockée et ensuite s'il ne comprend que les éléments de second type mais je crois que je suis trop compliqué et qu'il existe une solution courte et simple.

+1

Pourquoi ne vous utilisez Defin ite clause grammaires? –

+0

@larsmans J'ai essayé une solution avec un DCG mais les exigences de A et B arbitraires et pas d'arithmétique ont rendu la solution pas beaucoup mieux que la notation normale. Pouvez-vous s'il vous plaît montrer votre solution? –

+0

Je peux me tromper, mais a^n b^n ce n'est pas une langue * régulière *. – CapelliC

Répondre

2

Edit: retour à la solution d'origine, et de s'y tenir:

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

Il est itérative, il ne crée pas le choix des points, il est évident, et il est correct, si tous les éléments du liste sont moulues.

+0

fonctionne bien. le tien, comme le mien (et les larsmans), accepte '[1,1,1,2,2, X]'. –

+0

@WillNess oui, ainsi que [A, a, b, B] et ainsi de suite. Je ne sais pas comment résoudre ce problème en ajoutant une exigence 'nonvar'. –

+0

ou peut-être cela n'a pas besoin de résoudre. :) (réponse de CapelliC aussi). –

0

je pense qu'il est plus simple que cela:

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

EDIT: Ceci est facilement généralisable à littéraux arbitraires.

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

EDIT: après Will Ness noter que ça mis sur écoute: ce que je voulais dire était

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

dif/2 c'est une bibliothèque plutôt sophistiquée. Sûrement plus difficile à implémenter là où ce n'est pas possible, WRT maplist/3 – CapelliC

+0

Peut-être que nous insistons sur le fait que StackOverflow se déplace trop vite :) – CapelliC

+1

'anbn ([1,1,2,3]).' Est accepté par ce code. –

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

équivalent à

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

Utilisez une grammaire clause définie.

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

Démo:

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

Très bien, +1. Contrairement aux autres solutions publiées ici, la vôtre fonctionne aussi correctement pour la requête la plus générale, '? - phrase (s (X, Y), Ls) .'. Remarquez cependant que vous ne remplissez pas encore l'exigence de OP que «X» et «Y» soient distincts. Utilisez 'dif/2' dans la première règle. Il faut toujours utiliser l'interface 'phrase/2' (ou' phrase/3') pour les DCG car la conversion des DCG en prédicats Prolog peut changer en fonction de l'implémentation ou de la version de Prolog. – mat

+2

La seule solution qui ne me brûle pas les yeux. :) +1 –

+0

@mat: J'ai lu le A! = B comme une exigence que la solution fonctionne dans ce cas, pas qu'elle soit réellement appliquée. J'ai supprimé l'exemple d'utilisation sans 'phrase/2', cependant. –

2

Il est fréquent que les variables DCG nues sont remis en forme comme phrase/3 lors de la traduction. Alors que l'on peut mettre en œuvre A^n B^n non seulement pour quand A et B sont des terminaux, mais aussi lorsque A et B sont des objectifs DCG arbitraires.

Voici le code pour que:

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

Ici, on voit la traduction qui se fait par SWI-Prolog. Comme on peut le voir les variables nues ont été converties à PHRASE/3 buts:

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

Voici une série d'échantillons, pour les terminaux A et 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 . 

Voici une série d'échantillons, pour certains objectifs DCG A et 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

Questions connexes