my @num = ( "0000", "0101", "1010", "1111" ); my ( $n1, $n2 ) = ( "0", "1" ); my $ndiff = abs( $n2 - $n1 ); for ( my $i = 0 ; $i < @num ; $i++ ) { for ( my $j = $i + 1 ; $j < @num ; $j++ ) { # Count oriented matches and mismatches along string print join( "\t", $num[$i], $num[$j], ( ( $num[$i] | $num[$j] ) =~ tr[0][0] ), #count 00 ( ( ~$num[$i] & $num[$j] ) =~ tr[\1][\1] ), #count 01 ( ( $num[$i] & ~$num[$j] ) =~ tr[\1][\1] ), #count 10 ( ( $num[$i] & $num[$j] ) =~ tr[1][1] ) #count 11 ), "\n"; # Attempt at flexible version via eval my ( $string1, $string2 ) = ( $num[$i], $num[$j] ); print join( "\t", $string1, $string2, ( eval "( $string1 | $string2 ) =~ tr[$n1][$n1]" ), ( eval "( ~$string1 & $string2 ) =~ tr[\$ndiff][\$ndiff]" ), ( eval "( $string1 & ~$string2 ) =~ tr[\$ndiff][\$ndiff]" ), ( eval "( $string1 & $string2 ) =~ tr[$n2][$n2]" ) ), "\n\n"; } } __END__ # Output from example # In each pair of lines, the first is the desired. 0000 0101 2 2 0 0 0000 0101 0 0 0 0 0000 1010 2 2 0 0 0000 1010 2 0 0 0 0000 1111 0 4 0 0 0000 1111 0 0 0 0 0101 1010 0 2 2 0 0101 1010 1 0 0 0 0101 1111 0 2 0 2 0101 1111 0 0 0 0 1010 1111 0 2 0 2 1010 1111 1 0 0 0