2016-06-16 20 views
1

Der Versuch, alle möglich zu erzeugen zieht (Kombinationen) für eine Lotterie mit einzigartigen 6 von 42C#/VB .NET Performance-Tuning, generieren alle möglichen Kombinationen Lottery

Eigentlich für die effizienteste Weg, um dies zu tun (damit die eigentliche Generation keine Tage braucht).

Abgesehen von der Verarbeitung HOG (was zu erwarten ist). Ich bin in einem Speicher Einschränkung Problem .. wo meine Maschine von 12 GB Ram kann nicht 10% der Menge auf Nummer, geschweige denn alle Combos halten.

Also entschied ich mich, in eine Datenbankalternative zu schauen. Aber damit habe ich das Problem der Duplikate (da ich nicht die ganze Liste im Speicher habe, um auf Existenz zu prüfen).

Ich habe viele Code-Versionen ausprobiert, aber alle sind ressourcenintensiv. beschäftigt

Aktuell Suche nach Alternativen, die wirklich funktionieren :)

Hier ist mein letztes Codebeispiel, das eine Datenbank für die spätere Satzverarbeitung und -filterung und Vervielfältigung Entfernung: i Feuer

public List<Draw> getDrawsContaining(List<int> initialBalls) 
    { 
     if (initialBalls == null) 
      initialBalls = new List<int>(); 

     if (initialBalls.Count >= 6) 
      return new List<Draw> { new Draw(initialBalls) }; 

     List<Draw> toReturn = new List<Draw>(); 
     for (int i = 1; i <= 42; i++) 
     { 
      if (initialBalls.IndexOf(i) != -1) 
       continue; 

      initialBalls.Add(i); 
      toReturn.AddRange(getDrawsContaining(initialBalls)); 
      initialBalls.Remove(i); 
     } 

     return toReturn;//.Distinct(dc).ToList(); 
    } 

und sagen, in den Page_Load dies:

try 
     { 
      using (SqlConnection connection = new SqlConnection(sqlConnectionString)) 
      { 
       connection.Open(); 
       String query = "TRUNCATE TABLE Draws"; 

       SqlCommand command = new SqlCommand(query, connection); 
       //command.Parameters.Add("@id", "abc"); 

       command.ExecuteNonQuery(); 
       connection.Close(); 
      } 

      DataTable dt = new DataTable("Draws"); 
      dt.Columns.Add("Ball1"); 
      dt.Columns.Add("Ball2"); 
      dt.Columns.Add("Ball3"); 
      dt.Columns.Add("Ball4"); 
      dt.Columns.Add("Ball5"); 
      dt.Columns.Add("Ball6"); 

      for (int j = 1, k = 1; j <= 42 && k <= 42;) 
      { 
       List<Draw> drawsPart = getDrawsContaining(new List<int> { j, k }); 

       if (drawsPart.Count > 0) 
       { 
        foreach (Draw d in drawsPart) 
        { 
         d.Balls.OrderBy(c => c); 

         DataRow dr = dt.NewRow(); 
         dr["Ball1"] = d.Balls[0]; 
         dr["Ball2"] = d.Balls[1]; 
         dr["Ball3"] = d.Balls[2]; 
         dr["Ball4"] = d.Balls[3]; 
         dr["Ball5"] = d.Balls[4]; 
         dr["Ball6"] = d.Balls[5]; 

         dt.Rows.Add(dr); 
        } 

        DataTable tmp = dt.Copy(); 
        dt.Rows.Clear(); 

        AsyncDBSave AsyncDBSaveInstance = new AsyncDBSave(tmp, AsyncDBSaveDispose); 
        Thread t = new Thread(new ThreadStart(AsyncDBSaveInstance.commit)); 
        t.Start(); 
       } 

       k++; 
       if (k == 43) { j++; k = 1; } 
      } 
     } 
     catch (Exception ex) 
     { 
      var v = ex.Message; 
      throw; 
     } 
+0

Sie sind nicht eine Datenbank überhaupt verwendet wird. Sie machen die gleichen Berechnungen wie zuvor langsamer und speichern sie immer noch im Speicher. Irgendwann versuchen Sie, sie an eine Datenbank anstelle einer Datei zu senden. Wenn Sie eine Datenbank verwenden, verwenden Sie SQL, um die Arbeit zu erledigen, behandeln Sie die Datenbank nicht als eine flache Datei. –

+1

'Aber damit habe ich das Problem der Duplikate' .... Wie erhalten Sie Duplikate, Generieren aller Kombinationen, wenn es richtig gemacht wird sollte nicht geben Sie irgendwelche Duplikate oO – Sidewinder94

+0

Die Zahlen zu berechnen und sie zB in einer Datei zu speichern, ist nicht so ein großes Problem, obwohl die Verwendung eines einzelnen Threads dafür viel Zeit in Anspruch nimmt. Was wirst du mit ihnen machen? Es macht keinen Sinn, sie in einer Datenbank zu speichern, wenn Sie nicht nach einzelnen Kombinationen * suchen * wollen. Wenn Sie suchen möchten, warum speichern Sie * alle * von ihnen statt nur die interessanten? –

Antwort

3

Hier gehen wir ... alles sehr schnell und effizient:

using System; 
using System.Diagnostics; 

static class Program 
{ 
    static void Main(string[] args) 
    { 

     byte[] results = new byte[6 * 5245786]; 
     byte[] current = new byte[6]; 
     int offset = 0; 
     var watch = Stopwatch.StartNew(); 
     Populate(results, ref offset, current, 0); 
     watch.Stop(); 
     Console.WriteLine("Time to generate: {0}ms", watch.ElapsedMilliseconds); 
     Console.WriteLine("Data size: {0}MiB", 
      (results.Length * sizeof(byte))/(1024 * 1024)); 
     Console.WriteLine("All generated; press any key to show them"); 
     Console.ReadKey(); 
     for (int i = 0; i < 5245786; i++) 
     { 
      Console.WriteLine(Format(results, i)); 
     } 
    } 
    static string Format(byte[] results, int index) 
    { 
     int offset = 6 * index; 
     return results[offset++] + "," + results[offset++] + "," + 
      results[offset++] + "," + results[offset++] + "," + 
      results[offset++] + "," + results[offset++]; 
    } 

    static void Populate(byte[] results, ref int offset, byte[] current, int level) 
    { 
     // pick a new candidate; note since we're doing C not P, assume ascending order 
     int last = level == 0 ? 0 : current[level - 1]; 
     for (byte i = (byte)(last + 1); i <= 42; i++) 
     { 
      current[level] = i; 
      if (level == 5) 
      { 
       // write the results 
       results[offset++] = current[0]; 
       results[offset++] = current[1]; 
       results[offset++] = current[2]; 
       results[offset++] = current[3]; 
       results[offset++] = current[4]; 
       results[offset++] = current[5]; 
      } 
      else 
      { 
       // dive down 
       Populate(results, ref offset, current, level + 1); 
      } 
     } 
    } 
} 
+0

heh, und für einen zusätzlichen Bonus - geändert von 'int []' nach 'byte []'; 30MiB Daten; und das Abrollen der "Array.Copy" dauert es <150ms auf meinem lokalen Rechner –

+0

Dient mir richtig für die Annahme der 12GB Wert, ohne tatsächlich die Anzahl der Kombinationen zu berechnen. –

+0

@PanagiotisKanavos meh, nur um einen Faktor von 410 ...;) –

0

Just for fun, nicht rekursive Version ist etwa 2-3 mal schneller

static byte[] Populate2() 
{ 
    byte[] results = new byte[6 * 5245786]; 
    int offset = 0; 
    for (byte a1 = 1; a1 <= 37; ++a1) 
     for (byte a2 = a1; ++a2 <= 38;) 
      for (byte a3 = a2; ++a3 <= 39;) 
       for (byte a4 = a3; ++a4 <= 40;) 
        for (byte a5 = a4; ++a5 <= 41;) 
         for (byte a6 = a5; ++a6 <= 42;) 
         { 
          results[offset] = a1; 
          results[offset+1] = a2; 
          results[offset+2] = a3; 
          results[offset+3] = a4; 
          results[offset+4] = a5; 
          results[offset+5] = a6; 
          offset += 6; 
         } 
    return results; 
} 
Verwandte Themen