Algoritmo che genera tutti i numeri possibili formati da 4 cifre

di il
40 risposte

40 Risposte - Pagina 3

  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    Nippolo ha scritto:


    Rubik ha scritto:


    Partecipo con un mio codice che genera tutte le password, con lunghezza definita a piacere, ottenibili in un range di caratteri scelto a piacere:
    - occhio, gen è una stringa o solo un array di caratteri?
    - dal punto di vista logico a quell'if potresti anche abbinare un else break.
    gen contiene interi, il codice non esegue nessuna operazione sulle stringhe ma solo tra interi unsigned, il mio codice è 2/3 volte più veloce proprio per questo.
    L'unica operazione di concatenamento di char avviene per la visualizzazione, che in un codice funzionante non servirebbe, perché sarebbe sufficiente mostrare il risultato.
    Per l'if, non ho capito bene cosa intendi, assumendo che i caratteri della passw siano 4, DEVO eseguire tre controlli, alle posizioni 3,2,1 perché qualsiasi di queste posizioni, ha raggiunto un indice superiore ai caratteri dell'alfabeto, va azzerata con conseguente incremento della posizione adiacente a sinistra. La posizione 0 invece viene controllata nel while e decreta anche la fine del ciclo.
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    Io non leggo nippolo, è nella mia plonk-list

    Però dalla citazione credo di aver capito cosa intendesse

    Quando controlli se una certa cifra ha 'fatto il giro' e quindi devi fare il riporto nella posizione a sinistra
    SE non è successo per quella in corso
    CERTAMENTE
    non succederà per nessuna delle altre
    (Scusa il maiuscolo è per segnalare il rapporto causa effetto)
    In quel caso puoi uscire subito dai controlli
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    @Rubik
    se guardi bene il QUOTE si riferiva al seguente post
    https://www.iprogrammatori.it/forum-programmazione/post8663622.html#p8663622
    dove gen è un array di char.
    E con

    Nippolo ha scritto:


    - occhio, gen è una stringa o solo un array di caratteri?
    mi riferivo alla seguente riga di codice
    printf("%s combinazione n. %d\n", gen, ++n);
    dove tratti gen alla stregua di una C-stringa, ma non lo è in quanto manca il carattere terminatore.

    Per la questione dell'if la spiegazione più o meno è quella fornita da @StandardOil.
    In pratica, premesso che lo scopo è quello di generare tutte le sequenze relative alle disposizioni con ripetizione di n elementi presi k alla volta, operando sugli indici e partendo da una configurazione costituita da tutti 0, il problema si riduce ad incrementare di 1 un numero di k cifre appartenente ad un sistema numerico posizionale in base n.
    Ed è proprio in questo senso che opera la funzione
    int disposizione_R_successiva(unsigned int *u, unsigned int n, unsigned int k)
    {
        unsigned int i;
        for(i = 0; i < k && !(u[i] = (u[i] + 1) % n); ++i);
        return i < k;
    }
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    StandardOil ha scritto:


    Quando controlli se una certa cifra ha 'fatto il giro' e quindi devi fare il riporto nella posizione a sinistra
    SE non è successo per quella in corso
    CERTAMENTE
    non succederà per nessuna delle altre
    (Scusa il maiuscolo è per segnalare il rapporto causa effetto)
    In quel caso puoi uscire subito dai controlli
    Giusto inutile continuare il for, con passw corte la differenza sarà minimale, ma più le passw si allungano e più il break inciderà...
    Grazie anche a Nippolo
    codice correto:
    
    #include <stdio.h>
    #include <string.h>
    
    #define DIM 4 // lunghezza della passw, modificabile a piacere
    
    int main()
    {
        char alfabeto[] = "0123456789ABCDEF"; // alfabeto personalizzato, modificabile a piacere anche in lunghezza, in fila solo per testing
    
        unsigned int LUN = sizeof(alfabeto)-1;
        unsigned int Indici[LUN]={0};
        unsigned int n=0, col=0, i=0;
    
        // indicizzo l'alfabeto ---------------------
        for (i=0; i<LUN; i++){
            Indici[i]=i;
            printf("Il carattre: %c ha indice: %d\n", alfabeto[i], Indici[i]);
        } //-----------------------------------------
    
        unsigned int gen[DIM]; // conterrà gli indici della stringa generata
        // indice di partenza in tutte le posizioni (colonne)
        for (col=0; col<DIM; col++){
            gen[col]= Indici[0]; // praticamente sono tutti zeri
        }
        char conc[DIM+1]={0};
        do{
            for (col=0; col<DIM; col++){
                conc[col]=alfabeto[gen[col]];// concateno il carattere che corrisponde all'indice
            }
            printf("%s combinazioni n. %d\n", conc, ++n);
    
            gen[DIM-1]++; // incremento indice più a destra
            for (col=DIM-1; col>0; col--){ // tutte le colonne eccetto la zero
                if (gen[col]==LUN){ // raggiunto il massimo indice colonna corrente
                    gen[col]=0; // azzero l'indice colonna corrente
                    gen[col-1]++; // incremento l'indice colonna precedente
                }
                else break;
            }
        }while (gen[0]<LUN); // controllo indice su colonna zero
    
        return 0;
    }
    
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    Nippolo ha scritto:


    @Rubik
    se guardi bene il QUOTE si riferiva al seguente post
    https://www.iprogrammatori.it/forum-programmazione/post8663622.html#p8663622
    dove gen è un array di char.
    E con

    Nippolo ha scritto:


    - occhio, gen è una stringa o solo un array di caratteri?
    mi riferivo alla seguente riga di codice
    printf("%s combinazione n. %d\n", gen, ++n);
    dove tratti gen alla stregua di una C-stringa, ma non lo è in quanto manca il carattere terminatore.
    Per la questione "stringa o char", ho agito in base al risultato ottenuto, infatti all'inizio avevo messo il "tappo" '\0', perché come ho studiato è la condizione per stampare attraverso %s un vettore di char come stringa, ma poi inserendolo aumentando il vettore di un elemento o omettendolo senza aumentare di un posto il vettore, non ho riscontarto differenze. E' sbagliato perché con altri compilatori diverso dal mio si potrebbero generare comportamenti diversi?

    Per quanto riguarda l'if break, ricevuto, una svista , ti ho ringraziato nel post precedente.
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    Rubik ha scritto:


    E' sbagliato perché con altri compilatori diverso dal mio si potrebbero generare comportamenti diversi?
    Magari anche il tuo stesso compilatore nei giorni di luna piena potrebbe generare un comportamento imprevisto!
    Scherzi a parte, tutto dipende dalla configurazione attuale della memoria, ossia, nello specifico, da cosa si trova nelle locazioni di memoria successive all'ultimo elemento dell'array di char considerato (in gergo tecnico si parla di undefined behavior).
    Per esempio se sei fortunato che gen[LUN]==0, allora il programma funzionerà correttamente, altrimenti potresti stampare "spazzatura" o incappare in un segfault.

    P.S.
    In riferimento all'ultimo codice che hai postato, l'array Indici è inutile, infatti tu stesso praticamente non lo utilizzi.
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    Nippolo ha scritto:


    Magari anche il tuo stesso compilatore nei giorni di luna piena potrebbe generare un comportamento imprevisto!
    Scherzi a parte, tutto dipende dalla configurazione attuale della memoria, ossia, nello specifico, da cosa si trova nelle locazioni di memoria successive all'ultimo elemento dell'array di char considerato (in gergo tecnico si parla di undefined behavior).
    Per esempio se sei fortunato che gen[LUN]==0, allora il programma funzionerà correttamente, altrimenti potresti stampare "spazzatura" o incappare in un segfault.
    Ricevuto.

    Nippolo ha scritto:


    P.S.
    In riferimento all'ultimo codice che hai postato, l'array Indici è inutile, infatti tu stesso praticamente non lo utilizzi.
    Rigiusto è il rimasuglio del ragionamento iniziale di indicizzare l'alfabeto, ma poi il vettore: char alfabeto[] = "0123456789ABCDEF"; è già indicizzato .
    Senza l'inutile indicizzazione Il codice è ancora più compatto, mi piace, ho messo anche il "tappo":
    
    #include <stdio.h>
    #include <string.h>
    
    #define DIM 4 // lunghezza della passw, modificabile a piacere
    
    int main()
    {
        char alfabeto[] = "0123456789ABCDEF"; // alfabeto personalizzato, modificabile a piacere anche in lunghezza, in fila solo per testing
    
        unsigned int LUN = sizeof(alfabeto)-1;
        unsigned int n=0, col=0, i=0;
    
        unsigned int gen[DIM]; // conterrà gli indici della stringa generata
        // indice di partenza in tutte le posizioni (colonne)
        for (col=0; col<DIM; col++){
            gen[col]= 0; // tutti zeri
        }
        char conc[DIM+1]={0};
        conc[DIM+1] = '\0'; // terminatore
        do{
            for (col=0; col<DIM; col++){
                conc[col]=alfabeto[gen[col]];// concateno il carattere che corrisponde all'indice
            }
            printf("%s combinazioni n. %d\n", conc, ++n);
            gen[DIM-1]++; // incremento indice più a destra
            for (col=DIM-1; col>0; col--){ // tutte le colonne eccetto la zero
                if (gen[col]==LUN){ // raggiunto il massimo indice colonna corrente
                    gen[col]=0; // azzero l'indice colonna corrente
                    gen[col-1]++; // incremento l'indice colonna precedente
                }
                else break;
            }
        }while (gen[0]<LUN); // controllo indice su colonna zero
    
        return 0;
    }
    
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    @Rubik
    alcune considerazioni:

    - per inizializzare gli elementi di gen a 0 basta fare
    unsigned int gen[DIM] = {0};
    quindi il primo for è superfluo;
    - se conc ha DIM+1 elementi, allora l'ultimo elemento avrà indice DIM, quindi con l'istruzione
    conc[DIM+1] = '\0'; // terminatore
    stai andando a scrivere in zone di memoria che non competono all'array. Al massimo avresti potuto scrivere
    conc[DIM] = '\0';
    ma sarebbe stato comunque superfluo in quanto la sequenza di escape \0 è del tutto equivalente a 0 e l'array era già stato inizializzato al momento della dichiarazione
    char conc[DIM+1]={0};
    - non serve includere string.h;
    - come indice per scorrere un array, al posto di col opterei per il più classico i. Inoltre ti consiglio di dichiarare tale variabile all'interno dello stesso for.
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    StandardOil ha scritto:


    Bellissima, posso farla mia?

    Ti offendi se la copio?
    E che problema c'è
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    Che bello, tutti i punti che hai esposto sono frutto di mie conclusioni, derivate da dubbi.

    Nippolo ha scritto:


    - per inizializzare gli elementi di gen a 0 basta fare
    unsigned int gen[DIM] = {0};
    quindi il primo for è superfluo;
    Visto, infatti in debug ci sono tutti zeri dopo la dichiarazione, avevo già fatto questo controllo ed ero convinto sbagliando che ={0} riempisse solo un elemento, bene, quasta istruzione fa comodo per inizializzare i vettori.
    - se conc ha DIM+1 elementi, allora l'ultimo elemento avrà indice DIM, quindi con l'istruzione
    conc[DIM+1] = '\0'; // terminatore
    stai andando a scrivere in zone di memoria che non competono all'array. Al massimo avresti potuto scrivere
    conc[DIM] = '\0';
    Ovvio, un errore, non è una bella cosa scrivere in una locazione ram alla cieca.
    ma sarebbe stato comunque superfluo in quanto la sequenza di escape \0 è del tutto equivalente a 0 e l'array era già stato inizializzato al momento della dichiarazione
    char conc[DIM+1]={0};
    Qui torniamo all'uso del tappo, che avevo deciso di non mettere...
    Ora capisco che il tappo va messo, ma se l'array di char è inizializzato non serve, perché praticamente gia c'è.
    - non serve includere string.h;
    Come si fa a sapere se le istruzioni che uso non hanno bisogno delle librerie che avevo inizialmente incluso? a volte provo a cancellare gli include e vedo se ho degli errori, ma non mi sembra un bel sistema.
    - come indice per scorrere un array, al posto di col opterei per il più classico i.
    Se è generico si, ma in questo caso l'indice è la colonna e col ci calza a pennello.
    Inoltre ti consiglio di dichiarare tale variabile all'interno dello stesso for.
    Sono abituato in C# a dichiarare le variabili all'interno del for, ma ho letto che non è C standard, si fa solo in C++

    Mi piacerebbe scrivere in C, anche perché se dovessi usare le peculiarità del C++, allora programmo in C#, o no?

    Il codice è ancora più corto:
    
    #include <stdio.h>
    
    #define DIM 4 // lunghezza della passw, modificabile a piacere
    
    int main()
    {
        char alfabeto[] = "0123456789ABCDEF"; // alfabeto personalizzato, modificabile a piacere anche in lunghezza, in fila solo per testing
    
        unsigned int LUN = sizeof(alfabeto)-1;
        unsigned int n=0, col=0, i=0;
        unsigned int gen[DIM]={0}; // conterrà gli indici della stringa generata, si parte con tutti zeri
        char conc[DIM+1]={0}; // inizializzata con spazio per il terminatore
    
        do{
            for (col=0; col<DIM; col++){
                conc[col]=alfabeto[gen[col]];// concateno il carattere che corrisponde all'indice
            }
            printf("%s combinazioni n. %d\n", conc, ++n);
            gen[DIM-1]++; // incremento indice più a destra
            for (col=DIM-1; col>0; col--){ // tutte le colonne eccetto la zero
                if (gen[col]==LUN){ // raggiunto il massimo indice colonna corrente
                    gen[col]=0; // azzero l'indice colonna corrente
                    gen[col-1]++; // incremento l'indice colonna precedente
                }else break;
            }
        }while (gen[0]<LUN); // controllo indice su colonna zero
    
        return 0;
    }
    
  • Re: Algoritmo che genera tutti i numeri possibili formati da 4 cifre

    Rubik ha scritto:


    Visto, infatti in debug ci sono tutti zeri dopo la dichiarazione, avevo già fatto questo controllo ed ero convinto sbagliando che ={0} riempisse solo un elemento, bene, quasta istruzione fa comodo per inizializzare i vettori.
    https://stackoverflow.com/questions/201101/how-to-initialize-all-members-of-an-array-to-the-same-value

    Rubik ha scritto:


    Come si fa a sapere se le istruzioni che uso non hanno bisogno delle librerie che avevo inizialmente incluso? a volte provo a cancellare gli include e vedo se ho degli errori, ma non mi sembra un bel sistema.
    Non è poi così malvagio come sistema! Cmq puoi sempre dare un'occhiata qui:
    https://www.cplusplus.com/reference
    http://cppreference.com

    Rubik ha scritto:


    Sono abituato in C# a dichiarare le variabili all'interno del for, ma ho letto che non è C standard, si fa solo in C++
    https://stackoverflow.com/questions/48453353/why-do-c-programmers-often-declare-the-counter-variable-outside-the-for-loop-c
Devi accedere o registrarti per scrivere nel forum
40 risposte