-
Notifications
You must be signed in to change notification settings - Fork 33
/
consecutive_partitions.pl
executable file
·73 lines (57 loc) · 1.59 KB
/
consecutive_partitions.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# Date: 30 April 2019
# https://github.com/trizen
# Given an array of `n` elements, generate all the possible consecutive partitions (with no swaps and go gaps).
# For example, given the array [1,2,3,4,5], there are 16 different ways to
# subdivide the array (using all of its elements in their original order):
#
# [[1, 2, 3, 4, 5]]
# [[1], [2, 3, 4, 5]]
# [[1, 2], [3, 4, 5]]
# [[1, 2, 3], [4, 5]]
# [[1, 2, 3, 4], [5]]
# [[1], [2], [3, 4, 5]]
# [[1], [2, 3], [4, 5]]
# [[1], [2, 3, 4], [5]]
# [[1, 2], [3], [4, 5]]
# [[1, 2], [3, 4], [5]]
# [[1, 2, 3], [4], [5]]
# [[1], [2], [3], [4, 5]]
# [[1], [2], [3, 4], [5]]
# [[1], [2, 3], [4], [5]]
# [[1, 2], [3], [4], [5]]
# [[1], [2], [3], [4], [5]]
#
# In general, for a given array with `n` elements, there are `2^(n-1)` possibilities.
use 5.014;
use strict;
use warnings;
use ntheory qw(forcomb vecsum);
sub split_at_indices {
my ($array, $indices) = @_;
my $i = 0;
my @parts;
foreach my $j (@$indices) {
push @parts, [@{$array}[$i .. $j]];
$i = $j + 1;
}
return @parts;
}
sub consecutive_partitions {
my (@array) = @_;
my @subsets;
foreach my $k (0 .. @array) {
forcomb {
my @t = split_at_indices(\@array, \@_);
if (vecsum(map { scalar(@$_) } @t) == @array) {
push @subsets, \@t;
}
} scalar(@array), $k;
}
return @subsets;
}
my @subsets = consecutive_partitions(1, 2, 3, 4, 5);
foreach my $subset (@subsets) {
say join(', ', map { "[@$_]" } @$subset);
}