Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Highly Repetitive & Pattern Incrementing #4

Merged
merged 6 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions filters/highly_repetitive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
def break_and_compare(ls: list, k: int) -> list:
aflah02 marked this conversation as resolved.
Show resolved Hide resolved
"""
This function takes a list ls and an integer k as input and returns a list which is the first chunk of ls that is repeated k times. If no such chunk exists, it returns an empty list.

Parameters:

ls (list): The input list.
k (int): The integer value used for splitting and comparing the list.

Returns:

A list based on the comparisons and operations performed.

Algorithm:
1. Get the length of the input list and assign it to variable `n`.
2. Reduce the value of `n` until it is divisible by `k` without any remainder. This ensures that `n` is a multiple of `k`.
3. Create a new list `to_break` containing the first `n` elements of the input list `ls`.
4. Create a new list `residual` containing the remaining elements of `ls` beyond the first `n` elements.
5. Calculate the chunk size by dividing `n` by `k` and assign it to variable `chunk_size`.
6. Enter a loop that continues until the length of `residual` is equal to the calculated `chunk_size`.
- Split the `to_break` list into chunks of size `chunk_size` using list slicing and list comprehension, and assign the result to the `chunks` variable.
- Set the `chunksMatch` variable to `True`.
- Iterate through each chunk in `chunks` starting from the second chunk.
- If the current chunk is not equal to the first chunk, set `chunksMatch` to `False` and break the loop.
- Check if `chunksMatch` is still `True`.
- If so, compare the `residual` list to the first chunk, up to the length of `residual`.
- If they are equal, return the first chunk as the result.
- Decrease the `chunk_size` by 1 to try a smaller chunk size.
- Calculate the new `new_residual` list by slicing `to_break` starting from `chunk_size * k`.
- Update `to_break` to contain only elements up to `chunk_size * k`.
- Update `residual` by concatenating `new_residual` with the previous `residual`.
7. If the loop completes without returning a result, return an empty list `[]`.
"""
n = len(ls)
while n % k != 0:
n -= 1
to_break = ls[:n]
residual = ls[n:]
chunk_size = n // k
while len(residual) < chunk_size:
# split into chunks
chunks = [to_break[i:i + chunk_size] for i in range(0, len(to_break), chunk_size)]
chunksMatch = True
# compare all chunks to first chunk
for chunk in chunks[1:]:
if chunk != chunks[0]:
chunksMatch = False
break
if chunksMatch:
# compare residual to first chunk
if residual == chunks[0][:len(residual)]:
return chunks[0]
chunk_size -= 1
new_residual = to_break[chunk_size * k:]
to_break = to_break[:chunk_size * k]
residual = new_residual + residual
return []

def break_and_compare_wrapper(ls: list, start_k: int, end_k: int) -> list:
"""

This function serves as a wrapper for the `break_and_compare` function. It takes an additional two integer parameters `start_k` and `end_k` to define a range of values for `k`. It iterates over this range and calls `break_and_compare` for each value of `k` within the range.

Parameters:
- `ls` (list): The input list.
- `start_k` (int): The starting value of `k` for the range (inclusive).
- `end_k` (int): The ending value of `k` for the range (inclusive).

Returns:
- A tuple containing the result and the corresponding value of `k` if a result is found.
- If no result is found, it returns an empty list `[]` and -1.

Algorithm:
1. Convert the input list `ls` to a new list from any other iterable type.
2. Iterate over the range of values from `start_k` to `end_k` (inclusive) using a `for` loop with variable `k`.
3. Call the `break_and_compare` function with the input list `ls` and the current value of `k`, and assign the result to the `result` variable.
4. Check if the `result` is not an empty list (indicating a successful result).
- If so, return a tuple containing the `result` and the current value of `k`.
5. If no result is found within the range, return an empty list `[]` and -1 as a tuple.
"""
# end_k is inclusive
ls = list(ls)
for k in range(start_k, end_k + 1):
result = break_and_compare(ls, k)
if result:
return result, k
return [], -1
64 changes: 64 additions & 0 deletions filters/highly_repetitive_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from highly_repetitive import break_and_compare, break_and_compare_wrapper
# Test cases for break_and_compare

# Test case 1: Matching chunks exist
ls1 = [1, 2, 3, 1, 2, 3, 1, 2, 3]
k1 = 3
expected1 = [1, 2, 3]
output1 = break_and_compare(ls1, k1)
assert output1 == expected1, f"Test case 1 failed. Output: {output1}, Expected: {expected1}"
aflah02 marked this conversation as resolved.
Show resolved Hide resolved

# Test case 2: No matching chunks
ls2 = [1, 2, 3, 4, 5, 6, 7]
k2 = 3
expected2 = []
output2 = break_and_compare(ls2, k2)
assert output2 == expected2, f"Test case 2 failed. Output: {output2}, Expected: {expected2}"

# Test case 3: Empty list
ls3 = []
k3 = 4
expected3 = []
output3 = break_and_compare(ls3, k3)
assert output3 == expected3, f"Test case 3 failed. Output: {output3}, Expected: {expected3}"

# Test case 4: Chunk size larger than list length
ls4 = [1, 2, 3]
k4 = 4
expected4 = []
output4 = break_and_compare(ls4, k4)
assert output4 == expected4, f"Test case 4 failed. Output: {output4}, Expected: {expected4}"

# Test cases for break_and_compare_wrapper

# Test case 1: Matching chunks within the range
ls1 = [1, 2, 3, 1, 2, 3, 1, 2, 3]
start_k1 = 2
end_k1 = 4
expected_result1 = ([1, 2, 3], 3)
output_result1 = break_and_compare_wrapper(ls1, start_k1, end_k1)
assert output_result1 == expected_result1, f"Test case 1 failed. Output: {output_result1}, Expected: {expected_result1}"

# Test case 2: No matching chunks within the range
ls2 = [1, 2, 3, 4, 5, 6, 7]
start_k2 = 2
end_k2 = 5
expected_result2 = ([], -1)
output_result2 = break_and_compare_wrapper(ls2, start_k2, end_k2)
assert output_result2 == expected_result2, f"Test case 2 failed. Output: {output_result2}, Expected: {expected_result2}"

# Test case 3: Empty list with range
ls3 = []
start_k3 = 1
end_k3 = 3
expected_result3 = ([], -1)
output_result3 = break_and_compare_wrapper(ls3, start_k3, end_k3)
assert output_result3 == expected_result3, f"Test case 3 failed. Output: {output_result3}, Expected: {expected_result3}"

# Test case 4: Single-element list with range
ls4 = [1]
start_k4 = 1
end_k4 = 3
expected_result4 = ([1], 1)
output_result4 = break_and_compare_wrapper(ls4, start_k4, end_k4)
assert output_result4 == expected_result4, f"Test case 4 failed. Output: {output_result4}, Expected: {expected_result4}"