sub _derange { my( $cb, $todo, @v ) = @_; @$todo or return $cb->( @v ); my %seen; @seen{@v}=(); my( $range, @todo ) = @$todo; _derange( $cb, \@todo, @v, $_ ) for grep { ! exists $seen{$_} } @$range; } sub derange(&@) { my $cb = shift; _derange( $cb, [ map { my $x = $_; [ grep { $_ ne $x } @_ ] } @_ ] ); }