V I S U A L I Z Z A D I S C U S S I O N E |
coma |
Inserito il - 23/09/2011 : 09:45:40 Tornato da un precorso al Dipartimento di Matematica ho trovato davvero stimolante ma soprattutto, rilassante, scrivere questo programmino che seppur sia davvero INUTILE, mi ha dato la possibilità di far pratica con il C, il che, a mio parere, non guasta mai! Ho cercato di commentarlo il più possibile e di cercare di ottimizzarlo al meglio, nonostante sia davvero un programma di scarsa utilità. Voi vi starete chiedendo, posti qui il tutto per farti figo? No assolutamente, ma bensì spero che qualcuno sappia dirmi come potrei eventualmente modificare quell'orrendo goto ( che ho l'estremo bisogno di usare per poter far terminare il ciclo e farlo ricominciare esattamente da dove voglio! ) rendendo così il tutto più fluido e dal punto di vista algoritmico, più performante. http://pastebin.com/RB4r8FCi
Nel caso vi dovessero essere degli errori, malfunzionamenti, bombe a mano e tric e trac, sono a disposizione!! :) ( non ho ancora inserito una funzione che effettui il controllo dell'id inserito e pertanto, nel caso aveste dei suggerimenti, sono a tutte orecchie! )
grazie ancora, coma.
|
18 U L T I M E R I S P O S T E (in alto le più recenti) |
coma |
Inserito il - 26/09/2011 : 14:37:45 Citazione: Messaggio inserito da noname
No è un problema d'uso. Inizializzi il generatore con lo stesso seme (il tempo) ad ogni chiamata di funzione. Se la funzione viene chiamata più volte in un secondo, il seme è lo stesso, e la sequenza di numeri "casuali" è la stessa. Praticamente ritorni per ogni secondo sempre lo stesso numero. Prova a vedere se è vero con una printf.
Fai benissimo ad adottare una scrittura virgolettata, poichè effettivamente non sono veri e propri numeri casuali ma, bensì, pseudo-casuali, visto che vengono generati a partire dal valore che ritorna la funzione time() che ovviamente, come ben saprai, è strettamente connessa con l'orologio di sistema e, quindi, un'invocazione della stessa in un lasso di tempo molto risicato, potrebbe portare addirittura li stessi risultati!
In ogni caso, ho ridotto notevolmente i tempi di esecuzione semplicemente rimuovendo la chiamata alla funzione srand() dalla funzione gen_num() e posizionandola all'inizio del main(). Questo un piccolo esempio del suo funzionamento : THE NUMBERS THAT YOU WILL USE TO THE LOTTERY :
[1] [2] [3] [4] [5] [6] 86 7 1 88 6 75
Process returned 0 (0x0) execution time : 0.024 s Press any key to continue.
Grazie ancora per la dritta noname!:) |
noname |
Inserito il - 26/09/2011 : 01:03:26 No è un problema d'uso. Inizializzi il generatore con lo stesso seme (il tempo) ad ogni chiamata di funzione. Se la funzione viene chiamata più volte in un secondo, il seme è lo stesso, e la sequenza di numeri "casuali" è la stessa. Praticamente ritorni per ogni secondo sempre lo stesso numero. Prova a vedere se è vero con una printf. |
coma |
Inserito il - 26/09/2011 : 00:29:31 Citazione: Messaggio inserito da noname
Con un approccio decente un programma del genere termina in una frazione di secondo. Il tuo approccio non è male nonostante non ci siano garanzie sul tempo di esecuzione, tralasciando bug e input ostili. Per cui ci deve essere un problema e il maggior indiziato è senza dubbio il modo in cui usi il generatore di numeri casuali. E infatti è lì... :)
Come mai?Pensi che la funzione rand() non sia abbastanza performante per tale compito? Potresti magari suggerirmi qualcosa per poterlo perfezionare? |
noname |
Inserito il - 26/09/2011 : 00:04:47 Con un approccio decente un programma del genere termina in una frazione di secondo. Il tuo approccio non è male nonostante non ci siano garanzie sul tempo di esecuzione, tralasciando bug e input ostili. Per cui ci deve essere un problema e il maggior indiziato è senza dubbio il modo in cui usi il generatore di numeri casuali. E infatti è lì... :) |
coma |
Inserito il - 25/09/2011 : 18:18:40 Citazione: Messaggio inserito da noname
Stai facendo benissimo, è così che si impara :)
Dovresti mantenere in memoria un array di 99 elementi, preferibilmente del tipo più piccolo che hai a disposizione. In C tipicamente un char equivale ad un byte. A te interessa mantenere solo informazioni sulla presenza di un elemento, 1 o 0, e per questo ti basterebbe solo un bit per elemento, ma senza complicarti la vita puoi usarne 8 ;)
Quindi:
char generated_numbers[99];
da 0 a 98 setti l'array a 0
generi un numero (che sarà compreso tra 1 e 99 inclusi) se generated_numbers[numero - 1] è uguale a 0 il numero non è stato ancora generato e setti l'elemento dell'array ad 1 altrimenti generi un altro numero
in questo modo eviti qualsiasi ricerca facendo solo un lookup nell'array
La stessa cosa si può fare utilizzando le operazioni sui bit su array di soli 13 byte.
Ora capisco cosa tu intenda dire ed è diciamo ciò che avrei voluto fare io mediante una flag che determinasse se fossero presenti o meno valori doppi nell'array, in modo tale da poter ridurre, in un certo qual modo, il numero di cicli adoperati da quel while( n < 6 ). Purtroppo però, l'altra questione che essenzialmente mi premeva portare a termine era gestire adeguatamente la generazione di numeri casuali valutando opportunamente di non generare numeri che si ripetessero sin nel while, in modo da poter subito porvi rimedio creando, al loro posto, nuovi numeri casuali.
Francamente, dubito che vi possano essere metodi di ottimizzazione che diminuirebbero la velocità di esecuzione visto che, di per sè, il compito da portare a termine è abbastanza contorto e non particolarmente adatto per una sua precisa riproposizione algoritmica.
Domani si inizia e quindi potrò dedicarmi alla risoluzione di eserizi ben precisi e sicuramente più stimolanti di questo!!:)
Spero che dal punto di vista formale il mio codice sia ben realizzato e nel caso non dovesse esserlo non esitate a farmi notare delle sviste. PS la versione del file postata è priva del free() per poter deallocare memoria per l'array temp precedentemente inizializzato nel main(). Ecco la nuova versione con la suddetta correzione : http://pastebin.com/m42Dp7ER |
noname |
Inserito il - 25/09/2011 : 15:05:59 Stai facendo benissimo, è così che si impara :)
Dovresti mantenere in memoria un array di 99 elementi, preferibilmente del tipo più piccolo che hai a disposizione. In C tipicamente un char equivale ad un byte. A te interessa mantenere solo informazioni sulla presenza di un elemento, 1 o 0, e per questo ti basterebbe solo un bit per elemento, ma senza complicarti la vita puoi usarne 8 ;)
Quindi:
char generated_numbers[99];
da 0 a 98 setti l'array a 0
generi un numero (che sarà compreso tra 1 e 99 inclusi) se generated_numbers[numero - 1] è uguale a 0 il numero non è stato ancora generato e setti l'elemento dell'array ad 1 altrimenti generi un altro numero
in questo modo eviti qualsiasi ricerca facendo solo un lookup nell'array
La stessa cosa si può fare utilizzando le operazioni sui bit su array di soli 13 byte. |
coma |
Inserito il - 25/09/2011 : 10:42:58 Citazione: Messaggio inserito da noname
Ciao!
Nel tuo caso specifico, dato che i numeri generabili sono davvero pochi, puoi evitare l'uso di algoritmi di ricerca allocando semplicemente un array di 99 byte e inizializzandolo a zero. Quando generi un numero, diciamo 53, vai alla posizione 52 e vedi se c'è uno zero (numero non ancora generato) e in tal caso setti ad uno. In realtà i numeri generabili dipendono da quante cifre diverse ci sono nella matricola ma allocare 99 byte ti semplifica la vita. Volendo puoi anche usare le operazioni sui bit, e ti basterebbero 99 bit per mantenere le stesse informazioni. In ogni caso il guadagno di queste ottimizzazioni, nel caso ci fosse, sarebbe irrisorio dati questi input e queste poche iterazioni.
Beh guarda, obiettivamente, ammetto che il programma abbia palesemente la sua inutilità, però mi intrigava il compito di poter realizzare qualcosa che mi facilitasse un determinato compito ed è stato esattamente questo il mio intento fondamentale e, non tanto realizzare il programma in sè, perchè, ripeto, è quasi completamente inutile. Se ti fosse possibile specificare qualche esempio di codice, sarebbe ben gradito in quanto, non ho ben capito a cosa ti riferisci parlando di una procedura di allocazione di 99byte. |
noname |
Inserito il - 25/09/2011 : 03:00:31 Ciao!
Nel tuo caso specifico, dato che i numeri generabili sono davvero pochi, puoi evitare l'uso di algoritmi di ricerca allocando semplicemente un array di 99 byte e inizializzandolo a zero. Quando generi un numero, diciamo 53, vai alla posizione 52 e vedi se c'è uno zero (numero non ancora generato) e in tal caso setti ad uno. In realtà i numeri generabili dipendono da quante cifre diverse ci sono nella matricola ma allocare 99 byte ti semplifica la vita. Volendo puoi anche usare le operazioni sui bit, e ti basterebbero 99 bit per mantenere le stesse informazioni. In ogni caso il guadagno di queste ottimizzazioni, nel caso ci fosse, sarebbe irrisorio dati questi input e queste poche iterazioni. |
coma |
Inserito il - 24/09/2011 : 13:56:39 Citazione: Messaggio inserito da ivan
Citazione: Messaggio inserito da coma
Chiedo scusa ai moderatori se mi son permesso di eliminare il post che avevo precedentemente creato, però ho ritenuto che fosse corretto farlo in quanto, stamattina, in seguito ad un lieto riposo, ho ricevuto l'zione e son riuscito a porre rimedio all'orrendo goto che avevo inserito, procedendo in una modulizazzione molto più precisa, che mi ha dato modo di rendere il codice più leggibile e lineare. Questo è il codice -> http://pastebin.com/7Z3LydBK
Ora però, vien fuori il problema dell'efficienza della sua esecuzione ed è qui che purtroppo subentrano i problemi più grossi visti i risultati che ho preso la briga di riportarvi qui sotto e che, obiettivamente, risultano, nonostante la mia inesperienza in questo campo, particolarmente alti.
alex@darknet:~/C$ time ./student_id THE NUMBERS THAT YOU WILL USE TO THE LOTTERY :
[1] [2] [3] [4] [5] [6] 5 6 51 8 1 78
real 0m5.640s user 0m5.630s sys 0m0.000s
Ho provato ad adottare la ricerca dicotomica, ma con scarsi risultati, nonostante abbia adottato come funzione di ordinamento l'ottima qsort() e non un algoritmo creato da me. Idee? PS Ringrazio FullMetalJacket che, nonostante la sua perenne freddezza, ha finalmente chiarito un dubbio che mi era venuto, riguardante la ormai convenzione di tutti i programmatori di non adottare il goto e che è giustificata appunto da una teoria formale rappresentata appunto dal Teorema di Böhm-Jacopini. Grazie mille!!:)
mitico STU che ci illumini! Eroe dei tempi che furono.
Ahahahah!!:D Non pensavo che ci fosse il parsing automatico delle parole e la corrispettiva attribuzione di faccine alle stesse!!Notevole! |
ivan |
Inserito il - 24/09/2011 : 13:26:21 Citazione: Messaggio inserito da coma
Chiedo scusa ai moderatori se mi son permesso di eliminare il post che avevo precedentemente creato, però ho ritenuto che fosse corretto farlo in quanto, stamattina, in seguito ad un lieto riposo, ho ricevuto l'zione e son riuscito a porre rimedio all'orrendo goto che avevo inserito, procedendo in una modulizazzione molto più precisa, che mi ha dato modo di rendere il codice più leggibile e lineare. Questo è il codice -> http://pastebin.com/7Z3LydBK
Ora però, vien fuori il problema dell'efficienza della sua esecuzione ed è qui che purtroppo subentrano i problemi più grossi visti i risultati che ho preso la briga di riportarvi qui sotto e che, obiettivamente, risultano, nonostante la mia inesperienza in questo campo, particolarmente alti.
alex@darknet:~/C$ time ./student_id THE NUMBERS THAT YOU WILL USE TO THE LOTTERY :
[1] [2] [3] [4] [5] [6] 5 6 51 8 1 78
real 0m5.640s user 0m5.630s sys 0m0.000s
Ho provato ad adottare la ricerca dicotomica, ma con scarsi risultati, nonostante abbia adottato come funzione di ordinamento l'ottima qsort() e non un algoritmo creato da me. Idee? PS Ringrazio FullMetalJacket che, nonostante la sua perenne freddezza, ha finalmente chiarito un dubbio che mi era venuto, riguardante la ormai convenzione di tutti i programmatori di non adottare il goto e che è giustificata appunto da una teoria formale rappresentata appunto dal Teorema di Böhm-Jacopini. Grazie mille!!:)
mitico STU che ci illumini! Eroe dei tempi che furono. |
coma |
Inserito il - 24/09/2011 : 13:20:01 Chiedo scusa ai moderatori se mi son permesso di eliminare il post che avevo precedentemente creato, però ho ritenuto che fosse corretto farlo in quanto, stamattina, in seguito ad un lieto riposo, ho ricevuto l'zione e son riuscito a porre rimedio all'orrendo goto che avevo inserito, procedendo in una modulizazzione molto più precisa, che mi ha dato modo di rendere il codice più leggibile e lineare. Questo è il codice -> http://pastebin.com/7Z3LydBK
Ora però, vien fuori il problema dell'efficienza della sua esecuzione ed è qui che purtroppo subentrano i problemi più grossi visti i risultati che ho preso la briga di riportarvi qui sotto e che, obiettivamente, risultano, nonostante la mia inesperienza in questo campo, particolarmente alti.
alex@darknet:~/C$ time ./student_id THE NUMBERS THAT YOU WILL USE TO THE LOTTERY :
[1] [2] [3] [4] [5] [6] 5 6 51 8 1 78
real 0m5.640s user 0m5.630s sys 0m0.000s
Ho provato ad adottare la ricerca dicotomica, ma con scarsi risultati, nonostante abbia adottato come funzione di ordinamento l'ottima qsort() e non un algoritmo creato da me. Idee? PS Ringrazio FullMetalJacket che, nonostante la sua perenne freddezza, ha finalmente chiarito un dubbio che mi era venuto, riguardante la ormai convenzione di tutti i programmatori di non adottare il goto e che è giustificata appunto da una teoria formale rappresentata appunto dal Teorema di Böhm-Jacopini. Grazie mille!!:)
|
FullMetalJacket |
Inserito il - 24/09/2011 : 07:13:59 Goto? Teorema di Böhm-Jacopini |
coma |
Inserito il - 23/09/2011 : 17:04:14 Citazione: Messaggio inserito da Premoli
Prima di tutto eviterei di usare quel goto che è veramente brutto
Per il resto ragionerei così (se ho capito bene quello che vuoi fare):
prima di tutto devo verificare che con i numeri della matricola riesco effettivamente a generare 6 numeri. Ad esempio metti caso che un utente abbia questa matricola (1 1 1 1 1 1) è evidente che si possono generare solo 2 numeri diversi 1 e 11.
poi all'interno di un ciclo che va da i=0 fino a i<6 (diciamo che sono sei i numeri che voglio generare) prendo a caso una cifra della matricola e la salvo in una variabile quindi faccio in questo modo
per numeri a una cifra: x = matricola[rand() % 6];
per numeri a due cifre: moltiplicherò x per 10 e estrarrò un altro numero della matricola che andrò a sommare a x, in questo modo sono sicuro che anche il numero a due cifre è composto da numeri presenti nella matricola
fatto questo, controllo (con un qualsiasi algoritmo) che non ci sono numeri uguali nel vettore che sto creando se non ci sono ripetizioni vado avanti altrimenti faccio tornare indietro di una posizione l'indice del vettore e sovrascrivo l'ultimo valore...
Questo è quello che mi è venuto in mente ora, probabilmente si può sensibilmente ottimizzare...
Infatti è stato esattamente ciò che ho, sin dal principio, cercato di eliminare, ma non vi è stato verso di far funzionare, almeno in parte, il codice senza di esso. Ed essenzilamente, in virtù del fatto che son sicuro che ci possa essere un'altra strada per poterlo implementare adeguatamente, ho ritenuto opportuno chiedere a voi una maniera elegante di procedere!
Esaminando il modo di operare che mi stai suggerendo,mi dici di effettuare qualcosa che ho già in parte realizzato, infatti, quel pow_fun, non fa altro che effettuare l'elevamento a potenza di 10 per i, che può assumere un valore tra 0 e 1, ed in tal modo, mi da modo di esprimere, mediante la notazione decimale, le prime due cifre della parte intera del numero considerato. |
Premoli |
Inserito il - 23/09/2011 : 16:25:41 Prima di tutto eviterei di usare quel goto che è veramente brutto
Per il resto ragionerei così (se ho capito bene quello che vuoi fare):
prima di tutto devo verificare che con i numeri della matricola riesco effettivamente a generare 6 numeri. Ad esempio metti caso che un utente abbia questa matricola (1 1 1 1 1 1) è evidente che si possono generare solo 2 numeri diversi 1 e 11.
poi all'interno di un ciclo che va da i=0 fino a i<6 (diciamo che sono sei i numeri che voglio generare) prendo a caso una cifra della matricola e la salvo in una variabile quindi faccio in questo modo
per numeri a una cifra: x = matricola[rand() % 6];
per numeri a due cifre: moltiplicherò x per 10 e estrarrò un altro numero della matricola che andrò a sommare a x, in questo modo sono sicuro che anche il numero a due cifre è composto da numeri presenti nella matricola
fatto questo, controllo (con un qualsiasi algoritmo) che non ci sono numeri uguali nel vettore che sto creando se non ci sono ripetizioni vado avanti altrimenti faccio tornare indietro di una posizione l'indice del vettore e sovrascrivo l'ultimo valore...
Questo è quello che mi è venuto in mente ora, probabilmente si può sensibilmente ottimizzare... |
coma |
Inserito il - 23/09/2011 : 15:18:03 Citazione: Messaggio inserito da Premoli
ciao!!!
credo di non aver capito quello che volevi fare... Il programma genera dei numeri che però non dipendono dall'input infatti anche lasciando lo stesso "student_id" i numeri che vengono generati cambiano (tralasciando le volte che il programma va in loop), quindi ora mi chiedo dato che i numeri sono casuali c'era bisogno di fare tutto quello per generarli? non sarebbe stato più immediato fare
for(i=0; i<di quanti numeri vuoi generare ( 6 visto che li vuoi giocare al lotto? ); i++) lotteria[i] = un numero a caso tra 1 e 90...
ma probabilmente non ho capito io cosa volevi fare...
Ciao! Il mio intento purtroppo va oltre la semplice generazione di numeri casuali che verrebbe agevolmente implementata con il codice da te suggerito! Ciò che al contrario vorrei realizzare, è creare 6 numeri casualmente partendo dal numero di matricola e componendo le singole cifre. es 587176 -> STUDENT_ID Possibili sei numeri : 5 - 71 - 87 - 87 - 76 - 65
Probabilmente il tutto va irreversibilmente in loop delle volte, vista la mia difficoltà nel verificare che un determinato numero non venga inserito più volte. Ed inoltre, provando ancora ad eseguirlo ho notato che vengono stampati numeri che non sono assolutamente presi dal numero di matricola iniziale, pertanto vi chiedo cosa potrebbe essere migliorato, perchè essenzialmente il tutto fallisce unicamente perchè è errato e non propriamente corretto l'algoritmo che è alla base.
MOD 2 : Ho apportato una modifica che dovrebbe risolvere perlomeno il problema dei valori coerenti al numero di matricola : http://pastebin.com/hw6n9iFs Ora i problemi restanti sono due fondamentalmente : 1 - qualche loop durante l'esecuzione dei quali non conosco ancora l'origine 2 - ripetizione di alcuni numeri nella sequenza che, dovrebbero non esser presenti visto che effettuo opportuni controlli sui numeri inseriti mediante la funzione check_id, ma seppur vi sia tale controllo, il tutto rimane incorretto. |
Premoli |
Inserito il - 23/09/2011 : 15:04:13 ciao!!!
credo di non aver capito quello che volevi fare... Il programma genera dei numeri che però non dipendono dall'input infatti anche lasciando lo stesso "student_id" i numeri che vengono generati cambiano (tralasciando le volte che il programma va in loop), quindi ora mi chiedo dato che i numeri sono casuali c'era bisogno di fare tutto quello per generarli? non sarebbe stato più immediato fare
for(i=0; i<di quanti numeri vuoi generare ( 6 visto che li vuoi giocare al lotto? ); i++) lotteria[i] = un numero a caso tra 1 e 90...
ma probabilmente non ho capito io cosa volevi fare... |
coma |
Inserito il - 23/09/2011 : 11:29:48 Beh guarda non devi aspettarti chissà quale sorta di funzionamento!! :D Semplicemente, dall'array di partenza, cerco di generare dei valori casuali che mi diano la possibilità di sfruttare le cifre del numero di matricola per poter creare 6 numeri diversi tra loro. Vuoi che sia sincero al 100%? Non appena ho visto il mio numero di matricola mi son detto, quasi quasi mi gioco questi numeri e da lì l'idea di creare un programma che casualmente generasse dei numeri da giocare! :D
|
genius |
Inserito il - 23/09/2011 : 10:28:20 Ti giuro, sto provando a capire cosa fa il programma, ma... potresti spiegarlo a grandi linee? |
|
|