I'd like to develop a self training algorithm for a specific problem. To keep things simple i'll nail it down to simple example.
Update: I have added a working solution as answer to this question below.
Let's say i have a huge list of entities coming from a database. Each entity is of the same type and has 4 properties of type byte.
public class Entity
{
public byte Prop1 { get; set; }
public byte Prop2 { get; set; }
public byte Prop3 { get; set; }
public byte Prop4 { get; set; }
}
Now I'd like to dynamically test one or more property of each entity against a simple condition. Which basically means that i want to test all possible combinations of all properties against this condition.
To get this done I have created a bit mask for the properties.
[Flags]
public enum EEntityValues
{
Undefined = 0,
Prop1 = 1,
Prop2 = 2,
Prop3 = 4,
Prop4 = 8,
}
And added an method to get the max value of the bit mask. Which returns 15 (1 + 2 + 4 + 8) for this example.
public static int GetMaxValue<T>() where T : struct
{
return Enum.GetValues( typeof(T) ).Cast<int>().Sum();
}
At this stage I'm able to iterate over all property combinations with a simple loop. In example within the first iteration the property Prop1 is tested, on the second iteration Prop2 is tested, on the third iteration Prop1 and Prop2 are tested and so on.
for(int i = 1; i <= GetMaxValue<EEntityValues>(); i++)
{
EEntityValues flags = (EEntityValues)i;
if(flags.HasSet(EEntityValues.Prop1))
{
....
}
}
Now let's get the entities into the game.
List<Entity> entities = GetEntitiesFromDb();
for(int i = 1; i <= GetMaxValue<EEntityValues>(); i++)
{
EEntityValues flags = (EEntityValues)i;
byte minProp1Value = 10, minProp2Value = 20, minProp3Value = 30, minProp4Value = 40;
foreach(Entitiy entity in entities)
{
if(flags.HasSet(EEntityValues.Prop1) && entitiy.Prop1 >= minProp1Value)
{
....
} else { continue; }
if(flags.HasSet(EEntityValues.Prop2) && entitiy.Prop2 >= minProp2Value)
{
....
} else { continue; }
}
}
Well, this works great if my minimum values are static.
Now let's get more complicated. As we remember, on the first iteration we are testing property Prop1 only, because the bit mask is 1. The value range for Prop1 is 0..255. I also defined a minimum value for this property which has a valid range of 1..255. This minimum value is just a filter to skip entities in the foreach loop.
Now i'd like to test the property Prop1 while i'm rising the minimum level. These tests are not part of the problem so i don't include them into my samples.
byte minProp1Value = 1;
while(minProp1Value <= 255)
{
foreach(Entitiy entity in entities)
{
if(flags.HasSet(EEntityValues.Prop1) && entitiy.Prop1 >= minProp1Value)
{
.... // Testing the matching entity and storing the result
} else { continue; }
}
minProp1Value++;
}
This is simple for a single property. On the third iteration i have to deal with 2 properties, Prop1 and Prop2, because the bit mask is 3.
byte minProp1Value = 1, minProp2Value = 1;
while(minProp1Value <= 255)
{
while(minProp2Value <= 255)
{
foreach(Entitiy entity in entities)
{
....
}
minProp2Value++;
}
minProp1Value++;
minProp2Value = 1;
}
As you can see, at this stage i'm testing Prop1 and Prop2 of each entity against a rising minimum level.
For the reason that i'm dealing with dynamically generated sets of multiple properties i can't hardcode the while loops into my code. That's why i'm looking for a smarter solution to test all possible combinations of minimum values for the given property-set (bit mask).