algorithm - semi-random set of subsets -


i'm trying generate semi-random subsets restrictions.

here variable descriptions example values:

  • objcount - number of objects (12)
  • visiblecount (aka setsize) - number of objects per set (6)
  • setcount - number of sets (12)
  • objappearances - number of set in object appears = setcount * visiblecount / objcount

i need produce given number of sets (setcount) follow these rules:

  1. each set collection of objects, no object can in single set more once.
  2. furthermore, each object should in same number of sets. if doesn't devide evenly, number sets in object appears can off 1 (some objects in 4 sets, , others in 5). i'll try avoid situation, it's not critical.

it's turning out far less trivial thought. me code/psuedocode? solution generalized version helpful too.

thanks in advance.

edit: visiblecount set size. number of times object appears (objappearances) setcount * visiblecount / objcount

edit2: should add want sets random. if sets have sequential objects (e.g. set1:5,6,7 set2:3,4,5 set3:10,11,0), solution isn't useful. sorry not making clear.

edit3: here solution not work. (in c#)

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(); // setcount-sized array of lists     var objectappearances = setsize * setcount / objectcount;     var rand = new random();      // fill sets     (int obj = 0; obj < objectcount; obj++)     {         (int = 0; < objectappearances; a++)         {             // collection of sets not full             var nonfullsets = sets.where(s => s.count < setsize);             // collection of non-full sets without obj             var setswithoutobj = nonfullsets.where(s => !s.contains(obj));             ///////////////////////             // here problem. of non-full sets may              // have copy of obj             ///////////////////////             // choose set @ random             var currentsetindex = rand.next(setswithoutobj.count());             var currentset = setswithoutobj.elementat(currentsetindex);             // add object             currentset.add(obj);         }     }      // randomize order within each set , output each     (int = 0; < 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(); } 

here's solution - implementation of mizardx's answer

static void main(string[] args) {     var objectcount = 12;     var setsize = 6;     var setcount = 10;     var rand = new random();      // make matrix [setcount][objectcount]     var matrix = new int[setcount][];     (int s = 0; s < setcount; s++)         matrix[s] = enumerable.repeat(0, objectcount).toarray();      // put approximately same number of objects in each set     // adding sequential objects sequential sets (not random)     (int s = 0; s < setcount; s++)     {         var firstobject = (int)math.ceiling((double)s * objectcount / setcount);         (int = 0; < setsize; i++)         {             var o = (firstobject + i) % objectcount;             matrix[s][o] = 1;         }     }      // output result     (int s = 0; s < setcount; s++)     {         (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 new matrix shuffle objects     var objorder = enumerable.range(0, objectcount).orderby(o => rand.next()).toarray();     var matrixsuffled = new int[setcount][];     (int s = 0; s < setcount; s++)         matrixsuffled[s] = enumerable.repeat(0, objectcount).toarray();     (int o = 0; o < objectcount; o++)     {         var oldobj = o;         var newobj = objorder[o];         (int s = 0; s < setcount; s++)         {             matrixsuffled[s][newobj] = matrix[s][oldobj];         }     }      // check , output result     var objectcounters = enumerable.repeat(0, objectcount).toarray();     (int s = 0; s < setcount; s++)     {         var objectsinthisset = 0;         (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();     (int o = 0; o < objectcount; o++)         console.write(string.format("{0}  ", objectcounters[o]));     console.readline(); } 

  1. create objcount × setcount matrix, , fill ones , zeros each column contains visiblecount ones, , each row contains (almost) equal number of ones. order irrelevant @ point.
  2. shuffle columns (and rows, if objcount not divide setcount × visiblecount evenly).
  3. for each column i, if cell @ row j equals 1, add object j set i.

for 12 objects, 6 sets , 3 visible, initial matrix might this:

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 

and after shuffle:

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 

resulting in sets:

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

Comments

Popular posts from this blog

c# - How to set Z index when using WPF DrawingContext? -

razor - Is this a bug in WebMatrix PageData? -

visual c++ - Using relative values in array sorting ( asm ) -