2017-09-09 1 views
2

Comment rechercher une répétition consécutive d'une chaîne dans une liste dans prolog?Rechercher des répétitions dans une liste

Ce que je suis exactement essayer de trouver, par exemple, est la suivante:

input => output 
AAAAAA => 6*(A) 
ABABAB => 3*(AB) 
ABCABCABC => 3*(ABC) 

j'ai écrit une grammaire DCG pour cela et je suis en train de le faire me donner cette suite.

est ici la grammaire, si nécessaire:

exp --> term. 
exp --> term, [+], exp. 

term --> factor. 
term --> digit, [*], exp. 

factor --> elem. 
factor --> ['S'], ['['], sym, [']']. %S[(A)(B),(C)] 
factor --> ['<'], alt, ['>'], ['/'], ['<'], alt, ['>']. %<(A)>/<(B)(C)(D)> 
factor --> ['('], exp, [')']. 

sym --> factor. 
sym --> factor, [','], factor. 
sym --> factor, sym. 

alt --> factor. 
alt --> factor, alt. 

elem --> char. 
elem --> char, elem. 
char --> [D], {is_alnum(D)}. 
digit --> [D], {is_alnum(D)}. 
digit --> [D], {number(D)}. 

nbr_to_char(N, Cs) :- 
    name(Cs, [N]). 
str_to_list(S, Cs) :- 
    name(S, Xs), 
    maplist(nbr_to_char, Xs, Cs). 

eval(L) :- 
    str_to_list(L, X), 
exp(X, []). 

Merci pour toute aide.

+0

Peut-être ce serait bien de fournir la grammaire? –

+0

Je n'ai pas trouvé cela nécessaire, car la grammaire gère bien plus de cas que celui-ci, mais je vais le mettre de toute façon. – CpCd0y

+0

Pourquoi 'ABCABCAB' aboutirait-il à' 3 * (ABC) '? Et que voudriez-vous que «AAABBBAAABBB» aboutisse? – lurker

Répondre

2

Je pense que ce que vous recherchez est pack (dcg_util). Mais aussi considérer ajouter/2:

?- A=`ababab`. 
A = [97, 98, 97, 98, 97, 98]. 

?- append([X,X,X],$A). 
X = [97, 98], 
A = [97, 98, 97, 98, 97, 98] ; 
false. 

Maintenant, si nous venons de trouver un moyen facile de faire des listes de variables répétées, nous avons une construction assez puissant, nous pouvons utiliser pour faire face à un problème. Essayons:

?- length(L,3),maplist(=(X),L). 
L = [X, X, X]. 

Alors:

?- length(L,_),maplist(=(X),L),append(L,$A). 
L = [[97, 98, 97, 98, 97, 98]], 
X = A, A = [97, 98, 97, 98, 97, 98] ; 
L = [[97, 98], [97, 98], [97, 98]], 
X = [97, 98], 
A = [97, 98, 97, 98, 97, 98] ; 
^CAction (h for help) ? abort 
% Execution Aborted 

oups, histoire sans fin ... mais un peu ennuyeux. Besoin d'un peu plus de code, l'application de la connaissance du domaine (ensachage, vraiment ...)

?- length($A,U),between(1,U,N),length(L,N),maplist(=(X),L),append(L,$A). 
U = 6, 
N = 1, 
L = [[97, 98, 97, 98, 97, 98]], 
X = A, A = A, A = [97, 98, 97, 98, 97, 98] ; 
U = 6, 
N = 3, 
L = [[97, 98], [97, 98], [97, 98]], 
X = [97, 98], 
A = A, A = [97, 98, 97, 98, 97, 98] ; 
false. 
+0

Je vois, merci pour votre réponse :) Cela semble ne fonctionner que pour les cas où il n'y a que des répétitions ai-je raison? Disons que j'ai A = 'mabcabc', comment pourrais-je trouver le même résultat que A = 'abcabc'? Dois-je tester toutes les sous-chaînes? – CpCd0y

+1

il est facile d'insérer des listes de saut dans un modèle fixe, pensez '? - append ([_, X, X, X], $ A) .', mais il n'est pas facile de généraliser ... Vous devriez vraiment essayer pack dcg_util, si vous utilisez SWI. C'est un peu raide à saisir, mais ** très ** vaut la peine. – CapelliC

+0

Oh ok, donc si je voulais essayer de généraliser cela, je le ferais dans le mapliste? – CpCd0y