I am trying to create semi-random subsets with some limitations.
The following are descriptions of variables with approximate values:
- ObjCount - number of objects (12)
- VisibleCount (AKA SetSize) - the number of objects in the set (6)
- SetCount - the number of sets (12)
- ObjAppearances - set number in which the object is displayed =
SetCount * VisibleCount / ObjCount
I need to create a certain number of sets (SetCount) that follow these rules:
- Each set is a set of objects, but no object can be in one set more than once.
- In addition, each object must be in the same number of sets. If it is not divided evenly, then the numerical sets in which the object appears can be disabled by 1 (some objects are in 4 sets, and others in 5). I will try to avoid this situation, so this is not critical.
This turned out to be much less trivial than I originally thought. Can someone help me with / psuedocode code? The solution for the generic version is also very useful.
Thanks in advance.
Edit: VisibleCount is the specified size. The number of times an object appears (ObjAppearances)SetCount * VisibleCount / ObjCount
Edit2: I should also add that I want the sets to be pretty random. If all sets have sequential objects (for example, set1: 5,6,7 set2: 3,4,5 set3: 10,11,0), the solution is not useful. Sorry for what you did not understand.
Edit3: , . ( #)
static void Main(string[] args)
{
var ObjectCount = 12;
var SetSize = 6;
var SetCount = 12;
var Sets = Enumerable.Range(0, SetCount).Select(i => new List<int>()).ToArray();
var ObjectAppearances = SetSize * SetCount / ObjectCount;
var rand = new Random();
for (int obj = 0; obj < ObjectCount; obj++)
{
for (int a = 0; a < ObjectAppearances; a++)
{
var nonFullSets = Sets.Where(s => s.Count < SetSize);
var setsWithoutObj = nonFullSets.Where(s => !s.Contains(obj));
var currentSetIndex = rand.Next(setsWithoutObj.Count());
var currentSet = setsWithoutObj.ElementAt(currentSetIndex);
currentSet.Add(obj);
}
}
for (int i = 0; i < SetCount; i++)
{
var randomlyOrderedSet = Sets[i].OrderBy(obj => rand.Next());
Sets[i] = new List<int>(randomlyOrderedSet);
foreach (var obj in Sets[i])
Console.Write(string.Format("{0}, ", obj));
Console.WriteLine();
}
Console.ReadLine();
}
- MizardX
static void Main(string[] args)
{
var ObjectCount = 12;
var SetSize = 6;
var SetCount = 10;
var rand = new Random();
var Matrix = new int[SetCount][];
for (int s = 0; s < SetCount; s++)
Matrix[s] = Enumerable.Repeat(0, ObjectCount).ToArray();
for (int s = 0; s < SetCount; s++)
{
var firstObject = (int)Math.Ceiling((double)s * ObjectCount / SetCount);
for (int i = 0; i < SetSize; i++)
{
var o = (firstObject + i) % ObjectCount;
Matrix[s][o] = 1;
}
}
for (int s = 0; s < SetCount; s++)
{
for (int o = 0; o < ObjectCount; o++)
{
Console.Write(string.Format("{0}, ", Matrix[s][o]));
}
Console.WriteLine();
}
Console.WriteLine();
Matrix = Matrix.OrderBy(s => rand.Next()).ToArray();
var objOrder = Enumerable.Range(0, ObjectCount).OrderBy(o => rand.Next()).ToArray();
var MatrixSuffled = new int[SetCount][];
for (int s = 0; s < SetCount; s++)
MatrixSuffled[s] = Enumerable.Repeat(0, ObjectCount).ToArray();
for (int o = 0; o < ObjectCount; o++)
{
var oldObj = o;
var newObj = objOrder[o];
for (int s = 0; s < SetCount; s++)
{
MatrixSuffled[s][newObj] = Matrix[s][oldObj];
}
}
var objectCounters = Enumerable.Repeat(0, ObjectCount).ToArray();
for (int s = 0; s < SetCount; s++)
{
var objectsInThisSet = 0;
for (int o = 0; o < ObjectCount; o++)
{
objectsInThisSet += MatrixSuffled[s][o];
objectCounters[o] += MatrixSuffled[s][o];
Console.Write(string.Format("{0}, ", MatrixSuffled[s][o]));
}
Console.Write(string.Format(" {0}", objectsInThisSet));
Console.WriteLine();
}
Console.WriteLine();
for (int o = 0; o < ObjectCount; o++)
Console.Write(string.Format("{0} ", objectCounters[o]));
Console.ReadLine();
}