[c++] Sempre coi casuali, ce la posso fare..

Messaggioda Giova411 » 28/05/2015, 17:22

Ho sempre problemi a generare numeri causuali fatti COME VOGLIO IO :shock:
In questo caso non mi cambia le permutazioni come vorrei, riga dopo riga.
Il mio desiderio è avere qualcosa del genere:
Codice:
1 :  4 3 1 2
2 :  2 1 3 4
3  : 1 3 4 2
4  : 4 3 1 2

Come si nota non si possono ripetere numeri uguali sulla stessa riga ed il range va da 1 al numero di righe totali 4.
Ovviamente il numero prima dei : è solo il numero di riga indicativo.
Quello che riesco a generare CON LE MIE CAPACITA' CRETINE sarebbe:
Codice:
1 : 4 1 3 2
2 : 4 1 3 2
3 : 4 1 3 2
4 : 4 1 3 2

Come si può notare, non riesco a fare cambiare la scelta casuale per ciascuna riga... Mi sembrava di essermi posto un qualcosa si facile ma non ce la faccio.
Secondo me sbaglio a "pensare" la funzione srand() che produce numeri pseudo-casuali ma non è possibile produrre la casualità naturale... Quindi non mi "azzera" e rigenera tutto come vorrei...
Spero di capire come lavorarci che sono diversi giorni alle prese con questi "algoritmi casuali" :?
Giova411
Advanced Member
Advanced Member
 
Messaggio: 1849 di 2254
Iscritto il: 16/11/2006, 00:34

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda vict85 » 28/05/2015, 18:23

Che compilatore usi? Che funzione? Lo dico perché ieri ho notato che mingw con random non funziona bene e ha un random_device deterministico. Mingw-w64 con GCC 4.9.2 non ha il problema se non ricordo male.
Prova ad usare
Codice:
std::default_random_engine<int> dre{time(0)};
invece che
Codice:
std::default_random_engine<int> dre{rd()};
dove rd è il random device.
Con rand non dovresti avere questo problema.

Comunque se vuoi generare tutte le permutazioni il problema è differente. La libreria standard l'hai guardata? Penso abbia qualcosa per le permutazioni come per fare lo shuffle.

Comunque cerca matters computational su google. C'è un libro che potresti apprezzare. Nota che c'è la versione online legalmente scaricabile, non hai bisogno di comprarlo. Il prezzo della versione stampata è incomprensibilmente alto.
vict85
Moderatore
Moderatore
 
Messaggio: 7846 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda Giova411 » 28/05/2015, 18:30

Vic senza di voi (te ed Apa) non saprei davvero che fare... Grazie davvero prima di tutto! E non mi stancherò mai di scriverlo, dirlo e pensarlo.

Ti posto il codice ma è in continuo cambiamento quindi ti metto qualcosa da cui partire.
Compilo semplicemente con g++ nome.cpp
Che poi è sempre lo stesso che produco senza fare copia incolla..

Codice:
#include <fstream>
#include <time.h>
#include <vector>

using namespace std;

void casualesenzaripet(vector < int >&v, int n){   
  int r;
  bool ripeti = false;
  for (int i = 0; i < n; i++)   
    {
      r = rand () % n + 1;   
      for (int c = 0; c < i; c++)   
   {
     if (v[c] == r)
       {         
         ripeti = true;   
         c = i;      
       }
   }
      if (ripeti == true)
   {
     i = i - 1;            
   }
      else
   {         
     v[i] = r;   
           //cout<<r<<endl;   
   }
      ripeti = false;      
    }
}

int
main (void)
{
 ofstream out ("provetta.txt");
int N = 4;

//forse la funzione srand() è una funzione che produce numeri pseudo-casuali e non è possibile produrre la casualità che vorrei

for (int ii=0; ii<N; ii++){
 out<<ii+1<<" : ";
 for (int jj=0; jj<N; jj++){
   srand (time (NULL));
   vector < int > v (N);
  casualesenzaripet(v,N);
  out<< v[jj] <<" "; 
  }
 out<<endl;
}
 return 0;
}

Ora pensavo di fare una matrice ma mi sto innervosendo non poco :oops:
Ultima modifica di Giova411 il 28/05/2015, 18:37, modificato 1 volta in totale.
Giova411
Advanced Member
Advanced Member
 
Messaggio: 1850 di 2254
Iscritto il: 16/11/2006, 00:34

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda vict85 » 28/05/2015, 18:36

Ora sono con il tablet ma srand dovresti toglierlo metterlo prima del ciclo, basta inizializzare una sola volta.
vict85
Moderatore
Moderatore
 
Messaggio: 7847 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda Giova411 » 28/05/2015, 18:38

Sì l'avevo provato ma poi mi ripete i numeri e non voglio ripetizioni.
Cioé su ogni riga non voglio ripetizioni ma su una riga nuova tutto inizia da zero.
Sembrava una cavolata invece, per me, non lo è. :x
Giova411
Advanced Member
Advanced Member
 
Messaggio: 1851 di 2254
Iscritto il: 16/11/2006, 00:34

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda vict85 » 28/05/2015, 19:34

Per n=4 ci sono n!=4! = 24 permutazioni diverse. In questo caso ti conviene probabilmente generare tutte le permutazioni e poi estrarne 4 con uno shuffle. Se avessi n=100 allora sarebbe molto improbabile trovare due volte la stessa permutazione e quindi ti conviene generarli separatamente (inoltre il numero di permutazioni non starebbe in memoria).
vict85
Moderatore
Moderatore
 
Messaggio: 7848 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda Giova411 » 28/05/2015, 19:42

Anche questo caso ho provato VIC :-D
Codice:
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include <vector>
using namespace std;
 
void scambia (int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}


void frulla ( int arr[], int n )
{
    srand ( time(NULL) );
    for (int i = n-1; i > 0; i--){       
        int j = rand() % (i+1);     
        scambia(&arr[i], &arr[j]);
    }
}

int main(void){
 ofstream out ("provetta2.txt");
 int arr[10];

for(int i=0; i<10; i++)
     arr[i] = i+1;
 int n = sizeof(arr)/ sizeof(arr[0]);
 for(int j=0; j<10; j++){
     frulla (arr, n);
     out<<j+1<<" : ";
    for (int i = 0; i < n; i++)
        out<< arr[i]<<" ";
 out<<endl;   
}
    return 0;
}

Come vedi l'impegno lo metto ma non HO MAI IN MANO QUELLO CHE MI FISSO COME OBIETTIVO!!!!
Anche il codice ultimo postato "potrebbe" andare bene ma non genero casuali riga per riga... E' come imbrogliare così [-(
Giova411
Advanced Member
Advanced Member
 
Messaggio: 1852 di 2254
Iscritto il: 16/11/2006, 00:34

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda apatriarca » 29/05/2015, 11:11

Perché non iniziare con le cose semplici? Genera una riga per volta in modo casuale e confrontala con le precedenti. Se non va bene ne generi una nuova. Per \(n\) basso la probabilità di dover generare una nuova permutazione è alta, ma con il crescere di \(n\) questo evento diventa sempre meno probabile. Per velocizzare i confronti potrebbe essere comodo generarti un qualche tipo di hash dalla permutazione (ma si tratta di una ottimizzazione che potresti considerare più avanti).
apatriarca
Moderatore
Moderatore
 
Messaggio: 3837 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda Giova411 » 29/05/2015, 13:41

Apa forse è il rand che non so usare bene ancora o forse, come dice Vic, c'é qualcosa che non va.
La seconda versione che ho scritto li mescola ma fa pietà....
Con i numeri casuali veramente è sempre un bordello però!
Giova411
Advanced Member
Advanced Member
 
Messaggio: 1853 di 2254
Iscritto il: 16/11/2006, 00:34

Re: [c++] Sempre coi casuali, ce la posso fare..

Messaggioda apatriarca » 29/05/2015, 13:57

Il problema continua ad essere srand. Va chiamato solo quando necessario. E se viene inizializzato con time va chiamato con almeno un secondo di differenza tra le diverse chiamate. Chiamare due volte srand con lo stesso valore porta a generare esattamente la stessa sequenza. L'unico vero elemento casuale di un generatore pseudocasuale è il seed (quello che setti con srand). Il resto è un metodo deterministico con particolari proprietà statistiche.
apatriarca
Moderatore
Moderatore
 
Messaggio: 3838 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Prossimo

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite