[C] l-cicli potenza
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
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
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
Un problema è in questo controllo
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
Ma a questo punto tanto vale risparmiare il controllo è fare semplicemente
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:
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
che hai usato un paio di volte (nella popolazione dell'array e nel calcolo dei sottocicli), sono più chiari usando cicli for:
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.
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.
grazie claudio, cercherò di aggiustarlo quanto prima. Grazie mille