rand()

Tråden skapades och har fått 16 svar. Det senaste inlägget skrevs .
1
  • Medlem
  • Sundsvall
  • 2007-01-08 20:15

Hej på er!

Det är så att jag har en uppgift som är att skriva ett program som slumpar fram 11 tal i en rad, dessa tal får då inte förekomma mer än en gång i samma rad.
Jag har gjort så att de 11 talen slumpas fram, men jag vet inte hur jag ska göra så att talen inte upprepas i samma rad och hur kan jag med en while sats eller annat skriva ut så många rader som användaren vill.
Vet någon hur jag ska gå tillväga?

#include <iostream>
using namespace std;
#include <cstdlib>
#include<iomanip>

int main () {

unsigned rader;
cout<<"Skriv in hur många lottorader du vill skriva ut"<<endl;
cin>>rader;
srand(rader);

for(int i =1; i<=11; i++)
{
      int slump_nr= 1 + rand()% 35;
      cout<<setw(5)<<slump_nr;

         if(i%11==0)
            cout<<endl;

}

       return 0;
}
  • Medlem
  • Sundsvall
  • 2007-01-08 20:39

Ok, nu har jag användt en while-slinga som upprepas lika många gånger som användaren väljer. Däremot är dublettproblemet kvar, misstänker att man fixar det med en array som måste jämföras med varje gång ett tal slumpas fram så att inte samma tal dyker upp i samma rad. men vet inte hur jag ska skriva det....

  • Medlem
  • Simrishamn
  • 2007-01-08 20:43

Jag kan inte C++ eller något av dess bibliotek, men finns det inte någon inbyggd Array-klass är mutable? (d.v.s. går att lägga till och ta bort objekt ifrån)
Isf kan du lägga till varje tal som slumpas fram där, och om ett annat tal överensstämmer med ett som ligger i den arrayen, slumpar du fram ett annat tal.

  • Medlem
  • Sundsvall
  • 2007-01-08 21:04

Jag vet inte...

  • Medlem
  • Sollentuna
  • 2007-01-08 21:44

// Bonusövning är att sortera resultatet

#include <iostream>
#include <cstdlib>
#include <iomanip>

using namespace std;

#define NO_OF_NUMBERS 11

int isunique(int *number_sequence, int numbers_previously_assigned, int test)
{
for (int i=0; i<numbers_previously_assigned; i++)
{
if (number_sequence[i] == test)
return 0;
}

return 1;
}

int main (int argc, char * const argv[])
{
// Initialize random generator
struct timeval t;
gettimeofday(&t, NULL);
srandom(t.tv_sec);

unsigned rader;
cout<<"Skriv in hur många lottorader du vill skriva ut"<<endl;
cin>>rader;

for(int rad=1; rad<=rader; rad++)
{
int current_lotto_sequence[NO_OF_NUMBERS];
int i, current_lotto_number = 0;

// Reset sequence
for (i=0; i<NO_OF_NUMBERS; i++) current_lotto_sequence[i] = -1;

do
{
int slump_nr= 1 + random()% 35;
if (isunique(current_lotto_sequence, current_lotto_number, slump_nr))
current_lotto_sequence[current_lotto_number++] = slump_nr;
} while (current_lotto_number < NO_OF_NUMBERS);

for (i=0; i<NO_OF_NUMBERS; i++)
cout<<setw(5)<<current_lotto_sequence[i];

cout<<endl;

}

return 0;
}

  • Medlem
  • Sundsvall
  • 2007-01-08 22:08

Oj! Tack Ulfis för du har ansträngt dig så.
Jag måste säga att detta är överkurs för mig med de metoder du använder, vi har inte lärt oss om något sånt under kursen så det ska gå att lösa på ett enklare sätt..är rädd att jag inte förstår dem..

  • Medlem
  • Sollentuna
  • 2007-01-08 22:15

Ok, låt oss reda ut vad som är komplicerat?

Tror inte det går att skriva 'enklare' mer än att undvika funktionsanropet. Det blir då inte enklare, snarare geggigare.

Man måste kolla bland föregående värden (i array:en current_lotto_sequence) om samma värde redan genererats.

  • Medlem
  • Sundsvall
  • 2007-01-08 22:25

#define NO_OF_NUMBERS 11 ?
current_lotto_sequence[i] = -1; ?
struct timeval t; ?
gettimeofday(&t, NULL); ?
srandom(t.tv_sec); ?

och vad händer här?
if (isunique(current_lotto_sequence, current_lotto_number, slump_nr))
current_lotto_sequence[current_lotto_number++] = slump_nr;
} while (current_lotto_number < NO_OF_NUMBERS);

  • Medlem
  • Sollentuna
  • 2007-01-08 22:37

#define NO_OF_NUMBERS 11

Istället för att ha konstanten '11' inskrivet på fler ställen kan man ändra på raden ovan om man t.ex vill generera sju nummer, lämpligt för Lotto. När filen "preprocessas" av kompilatorn byts 'NO_OF_NUMBERS' ut mot '11'.

current_lotto_sequence[i] = -1;

För att hålla koll på vilka nummer i vektorn som tilldelats ett slumpvärde (>0), initierar vi vektorn med -1 som indikerar att detta index inte är tilldelat. Men eftersom jag har en variablel som håller koll på vilket nuvarande index är [current_lotto_number], så kan man ta bort den raden.

struct timeval t;
gettimeofday(&t, NULL);
srandom(t.tv_sec);

Slumptalsgeneratorn skall initieras, men hellre än att ta initieringsvärdet från antal rader (som ditt första kodförslag), så tar man och hämtar ut antal sekunder från midnatt och skickar det som initieringsvärde. Det ger en bättre spridning på de tal som genereras. Osannolikt att du skulle köra samma sekvens i morgon på samma sekund.

Hade tagit initieringsvärdet från antalet rader och Du som exempel genererat 10 st rader två gånger efter varanda så hade ju samma sekvens skapats i bägge fallen. Detta är såklart inte önskvärt.

  • Medlem
  • Sundsvall
  • 2007-01-08 23:04

Så jag kan skriva const int STORLEK=11; istället för #define NO_OF_NUMBERS 11 ?

Hur vet du vad värdet för dessa tre variablerna är?
int isunique(int *number_sequence, int numbers_previously_assigned, int test)
{

När retuneras noll?

return 0;
}

När retuneras ett?
return 1;
}

  • Medlem
  • Sollentuna
  • 2007-01-08 23:24

> Så jag kan skriva const int STORLEK=11; istället för #define NO_OF_NUMBERS 11 ?

Japp. Om Du då byter ut preprocessor-variablen 'NO_OF_NUMBERS' mot C-konstanten 'STORLEK' överallt.

> Hur vet du vad värdet för dessa tre variablerna är?

'variablerna' är parametrar till en funktion. Se anropet längre ned:
isunique(current_lotto_sequence, current_lotto_number, slump_nr)

parametrarnas värde blir de man skickar in vid anropet. Så om current_lotto_number är 2 och slump_nr är 17, blir det värdena 2 resp 17 på motsvarande parameters plats i funktionen. Första parameter är en pekare till array:en med heltal, dvs våra lottonummer.

> När retuneras noll?

När villkoret som Du klippte bort är uppfyllt, dvs när något tal i array:en mathcar det vi testar mot. Vi returnerar 0 som indikerar att talet redan finns och således inte är unikt. Vi fortsätter INTE slingan/loopen.

> När retuneras ett?

I samtliga andra fall. Dvs hittar vi inget matchande tal i vår array kommer vi att slutföra slingan 'for (int i=0; i<numbers_previously_assigned; i++)'. Väl ute ur den returnerar vi 1 som då indikerar att vårt tal (i parametern test) inte finns i array:en number_sequence. Vårt tal är således unikt.

  • Medlem
  • Stockholm
  • 2007-01-08 23:36

Jag hade skapat en array (eller vektor som en del kallar det) där jag sedan matar in talen (0-10;eller vilka det nu ska vara).

Sedan så hade jag, genom en for loop, 100 ggr iterativt, genererat två slumptal mellan 0 och 10. Dessa värden hade jag senare använd mig av, ihop med en variabel, för att flytta runt värderna i arrayen.

ex.

int array = {0,1,2,3,4,5,6,7,8,9,10};// array med de tal man vill ha.
int x,y,z; // variabler som pekar och container,

for (int i=0; i<100;i++) {
y=makeRandomInt();//y får ett tal mellan 0 och 10.
z=makeRandomInt();//z får ett tal mellan 0 och 10.
x=array[y]; //container x får talet vid y i array
array[y]=array[z]; // talet vid array som pekar på z. Ger array som pekar på y talet.
array[z]=x;// array vid z får talet x
}

Då flyttas värderna runt slumpmässig i en array och värderna är de som du bestämt får vara med.

Lycka till Cypher!

ps. glöm inte att skiva ut alla värden i array:en på skärmen.
ds.

Ursprungligen av Banaz:

Hej på er!

Det är så att jag har en uppgift som är att skriva ett program som slumpar fram 11 tal i en rad, dessa tal får då inte förekomma mer än en gång i samma rad.
Jag har gjort så att de 11 talen slumpas fram, men jag vet inte hur jag ska göra så att talen inte upprepas i samma rad och hur kan jag med en while sats eller annat skriva ut så många rader som användaren vill.
Vet någon hur jag ska gå tillväga?

Senast redigerat 2007-01-08 23:52
  • Medlem
  • Härnösand
  • 2007-01-09 01:45

Eller denna lösning.

Citat:

#include <iostream>
#include <cstdlib>
#include <ctime> // Denna för att kunna nollställa slumpen

using namespace std;

// Funktionsprototyper
int SlumpaNummer (void);
int KollaNummer (int tal[],int siffra);

int main (int argc, char * const argv[])
{
int tal [11], rad, antal;
char svar = 'n';
do
{
rad = 1;
srand(time(NULL)); //Förhindra samma resultat varje körning.
cout << "Detta program skriver ut lottorader!\n"
<< "Ange antalet rader som skall produceras"
<< " (max 10): ";
cin >> antal;

// Antal ska vara mellan 1 och 10, annars mata in antal igen
while (antal < 1 || antal > 10)
{
cout << "Antalet rader måste vara mellan 1-10\n"
<< "\nAnge antalet lotto rader: ";
cin >> antal;
}
cout << "Rad\t\tSiffror\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tTilläggsnummer\n";
// Formatering så att det ser hyffsat ut på skärmen

while (antal > 0) // så länge antal är mer än 0
{
int siffra = 0;
int flagga = 1; // sätt en flagga till 1

cout << rad; // skriv ut vilken rad

while (siffra < 11) // så länge det är pos
{
while (flagga)
{
tal[siffra] = SlumpaNummer() ;

if (siffra == 0) break;
flagga = (KollaNummer (tal, siffra));
}

if (siffra == 7) cout << "\t....";
cout << "\t\t" << tal[siffra];

flagga = 1;
siffra++ ;
}
rad++;
antal--;
cout << endl;
}

cout << "Prova igen? (y,Y,j,J)";

cin >> svar;

}while ((svar =='y') || (svar =='Y') || (svar == 'j') || (svar == 'J'));

return 0;

}

int SlumpaNummer (void)
{
int nummer;

do
{
nummer = (rand () % 100);

}while (nummer > 35 || nummer < 1);

return nummer;
}

int KollaNummer (int tal[],int siffra)
{
int koll;

for (koll = siffra - 1; koll >= 0; koll--)
{
if (tal[siffra] == tal[koll]) return 1 ;
}

return 0;
}

eller

Citat:

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int KollaRad(int piArray[11],int iMax);
void SlumpaRad(int piArray[11]);
void SkrivUtLottoRad(int piArray[11]);

int main(int argc, char * const argv[])
{
int piLottoRad[11];

srand(time(NULL));
SlumpaRad(piLottoRad);
SkrivUtLottoRad(piLottoRad);
return 0;
}

int KollaRad(int piArray[11],int iMax)
{
int j;

for(j = iMax - 1; j >= 0; j--) // kolla alla nummer under iMax
{
if(piArray[j] == piArray[iMax]) return 0;
}
return 1;
}

void SlumpaRad(int piArray[11])
{
int i, j = 1;

for(i = 0; i < 11; i++)
{
do
{
do // slumpa så länge j är 0
{
j = (int) rand() % 36;
} while ((j == 0));
piArray[i] = j; // Slumpa om tills unikt nummer
} while (!KollaRad(piArray, i));
}
}

void SkrivUtLottoRad(int piArray[11])
{
int i;

cout << "Ordinare nummer: ";
for(i = 0; i < 7; i++) cout << piArray[i] << ", ";

cout << "\nTillaeggsnummer: ";

for(i = 7; i < 11; i++) cout << piArray[i] << ", ";

cout << endl;
}

-EDIT-

Det saknas verkligen en CODE-tag

  • Medlem
  • Sollentuna
  • 2007-01-09 11:14

// Eller varför inte ännu kortare:

#include <iostream>
#include <cstdlib>
#include <iomanip>

using namespace std;

#define NUMBER_LIMIT 36

int main (int argc, char * const argv[])
{
// Initialize random generator
struct timeval t;
gettimeofday(&t, NULL);
srandom(t.tv_sec);

unsigned rader;
cout<<"Skriv in hur många lottorader du vill skriva ut"<<endl;
cin>>rader;

for(int rad=1; rad<=rader; rad++)
{
int current_lotto_sequence[NUMBER_LIMIT];
int i, swap1, swap2;

// Reset sequence
for (i=0; i<NUMBER_LIMIT; i++) current_lotto_sequence[i] = i+1;

do
{
swap1 = random()% 35;
do swap2 = random()% 35; while (swap2 == swap1);

int tmp = current_lotto_sequence[swap1];
current_lotto_sequence[swap1] = current_lotto_sequence[swap2];
current_lotto_sequence[swap2] = tmp;

i++;
} while (i<10000);

for (i=0; i<11; i++)
cout<<setw(5)<<current_lotto_sequence[i];

cout<<endl;

}

return 0;
}

  • Medlem
  • Sundsvall
  • 2007-01-09 14:16

Ulfis, skönt med mindre kod :), men vill du vara snäll och förklara dessa punkter så är jag jättetacksam.

1. Dessa tre raderna vill jag att du förklarar mera för mig
struct timeval t; //är detta en deklaration?
gettimeofday(&t, NULL); //så den är en funktion som har referensen t som parameter? srandom(t.tv_sec); //om t kommer från ovan, var kommer tv_sec ifrån, eller är det en
fördefinerad funktion?

2. int current_lotto_sequence[NUMBER_LIMIT]; // så du skapar en vektor av längden 36,
alltså alla talen mellan 0 och 36 ska ligga i den här vektorn? Varför måste de 36 talen
ligga i en vektor, räcker det inte att man sparar de slumpade talen i en vektor?

3. for (i=0; i<NUMBER_LIMIT; i++) current_lotto_sequence[i] = i+1; //här fyller du alltså
arrayen med talen 0 till 35?

4. swap1 = random()% 35; do swap2 = random()% 35; //så du slumpar fram två tal och
kollar om de är lika så byter du plats på dem, men hur vet du vad start värdet är när
du har skrivit max värdet till 35?
5. i++; // vilket är det du ökar värdet på, och vad har det för värde?
6. while (i<10000); //Varför 10000?

  • Medlem
  • Sollentuna
  • 2007-01-09 14:39

> struct timeval t; //är detta en deklaration?

Japp.

> gettimeofday(&t, NULL); //så den är en funktion som har referensen t
> som parameter?

Japp.

> srandom(t.tv_sec); //om t kommer från ovan, var kommer tv_sec ifrån,
> eller är det en fördefinerad funktion?

en struct kan Du se på som en låda med innehåll. tv_sec är en heltalsvariabel i lådan. Skälet att man använder struct's är att man håller samman relaterade data. I detta fall håller struct:en timeval antal sekunder och mikrosekunder för anropet gettimeofday().

> 2. int current_lotto_sequence[NUMBER_LIMIT]; // så du skapar en vektor av
> längden 36, alltså alla talen mellan 0 och 36 ska ligga i den här vektorn?

Nästan. De skall rymma talen 1-36 och för detta använder vi indexen [0-35].
Mina två kodexempel visar på olika algoritmer att lösa problemet. Det ena lagrar de slumpade talen efter hand som de genereras. Det andra exemplet genererar alla möjliga tal och slumpar fram vilka vi skall välja. Olika approach på samma problem.
Man skulle kunna förklara uppbyggnaden och logiken i ord:

Lösning 1) Generera 11 st olika slumptal mellan 1 och 36. Generera ett nummer i taget tills att man fått ett ej redan tidigare genererat nummer.

Lösning 2) Lägg talen 1-36 i en sorterad array (jämför en burk med 36 nummer på bollar). Byt plats på två värden (bollar) med varandra (= skaka burken) godtyckligt antal gånger (t.ex 10000). Tag de 11 första numren (bollarna).

> 3. for (i=0; i<NUMBER_LIMIT; i++) current_lotto_sequence[i] = i+1; //här fyller
> du alltså arrayen med talen 0 till 35?

Nix, 1-36. Notera i stegar från 0-35, vilket ger i+1 = [1-36].

> 4. swap1 = random()% 35; do swap2 = random()% 35; //så du slumpar fram
> två tal och kollar om de är lika så byter du plats på dem, men hur vet du vad
> start värdet är när du har skrivit max värdet till 35?

Nej, jag slumpar fram ett index i vektorn (swap1) som skall ligga mellan 0-35. Därefter slumpar jag fram det andra indexet (swap2) att byta plats med, och gör det dessutom så länge som jag av någon händelse genererat samma tal igen (swap1 == swap2). Det fyller ju ingen funktion att plats 4 i vektorn byter innehåll med plats 4?

> 5. i++; // vilket är det du ökar värdet på, och vad har det för värde?

När man kommit ut ut loopen "for (i=0; i<NUMBER_LIMIT; i++) ..." så är i = NUMBER_LIMIT. Jag sparar detta värde på variabeln i och använder värdet i loopen nedanför.

> 6. while (i<10000); //Varför 10000?

Varför inte? Skulle kunna lägga ett slumpvärde där också. Gränsen går vid hur många gånger man skall byta plats på värdena i array:en, dvs "bollarna"... Så i vårt fall startar vi på 36 och går till 10000, dvs vi skakar burken 9964 ggr. Tillräckligt? Det avgör Du!

  • Medlem
  • Sundsvall
  • 2007-01-09 19:01

Vilken tålamod du har med mig Ulfis, tack så hjärtligt! Undrar jag mer så skriver jag igen

Tack alla ni andra som har också hjälpt mig, det uppskattar jag verkligen.

Kram på er,

1
Bevaka tråden