Fattorizzatore di permutazioni

Stato
Discussione chiusa ad ulteriori risposte.

Cynical

Utente Silver
10 Febbraio 2011
2
1
0
51
Ecco un programma che fattorizza una permutazione nel prodotto di cicli disgiunti
(l'avevo messo nella senzione sbagliata mi ero confuso xD)

richiami teorici :
per semplicità si può pensare ad una permutazione come ad un modo di disporre n oggetti senza ripeterli....
in realtà le permutazioni degli elementi di un insieme sono l'insieme di tutte le funzioni bigettive tra un insieme e se stesso.

se abc , acb, cab, cba, bca, bac sono permutazioni, si possono pensare come funzioni di questo tipo

Codice:
 / a b c \
|          | = f   questa è la permutazione identica
 \ a b c /
Codice:
/ a b c\
|        |   =g      se seguite le immagini degli elementi vedrete un ciclo :
\ b c a/           a - > b -> c -> a e così via, la permutazione si può scrivere (abc)
che non c'entra con la prima riga!

altro esempio....
Codice:
  / 1 2 3 4 5 6 \
 |                  |   = f    stesso ragionamento, 1 -> 4 -> 6 -> 1 e mi fermo
 \ 4 3 5 6 2 1 /         2 -> 3 -> 5 -> 2 mi fermo ancora
quindi f = (146)(235)

questo è il lavoro che deve fare il programma.

ecco la mia soluzione

Codice:
#include <stdio.h>
#include<stdlib.h>

#define ORDINE printf("\n\n")

int leggiN(void);
void leggiPerm(int *, int);
void inizVettVal(int *, int, int);
void fattInCicli(int *, int);
void outputRisultati(int *, int);

int main(void)
{  int n;

   n = leggiN();
   int perm[n];

   leggiPerm(perm, n);

   ORDINE;
   outputRisultati(perm, n);
  
   printf("\npremere un tasto per continuare...");
   while(getchar() != '\n');
 
   return 0;
}

int leggiN()
{ int n;
   printf("inserisci n:\n");
   do {   scanf("%d",&n);
          if(n<2)
           {
               ORDINE;
               printf("ERRORE: n deve essere maggiore o uguale a 2.");
               ORDINE;
           }
      }while(n<2);

  return n;
}

void leggiPerm(int *p, int n)
{ int i,j,flag;

     for(i=0; i<n; i++)
        do{
            flag = 0;
            printf("%d va in ?:\n", i+1);
            scanf("%d",&p[i]);

            for(j=0;j<i && p[i]!=p[j];j++);
            if((p[i] < 1 || p[i] > n ) || j<i)
            {
               flag = 1;
               ORDINE;
               if(j<i)
                   printf("ERRORE: valore già inserito, il %d va in %d.", j+1, p[i]);
               else
                   printf("ERRORE: inserisci valori compresi tra 1 e %d.", n);
               ORDINE;
            }
         }while(flag);
}


void fattInCicli(int *p, int n)
{ int i, j, check[n], primo;

    for(i=0; i<n; i++) // uso quest'array per stabilire se ho controllato
        check[i]=1;   // un elemento o meno.
                      // 1 significa che li devo controllare, 0 già fatto.
    for(i=0; i<n; i++)
        if(check[i])
           {
              check[i] = 0; // checked ;)
              if(p[i] != i+1) // se l'elemento non è tenuto fisso dalla permutazione...
                 { 
                   j = i;
                   primo = j+1;
                   printf("(%d",j+1);
                   while(p[j] != j+1 && p[j] != primo)
                   {
                     printf("%d", p[j]);
                     j = p[j] -1;
                     check[j] = 0;
                   }
                   printf(")");
                 }
           }
}

void outputRisultati(int *p, int n)
{ int i;
  
  printf("    / ");
  for(i=0; i<n; i++)
     printf("%d ",i+1);
  printf("\\\n");
  
  printf("f =|");
  for(i=0; i<n; i++)
     printf("  ");
  printf("    | = ");
  fattInCicli(p, n);
  printf("\n");
  printf("    \\ ");
  for(i=0; i<n; i++)
     printf("%d ",p[i]);
  printf("/\n");       
}
 
Stato
Discussione chiusa ad ulteriori risposte.