La recherche d'OPMO est relativement simple :
sequence = [6, 3, 2, 5, 4, 8, 9, 10, 11, 1, 7, 0] pattern = [10, 11, 2, 1] pattern.sort() def norm(n): return n%12 def neg(n): return (12-n)%12 def analyse_p(seq,pat): pat.sort() for i in range(12): l1 = [norm(i+j) for j in seq] if sorted(l1[:len(pat)]) == pat: yield(i, l1[:len(pat)], l1[len(pat):]) for i,l1, l2 in analyse_p(sequence,pattern): print ("P",i,l1,l2) for i,l1, l2 in analyse_p(list(map(neg,sequence)), pattern)): print ("I",i,l1,l2)
P 8 [2, 11, 10, 1] [0, 4, 5, 6, 7, 9, 3, 8] I 4 [10, 1, 2, 11] [0, 8, 7, 6, 5, 3, 9, 4]
Le résultat (R10 ((10 5 11 9 8 7 6 2 3) (0 1 4))) (P10 ((4 1 0) (3 2 6 7 8 9 11 5 10))) me surprend : tu recherches 11 5 10, et cela isole 0 1 4. J'aurais proposé (R10 ((10 5 11) (9 8 7 6 2 3 0 1 4))) (P10 ((4 1 0 3 2 6 7 8 9) (11 5 10))) qui pour le coup reprend la logique.
Ceci dit, en Python extraire les n derniers éléments s'écrit sequence[-n:] au lieu de sequence[:n]... adapter mon programme pour chercher une chaîne à la fin ne présenterait aucun problème.
Adapter le programme pour chercher partout au milieu (à la OpenOffice) nécessiterait d'ajouter une boucle pour itérer au milieu, mais n'ajouterait que cette complexité.
Ma question sur la plus-value résulte d'une comparaison entre (P9 ((3 0) (11 2 1 5 6 7 8 10 4 9))) et (R9 ((9 4 10 8 7 6 5 1 2 11) (0 3))) qui ne sont que deux présentations d'un même résultat. (L'un est la rédaction à l'envers de l'autre). C'est différent des P et I qui pour le coup sont deux résultats différents.
--
PS : Tu remarques que je n'essaye pas de trouver toutes les permutations (ce serait trop compliqué), mais cherche une chaine au début en comparant les versions triées. Tu noteras des notations très puissantes en Python. La notation [ f(x) for x in liste ] itère x dans une liste et retourne la liste des f(x). Plus puissant encore : la fonction "analyse_p" retourne plusieurs résultats à l'aide du mot clé yield. Cette fonction agit un peu comme return pour retourner un résultat mais n'arrête pas la fonction. AU final lorsque l'on appelle la fonction, on obtient un objet itérable (un peu comme une liste) avec tous les résultats trouvés. C'est plus élégant que d'initier un "result = []", d'ajouter des résultats au fil de l'eau "result.append(x)" et retourner le résultat à la fin "return result". Pour des grands résultats voire inifini, yield n'alloue pas de liste importante en mémoire, mais s'assure que la fonction appelante récupère les résultats au fil de l'eau.
Commentaire