Skip to content

Commit

Permalink
- Optimized and extended the Array.combinations() method to accept a …
Browse files Browse the repository at this point in the history
…block as the second argument.

Example:
	[1,2,3,4].combinations(2, { |c| say c });

In addition, when n is 0, it returns [[]] instead of []
  • Loading branch information
trizen committed Dec 16, 2015
1 parent ce2fc7b commit be956e5
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 17 deletions.
68 changes: 55 additions & 13 deletions lib/Sidef/Types/Array/Array.pm
Original file line number Diff line number Diff line change
Expand Up @@ -260,23 +260,65 @@ package Sidef::Types::Array::Array {
*lev = \&levenshtein;
*leven = \&levenshtein;

sub _combinations {
my ($n, @set) = @_;
sub combinations {
my ($self, $k, $block) = @_;

do {
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$k = $k->get_value;
};

if (defined($block)) {

if ($k == 0) {
$block->run($self->new);
return $self;
}

@set || return;
$n == 1 && return map { [$_] } @set;
return if $k < 0;

my $head = shift @set;
my @result = _combinations($n - 1, @set);
foreach my $subarray (@result) {
CORE::unshift @{$subarray}, $head;
my $n = @{$self};
return $self if ($k > $n or $n == 0);

my @c = (0 .. $k - 1);

while (1) {

if (defined(my $res = $block->_run_code($self->new(@{$self}[@c])))) {
return $res;
}

next if ($c[$k - 1]++ < $n - 1);
my $i = $k - 2;
$i-- while ($i >= 0 && $c[$i] >= $n - ($k - $i));
last if $i < 0;
$c[$i]++;
while (++$i < $k) { $c[$i] = $c[$i - 1] + 1; }
}

return $self;
}
(@result, _combinations($n, @set));
}

sub combinations {
my ($self, $n) = @_;
Sidef::Types::Array::Array->new(map { Sidef::Types::Array::Array->new(@{$_}) } _combinations($n->get_value, @{$self}));
return $self->new($self->new) if $k == 0;
return if $k < 0;

my $n = @{$self};
return $self->new if ($k > $n or $n == 0);

my @c = (0 .. $k - 1);
my @result;

while (1) {
push @result, $self->new(@{$self}[@c]);
next if ($c[$k - 1]++ < $n - 1);
my $i = $k - 2;
$i-- while ($i >= 0 && $c[$i] >= $n - ($k - $i));
last if $i < 0;
$c[$i]++;
while (++$i < $k) { $c[$i] = $c[$i - 1] + 1; }
}

$self->new(@result);
}

*combination = \&combinations;
Expand Down
6 changes: 2 additions & 4 deletions scripts/RosettaCode/ordered_partitions.sf
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ func partitions({.is_empty}) { [[]] }

func part(s, args) {
var res = [];
var combs = s.combinations(args[0]);
combs << [] if combs.is_empty;
combs.each { |c|
s.combinations(args[0], { |c|
part(s - c, args.ft(1)).each{|r| res << ([c] + r)}
}
})
res
}

Expand Down

0 comments on commit be956e5

Please sign in to comment.