71 lines
3.1 KiB
Python
71 lines
3.1 KiB
Python
import collections
|
|
import pickle
|
|
|
|
def find_repeating_subsequences(data_sequence, max_length=10, min_repetitions=3):
|
|
"""
|
|
Analyzes a sequence of integers to find repeating subsequences (patterns).
|
|
|
|
The search checks subsequence lengths from 2 up to max_length.
|
|
|
|
Args:
|
|
data_sequence (list or tuple): The list of integer block widths.
|
|
max_length (int): The maximum length of a pattern to search for.
|
|
min_repetitions (int): The minimum number of times a pattern must repeat.
|
|
|
|
Returns:
|
|
dict: A dictionary where keys are the repeating patterns (as tuples)
|
|
and values are the count of their non-overlapping repetitions.
|
|
"""
|
|
|
|
# Store results in a dictionary: {pattern_tuple: count}
|
|
repeating_patterns = {}
|
|
n = len(data_sequence)
|
|
|
|
# 1. Iterate through all possible pattern lengths
|
|
for length in range(6, max_length + 1):
|
|
|
|
# Dictionary to count how often a subsequence of 'length' occurs
|
|
subsequence_counts = collections.defaultdict(int)
|
|
|
|
# 2. Iterate through the sequence, extracting all possible non-overlapping subsequences
|
|
# of the current 'length'. The step size is equal to the length to ensure
|
|
# non-overlapping, immediately-adjacent repetitions.
|
|
for i in range(0, n - length + 1, length):
|
|
subsequence = tuple(data_sequence[i:i + length])
|
|
|
|
# Check for immediate, adjacent repetition:
|
|
# Check if the current pattern matches the pattern from the previous step
|
|
if i >= length and subsequence == tuple(data_sequence[i - length: i]):
|
|
# If it's a repetition, increment the count for this existing pattern
|
|
subsequence_counts[subsequence] += 1
|
|
elif i < length or subsequence != tuple(data_sequence[i - length: i]):
|
|
# If it's the start of a new potential repetition sequence, initialize it to 1
|
|
# (since the outer loop advances by 'length', the counter starts at 1,
|
|
# meaning 'one instance' found so far).
|
|
pass
|
|
|
|
# 3. Filter and store significant repeating patterns
|
|
for pattern, count in subsequence_counts.items():
|
|
# The count stored is the number of *additional* times it repeated immediately
|
|
# after the first instance. We check for 'min_repetitions - 1' additional repetitions.
|
|
if count + 1 >= min_repetitions:
|
|
repeating_patterns[pattern] = count + 1
|
|
|
|
return repeating_patterns
|
|
|
|
with open('width_arr.pkl', 'rb') as f:
|
|
USER_DATA = pickle.load(f)
|
|
|
|
patterns = find_repeating_subsequences(USER_DATA, max_length=6, min_repetitions=2)
|
|
|
|
sorted_patterns = dict(sorted(patterns.items(), key=lambda item: item[1]))
|
|
|
|
if patterns:
|
|
print("\nFound the following repeating, adjacent patterns (Pattern: Count):")
|
|
for pattern, count in patterns.items():
|
|
print(f" Pattern: {pattern} repeated {count} times.")
|
|
else:
|
|
print("\nNo immediately adjacent patterns found with the specified criteria.")
|
|
|
|
print((len(USER_DATA)-2) / 6)
|