Files
ctf/2025/hack.lu/rev/FLAN/find_patterns.py
2025-10-19 20:35:43 +02:00

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)