# ETOOBUSY š minimal blogging for the impatient

# All partitions of a set into differently arranged subsets

**TL;DR**

Well, moving on in this seriesā¦

Previous post All partitions of a set into same-sized subsets set
the base for doing the partitioning of a set of items into subsets with
the same size, making sure to only include *different* arrangements.

With this in our pocket, we can now proceed to generate all possible partitions following a pre-definite scheme. An example of such a scheme would be to partition set:

\[\{ a, b, c, d, e, f, g, h, i, l \}\]into two $3$-sized subsets and two $2$-sized subsets.

Does this ring a bell? Itās like weāre saying that our starting set has $10$ items, and we would like to partition it according to the following partition of the integer $10$:

\[10 = 2 \cdot 3 + 2 \cdot 2\]Take a look at previous post All positive integer sums, as iterator for a refresher, if you donāt know what Iām talking about!

OK, letās then move on with an implementation of a Perl function that provides an iterator for all possible partitions according to the provided scheme:

```
sub differsets_partition_iterator ($sizs, @items) {
my ($fs, @sizes) = $sizs->@*;
return equalsets_partition_iterator($fs->[1], @items)
if @sizes == 0;
my $cit = combinations_iterator($fs->[0] * $fs->[1], @items);
my ($leader_it, $rest_it);
my @leader;
my $rref; # "rest" after leader
return sub {
return unless $cit;
while ('necessary') {
$leader_it //= do {
(my $lref, $rref) = $cit->() or do {
$cit = undef;
return;
};
equalsets_partition_iterator($fs->[1], $lref->@*);
};
$rest_it //= do {
@leader = $leader_it->() or do {
$leader_it = undef;
redo;
};
differsets_partition_iterator(\@sizes, $rref->@*);
};
my @sequence = $rest_it->() or do {
$rest_it = undef;
redo;
};
return (@leader, @sequence);
}
};
}
```

The name isā¦ far from being catchy. Whatever, Stat rosa pristina nomine, nomina nuda tenemus.

We receive the scheme as an array reference `$sizs`

, filled with array
references that each carry two integer values, i.e. a count and a size.
In other terms, exactly one of the possible outputs from what we
described in All positive integer sums, as iterator. The rest of the
inputs is the list of items in our set.

The idea is to adopt a *divide et impera* approach: take the first pair
and generate all combinations of the combined size, and recurse with the
rest.

Well, letās see an example. Suppose that we want to do the partitioning in the example above: $10$ items, partitioned as two $3$-sized and two $2$-sized subsets.

The two sets with three items inside have to be treated like we described in the previous post, because they share the same size. To do this, we can:

- first generate all possible combinations of $6$ elements out of the available $10$, i.e. getting as many items as will be needed to fill the two $3$-sized subsets exactly;
- then apply the reasoning to the rest of $4$ items from each combinations, fitting them into $2$-sized subsets.

The ending condition for the recursion is when we are left with only one
pair in the scheme: in this case, we can just hand over to
`equalsets_partition_iterator`

and call it a day. This is why we check
for this condition at the beginning of the function.

Inside the *main* iterator, though, we have to keep track of two
different levels of iteration:

- the
*external*one, where we iterate through all possible sequences generated by the*leader*(in our example, it would be all possible partitions of a specific combination of $6$ items into two subsets containing $3$ items each); - the
*internal*one, where we keep the`@leader`

fixed, and iterate through what the recursion provides us (in our example, this means iterating through all partitions of a specific subset of $4$ elements left from the $6$-combination drawn for generating the leaders).

This is why we keep two iterators `$leader_it`

and `$rest_it`

. Pretty
complicated, uh?

The result is encouraging though:

```
{ {a b c}, {d e f}, {g h}, {i l} }
{ {a b c}, {d e f}, {g i}, {h l} }
... 6296 items in between...
{ {e i l}, {f g h}, {a c}, {b d} }
{ {e i l}, {f g h}, {a d}, {b c} }
```

Is $6300$ the number of partitions of this kind we were expecting? Letās seeā¦

\[\binom{10}{6} \binom{5}{2} \binom{3}{1} = 210 \cdot 10 \cdot 3 = 6300\]Now weāre ready for the big prize: generating all distinct partitions of a set! Letās just wait for the next postā¦ š

*Comments? Octodon, Twitter, GitHub, Reddit, or drop me a line!*