'Finding repetitions of a string by length
I have a string of letters similar to that shown below:
'ABTSOFDNSOHASAPMAPDSNFAKSGMOMAPEPTNSNTROMAPKSDFANSDHASOMAPDODDFG'
I am treating this as a cipher text and therefore want to begin to find the position of repetitions in order to find the length of the encryption key (the example above is random so no direct answers will come from it)
For now what I want to be able to do is write a code that can find repetitions of length 3 - for example 'MAP' and 'HAS' are repeated. I want the code to find these repetitions as opposed to me having to specify the substring it should look for.
Previously I have used:
text.find("MAP")
Using the answer below I have written:
substring = []
for i in range(len(Phrase)-4):
substring.append(Phrase[i:i+4])
for index, value in freq.iteritems():
if value > 1:
for i in range(len(Phrase)-4):
if index == Phrase[i:i+4]:
print(index)
This gives a list of each repeated substring as many times as it appears, ideally I want this to just be a list of the substring with the positions it appears in
Solution 1:[1]
Here is a solution using only built-ins
import itertools, collections
text = 'ABTSOFDNSOHASAPMAPDSNFAKSGMOMAPEPTNSNTROMAPKSDFANSDHASOMAPDODDFG'
Make a function that will produce overlapping chunks of three - inspired by the pairwise function.
def three_at_a_time(text):
'''Overlapping chunks of three.
text : str
returns generator
'''
a,b,c = itertools.tee(text,3)
# advance the second and third iterators
next(b)
next(c)
next(c)
return (''.join(t) for t in zip(a,b,c))
Make a dictionary with the position(s) of each chunk.
triples = enumerate(three_at_a_time(text))
d = collections.defaultdict(list)
for i,triple in triples:
d[triple].append(i)
Filter the dictionary for chunks that have more than one position.
# repeats = itertools.filterfalse(lambda item: len(item[1])==1,d.items())
repeats = [(k,v) for k,v in d.items() if len(v)>1]
Example:
>>> for chunk in repeats:
... print(chunk)
...
('HAS', [10, 51])
('MAP', [15, 28, 40, 55])
('OMA', [27, 39, 54])
('APD', [16, 56])
>>>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
