C# :: Aufgabe #13 :: Lösung #1
14 Lösungen

#13
Lotto - Simulation - 6 aus 49
Anfänger - C#
von Gustl
- 25.11.2012 um 16:16 Uhr
Schreiben Sie ein Programm, welches 6 Zahlen zwischen 1 und 49 abfrägt. Danach soll das Programm solange 6 Zufallszahlen berechnen bis alle 6 eingegebenen Zahlen übereinstimmen. Natürlich darf eine Zahl nicht zweimal vorkommen.
Dann soll ausgegeben werden nach wie vielen "Spielen" ein 6er erzielt wurde und wie hoch die Chance auf einen 3er, einen 4er und einen 5er war.
Dann soll ausgegeben werden nach wie vielen "Spielen" ein 6er erzielt wurde und wie hoch die Chance auf einen 3er, einen 4er und einen 5er war.
#1

von pocki (4190 Punkte)
- 27.11.2012 um 21:02 Uhr
Hier ist eine alternative Lösung:
Da hier sehr viele Schleifendurchläufe erforderlich sind, kann durch Parallelisieren eine höhere Performance (bei Mehrkern-CPUs) erreicht werden.
Diese Lösung nutzt die TPL, welche ab .NET Framework 4 enthalten ist.
Da bei parallelen Aufrufen kein direkter Zugriff aus den Methoden (direkt)möglich ist bzw. auch nicht verwendet werden soll schaut der Aufbau im ersten Moment wahrscheinlich etwas komplizierter aus. Die Grundfunktionen sind allerdings die gleichen zur vorherigen Lösung.
C#-Code
Da hier sehr viele Schleifendurchläufe erforderlich sind, kann durch Parallelisieren eine höhere Performance (bei Mehrkern-CPUs) erreicht werden.
Diese Lösung nutzt die TPL, welche ab .NET Framework 4 enthalten ist.
Da bei parallelen Aufrufen kein direkter Zugriff aus den Methoden (direkt)möglich ist bzw. auch nicht verwendet werden soll schaut der Aufbau im ersten Moment wahrscheinlich etwas komplizierter aus. Die Grundfunktionen sind allerdings die gleichen zur vorherigen Lösung.

using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; namespace UE13Parallel { internal class Program { private static List<int> Moeglichkeiten; private static readonly object mylock = new object(); private static readonly clsLotto Lotto = new clsLotto(); internal static void Main(string[] args) { const int minZahl = 1; const int maxZahl = 49; //Lottokugeln anlegen Moeglichkeiten = Enumerable.Range(minZahl, maxZahl).ToList(); List<int> tipps = new List<int>(); while (tipps.Count < 6) { Console.Write("Bitte die {0}. Zahl des Tipps eingeben: ", tipps.Count + 1); int tipp; if (int.TryParse(Console.ReadLine(), out tipp)) { if (tipp >= minZahl && tipp <= maxZahl) { tipps.Add(tipp); } } } Console.WriteLine("Lotto wird simuliert. Bitte warten."); Stopwatch sw = new Stopwatch(); sw.Start(); //Parallele "While"-Schleife mit den unten beschriebenen Methoden Parallel.ForEach(Extensions.Infinite(), () => new clsLotto(tipps, Moeglichkeiten), RunIteration, FinishThread); sw.Stop(); Console.WriteLine("Simulation beendet nach {0:#,##0.000} Sekunden.", sw.ElapsedMilliseconds / 1000m); Console.WriteLine("Nach {0} Spielen wurde ein 6er erziehlt", Lotto.Durchlaeufe); Console.WriteLine("Die Chance auf einer 3er lag bei {0:#0.000}%", Lotto.Dreier / (decimal)Lotto.Durchlaeufe * 100m); Console.WriteLine("Die Chance auf einer 4er lag bei {0:#0.000}%", Lotto.Vierer / (decimal)Lotto.Durchlaeufe * 100m); Console.WriteLine("Die Chance auf einer 5er lag bei {0:#0.000}%", Lotto.Fuenfer / (decimal)Lotto.Durchlaeufe * 100m); Console.ReadKey(); } /// <summary> /// Methode für einen Schleifendurchlauf /// </summary> /// <param name="i"></param> /// <param name="state">Wird zum Abbrechen der Schleife bei 6er benötigt</param> /// <param name="localLotto">das lokale Objekt - muss am Ende noch weiterverarbeitet werden</param> /// <returns></returns> private static clsLotto RunIteration(bool i, ParallelLoopState state, clsLotto localLotto) { var ziehung = localLotto.Moeglichkeiten.ToList().Shuffle().Take(6); //Anzahl der Übereinstimmungen zählen int gleiche = localLotto.Tipps.Intersect(ziehung).Count(); switch (gleiche) { case 3: { localLotto.Dreier++; break; } case 4: { localLotto.Vierer++; break; } case 5: { localLotto.Fuenfer++; break; } case 6: { state.Break(); break; } } localLotto.Durchlaeufe++; return localLotto; } /// <summary> /// Abschlussmethode des SchleifenThreads. Addition der Teilergebnisse. /// </summary> /// <param name="localLotto"></param> private static void FinishThread(clsLotto localLotto) { lock (mylock) { Lotto.Dreier += localLotto.Dreier; Lotto.Vierer += localLotto.Vierer; Lotto.Fuenfer += localLotto.Fuenfer; Lotto.Durchlaeufe += localLotto.Durchlaeufe; } } } /// <summary> /// Hilfsklasse, bei paralleler Ausführung kann nur ein Objekt übergeben werden. /// </summary> internal class clsLotto { public clsLotto() {} public clsLotto(List<int> tipps, List<int> moeglichkeiten) { Tipps = tipps; Moeglichkeiten = moeglichkeiten; } public List<int> Tipps { get; set; } public List<int> Moeglichkeiten { get; set; } public int Durchlaeufe { get; set; } public int Dreier { get; set; } public int Vierer { get; set; } public int Fuenfer { get; set; } } internal static class Extensions { /// <summary> /// Random ordering of a list. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="list"></param> internal static List<T> Shuffle<T>(this List<T> list) { var provider = new RNGCryptoServiceProvider(); int n = list.Count; while (n > 1) { var box = new byte[1]; do { provider.GetBytes(box); } while (!(box[0] < n * (Byte.MaxValue / n))); var k = (box[0] % n); n--; var value = list[k]; list[k] = list[n]; list[n] = value; } return list; } /// <summary> /// Hilfsmethode um von einer ForEach zu einer While-Schleife zu kommen. /// Bemerkung: in TPL gibts keine While-Schleife /// </summary> /// <returns></returns> internal static IEnumerable<bool> Infinite() { while (true) yield return true; } } }
Kommentare:
Für diese Lösung gibt es noch keinen Kommentar
Seite 1 von 0
1