|
You last visited: Today at 22:55
Advertisement
Lottozahlen Gen. C
Discussion on Lottozahlen Gen. C within the C/C++ forum part of the Coders Den category.
01/25/2013, 15:22
|
#1
|
elite*gold: 0
Join Date: Jan 2011
Posts: 362
Received Thanks: 41
|
Lottozahlen Gen. C
Hallo , habe ein kleines Problem .
Habe einen Lottozahlen Generator geschrieben der 6 Zahlen random von 1-49 ausgibt und diese aufsteigen Sortiert. Leider bekomme ich es nicht gebacken das er keine Zahlen doppelt ausgibt und mir fällt leider auch keine idee ein wie ich dies umsetzen könnte.
Für Tipps wäre ich sehr Dankbar.!
Code:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main (void){
int lotto[7];
int i,x;
int a,b,c,zz;
srand(time(NULL));
for(a=0;a<7;a++){
zz=rand()%49+1;
lotto[a]=zz;
}
for(i=0;i<7;i++){
for(c=0;c<7;c++){
if(lotto[i]<lotto[c]){
x=lotto[i];
lotto[i]=lotto[c];
lotto[c]=x;
}
}
}
for(b=0;b<7;b++){
printf("%i ",lotto[b]);
}
system("PAUSE");
return 0;
}
|
|
|
01/25/2013, 15:51
|
#2
|
elite*gold: 0
Join Date: May 2010
Posts: 793
Received Thanks: 268
|
du könntest eine liste mit alle zahlen zwischen 1 und 49 machen, aus der du immer random eine ziehst und diese dann aus der liste entfernst.
hier ist mna ein C# code der das macht hoffe du kannst damit was anfangen(die zahlen werden noch nicht sortiert):
Code:
List<int> numbers = Enumerable.Range(1,49); //(.ToList))
int[] ergebniss = new ergebniss[7];
for(int i = 0; i < 7; i++)
{
int r = rand()%numbers.Count;
ergebniss[i] = numbers[i];
numbers.RemoveAt(r);
}
|
|
|
01/25/2013, 16:05
|
#3
|
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
|
Als Alternative zur schon erwähnten Liste (std::vector in C++?), kann man auch checken, ob sich die generierte Zahl schon im Array befindet und wenn das der Fall ist, dann einfach nochmal eine Zahl generieren bzw. solange eine Zahl generieren, bis eine generierte Zahl noch nicht im Array steht (Do-While-Schleife). Doch gerade bei größeren Arrays könnte es hier zu Problemen bzw. Verzögerungen kommen, da das Array beim checken, ob sich die generierte Zahl schon darin befindet, vollständig durchgegangen werden muss.
Trotzdem hier mal der Code für diese Variante:
Code:
for(a=0;a<7;a++){
do
{
zz=rand()%49+1;
} while (AlreadyInside(lotto, zz, 7)); // solange neue zahlen generieren, bis eine neue dabei ist
lotto[a]=zz;
}
(...)
bool AlreadyInside(int* array, int number, unsigned int arraylength) // prüft ob eine gegebene zahl innerhalb eines arrays ist
{
for (int i = 0; i < arraylength; i++) // das array durchgehen
{
if (array[i] == number) // number ist im array
{
return true;
}
}
return false;
}
(vergib mir etwaige Fehler, ich hab nur im epvp-editor gemacht)
Ich hoffe, ich konnte helfen 
Jeoni
|
|
|
01/25/2013, 16:16
|
#4
|
elite*gold: 0
Join Date: May 2010
Posts: 793
Received Thanks: 268
|
Quote:
Originally Posted by Jeoni
Als Alternative zur schon erwähnten Liste (std::vector in C++?), kann man auch checken, ob sich die generierte Zahl schon im Array befindet und wenn das der Fall ist, dann einfach nochmal eine Zahl generieren bzw. solange eine Zahl generieren, bis eine generierte Zahl noch nicht im Array steht
Jeoni
|
ja das kann man in dem fall machen. Ist aber im allgemeinen keine schöne lösung, da wenn man z.B. 999 zahlen aus 1000 ziehen will (unter beachtung der reihenfolge).
muss man z.B. bei der 999 zahl durchschnittlich 500 mal versuchen muss zu ziehen bevor man die eine der beiden zahlen zieht die noch nicht gezogen ist. Da die zufallsgeneratorn oft nicht ganz so gut sind eher mehr. D.h wie schnell der algoritmus ist hängt sehr stak vom zufall ab.
|
|
|
01/25/2013, 16:44
|
#5
|
elite*gold: 724
Join Date: Mar 2011
Posts: 10,479
Received Thanks: 3,318
|
Ganz primitive Lösung:
Array mit 49 Feldern. Allen Feldern den Wert 0 zuweisen
-> int zahlen[49];
for (int i = 0; i < 49; i++) {
zahlen[i] = 0;
}
Und dann 6x eine random-Zahl auswerfen:
for (int i = 0; i < 6; i++) {
int random = rand() %49; // somit sind die Zahlen von 0 - 48, also unser Array abgedeckt
if (zahlen[random] == 0)
zahlen[random] = random + 1; // der Zahl am n. Index den Wert n + 1 zuweisen (zahlen[9] = 10 z.B.)
else
--i; // wenn die Zahl noch nicht gesetzt wurde, Zahl setzen, ansonsten i um eins reduzieren, damit es noch einen Durchlauf macht.
}
Und jetzt kannst du die Lottozahlen ausgeben lassen & sie sind sortiert:
for (int i = 0; i < 49; i++) {
if (zahlen[i] != 0)
printf("Lottozahl: %d\n", zahlen[i]);
}
Wir mussten so eine Aufgabe für die Vorlesung machen und ich hab es auch über Sortieren und Durchläufe und was weiß ich gelöst, aber die Lösung hier oben stammt von einem Kommilitonen - finde ich ziemlich gut.
|
|
|
01/25/2013, 18:27
|
#6
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Du könntest ein Feld der möglichen Werte erstellen und dann das gezogene Element entfernen, wie nkkk vorschlug. Dabei könntest du das Element entfernen, indem du das Element mit dem gezogenen Index durch das letzte Element der Liste ersetzt und die "Länge" des Feldes dekrementierst. Damit ist das Feld danach zwar nicht mehr sortiert, aber das war ja auch nicht gefordert.
In C könnte das etwa so aussehen:
Code:
const int Länge = 49, Anzahl = 7;
int Feld [Länge];
int Ergebnis [Anzahl];
int gezogen, i = 0, Länge_übrig = Länge;
//das Feld füllen und undefiniertes Verhalten vermeiden
while (i < Länge) {
Feld [i] = i + 1;
++i;
}
//die Zahlen auswählen
for (i = 0; i < Anzahl; ++i) {
gezogen = rand () % Länge_übrig;
Ergebnis [i] = Feld [gezogen];
--Länge_übrig;
Feld [gezogen] = Feld [Länge_übrig];
}
Es wäre auch ganz sinnvoll, nicht Bubblesort zum Sortieren zu nutzen, wenn es mal viele Elemente werden sollten, die sortiert werden sollen.
|
|
|
01/29/2013, 00:55
|
#7
|
elite*gold: 297
Join Date: Dec 2010
Posts: 1,129
Received Thanks: 1,687
|
Hier sind noch einmal zwei vollständige Lottozahlen-Generatoren: Einer in C ("lottery_c") und einer in C++ ("lottery_cpp").
Code:
// cpp-version
#include <iostream>
#include <random>
#include <set>
// c-version
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// cpp-version
void lottery_cpp();
// c-version
void lottery_c();
void quicksort_c(int *data, int count);
int main(int argc, const char *argv[]) {
// Test it!
lottery_cpp();
lottery_c();
return 0;
}
void lottery_cpp() {
// Using-Direktiven
using std::cout; using std::endl;
using std::size_t; using std::set; using std::less;
using std::mt19937; using std::random_device;
using std::uniform_int_distribution;
// Einstellung für 7 aus 49
constexpr size_t lottery_numbers_to_draw = 7;
constexpr size_t lottery_numbers_range_min = 1;
constexpr size_t lottery_numbers_range_max = 49;
// Ein std::set<T> mit der Sortierung std::less<T> und T = std::size_t für
// die Lottozahlen.
set<size_t, less<size_t>> lottery_numbers;
// Ein simpler Zufallsgenerator für Integer-Werte im gewählten Wertebereich
// und ein Lambda-Ausdruck, der einen solchen Wert berechnet.
mt19937 random_generator({ random_device()() });
uniform_int_distribution<> lottery_distribution(lottery_numbers_range_min,
lottery_numbers_range_max);
auto draw_lottery_number = [&random_generator, &lottery_distribution] {
return lottery_distribution(random_generator);
};
// Wir fügen solange zufällige Werte hinzu, bis wir die gewollte Anzahl an
// Werten im std::set lottery_numbers haben. std::set().insert().second ist
// true, wenn der Wert erfolgreich eingefügt wurde.
for (size_t draw_count = 0;
draw_count < lottery_numbers_to_draw;
++draw_count) {
while (!lottery_numbers.insert(draw_lottery_number()).second) {
}
}
// Gibt die Lottozahlen auf der Konsole aus
for (auto n: lottery_numbers) {
cout << n << ' ';
}
cout << endl;
}
void lottery_c() {
// Initialisierung von rand()
srand((unsigned)time(0));
// Array, in dem die Zahlen gespeichert und dann "In-Place" sortiert werden
int lottery_numbers[7];
// Berechnet zufällige Werte zwischen aus [1,49], wenn diese noch nicht in
// lottery_numbers vorhanden sind, werden sie hinzugefügt.
// Am Ende der Schleife ist garantiert, dass lottery_numbers 7 verschiedene
// Elemente enthält.
for (int draw_count = 0; draw_count < 7; ++draw_count) {
bool already_drawn;
int drawn_number;
do {
already_drawn = false;
drawn_number = rand() % 49 + 1;
for (int i = 0; i < 7; ++i) {
if (lottery_numbers[i] == drawn_number) {
already_drawn = true;
break;
}
}
} while (already_drawn == true);
lottery_numbers[draw_count] = drawn_number;
}
// Sortiert die 7 Werte in lottery_numbers aufsteigend mit einem
// "In-Place"-Quicksort Verfahren (Implementation siehe unten)
quicksort_c(lottery_numbers, 7);
// Gibt die Lottozahlen auf der Konsole aus
for (int i = 0; i < 7; ++i) {
printf("%d ", lottery_numbers[i]);
}
printf("\n");
}
// In-Place-Quicksort, rekursiv
// Funktionsweise: http://en.wikipedia.org/wiki/Quicksort
void quicksort_c(int *data, int count) {
if (count < 2) {
return;
}
int pivot = data[count / 2];
int *left = data;
int *right = data + count - 1;
while (left <= right) {
if (*left < pivot) {
left++;
continue;
}
if (*right > pivot) {
right--;
continue;
}
int temp = *left;
*left++ = *right;
*right-- = temp;
}
quicksort_c(data, (int)(right - data + 1));
quicksort_c(left, (int)(data + count - left));
}
Ein möglicher Output wäre:
Code:
21 26 27 36 37 43 46
6 28 32 35 37 42 45
Offensichtlicher Nachteil der C-Variante: Bei größeren Arrays wird es mit Komplexität O(n) langsamer zu überprüfen, ob bereits Werte existieren. Das kann jedoch elegant umgangen werden, wenn man die von snow911 genannte Methode verwendet. Die wird übrigens dann ineffizient, wenn man wenige Elemente aus einer großen Range aussuchen soll. Bestenfalls benutzt man diese also nicht, wenn die Range groß ist, sondern wenn die gesuchte Anzahl an Elementen nicht sehr viel kleiner als die Range ist.
Bei der C++-Variante kann man anstelle des Lambdas auch std::bind benutzen, das mag clang++ aber manchmal nicht (Ist nicht so ganz fehlerfrei im aktuellen Xcode Dev Preview):
Code:
auto draw_lottery_number = std::bind(std::uniform_int_distribution<>{1, 49}, std::mt19937{std::random_device{}()});
Die weitere Optimierung überlässt man dann std::set. Übrigens kann man hier auch anders sortieren, man ist ja nicht an std::less<T> gebunden.
|
|
|
02/09/2013, 00:18
|
#8
|
elite*gold: 0
Join Date: Oct 2011
Posts: 322
Received Thanks: 12
|
hat mir auch weitergeholfen ^^ danke....
|
|
|
02/09/2013, 00:29
|
#9
|
elite*gold: 0
Join Date: Jan 2011
Posts: 362
Received Thanks: 41
|
Habe es so gelöst falls es jemanden interessiert
Code:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main (void){
int lotto[7];
int i,j,x,temp;
int a,b,c,zz;
srand(time(NULL));
for(i=0;i<7;i++){
lotto[i]=rand()%49+1;
for(j=0;j<=i-1;j++){
if(lotto[j]==lotto[i]){
j=i;
i--;
}
}
}
for(i=0;i<7;i++){
for(c=0;c<7;c++){
if(lotto[i]<lotto[c]){
x=lotto[i];
lotto[i]=lotto[c];
lotto[c]=x;
}
}
}
for(b=0;b<7;b++){
printf("Zahl %i = %i\n ",b+1,lotto[b]);
}
system("PAUSE");
return 0;
}
|
|
|
02/09/2013, 01:31
|
#10
|
elite*gold: 0
Join Date: Feb 2013
Posts: 1,137
Received Thanks: 869
|
Sieht beim Überfliegen gut aus, nur lass das system("PAUSE") weg. Das ist Pfui!
|
|
|
02/09/2013, 16:53
|
#11
|
elite*gold: 0
Join Date: Jan 2011
Posts: 362
Received Thanks: 41
|
Quote:
Originally Posted by Schlüsselbein
Sieht beim Überfliegen gut aus, nur lass das system("PAUSE") weg. Das ist Pfui!
|
Nein ist es nicht sonst schließt sich die Konsole bei mir immer direkt nach dem öffnen des pause verhindert dies
|
|
|
02/09/2013, 17:23
|
#12
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
Quote:
Originally Posted by Rullx3
Nein ist es nicht sonst schließt sich die Konsole bei mir immer direkt nach dem öffnen des pause verhindert dies 
|
nope, er meint, dass system("pause"); bzw. allg. system "böse" wäre.
das stimmt zwar zu einem gewissen grad, ist aber vollkommen irrelevant für dieses programm.
|
|
|
02/09/2013, 17:35
|
#13
|
elite*gold: 0
Join Date: Feb 2013
Posts: 1,137
Received Thanks: 869
|
Genauso wie es für viele Programme irrelevant ist, Speicher wieder frei zu geben etc. Von der Relevanz abgesehen ist es vorteilhaft, wenn ein Anfänger auch zu Beginn lernt, sauber zu programmieren. Und dazu gehört m.E. kein system("PAUSE").
Quote:
|
Nein ist es nicht sonst schließt sich die Konsole bei mir immer direkt nach dem öffnen des pause verhindert dies
|
Je nach IDE kannst du die Konsole auch nach Beendigung des Programms offenthalten. Beim Visual Studio gehts mit STRG+F5.
|
|
|
All times are GMT +1. The time now is 22:55.
|
|