@pytest.mark.parametrize("array, k, expected", [([1, 2, 3, 4, 5, 6, 7], 3, [3, 4, 5, 6, 1, 2])])
def test_rotate(array, k, expected):
    assert rotate(array, k) == expected


@pytest.mark.parametrize("s, expected", [(",,,,,,,,,,,,acva", False)])
def test_palindrome(s, expected):
    assert isPalindrome(s) == expected


@pytest.mark.parametrize("s, expected", [(",,,,,,,,,,,,acva", False)])
def test_text_to_telex_encoding(s, expected):
    assert text_to_telex_encoding(s) == expected




def isPalindrome(s: str) -> bool:
    left = 0
    i = len(s) - 1
    while i >= 0 and left < i:
        if s[i].isalnum() and s[left].isalnum():
            if s[i].lower() != s[left].lower():
                return False
            while left < i:
                left += 1
                if s[left].isalnum():
                    break
        i -= 1
    return True


def rotate(nums: list[int], k: int) -> None:
    k = k % len(nums)
    startIndex = len(nums) - k
    left = 0
    if k == 1:
        for x in range(0, len(nums) - 1):
            nums[x], nums[len(nums) - 1] = nums[len(nums) - 1], nums[x]
        return
    for right in range(startIndex, len(nums)):
        nums[left], nums[right] = nums[right], nums[left]
        left += 1

    def reverse(left, right):
        while left < right:
            nums[left], nums[right] = nums[right], nums[left]
            left += 1
            right -= 1

    reverse(k, len(nums) - 1)


def a_by_dd_remove_b(s: str) -> None:
    write_idx = 0
    curr_idx = 0
    a_count = 0
    while curr_idx < len(s):
        if s[curr_idx] != "b":
            s[write_idx] = s[curr_idx]
            write_idx += 1
        if s[curr_idx] == "a":
            a_count += 1

    curr_idx = write_idx - 1
    write_idx += a_count - 1
    final_size = write_idx + 1
    while curr_idx >= 0:
        if s[curr_idx] == "a":
            s[write_idx - 1 : write_idx + 1] = "dd"
            write_idx -= 2
        else:
            s[write_idx] = s[curr_idx]
            write_idx -= 1
        curr_idx -= 1
    return final_size


def text_to_telex_encoding(size: int, s: list[str]) -> int:
    ex_mark, ex_mark_len = "EXCLAMATION MARK", 13
    dot, dot_len = "DOT", 3
    comma, comma_len = "COMMA", 5
    q_mark, q_mark_len = "QUESTION MARK", 13

    def is_punctuation(ch) -> bool:
        if ch == "!" or ch == "?" or ch == "," or ch == ".":
            return True
        return False

    cnt = 0

    for i in range(len(s)):
        if s[i] == "!":
            cnt += ex_mark_len
        elif s[i] == ",":
            cnt += comma_len
        elif s[i] == ".":
            cnt += dot_len
        elif s[i] == "?":
            cnt += q_mark_len
        else:
            cnt += 1

    curr_idx = len(s) - 1
    write_idx = cnt - 1
    s.extend([None] * cnt - len(s))

    while curr_idx >= 0 and write_idx > curr_idx:
        if not is_punctuation(s[curr_idx]):
            s[write_idx] = s[curr_idx]
            write_idx -= 1
            curr_idx -= 1
        else:
            if s[curr_idx] == "!":
                s[write_idx - ex_mark : write_idx + 1] = ex_mark
            elif s[curr_idx] == ",":
                s[write_idx - comma_len, : write_idx + 1] = comma
            elif s[curr_idx] == ".":
                s[write_idx - dot_len : write_idx + 1] = dot
            elif s[curr_idx] == "?":
                s[write_idx - q_mark_len : write_idx + 1] = q_mark
    return len(s)
