I'm doing some frequency analysis on an encrypted plaintext. Tally[] and Characters[] make the basic task quite easy. To count the number of times each character appears (sorted alphabetically; Plaintext has been pre-sanitized), I can carry out
Sort[Tally[Characters[Plaintext], #1[[2]] > #2[[2]] &]
For a more nuanced cryptanalytic approach, I will also want to count the frequency of each digraph (pair of adjacent characters), trigraph (triple of same), ..., n-graph. Tally[] will still work fine here, but the original splitting task (previously performed by Characters[]) is slightly more complicated. I want a functionnGraphList[PTstring_String, Chunklength_Integer]
that outputs a list (including repeats) of the Chunklength-graphs found in PTstring. When Chunklength = 1, the function should give identical output to Characters[].
Okay, so the problem isn't really that hard. A quick approach is
nGraphList[PTstring_String, Chunklength_Integer]:=
Table[
StringTake[PTstring, {k, k + Chunklength - 1}],
{k, 1, StringLength[PTstring] - Chunklength + 1}]
The thing drives me crazy, though. It seems like a terribly easy string operation of the sort Mathematica would be able to do in a snap. My solution is clunky, and I can't find any better ideas in the documentation or here. Can you show any different ways to do this? Any smarter or prettier ways?
Related: Clif's question hints at possible usage of stream methods, but 1) I know little on the subject and 2) it looks equally if not more clunky.
StringCases[string, Repeated[_, {n}], Overlaps -> All]
for your application. $\endgroup$