2016-05-02 12 views
0

Ich habe eine bool[] und von diesem ursprünglichen Array möchte ich Versionen/Szenarien des Arrays generieren und speichern Sie es auf list<bool[]>.Gibt es eine effizientere Möglichkeit zum Erstellen von Versionen eines Arrays als Brute Force?

Wenn das Array so aussieht wie {true,true,false,true,true,true}. Die Idee ist, dass, wenn bool[0] und bool[1] beide wahr sind und bool[2] falsch ist. Ich möchte ein Szenario erstellen, in dem bool[0] und bool[1] falsch sind und bool[2] wahr ist und dieses Szenario zu meiner Liste hinzufügen. Ich mache dies derzeit in einer for-Schleife, um jeden Steckplatz im Array für das Muster {true,true,false} oder {false, true,true} zu überprüfen. Das Ziel ist, das Szenario zu finden, in dem ich so wenig Elemente von bool = true wie möglich in dem Array habe und das Array zurückgeben.

Ich versuche, dies mit roher Gewalt zu tun, aber es ist zu langsam (manchmal Minuten). Die Sprache, für die ich dies möchte, ist C#. Gibt es eine effizientere Möglichkeit, Szenarien zu erstellen als mit roher Gewalt?

Mein Code die Szenarien zur Erzeugung:

class Program 
{ 
    public static List<bool[]> alternativs = new List<bool[]>(); 
    public static int arrayCount = 23; 
    public static int tempCount = 0; 
    static void Main(string[] args) 
    { 
     //this works fast 
     bool[] easyInput = new bool[23] { true, true, false, false, false, false, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false }; 
     //this takes forever 
     bool[] hardInput = new bool[23] { true, true, false, true, true, false, true, true, false, true, true, false, true, true, false, true, true, false, true, true, false, true, true }; 

     alternativs.Add(easyInput); 
     while (alternativs.Count > 0) 
     { 
      for (int i = 0; i < 21; i++) 
      { 
       if (alternativs[0][i] == true && alternativs[0][i + 1] == true && alternativs[0][i + 2] == false) 
       { 
        bool[] temp = new bool[23]; 
        bool[] temp3 = new bool[23]; 

        Array.Copy(alternativs[0], temp, 23); 
        Array.Copy(temp, temp3, 23); 
        Array.Reverse(temp3); 
        temp[i] = false; 
        temp[i + 1] = false; 
        temp[i + 2] = true; 

        if (!alternativs.Contains(temp) && !alternativs.Contains(temp3)) 
        { 
         alternativs.Add(temp); 
        } 
       } 
       if (alternativs[0][i] == false && alternativs[0][i + 1] == true && alternativs[0][i + 2] == true) 
       { 
        bool[] temp2 = new bool[23]; 
        bool[] temp4 = new bool[23]; 

        Array.Copy(alternativs[0], temp2, 23); 
        Array.Copy(temp2, temp4, 23); 

        temp2[i] = true; 
        temp2[i + 1] = false; 
        temp2[i + 2] = false; 
        if (!alternativs.Contains(temp2) && !alternativs.Contains(temp4)) 
        { 
         alternativs.Add(temp2); 
        } 
       } 
      } 
      tempCount = 0; 
      for (int j = 0; j < 23; j++) 
      { 
       if (alternativs[0][j] == true) 
        tempCount++; 
      } 
      if (tempCount < arrayCount) 
      { 
       arrayCount = tempCount; 
      } 
      alternativs.RemoveAt(0); 
     } 
     Console.WriteLine(arrayCount); 
    } 
} 

Nach einigen Änderungen sieht der Code wie folgt aus:

class Program 
{ 
    public static List<string> alternativs = new List<string>(); 
    public static int arrayCount = 23; 
    public static int tempCount = 0; 
    static void Main(string[] args) 
    { 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     //this works fast 
     //string easyInput = "11000011110000000000000"; 
     //this takes forever 
     string hardInput = "11011011011011011011011"; 
     string xtra = "00101100011010000000000"; 

     string TmpVal = ""; 
     string RevVal = ""; 

     alternativs.Add(xtra); 
     while (alternativs.Count > 0) 
     { 
      if (alternativs[0].Contains("110")) 
      { 
       TmpVal = alternativs[0]; 
       TmpVal = TmpVal.Replace("110", "001"); 
       RevVal = string.Concat(Enumerable.Reverse(TmpVal)); //String Reverse 

       if (!alternativs.Any(xs => xs.SequenceEqual(TmpVal)) && !alternativs.Any(xs => xs.SequenceEqual(RevVal))) 
       { 
        alternativs.Add(TmpVal); 
       } 
      } 
      if (alternativs[0].Contains("011")) 
      { 
       TmpVal = alternativs[0]; 
       TmpVal = TmpVal.Replace("011", "100"); 
       RevVal = string.Concat(Enumerable.Reverse(TmpVal)); //String Reverse 

       if (!alternativs.Any(xs => xs.SequenceEqual(TmpVal)) && !alternativs.Any(xs => xs.SequenceEqual(RevVal))) 
       { 
        alternativs.Add(TmpVal); 
       } 

      } 

      tempCount = alternativs[0].Count(x => x == '1'); 
      if (tempCount < arrayCount) 
      { 
       arrayCount = tempCount; 
      } 
      alternativs.RemoveAt(0); 

     } 
     Console.WriteLine(arrayCount); 
     sw.Stop(); 
     Console.WriteLine(sw.Elapsed); 
     Console.ReadLine(); 
    } 
} 

Da bat ich durch den Prozess von der ursprünglichen Anordnung in ein Array gehen gehen mit so wenig wie möglich {true}. Im folgenden Beispiel verwende ich 1 für true und 0 für false.

ich ein einfaches Beispiel verwenden und zeige, wie es manuell durchgeführt wird:

wir es Dies ist der Eingangs-Array {0110100101011}, nennen sie myInput. Schritt 1: Ich wähle das 1 Formular myInput[1] und überspringe myInput[2] und lande in myInput[3]. Dies wird myIput[1] zu 0 und myInput[2] zu 0 und myInput[3] zu 1 umwandeln. Das resultierende Array von diesem Zug ist {0001100101011}. Wenn ich myInput[2] stattdessen auf myInput[1] verschoben hätte, hätte myInput[2] zu myInput[0] springen müssen und in einem Array wie so resultieren. Dies würde es unmöglich machen, die 1 bei myInput[4] zu entfernen, da sie jetzt von 0 umgeben ist.

Lassen Sie uns mit der ersten und richtigen Bewegung fortfahren, die in {0001100101011} resultierte. Der nächste Schritt, den ich machen würde, ist myInput[3] bis myInut[5]. Gibt uns dieses Ergebnis {0000010101011}. Dann myInput[12] zu myInput[10]. Ergebnis {0000010101100}. myInput[10] bis myInput[8]. Ergebnis {0000010110000}. myInput[8] bis myInput[6]. Ergebnis {0000011000000}. Und schließlich myInput[6] zu myInput[4]. Ergebnis {0000100000000}. Geben Sie uns das Ergebnis von 1 für das Array {0001100101011} seit es keine möglichen Bewegungen mehr gibt.

Da das Programm, das ich geschrieben habe, haben alle verschiedene Bewegungen zu überprüfen und kann nicht sagen, dass es unklug ist, mit der Bewegung des 1myInput[2]-myInput[0] muss ich machen das Programm Test att die verschiedenen Bewegungen und deren Speicherung zu starten zu meiner Liste alternativs. Dies erzeugt eine große Menge an Szenarien und das verlangsamt mein Programm.

Ich habe es immer noch nicht geschafft, eine Lösung dafür zu finden.

+5

Vielleicht bin ich noch ein bisschen eingeschlafen, aber ich verstehe deine Frage nicht. Möchten Sie Kombinationen oder Permutationen Ihres ursprünglichen Arrays erhalten? Vielleicht, wenn Sie uns Ihren Code zeigen, würde es alles klarer machen – Pikoh

+2

Ja, bitte zeigen Sie uns Ihren Code. Ich wäre gerne in der Lage zu kopieren, einfügen und laufen. – Enigmativity

+0

Ich habe das Code-Bit hinzugefügt, in dem ich versuche, die Szenarien zu erstellen. Ich möchte ein neues modifiziertes Array von dem ursprünglichen erhalten. Ich füge alle generierten Szenarien zu einer Liste hinzu und diese Liste wächst schnell! – Billy

Antwort

0

Ich verstehe immer noch nicht, was Sie versuchen zu tun. Ich hoffe es hilft.

Verwendet einen alternativen Ansatz, um das Programm zu beschleunigen. Ersetzt alle Wahr durch 1 und alle falsch bis 0. Statt Byte-Array gespeicherten Daten in String. Got führen leicht = 3 und hart = 16.

class Program 
{ 
    public static List<string> alternativs = new List<string>(); 
    public static int arrayCount = 23; 
    public static int tempCount = 0; 
    static void Main(string[] args) 
    { 
     //this works fast 
     string easyInput = "11000011110000000000000"; 
     //this takes forever 
     string hardInput = "11011011011011011011011"; 

     string TmpVal = ""; 
     string RevVal = ""; 
     bool CanAdd; 

     alternativs.Add(hardInput); 
     while (alternativs.Count > 0) 
     { 
      CanAdd = false; 
      if (alternativs[0].Contains("110")) 
      { 
       TmpVal = alternativs[0]; 
       RevVal = string.Concat(Enumerable.Reverse(TmpVal)); //String Reverse 
       TmpVal = TmpVal.Replace("110", "001"); 
       CanAdd = true; 
      } 
      if (alternativs[0].Contains("011")) 
      { 
       TmpVal = alternativs[0]; 
       RevVal = string.Concat(Enumerable.Reverse(TmpVal)); //String Reverse 
       TmpVal = TmpVal.Replace("011", "100"); 
       CanAdd = true; 
      } 
      if (CanAdd == true) 
      { 
       if (!alternativs.Contains(TmpVal) && !alternativs.Contains(RevVal)) 
       { 
        alternativs.Add(TmpVal); 
       } 
      } 
      tempCount = alternativs[0].Count(x => x == '1'); 
      if (tempCount < arrayCount) 
      { 
       arrayCount = tempCount; 
      } 
      alternativs.RemoveAt(0); 

     } 
     Console.WriteLine(arrayCount); 
     Console.ReadLine(); 
    } 
} 

Es stellt sich heraus, ob Sie die kleinste Einheit des wahren müssen, wird der obige Code gerade Ebene kompliziert und falsch. Bitte gehen Sie durch den Code unten ... Das harte Ergebnis bekam ist 8.

class Program 
{ 
    public static string CurStr; 
    public static int arrayCount = 23; 
    public static int tempCount = 0; 
    static void Main(string[] args) 
    { 
     //this works fast 
     string easyInput = "11000011110000000000000"; 
     //this takes forever 
     string hardInput = "11011011011011011011011"; 

     string TmpVal = ""; 
     bool CanAdd; 

     CurStr = hardInput; 
     CanAdd = true; 
     while (CanAdd) 
     { 
      TmpVal = CurStr; 
      CanAdd = false; 
      if (TmpVal.Contains("110")) 
      { 
       TmpVal = TmpVal.Replace("110", "001"); 
       CanAdd = true; 
      } 
      if (TmpVal.Contains("011")) 
      { 
       TmpVal = TmpVal.Replace("011", "100"); 
       CanAdd = true; 
      } 
      if (CanAdd == true) 
      { 
       CurStr = TmpVal; 
      } 
      tempCount = CurStr.Count(x => x == '1'); 
      if (tempCount < arrayCount) 
      { 
       arrayCount = tempCount; 
      } 
     } 
     Console.WriteLine(arrayCount); 
     Console.ReadLine(); 
    } 
} 
+0

Vielen Dank für Ihre Antwort! Ich werde deine Lösung testen und ein wenig herumspielen. Hovever, sollte die richtige Antwort für die "harte" Eingabe 6 und nicht 16 sein. – Billy

+0

Ooh .. danke :) – lal

+0

Können Sie bitte einen Blick auf den 2. Code unten. Und ich kann immer noch nicht herausfinden, wie du 6 hast, auch wenn ich manuell versuche, bekomme ich 8. – lal

0

Ich glaube, Sie mit dem .Contains Operator ein Problem haben.

Wenn Sie diesen Code haben:

var list_of_bool_arrays = new List<bool[]>() 
{ 
    new [] { true, false }, 
}; 

Console.WriteLine(list_of_bool_arrays.Contains(new [] { true, false })); 

... Sie könnten es erwarten True zu drucken - ganz klar das Array new [] { true, false } ist in der Liste des Arrays. Es druckt jedoch False. Arrays sind Referenztypen, die nur dann Gleichheit melden, wenn die Referenz gleich und nicht der Inhalt ist.

Um ein True Sie diesen Code tun müssen:

Console.WriteLine(list_of_bool_arrays.Any(xs => xs.SequenceEqual(new [] { true, false }))); 

So, jetzt diese Zeilen im Code Ich schrieb nur:

if (!alternativs.Any(xs => xs.SequenceEqual(temp)) && !alternativs.Any(xs => xs.SequenceEqual(temp3))) 

... und:

if (!alternativs.Any(xs => xs.SequenceEqual(temp2)) && !alternativs.Any(xs => xs.SequenceEqual(temp4))) 

Der Code lief dann fast sofort hardInput mit einem Ergebnis von 16.

+0

Vielen Dank! Ich wusste das nicht über "enthält". Aber die Ausgabe für hardInput sollte 6 und nicht 16 sein. – Billy

+0

@Billy - Es ist seltsam, dass lal auch 16 bekam. Bist du sicher, dass es 6 ist? – Enigmativity

+0

Ja, ich bin mir ziemlich sicher. – Billy