use warnings; use strict; my $desired_page_count = 10; # Structure holding all the different page layouts. ('l' = Landscape, 'p' = Portrait) my $pages = { ll => '01', pp => '02', lp => '03', pl => '04', lpp => '05', pll => '06', plp => '07', lpl => '08', lll => '09', ppp => '10', ppl => '11', llp => '12', ppll => '13', llpp => '14', }; # Construct a hash of regexen: each value is all the patterns except for the # key. This way, they don't need to be constructed repeatedly during the matching my @patterns = keys %$pages; my %all_except = map {my $k=$_; ($k => join '|', sort {rand(1) <=> rand(1)} grep {$_ ne $k} @patterns)} @patterns; my $photos = "llppllpplpppllplpplpplpllplpll"; # Make a really long layout $photos .= substr 'lp', rand 2 for 1..50; $desired_page_count = int( length($photos)/ 2.7 ); my $page_regex = join '|', sort {rand(1) <=> rand(1)} @patterns; my $regex = "^($page_regex)"; $regex .= "((??{\$all_except{\$$_}}))" for 1..($desired_page_count - 1); $regex .= "\$"; print "\$regex is $regex\n"; use re 'eval'; if (my @pages = $photos =~ /$regex/) { print "$pages->{$_}\n" for @pages; } else { print "Could not come up with no-repeat layout in $desired_page_count pages\n"; }