Benötige Hilfe! Zufallszahlen eingrenzen (Lotto)
-
Was soll ein Zahlenpaar sein?
#include <iostream> #include <time.h> int _tmain(int argc, _TCHAR* argv[]) { unsigned int zufallszahlen[6]; bool eindeutig = false; bool valid = false; unsigned int anzKlein = 0; unsigned int anzGerade = 0; unsigned int summe = 0; srand((unsigned)time(NULL)); while (!valid) { anzKlein = 0; anzGerade = 0; summe = 0; for (int i = 0; i<6; i++) { while (!eindeutig) { int zufallszahl = rand()%49+1; zufallszahlen[i] = zufallszahl; eindeutig = true; for (int j = 0; j<i; j++) { if (zufallszahl == zufallszahlen[j]) eindeutig = false; } } eindeutig = false; } for (int i = 0; i<6; i++) { if (zufallszahlen[i] <25) anzKlein++; if (zufallszahlen[i] %2 == 0) anzGerade++; summe += zufallszahlen[i]; } if ((anzKlein == 2) && (anzGerade == 2)) valid = true; } for (int i = 0; i<6; i++) std::cout << zufallszahlen[i] << " "; getchar(); return 0; }Das kommentieren kannst du ja als Verständnisübung selber machen ^^
-
Für Zufallszahlen aus einer kleinen Menge ginge das hier. Es wird eine Menge aller möglichen Zufallszahlen erzeugt und gemischt. Anschliessend kann per next() die erste Zahl aus der Menge gelesen werden, die dann aus der Menge entfernt wird. Damit ist es unmöglich, Duplikate zu bekommen, da alle gezogenenen Zahlen aus der Menge der verbleibenden Kandiaten entfernt werden.
#include <cassert> #include <vector> #include <iostream> #include <algorithm> class RangeRNG { std::vector<unsigned int> Numbers_; public: RangeRNG( unsigned int Min, unsigned int Max ) { First = std::min( Min, Max ); Last = std::max( Min, Max ); Numbers_.reserve( Last - First +1 ); while( First <= Last ) Numbers_.push_back( First++ ); std::random_shuffle( Numbers_.begin(), Numbers.end() ); } bool empty() const { return Numbers_.empty(); } unsigned int next() { assert( !empty() ); // aus Performancegründen werden Zahlen von hinten aus // dem Vektor entfernt... auch wenn´s nur Spielerei ist unsigned int n = Numbers_.back(); Numbers_.erase( Numbers_.end() -1 ); return n; } }; int main() { RangeRNG Lottoziehung( 1,49 ); for( unsigned int i = 0; i < 6; ++i ) { std::cout << "Zahl " << i << ": " << Lottoziehung.next() << std::endl; } }Edit: Anfangsposting nur halb gelesen und für das typische Anfänger-Lottozahlen-Problem gehalten und dazu eine Lösung gebastelt...
-
dann erklähr mir doch bitte mal warum das bullshit ist!?
es funktionier doch so!
ich habe jetzt auch meine erste anforderung gelöst mit ner do-while schleife.
aber wenn er keine zahlen mit der summe zwischen 142-156 findet, dauert jede neue berechnung der zahlen immer länger.
was kann ich machen um den zwichenspeicher zu löschen, das er quasi wieder ganz von forne anfängt?
-
uuuups nicht aktuallisiert!
ein zahlen paar = zwei auf einander folgende zahlen z.b. 35, 36
-
#include "stdafx.h" #include <iostream> #include <time.h> #include <string> int _tmain(int argc, _TCHAR* argv[]) { unsigned int zufallszahlen[6]; bool eindeutig = false; bool valid = false; unsigned int anzKlein = 0; unsigned int anzGerade = 0; unsigned int summe = 0; srand((unsigned)time(NULL)); while (!valid) { for (int i = 0; i<6; i++) { while (!eindeutig) { int zufallszahl = rand()%49+1; zufallszahlen[i] = zufallszahl; eindeutig = true; for (int j = 0; j<i; j++) { if (zufallszahl == zufallszahlen[j]) eindeutig = false; } } eindeutig = false; } // sortieren for (int i = 0; i<6-1; i++) { for (int j = i+1; j<6; j++) { if (zufallszahlen[i] > zufallszahlen[j]) { int temp = zufallszahlen[i]; zufallszahlen[i] = zufallszahlen[j]; zufallszahlen[j] = temp; } } } anzKlein = 0; anzGerade = 0; summe = 0; // Kleine zählen for (int i = 0; i<6; i++) if (zufallszahlen[i] <25) anzKlein++; // Gerade zählen if (anzKlein == 2) { for (int i = 0; i<6; i++) if (zufallszahlen[i] %2 == 0) anzGerade++; // Summe berechnen if (anzGerade == 2) { for (int i = 0; i < 6; i++) summe += zufallszahlen[i]; // Nach Pärchen prüfen if (summe >=142 && summe <= 156) for (int i = 0; i<6-1; i++) if (zufallszahlen[i]+1 == zufallszahlen[i+1]) valid = true; } } } for (int i = 0; i<6; i++) std::cout << zufallszahlen[i] << " "; getchar(); return 0; }
-
keyzer777 schrieb:
dann erklähr mir doch bitte mal warum das bullshit ist!?
es funktionier doch so!Nö, tuts nicht, du erkennst es bloß nicht. Wenn du zu faul bist zu googlen und ein wenig selbst nachzudenken, probier doch mal sowas:
while(true) { srand(time(NULL)); int i = rand(); cout << i << "\n"; }
-
Mit welcher IDE arbeitest du? Unter Code-Blocks wurden mehrere Fehler ausgegeben.
Unter Einbindung dieser Bibliotheken geht es:#include <iostream> #include <cstdio> #include <cstdlib> #include <time.h>
-
hi matze-o
bei deinem programm blicke ich so einigermasen durch leider funzt es nicht.`_TCHAR has not been declared
auch mit #include "stdafx.h"
kann ich nichts anfangen
grüße
ach noch ne frage kanns auch daran liegen das ich nur den dev-C++ nutze?
-
keyzer777 schrieb:
hi matze-o
bei deinem programm blicke ich so einigermasen durch leider funzt es nicht.Doch es funktioniert, musst nur die includes ändern:
#include <iostream> #include <cstdio> #include <cstdlib> #include <time.h>Und lad dir anstatt devc++ lieber Code::Blocks, das wir noch weiterentwickelt!
-
volkard schrieb:
brotbernd schrieb:
class SupaDupaDistribution { public: SupaDupaDistribution() : ..., dist(0,49), ... {} unsigned int operator()() { unsigned int n = dist(eng); if (good(n)) return n; else nochmal //(bzw while nicht good) } private: size_t count, odd, sum usw... std::mt19937 eng; // o.a. std::uniform_int<unsigned int> dist; };Was soll das denn?
Das ist ne Mischung aus C++ und Pseudocode

Ziehe ne Zufallszahl so lange sie bestimmte Bedingungen erfüllt. Ich dachte das könne man vielleicht daraus ablesen.
-
ja das hab ich auch nich kapiert was da steht...
sack und asche wenn ich bei einer do-while-schleife eine UND bedingung festlegen will könnte das doch so aussehen?
do
{
blablabla
}
while ( summe >= 142 && summe <= 156);er soll nur weiter machen im programm, wenn die zahl aus bla bla zwischen 142 und 156 liegt!
das macht er irgendwie nicht er beachte irgendwie nur die erste regel.und kann ich dann noch mehrere bedingungen in die gleiche klammer einbauen? wieviele?
-
keyzer777 schrieb:
er soll nur weiter machen im programm, wenn die zahl aus bla bla zwischen 142 und 156 liegt!
das macht er irgendwie nicht er beachte irgendwie nur die erste regel.Das ist aber richtig, so wie es da steht. Du hast vermutlich noch einen anderen Fehler im Programmablauf.
und kann ich dann noch mehrere bedingungen in die gleiche klammer einbauen? wieviele?
So viele wie du willst. Achte bei komplizierten logischen Ausdrücken aber auf die Rangfolge der Operatoren und setz gegebenenfalls Klammern.
-
keyzer777 schrieb:
do
{
blablabla
}
while ( summe >= 142 && summe <= 156);er soll nur weiter machen im programm, wenn die zahl aus bla bla zwischen 142 und 156 liegt!
Da steht aber: tue blablabla solange summe zwischen 142 und 156 und nicht höre auf wenn ...
Wenn der Ausdruck in while() wahr ist, wird die Schleife wiederholt.
-
brotbernd schrieb:
Da steht aber: tue blablabla solange summe zwischen 142 und 156 und nicht höre auf wenn ...
Wenn der Ausdruck in while() wahr ist, wird die Schleife wiederholt.Ach so war das gemeint mit dem "weitermachen". Ich hatte gedacht "mach weiter mit der Schleife" wäre gemeint. war schon total verwirrt, wie man bei der Konstruktion etwas falsch machen kann.
@keyzer777: Ein paar Vokabeln Englisch helfen solche Fehler in Zukunft zu vermeiden.
-
SeppJ schrieb:
@keyzer777: Ein paar Vokabeln Englisch helfen solche Fehler in Zukunft zu vermeiden.
Vielleicht mit REPEAT UNTIL verwechselt..

-
Müsste nicht das hier auch gehen (Nur auf die schnelle hingeklatscht):
bool weiter = false; int summe; int i = 0; // Durchgänge while(!weiter && i < 6) { // Berechnungen rein usw. if(summe >= 142 && summe <= 156) { weiter = true; } }
-
schrieb:Müsste nicht das hier auch gehen (Nur auf die schnelle hingeklatscht):
Ja, aber wieso sollte man so etwas tun?

-
schrieb:Müsste nicht das hier auch gehen (Nur auf die schnelle hingeklatscht):
bool weiter = false; int summe; int i = 0; // Durchgänge while(!weiter && i < 6) { // Berechnungen rein usw. if(summe >= 142 && summe <= 156) { weiter = true; } }.........!!
-
keyzer777 schrieb:
Da ich leider schon länger nicht mehr mit C++ gearbeitet hat komme ich zur Zeit da nicht weiter und hoffe das mir hier vielleicht jemand etwas unter die Arme greifen kann.
Hallo keyzer,
unabhängig davon, ob Du mit C++ oder einer anderen Sprache arbeitest, sollte man sich vorher überlegen, wie man sein Problem in kleine handliche Teile zerlegen kann. In Deinem Fall gibt es eine Menge verschiedener Möglichkeiten - eine naheliegende, die hier auch schon angewendet wurde, ist:
1.) 6 verschiedene Zahlen aus 1 bis 49 bestimmen
2.) prüfen, ob diese die gewünschten Eigenschaften haben
3.) wenn nein, dann bei 1.) weitermachen
4.) Zahlen ausgebenAllein für den Teil 1.) ist hier im Forum schon einiges gesagt worden, suche einfach mal nach dem Stichwort 'Lotto'. Um 6 paarweise verschieden(!) Zahlen aus 1 bis 49 zu bestimmen gibt es im wesentlichen zwei Möglichkeiten:
1a) bestimme eine Zahl zwischen 1 bis 49
1b) falls sie noch nicht im Ergebnis vorkommt, füge sie hinzu
1c) falls noch keine 6 Zahlen beisammen sind, mache bei 1a) weiteroder
1a) generiere eine Menge von Zahlen von 1 bis 49
1b) mache 6 mal:
1c) wähle zufällig eine Zahl aus der Menge aus und lösche sie dort und füge sie dem Ergebnis hinzuDie erste Variante ist vielleicht einfacher zu codieren, aber hat u.a. den Nachteil, dass sie länger dauert, wenn eine Zahl ausgewählt wird, aber nur noch wenige zur Auswahl stehen. Bei 6 aus 49 ist das noch kein Problem, aber da Du weitere Bedingungen eingeführt hast, die die Auswahl irgendwann einschränken, würde ich hier die zweite Variante wählen.
Dazu baue ich zunächst eine Klasse, die den Pott von 49 Kugeln (jede Kugel mit einer Zahl drauf) modelliert. Dort kann man zufällig Zahlen entnehmen.
#include <cstdlib> // rand, srand #include <iostream> #include <ctime> // time() #include <vector> class _49 { public: _49() : m_kugeln() { // hier wird 'm_kugeln' mit den Werten von 1 bis 49 gefüllt for( int kugel = 1; kugel <= 49; ++kugel ) m_kugeln.push_back( kugel ); } // -- liefert zufällig eine der noch enthaltenen Kugeln und entfernt sie aus der Menge int zieheEineKugel() { init(); using namespace std; const vector< int >::iterator zufaelligerIndex = m_kugeln.begin() + int( (rand() / (RAND_MAX+1.0)) * m_kugeln.size() ); const int gezogeneKugeln = *zufaelligerIndex; m_kugeln.erase( zufaelligerIndex ); return gezogeneKugeln; } private: static void init() { if( !m_initialized ) { using namespace std; srand( static_cast< unsigned int >( time(0) ) ); m_initialized = true; } } static bool m_initialized; std::vector< int > m_kugeln; }; bool _49::m_initialized = false; int main() { using namespace std; _49 kugeln; for( int i = 0; i < 6; ++i ) cout << kugeln.zieheEineKugel() << endl; return 0; }im main() ist ein einfaches Beispiel, wie diese Klasse zu benutzen ist. Also einfach ein Objekt mit diesem Typ anlegen - hier 'kugeln' und dann immer eine ziehen. Es ist garantiert, dass Du nie zwei Kugeln mit dem gleichem Wert ziehst.
Jetzt gehe ich einen kleinen Schritt weiter und betrachte die Ziehung der 6 Kugeln als Einheit. Ziel ist es, eine Ziehung vom einem Algorithmus generieren zu lassen
#include <algorithm> // copy #include <cstdlib> // rand, srand #include <ctime> // time() #include <iostream> #include <iterator> // ostream_iterator #include <set> #include <vector> class _49 ... // wie oben // -- liefert 6 'Kugeln' aus 1 bis 49 std::set< int > ziehung_6_aus_49() { _49 kugeln; std::set< int > ergebnis; for( int i=0; i<6; ++i ) ergebnis.insert( kugeln.zieheEineKugel() ); return ergebnis; } int main() { using namespace std; set< int > gezogenenKugeln = ziehung_6_aus_49(); // -- Ergebnis der Ziehung ausgeben copy( gezogenenKugeln.begin(), gezogenenKugeln.end(), ostream_iterator< int >( cout, " " ) ); cout << endl; return 0; }damit wäre der oben erwähnte Teil 1 erledigt; und Teil 4 bei der Gelegenheit auch - sonst sieht man ja nicht, ob Teil 1 erfolgreich war

Jetzt zu "2.) prüfen, ob diese die gewünschten Eigenschaften haben".
Hier kann man massiv Algorithmen aus dem C++-Standard einsetzen. Zusammen mit dem Funktoren aus <functional>. Ich unterstelle mal, dass Du damit nicht vertraut bist, aber ich versuch' es trotzdem mal - wir sind ja hier schließlich im C++-Forum und das ist alles Standard!#include <algorithm> // copy #include <cassert> #include <cmath> // abs #include <cstdlib> // rand, srand #include <ctime> // time() #include <functional> // bind*, less, usw. #include <iostream> #include <iterator> // ostream_iterator #include <numeric> // accumulate #include <set> #include <vector> class _49 ... // wie oben // -- liefert 6 'Kugeln' aus 1 bis 49 std::set< int > ziehung_6_aus_49() .. // wie oben struct istPaerchen : std::binary_function< int, int, bool > { // liefert true, falls a und b ein Pärchen sind result_type operator()( first_argument_type a, first_argument_type b ) const { return std::abs( a - b ) == 1; } }; // -- liefert 'true', falls die Menge der gezogenen Kugeln im Intervall [first,last) // die Anforderungen erfüllt template< typename T > bool passt( T first, T last ) { using namespace std; assert( distance( first, last ) == 6 ); const int summe = accumulate( first, last, 0 ); return summe >= 142 && summe <= 156 // 142 <= summe <= 256 && count_if( first, last, bind2nd( less< int >(), 25 ) ) == 2 // 2 mal x < 25 && count_if( first, last, bind2nd( greater< int >(), 25 ) ) == 4 // 4 mal x > 25 && count_if( first, last, bind2nd( modulus< int >(), 2 ) ) == 4 // 4 mal x ist ungerade (=> 2 mal gerade) && adjacent_find( first, last, istPaerchen() ) != last // mindestens ein Pärchen existiert ; } int main() { using namespace std; set< int > gezogenenKugeln = ziehung_6_aus_49(); // -- Ergebnis der Ziehung ausgeben copy( gezogenenKugeln.begin(), gezogenenKugeln.end(), ostream_iterator< int >( cout, " " ) ); cout << endl; cout << "Die Ziehung erfuellt " << (passt( gezogenenKugeln.begin(), gezogenenKugeln.end() )? "" : "NICHT") << " die Anforderungen" << endl; return 0; }Neu ist der Algorithmus 'passt()', der aus einer Menge von (6) 'Kugeln' bestimmt, ob die von Dir gesetzten Anforderungen erfüllt sind.
Wenn Du dieses Programm jetzt ein paar Mal ausführst, so wirst Du merken, dass Deine Anforderungen praktisch nie erfüllt sind. Nach meiner Abschätzung wirst Du das Programm im Mittel 280 Mal aufrufen, bevor es einmal meldet 'Anforderungen erfüllt'. Das geht natürlich einfacher in einer Schleife, und damit sind wir bei
"3.) wenn nein, dann bei 1.) weitermachen" .. und dazu muss man nur noch das main() erweitern:
int main() { using namespace std; set< int > gezogenenKugeln; do { gezogenenKugeln = ziehung_6_aus_49(); } while( !passt( gezogenenKugeln.begin(), gezogenenKugeln.end() ) ); // wiederholen, solange es nicht passt // -- Ergebnis der Ziehung ausgeben copy( gezogenenKugeln.begin(), gezogenenKugeln.end(), ostream_iterator< int >( cout, " " ) ); cout << endl; return 0; }.. das soll für's erste reichen.
Gruß
Werner
-
int( (rand() / (RAND_MAX+1.0)) * m_kugeln.size() );Den Trick werde ich nie verstehen. Jetzt sind nicht mehr die ersten 36 Zahlen um 0.1497% häufiger, sondern die Häufigeren Zahlen verteilen sich jetzt gleichmäßig über das Intervall.
Klingt für mich nach Mystik wiesrand(time(0)*time(0));Mein Tipp: Entweder nicht machen oder richtig machen.