I have a bool[]
and from that original array I want to generate versions/scenarios of the array and save it to a list<bool[]>
.
If the array looks something like {true,true,false,true,true,true}
. The idea is that if bool[0]
and bool[1]
both are true and bool[2]
is false. I want to create a scenario where bool[0]
and bool[1]
are false and bool[2]
is true and add that scenario to my list. I am currently doing this in a for-loop to check every slot in the array for the pattern {true,true,false}
or {false, true,true}
. The goal is to find the scenario where I have as few elements of bool = true
as possible in the array and return that array.
I am trying to do this with brute force but it is too slow (sometimes minutes). The language I want this to work for is C#. Is there an more efficient way to create the scenarios than with brute force?
My code for generating the scenarios:
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);
}
}
After some modifications the code looks like this:
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();
}
}
As requested I will go through the process going from original array to an array with as few {true}
as possible. In the example below i will use 1
for true
and 0
for false
.
I will use a simple example and show how it is done manually:
This is the input array {0110100101011}
, let us call it myInput
.
Step 1: I pick the 1
form myInput[1]
and jump over myInput[2]
and land in myInput[3]
. This will transform myIput[1]
to a 0
and myInput[2]
to a 0
and myInput[3]
to 1
.
The resulting array from this move is {0001100101011}
.
If I had moved myInput[2]
instead on myInput[1]
, myInput[2]
would have had to jump to myInput[0]
and resulting in an array like so {1000100101011}
. This would make it impossible to remove the 1
at myInput[4]
since it is now surrounded by 0
.
Let us continue with the first and correct move which resulted in {0001100101011}
. The next move I would make is myInput[3]
to myInut[5]
. Giving us this result {0000010101011}
. Then myInput[12]
to myInput[10]
. Result {0000010101100}
. myInput[10]
to myInput[8]
. Result {0000010110000}
. myInput[8]
to myInput[6]
. Result {0000011000000}
. And finally, myInput[6]
to myInput[4]
. Result {0000100000000}
.
Giving us the result of one 1
for the array {0001100101011}
since there are no more posible moves.
Since the program I have written have to check all the different moves and can´t tell that it is unwise to start with moving the 1
from myInput[2]
to myInput[0]
I have to make the program test att the different moves and storing them to my list alternativs
. This creates a huge amount of scenarios and that is what is slowing down my program.
I still havent managed to find a solution to this.