I want to compare two strings by counting how many common characters they have at the same position - but overall in all possible alignments of the two strings.
SeedRandom[1]
str1 = RandomInteger[{1, 26}, 90] /.
Thread[Range[26] -> CharacterRange["A", "Z"]] // StringJoin
str2 = RandomInteger[{1, 26}, 850] /.
Thread[Range[26] -> CharacterRange["A", "Z"]] // StringJoin
fu[x_, y_] :=
Module[{par = Partition[Characters[y], StringLength[x], 1, {1, 1}]},
Count[Flatten[(Transpose[{#, Characters[x]}] & /@ par), 1], {z_, z_}]
]
fu[str1, str2] // Timing
(*{0.046875, 3013}*)
This means that strings str1
and str2
have 3013
common characters in total in all possible alignments.
Can it be done more efficiently, perhaps without converting strings into lists?
{c1, c2} = Characters /@ {str1, str2}; Sum[Boole[c1[[i]] == c2[[j]]], {i, Length[c1]}, {j, Length[c2]}]
which also gives 3013? Or more compactly you could doTotal[Outer[Boole@*Equal, c1, c2], 2]
$\endgroup$fu[x_, y_] := Module[{ par = Partition[Characters[y], StringLength[x], 1, {1, 1}], len = StringLength[x] }, Total[len - HammingDistance[x, StringJoin[#]] & /@ par] ]
$\endgroup$