Skip to content
Closed
96 changes: 96 additions & 0 deletions strings/wildcard_pattern_matching_fft.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import numpy as np
from numpy.fft import fft, ifft

def preprocess_text_and_pattern(text, pattern):

Check failure on line 4 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

strings/wildcard_pattern_matching_fft.py:1:1: I001 Import block is un-sorted or un-formatted
"""Preprocesses text and pattern for pattern matching.

Args:
text: The input text string.
pattern: The input pattern string, potentially containing wildcards ('*').

Returns:
A tuple containing:
- A list of integers representing the text characters.
- A list of integers representing the pattern characters, with 0 for wildcards.

Check failure on line 14 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

strings/wildcard_pattern_matching_fft.py:14:89: E501 Line too long (91 > 88)
"""

unique_chars = set(text + pattern)
char_to_int = {char: i + 1 for i, char in enumerate(unique_chars)} # Unique non-zero integers

Check failure on line 18 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

strings/wildcard_pattern_matching_fft.py:18:89: E501 Line too long (98 > 88)

# Replace pattern '*' with 0, other characters with their unique integers
pattern_int = [char_to_int[char] if char != '*' else 0 for char in pattern]
text_int = [char_to_int[char] for char in text]

return text_int, pattern_int

def fft_convolution(a, b):
"""Performs convolution using the Fast Fourier Transform (FFT).

Args:
a: The first sequence.
b: The second sequence.

Returns:
The convolution of the two sequences.
"""

n = len(a) + len(b) - 1
A = fft(a, n)

Check failure on line 38 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (N806)

strings/wildcard_pattern_matching_fft.py:38:5: N806 Variable `A` in function should be lowercase
B = fft(b, n)

Check failure on line 39 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (N806)

strings/wildcard_pattern_matching_fft.py:39:5: N806 Variable `B` in function should be lowercase
return np.real(ifft(A * B))

def compute_A_fft(text_int, pattern_int):

Check failure on line 42 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (N802)

strings/wildcard_pattern_matching_fft.py:42:5: N802 Function name `compute_A_fft` should be lowercase
"""Computes the A array for the pattern matching algorithm.

Args:
text_int: The integer representation of the text.
pattern_int: The integer representation of the pattern.

Returns:
The A array.
"""

n = len(text_int)
m = len(pattern_int)

# Power transforms of the pattern and text based on the formula
p1 = np.array(pattern_int)
p2 = np.array([p**2 for p in pattern_int])
p3 = np.array([p**3 for p in pattern_int])

t1 = np.array(text_int)
t2 = np.array([t**2 for t in text_int])
t3 = np.array([t**3 for t in text_int])

# Convolution to calculate the terms for A[i]
sum1 = fft_convolution(p3[::-1], t1)
sum2 = fft_convolution(p2[::-1], t2)
sum3 = fft_convolution(p1[::-1], t3)

# Calculate A[i] using the convolution results
A = sum1[:n - m + 1] - 2 * sum2[:n - m + 1] + sum3[:n - m + 1]

Check failure on line 71 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (N806)

strings/wildcard_pattern_matching_fft.py:71:5: N806 Variable `A` in function should be lowercase

return A

# Main function to run the matching
if __name__ == "__main__":

import doctest
doctest.testmod()
# Get text and pattern as input from the user
# text = input("Enter the text: ")
# pattern = input("Enter the pattern (use '*' for wildcard): ")

text = "abcabc"
pattern = "abc*"




text_int, pattern_int = preprocess_text_and_pattern(text, pattern)
A = compute_A_fft(text_int, pattern_int)

# Matches occur where A[i] == 0
matches = [i for i in range(len(A)) if np.isclose(A[i], 0)]
print("Pattern matches at indices:", matches)

Check failure on line 96 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

strings/wildcard_pattern_matching_fft.py:96:1: W293 Blank line contains whitespace

Check failure on line 96 in strings/wildcard_pattern_matching_fft.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W292)

strings/wildcard_pattern_matching_fft.py:96:5: W292 No newline at end of file
Loading