//echange ds l les elements d'indices j et k echange(l,j,k):={ local a; a:=l[j]; l[j]:=l[k]; l[k]:=a; return l; };
On peut décrire l'arbre des permutations de la liste l :
à partir de la racine on a n=size(l) branches. Chaque branche
commence respectivement par chacun des éléments de la liste l.
On va donc parcourir cet arbre de la racine (nud de niveau 0) aux
différentes extrémités,
en renvoyant la liste des branches parcourues pour arriver à cette
extrémité.
On va parcourir cet arbre en parcourant les n branches. On numérote ces
branches par p = 1..n et le niveau des nuds q = 0..n.
On aura donc n appels récursifs.
Chaque branche p peut être considérée à leur tour comme un arbre
ayant n - 1 branches.La branche p aboutit aux permutations qui laissent
invariant le p-ième élément de l (l[p - 1]).
C'est cet élément que l'on va
échanger avec l[0] pour que chaque branche p laisse
invariant l' élément l[0].
On sait que l'on est arrivé au bout de la branche, quand on se trouve au
nud de niveau n - 1, dans ce cas la permutation chechée est l (c'est
la permutation obtenue à partir de l en laissant ces n - 1 premiers
éléments invariants).
On utilise une variable locale lr, égale à la liste à renvoyer et
un paramètre k, pour que permus(l,k) renvoie toutes les
permutations de l qui laissent invariant les k premiers éléments de
l. On tape :
//utilise echange et la variable locale lr (liste resultat) //permus(l,k) laisse invariant les k premiers elements de l //permus([1,2,3,4],0); renvoie toutes les permutations de l permus(l,k):={ local lr; if (k==size(l)-1) return [l]; lr:=[]; for (j:=k;j<size(l);j++){ l:=echange(l,k,j); lr:=[op(lr),op(permus(l,k+1))]; l:=echange(l,j,k); } return lr; };On n'est pas obligé de remettre la suite l à sa valeur de départ pour recommencer l'itération puisque le premier échange dans l'itération revient à transformer l en la liste où on a mis son j-ième élément en tête (j = 0..n - 1).
//utilise echange permuts([1,2,3,4],0) //la 2ieme instruction echange est inutile car on echange // 0 et 1 ([1,0,2..]) puis 0 et 2 ([2,0,1..]) etc //avec la 2ieme instruction echange, on echange //0 et 1 ([1,0,2..]) puis 0 et 2 ([2,1,0..]) etc permuts(l,k):={ local lr; if (k==size(l)-1) return [l]; lr:=[]; for (j:=k;j<size(l);j++){ l:=echange(l,k,j); lr:=[op(lr),op(permuts(l,k+1))]; } return lr; };
Comme il faut 2 paramètres pour écrire la fonction récursive permuts, on écrit la fonction permutation qui utilise permuts:
//l:=[1,2,3];permutation(l); //renvoie toutes les permutations de l //utilise permuts permutation(l):={ return permuts(l,0); };On tape :
//au debut ld=[] et lf=l, //groupe_s([],l) renvoie toutes les permutations de l groupe_s(ld,lf):={ local j,n,res; n:=size(lf); res:=NULL; if (n==1) return concat(ld,lf); for (j:=0;j<n;j++){ res:=res,groupe_s(append(ld,lf[0]),tail(lf)); // permutation circulaire lf:=append(tail(lf),lf[0]); } return res; };Et la fonction groupesym qui utilise la fonction récursive groupe_s :
//utilise groupe_s //groupesym(l) renvoie toutes les permutations de l groupesym(l):=return(groupe_s([],l));2/ En faisant 2 appels récursifs.
//l:=[1,2,3]; circulaire(l) //renvoie la liste l ou la tete est mise a la fin. circulaire(l):={ return concat(tail(l),l[0]); };On peut décrire l'arbre des permutations de la liste l :
// utilise circulaire, l:=[1,2];permss([],l,l); //ldl=debut de l, l=liste a permuter, //ld=liste de reference (=l au debut) permss(ldl,l,ld):={ if (l==[]) return [ldl]; if (ld==[]) return ld; return [op(permss(concat(ldl,l[0]),tail(l),tail(l))), op(permss(ldl,circulaire(l),tail(ld)))]; };On écrit permss1 qui utilise comme paramètre n qui représente la longueur de la liste qui reste à permuter (n=size(l) au départ) :
//utilise circulaire, l:=[1,2,3,4];permss1([],l,size(l)); //ldl=debut de l, l=liste a permuter, n=size(l) au debut permss1(ldl,l,n):={ if (l==[]) return [ldl]; if (n==0) return []; return [op(permss1(concat(ldl,l[0]),tail(l),size(tail(l)))), op(permss1(ldl,circulaire(l),n-1))]; };On a aussi écrit la fonction permss2 contenant une variable locale lr qui est la liste à renvoyer et qui donne un algorithme plus lisible.
//l:=[1,2];permss2([],l,l); //ldl=debut de l, l=liste a permuter, //ld=liste de reference (=l au debut) // lr liste a renvoyer en variable locale permss2(ldl,l,ld):={ local lr; if (l==[]) return [ldl]; if (ld==[]) return []; lr:=permss2(concat(ldl,l[0]),tail(l),tail(l)); lr:=append(lr,op(permss2(ldl,concat(tail(l),l[0]),tail(ld)))); return lr };puis la fonction permute qui utilise permss2 :
//utilise permss2, //permute(l) renvoie toutes les permutations de l permute(l):={ return permss2([],l,l); };On tape :