How do I make it simpler and faster?
A more efficient approach:
- Iterate on
piwith a sliding window of sizen. - Save each sequence (and the starting position) in a lookup map
- Return as soon as you find a match in the lookup map
Something like this:
def repeats(n):
lookup = {}
pi_s = str(pi)[2:]
for i in range(n, len(pi_s)):
start = i - n
seq = pi_s[start:i]
if seq in lookup:
return list(map(int, seq)), lookup[seq], start
lookup[seq] = start
For n=5 this runs in 0.001 seconds, while your approach takes ~40 seconds.
For n=10 and 1 million digits, this approach finds ([4, 3, 9, 2, 3, 6, 6, 4, 8, 4], 182104, 240478) in ~50 seconds. The slowest part now seems to be str(pi), which generates the digits. Once the digits are generated, searching for the sequence with this approach takes less than a second.
Review
- Naming: the function name
repeatsis a bit ambiguous, it sounds like how many timesnappears in the sequence. A better name could befirst_repeating_sequence_of. - Edge case: for bigger
n, more digits of pi are required, otherwise no matches are found. Consider passing the max number of digits of pi as an argument so the caller is aware of this limit.