use 5.12.0; use strict; use warnings; use Data::Dump qw/pp dd/; use Test::More; my $ones = 3; my $len = 5; my @res; my ($zero,$one) = ('0','1'); # optimize dual case if ($ones > $len/2) { ($zero,$one) = ($one,$zero); $ones = $len-$ones; } my $max = $len - 1; our $str = $zero x $len; our $level = 0; rec(0); pp \@res; sub rec { local $level = $level + 1; my ($start) =@_; for my $idx ( $start .. $max ) { local $str = $str; substr $str, $idx, 1, $one; if ($level < $ones) { rec( $idx + 1 ); } else { push @res, $str; } } }