intelligently generating combinations of combinations

后端 未结 4 1345
遇见更好的自我
遇见更好的自我 2021-01-19 15:23

Let\'s say I have a class of 30 students and want generate every possible way in which they can be partitioned into groups of 5 (order is irrelevant).

I know how to

相关标签:
4条回答
  • 2021-01-19 15:47

    One possibility would be to find all combinations to form an individual group, then go through and generate combinations that don't contain members of that individual group. Something like:

    List<List<Student>> combinations=Combinations(students);
    public void GenerateCombinations(int startingIndex, List<List<Student>> currentGroups, int groupsLeft)
    {
        if(groupsLeft==0) ProcessCombination(currentGroups);
    
        for(int i=startingIndex; i<combinations.Count; i++)
        {
            if combinations[i] does not contain a student in current groups
                GenerateCombinations(i+1, currentGroups + combinations[i], groupsLeft -1);
        }
    }
    

    It won't be the most efficient method to go about it, but it should generate all combinations of groups. I suspect better performance could be had if you were to generate temporary lists of combinations, where in all groups that can't occur were removed, but that would be a bit more complex.

    As a slight aside, there should be 142,506 combinations of 30 students to form a single group of 5. My <sarcasm> awesome </sarcasm> math skills suggest that there should be about 10^17 = 100 quadrillion combinations of groups of students (30!/((5!^6)*6!); 30! orderings of students, ordering of 6 groups of 5 does not matter, and ordering of those 6 groups doesn't matter). You might be sitting there a while waiting for this to finish.

    0 讨论(0)
  • 2021-01-19 15:54

    Well, there's (30C5*25C5*20C5*15C5*10C5*5C5)/6! = 30!/(6!*5!6) = 123,378,675,083,039,376 different partitons of 30 into groups of 5, so generating them all will take some time, no matter what method you use.

    In general, though, a good method to selecting such a partition is to use some ordering on the elements, and find the grouping for the highest ungrouped element, and then group the rest.

         find_partition = lambda do |elts|
            if elts.empty?
             [[]]
            else
             highest = elts.pop
             elts.combination(4).map do |others|
                find_partition[elts - others].map { |part| part << [highest,*others] }
             end.inject(:+)
            end
         end
         find_partition[(1..30).to_a]
    

    This way you're only generating each partition once

    0 讨论(0)
  • 2021-01-19 16:04

    This is an old question, but anyway, for the record, that's how I would it in Ruby:

    class Array
      def groups_of_size(n)
        Enumerator.new do |yielder|
          if self.empty?
            yielder.yield([])
          else
            self.drop(1).combination(n-1).map { |vs| [self.first] + vs }.each do |values|
              (self - values).groups_of_size(n).each do |group|
                yielder.yield([values] + group)
              end   
            end
          end
        end
      end
    end
    

    I use an enumerator because the output can grow very quickly, a strict output (an array for example) wouldn't be useful. A usage example:

    >> pp [0, 1, 2, 3, 4, 5].groups_of_size(3).to_a
    => 
    [[[0, 1, 2], [3, 4, 5]],
     [[0, 1, 3], [2, 4, 5]],
     [[0, 1, 4], [2, 3, 5]],
     [[0, 1, 5], [2, 3, 4]],
     [[0, 2, 3], [1, 4, 5]],
     [[0, 2, 4], [1, 3, 5]],
     [[0, 2, 5], [1, 3, 4]],
     [[0, 3, 4], [1, 2, 5]],
     [[0, 3, 5], [1, 2, 4]],
     [[0, 4, 5], [1, 2, 3]]]
    
    0 讨论(0)
  • 2021-01-19 16:04

    You could do some post-processing on the permutations. Some pseudo-code (implement in the language of your choice...):

    // We have a list of lists called 'permutations'
    // combinations is an (empty) list of lists
    for each permutation in permutations
    {
       sortedPermutation = permutation.sort()
       if (! combinations.find(sortedPermutation) )
       {
           combinations.add(sortedPermutation);
       }
    }
    

    Probably not the most efficient; I'd add the sort & compare to the code that generates the permutations personally.

    0 讨论(0)
提交回复
热议问题