use Data::Dumper; my $site1 = 'AATKKM' x 20; my $site2 = 'GGGGGA' x 20; # brute force my (%hash, $loops); for my $base1( split //, $site1 ) { for my $base2( split //, $site2 ) { $hash{"${base1}_$base2"}++; $loops++; } } # precount incidence of tokens my (%s1, %s2, %hash_e, $loops_e); do{ $s1{$_}++; $loops_e++ } for split //, $site1; do{ $s2{$_}++; $loops_e++ } for split //, $site2; # still loop within loop but the are now far fewer loops to do # as we only do one per token pair and calculate the total pairs # from our precount data for my $base1( keys %s1 ) { for my $base2( keys %s2 ) { $hash_e{"${base1}_$base2"} = $s1{$base1}*$s2{$base2}; $loops_e++; } } print "Brute force loops $loops\nEfficeient Loops $loops_e\n\n"; print Data::Dumper->Dump([\%hash, \%s1, \%s2, \%hash_e], [qw( hash s1 s2 hash_e)] ); __DATA__ Brute force loops 14400 Efficeient Loops 248 $hash = { 'T_G' => '2000', 'A_A' => '800', 'T_A' => '400', 'M_G' => '2000', 'M_A' => '400', 'K_G' => '4000', 'K_A' => '800', 'A_G' => '4000' }; $s1 = { 'A' => '40', 'K' => '40', 'T' => '20', 'M' => '20' }; $s2 = { 'G' => '100', 'A' => '20' }; $hash_e = { 'T_G' => '2000', 'A_A' => '800', 'T_A' => '400', 'M_G' => '2000', 'M_A' => '400', 'K_G' => '4000', 'K_A' => '800', 'A_G' => '4000' };