[C] l-cicli potenza

Kashaman
Salve ragazzi , sto cercando di implementare un programma puramente algebrico. Vi spiego , sto cercando di implementare un programma che dato in input un $l-ciclo$ del tipo $\sigma=(1,2,....n)$ mi calcoli $\sigma^i$ con $i$ un intero.
Quello che sono riuscito a fare è questo
/* Potenza l-ciclo */
#include <stdio.h>
main()
{
       int l;
      do {
      printf("Inserisci lunghezza del ciclo\n");
      scanf("%d",&l);
      int ci[l];
      int i=0;
      while (i<l) {
            printf("inserisci il termine %d\n", i+1 );
            scanf("%d",&ci[i]);
            ++i;}
       int n;
      int j=0;
      int count=0;
       printf("\nInserisci indice di potenza\n");
       scanf("%d",&n);
     while (count!=l) {
           printf("%d\t",ci[j]);
          if (j<n) j=j+n;  else j=(j+n)%l;
           ++count;
} } while (l!=0);

            }

Ottengo i seguenti errori.
Se inserisco un $n>l$ mi si generano numeri a caso... come risolvo ciò?
Se inserisco un $n$ divisore di $l$ mi viene una sequenza del tipo $a_l , a_(l+1) , a_l , a_(l+1) $...
mi spiego, di norma , ad esempio se ho $(1,2,3,4)$
$(1,2,3,4)^2=(1,3)(2,4)$ ma il codice mi stampa $1 3 1 3$ , come posso correggere ciò?
potete darmi un piccolo hint?
grazie di cuore, arrivederci

Risposte
claudio862
Un problema è in questo controllo

if (j < n)
    j = j + n;
else
    j = (j + n) % l;

Anche se j < n, j + n è sicuramente maggiore di n, che è maggiore di l. Quindi alla prossima iterazione j è oltre la fine dell'array. Un controllo più corretto sarebbe

if (j + n < l)
    j = j + n;
else
    j = (j + n) % l;

Ma a questo punto tanto vale risparmiare il controllo è fare semplicemente

j = (j + n) % l;



Il fatto che ti esca 1313 invece è proprio per la proprietà dei gruppi ciclici. Nel tuo esempio, 1² = 3 e 3² = 1, e nel ciclo applichi solo l'operazione ()², quindi se parti da 1 o 3 non visiterai altri elementi.
Potresti, una volta che completi un sottociclo, far ripartire l'operazione dall'elemento successivo. Qualcosa di simile:

for (int k = 0; k < numero_cicli; ++k) {
    int j = k; // Parti da elementi successivi
    printf("Ciclo %d:\t", k + 1);
    for (int count = 0; count < lunghezza_ciclo; ++count) {
        printf("%d\t", ci[j]);
        j = (j + n) % l;
    }
    puts("");
}


numero_cicli e lunghezza_ciclo dovresti ricavarli dalle proprietà dei gruppi ciclici. Altrimenti impostali entrambi a l, ci saranno delle ripetizioni ma avrai comunque tutti i cicli.


P.S.
Cicli del tipo

int i = 0;
while (i < l) {
    // Codice vario
    ++i;
}

che hai usato un paio di volte (nella popolazione dell'array e nel calcolo dei sottocicli), sono più chiari usando cicli for:

for (int i = 0; i < l; ++i) {
    // Codice vario
}


Cicli while dovrebbero essere usati quando non sai a priori quante iterazioni farai, cicli for se invece hai questa informazione. Inoltre con il ciclo for è possibile dichiarare la variabile di iterazione (i) dentro il ciclo (cioè nella sua intestazione). In questo modo tale variabile esiste solo all'interno del ciclo, e questo riduce possibilità di errori.

Kashaman
grazie claudio, cercherò di aggiustarlo quanto prima. Grazie mille

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.