Semi-random set of subsets

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(); // a SetCount-sized array of lists
    var ObjectAppearances = SetSize * SetCount / ObjectCount;
    var rand = new Random();

    // fill the sets
    for (int obj = 0; obj < ObjectCount; obj++)
    {
        for (int a = 0; a < ObjectAppearances; a++)
        {
            // get the collection of sets that are not full
            var nonFullSets = Sets.Where(s => s.Count < SetSize);
            // get the collection of non-full sets without obj
            var setsWithoutObj = nonFullSets.Where(s => !s.Contains(obj));
            ///////////////////////
            // Here is the problem. All of the non-full sets may already 
            // have a copy of obj
            ///////////////////////
            // choose a set at random
            var currentSetIndex = rand.Next(setsWithoutObj.Count());
            var currentSet = setsWithoutObj.ElementAt(currentSetIndex);
            // add the object
            currentSet.Add(obj);
        }
    }

    // randomize the order within each set and output each
    for (int i = 0; i < SetCount; i++)
    {
        var randomlyOrderedSet = Sets[i].OrderBy(obj => rand.Next());
        Sets[i] = new List<int>(randomlyOrderedSet);

        // output
        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();

    // make a matrix [SetCount][ObjectCount]
    var Matrix = new int[SetCount][];
    for (int s = 0; s < SetCount; s++)
        Matrix[s] = Enumerable.Repeat(0, ObjectCount).ToArray();

    // put approximately the same number of objects in each set by
    // adding sequential objects to sequential sets (not random)
    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;
        }
    }

    // output the result
    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();

    // shuffle sets
    Matrix = Matrix.OrderBy(s => rand.Next()).ToArray();
    // make a new matrix for shuffle objects
    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];
        }
    }

    // check and output the result
    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();
    }
    // output object count
    Console.WriteLine();
    for (int o = 0; o < ObjectCount; o++)
        Console.Write(string.Format("{0}  ", objectCounters[o]));
    Console.ReadLine();
}
+3
3
  • ObjCount & times; SetCount , VisibleCount, () . .
  • ( , ObjCount SetCount times; VisibleCount ).
  • i, j 1, j, i.

12 , 6 3 , :

1 0 0 0 0 0
1 0 0 0 0 0
1 1 0 0 0 0
0 1 0 0 0 0
0 1 1 0 0 0
0 0 1 0 0 0
0 0 1 1 0 0
0 0 0 1 0 0
0 0 0 1 1 0
0 0 0 0 1 1
0 0 0 0 1 1
0 0 0 0 0 1

:

1 0 1 0 0 0
0 0 0 0 1 0
1 1 0 0 0 0
0 0 0 1 1 0
0 1 0 0 0 0
0 0 0 1 0 0
0 0 1 0 0 0
1 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 1
0 1 0 0 0 1
0 0 0 0 0 1

:

{1,3,8}
{3,5,11}
{1,7,8}
{4,6,9}
{2,4,10}
{10,11,12}
+1

o - , v - , s - .

  • [ o ]
    1.1. v .
           1.1.1. - , 1.1.

: , . . , .

+1
resultSets = new Set[SetCount];  // create an array of sets to hold the results

totalObjectsPlaced = 0;
currentObjectIndex = 0;

while (totalObjectsPlaced < (ObjCount * VisibleCount)) {
  do {
    randomSet = rand(SetCount);
  } while (!resultSets[randomSet].contains(object[currentObjectIndex]));
  resultSets[randomSet].add(object[currentObjectIndex]);
  currentObjectIndex = (currentObjectIndex + 1) % ObjCount;
  totalObjectsPlaced++;
}
0
source

Source: https://habr.com/ru/post/1794989/


All Articles