internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: TheAlgorithms/Python

Issue:
[PYTEST WARNING] QasmSimulator will be deprecated
### Feature description

The use of `q.Aer.get_backend("qasm_simulator")` raises the warning
```
/opt/hostedtoolcache/Python/3.10.7/x64/lib/python3.10/site-packages/qiskit_aer/backends/qasm_simulator.py:360: PendingDeprecationWarning: The `QasmSimulator` backend will be deprecated in the future. It has been superseded by the `AerSimulator` backend.
    warn('The `QasmSimulator` backend will be deprecated in the'
```
This code is found in the following files:
    - deutsch_jozsa @abhishekjiitr 
    - half_adder @abhishekjiitr 
    - not_gate @abhishekjiitr 
    - single_quibit_measure @abhishekjiitr 

origin: #7211


Discussion:

Resolving patch:
diff --git a/quantum/superdense_coding.py b/quantum/superdense_coding.py
--- a/quantum/superdense_coding.py
+++ b/quantum/superdense_coding.py
@@ -92,7 +92,7 @@ def superdense_coding(bit_1: int = 1, bit_2: int = 1) -> qiskit.result.counts.Co
     # measure the circuit
     quantum_circuit.measure(qr, cr)
 
-    backend = Aer.get_backend("qasm_simulator")
+    backend = Aer.get_backend("aer_simulator")
     job = execute(quantum_circuit, backend, shots=1000)
 
     return job.result().get_counts(quantum_circuit)


Test patch:
Repository: TheAlgorithms/Python

Issue:
Revert "Create guess_the_number_search.py"
Reverts TheAlgorithms/Python#7937
@ChrisO345 the algorithm you merged failed tests, you shouldn't have merged it

> https://github.com/TheAlgorithms/Python/actions/runs/4997927546/jobs/8952811360
> https://results.pre-commit.ci/run/github/63476337/1684282951.oykZY7Z4R3qR94KO0YZS2Q


Discussion:

Resolving patch:
diff --git a/other/guess_the_number_search.py b/other/guess_the_number_search.py
--- a/other/guess_the_number_search.py
+++ b/other/guess_the_number_search.py
@@ -148,7 +148,7 @@ def answer(number: int) -> str:
             break
 
     print(f"guess the number : {last_numbers[-1]}")
-    print(f"details : {str(last_numbers)}")
+    print(f"details : {last_numbers!s}")
 
 
 def main() -> None:


Test patch:
Repository: TheAlgorithms/Python

Issue:
I found typo in graphs/greedy_best_first
### What would you like to share?

The dx and dy are reversed!
https://github.com/TheAlgorithms/Python/blob/ce43a8ac4ad14e1639014d374b1137906218cfe3/graphs/greedy_best_first.py#L61-L63

Expected correction
```python
dx = abs(self.pos_x - self.goal_x)
dy = abs(self.pos_y - self.goal_y)
return dx + dy
```

### Additional information

_No response_


Discussion:

Resolving patch:
diff --git a/graphs/greedy_best_first.py b/graphs/greedy_best_first.py
--- a/graphs/greedy_best_first.py
+++ b/graphs/greedy_best_first.py
@@ -58,8 +58,8 @@ def calculate_heuristic(self) -> float:
         The heuristic here is the Manhattan Distance
         Could elaborate to offer more than one choice
         """
-        dy = abs(self.pos_x - self.goal_x)
-        dx = abs(self.pos_y - self.goal_y)
+        dx = abs(self.pos_x - self.goal_x)
+        dy = abs(self.pos_y - self.goal_y)
         return dx + dy
 
     def __lt__(self, other) -> bool:


Test patch:
Repository: TheAlgorithms/Python

Issue:
Strassen matrix multiplication broken
### Repository commit

e4ecefabe0448f7c5d643f34aa2cef9d1246598e

### Python version (python --version)

Python 3.11.3

### Dependencies version (pip freeze)

-

### Expected behavior

-

### Actual behavior

Argument of type "tuple[int, int]" cannot be assigned to parameter "__x" of type "_SupportsFloatOrIndex" in function "log2"
  Type "tuple[int, int]" cannot be assigned to type "_SupportsFloatOrIndex"
    "tuple[int, int]" is incompatible with protocol "SupportsFloat"
      "__float__" is not present
    "tuple[int, int]" is incompatible with protocol "SupportsIndex"
      "__index__" is not presentPylance[reportGeneralTypeIssues](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportGeneralTypeIssues)
(variable) maximum: tuple[int, int]

divide_and_conquer/strassen_matrix_multiplication.py
line 126


Discussion:

Resolving patch:
diff --git a/divide_and_conquer/strassen_matrix_multiplication.py.BROKEN b/divide_and_conquer/strassen_matrix_multiplication.py
similarity index 97%
rename from divide_and_conquer/strassen_matrix_multiplication.py.BROKEN
rename to divide_and_conquer/strassen_matrix_multiplication.py
--- a/divide_and_conquer/strassen_matrix_multiplication.py.BROKEN
+++ b/divide_and_conquer/strassen_matrix_multiplication.py
@@ -112,17 +112,19 @@ def strassen(matrix1: list, matrix2: list) -> list:
     [[139, 163], [121, 134], [100, 121]]
     """
     if matrix_dimensions(matrix1)[1] != matrix_dimensions(matrix2)[0]:
-        raise Exception(
-            "Unable to multiply these matrices, please check the dimensions. \n"
-            f"Matrix A:{matrix1} \nMatrix B:{matrix2}"
+        msg = (
+            "Unable to multiply these matrices, please check the dimensions.\n"
+            f"Matrix A: {matrix1}\n"
+            f"Matrix B: {matrix2}"
         )
+        raise Exception(msg)
     dimension1 = matrix_dimensions(matrix1)
     dimension2 = matrix_dimensions(matrix2)
 
     if dimension1[0] == dimension1[1] and dimension2[0] == dimension2[1]:
         return [matrix1, matrix2]
 
-    maximum = max(dimension1, dimension2)
+    maximum = max(*dimension1, *dimension2)
     maxim = int(math.pow(2, math.ceil(math.log2(maximum))))
     new_matrix1 = matrix1
     new_matrix2 = matrix2


Test patch:
Repository: TheAlgorithms/Python

Issue:
Other Activation Functions
### Feature description

Hi, I'm relatively new to open source and found this repo friendly for early contributions. But is there a reason as to why there are only two activations (ELU and Leaky ReLU), under neural_network / activation_functions.? Also, can I contribute new activations into it?


Discussion:

Resolving patch:
diff --git a/neural_network/activation_functions/scaled_exponential_linear_unit.py b/neural_network/activation_functions/scaled_exponential_linear_unit.py
new file mode 100644
--- /dev/null
+++ b/neural_network/activation_functions/scaled_exponential_linear_unit.py
@@ -0,0 +1,44 @@
+"""
+Implements the Scaled Exponential Linear Unit or SELU function.
+The function takes a vector of K real numbers and two real numbers
+alpha(default = 1.6732) & lambda (default = 1.0507) as input and
+then applies the SELU function to each element of the vector.
+SELU is a self-normalizing activation function. It is a variant
+of the ELU. The main advantage of SELU is that we can be sure
+that the output will always be standardized due to its
+self-normalizing behavior. That means there is no need to
+include Batch-Normalization layers.
+References :
+https://iq.opengenus.org/scaled-exponential-linear-unit/
+"""
+
+import numpy as np
+
+
+def scaled_exponential_linear_unit(
+    vector: np.ndarray, alpha: float = 1.6732, lambda_: float = 1.0507
+) -> np.ndarray:
+    """
+    Applies the Scaled Exponential Linear Unit function to each element of the vector.
+    Parameters :
+        vector : np.ndarray
+        alpha : float (default = 1.6732)
+        lambda_ : float (default = 1.0507)
+
+    Returns : np.ndarray
+    Formula : f(x) = lambda_ * x if x > 0
+                     lambda_ * alpha * (e**x - 1) if x <= 0
+    Examples :
+    >>> scaled_exponential_linear_unit(vector=np.array([1.3, 3.7, 2.4]))
+    array([1.36591, 3.88759, 2.52168])
+
+    >>> scaled_exponential_linear_unit(vector=np.array([1.3, 4.7, 8.2]))
+    array([1.36591, 4.93829, 8.61574])
+    """
+    return lambda_ * np.where(vector > 0, vector, alpha * (np.exp(vector) - 1))
+
+
+if __name__ == "__main__":
+    import doctest
+
+    doctest.testmod()


Test patch:
Repository: TheAlgorithms/Python

Issue:
Returning index instead of boolean when knuth_morris_pratt matches.
In [knuth morris pratt algorithm](https://github.com/TheAlgorithms/Python/blob/master/strings/knuth_morris_pratt.py), I think it's better to return the "index" of the matched substring in case of success, and `-1` in case of failure, so that it would be consistent with the `str.find()` in Python. `True` and `False` aren't that helpful.


Discussion:

Resolving patch:
diff --git a/strings/knuth_morris_pratt.py b/strings/knuth_morris_pratt.py
--- a/strings/knuth_morris_pratt.py
+++ b/strings/knuth_morris_pratt.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 
-def kmp(pattern: str, text: str) -> bool:
+def knuth_morris_pratt(text: str, pattern: str) -> int:
     """
     The Knuth-Morris-Pratt Algorithm for finding a pattern within a piece of text
     with complexity O(n + m)
@@ -14,6 +14,12 @@ def kmp(pattern: str, text: str) -> bool:
     2) Step through the text one character at a time and compare it to a character in
         the pattern updating our location within the pattern if necessary
 
+    >>> kmp = "knuth_morris_pratt"
+    >>> all(
+    ...    knuth_morris_pratt(kmp, s) == kmp.find(s)
+    ...    for s in ("kn", "h_m", "rr", "tt", "not there")
+    ... )
+    True
     """
 
     # 1) Construct the failure array
@@ -24,7 +30,7 @@ def kmp(pattern: str, text: str) -> bool:
     while i < len(text):
         if pattern[j] == text[i]:
             if j == (len(pattern) - 1):
-                return True
+                return i - j
             j += 1
 
         # if this is a prefix in our pattern
@@ -33,7 +39,7 @@ def kmp(pattern: str, text: str) -> bool:
             j = failure[j - 1]
             continue
         i += 1
-    return False
+    return -1
 
 
 def get_failure_array(pattern: str) -> list[int]:
@@ -57,27 +63,38 @@ def get_failure_array(pattern: str) -> list[int]:
 
 
 if __name__ == "__main__":
+    import doctest
+
+    doctest.testmod()
+
     # Test 1)
     pattern = "abc1abc12"
     text1 = "alskfjaldsabc1abc1abc12k23adsfabcabc"
     text2 = "alskfjaldsk23adsfabcabc"
-    assert kmp(pattern, text1) and not kmp(pattern, text2)
+    assert knuth_morris_pratt(text1, pattern) and knuth_morris_pratt(text2, pattern)
 
     # Test 2)
     pattern = "ABABX"
     text = "ABABZABABYABABX"
-    assert kmp(pattern, text)
+    assert knuth_morris_pratt(text, pattern)
 
     # Test 3)
     pattern = "AAAB"
     text = "ABAAAAAB"
-    assert kmp(pattern, text)
+    assert knuth_morris_pratt(text, pattern)
 
     # Test 4)
     pattern = "abcdabcy"
     text = "abcxabcdabxabcdabcdabcy"
-    assert kmp(pattern, text)
+    assert knuth_morris_pratt(text, pattern)
+
+    # Test 5) -> Doctests
+    kmp = "knuth_morris_pratt"
+    assert all(
+        knuth_morris_pratt(kmp, s) == kmp.find(s)
+        for s in ("kn", "h_m", "rr", "tt", "not there")
+    )
 
-    # Test 5)
+    # Test 6)
     pattern = "aabaabaaa"
     assert get_failure_array(pattern) == [0, 1, 0, 1, 2, 3, 4, 5, 2]


Test patch:
Repository: TheAlgorithms/Python

Issue:
Remove duplicate GCD implementation
### Feature description

[`greatest_common_divisor.py`](https://github.com/TheAlgorithms/Python/blob/master/maths/greatest_common_divisor.py) and [`euclidean_gcd.py`](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_gcd.py) both have basically the same two implementations of the Euclidean algorithm for calculating the GCD of 2 numbers. Thus, one of them should probably be removed as a duplicate.


Discussion:
@cclauss which one we should keep 
Hey, I am Arhama . I  am a beginner  in open source contribution. I think I  Can work on this issue. can you assign me this work.  
> can you assign me this work.

https://github.com/TheAlgorithms/Python/pull/8871/files

My preference would be to delete the file whose name uses the gcd acronym and keep the file whose name is self-documenting (as #8078 attempted to do).
* #8078
Hey, is this still an issue to work on if yes can I do it

@HimanshuMahto Read the [contributing guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md#contribution).
> If you are interested in resolving an open issue, simply make a pull request with your proposed fix. **We do not assign issues in this repo** so please do not ask for permission to work on an issue.

Resolving patch:
diff --git a/maths/euclidean_gcd.py b/maths/euclidean_gcd.py
deleted file mode 100644
--- a/maths/euclidean_gcd.py
+++ /dev/null
@@ -1,47 +0,0 @@
-""" https://en.wikipedia.org/wiki/Euclidean_algorithm """
-
-
-def euclidean_gcd(a: int, b: int) -> int:
-    """
-    Examples:
-    >>> euclidean_gcd(3, 5)
-    1
-
-    >>> euclidean_gcd(6, 3)
-    3
-    """
-    while b:
-        a, b = b, a % b
-    return a
-
-
-def euclidean_gcd_recursive(a: int, b: int) -> int:
-    """
-    Recursive method for euclicedan gcd algorithm
-
-    Examples:
-    >>> euclidean_gcd_recursive(3, 5)
-    1
-
-    >>> euclidean_gcd_recursive(6, 3)
-    3
-    """
-    return a if b == 0 else euclidean_gcd_recursive(b, a % b)
-
-
-def main():
-    print(f"euclidean_gcd(3, 5) = {euclidean_gcd(3, 5)}")
-    print(f"euclidean_gcd(5, 3) = {euclidean_gcd(5, 3)}")
-    print(f"euclidean_gcd(1, 3) = {euclidean_gcd(1, 3)}")
-    print(f"euclidean_gcd(3, 6) = {euclidean_gcd(3, 6)}")
-    print(f"euclidean_gcd(6, 3) = {euclidean_gcd(6, 3)}")
-
-    print(f"euclidean_gcd_recursive(3, 5) = {euclidean_gcd_recursive(3, 5)}")
-    print(f"euclidean_gcd_recursive(5, 3) = {euclidean_gcd_recursive(5, 3)}")
-    print(f"euclidean_gcd_recursive(1, 3) = {euclidean_gcd_recursive(1, 3)}")
-    print(f"euclidean_gcd_recursive(3, 6) = {euclidean_gcd_recursive(3, 6)}")
-    print(f"euclidean_gcd_recursive(6, 3) = {euclidean_gcd_recursive(6, 3)}")
-
-
-if __name__ == "__main__":
-    main()


Test patch:
Repository: TheAlgorithms/Python

Issue:
issue with permute_recursive
### What would you like to share?

Your code looks mostly correct, but there's one issue in the `permute_recursive` function due to the modification of the `nums` list. Lists in Python are mutable, and when you use `nums.pop(0)`, it modifies the original `nums` list. This can lead to incorrect results and even an infinite loop.

To fix this, you should pass a copy of the `nums` list to the recursive function. Here's the corrected `permute_recursive` function:


def permute_recursive(nums: list[int]) -> list[list[int]]:
    """
    Return all permutations.

    >>> permute_recursive([1, 2, 3])
    [[3, 2, 1], [2, 3, 1], [1, 3, 2], [3, 1, 2], [2, 1, 3], [1, 2, 3]]
    """
    result: list[list[int]] = []
    if len(nums) == 0:
        return [[]]
    for _ in range(len(nums)):
        n = nums.pop(0)
        permutations = permute_recursive(nums[:])  # Make a copy of nums
        for perm in permutations:
            perm.append(n)
        result.extend(permutations)
        nums.append(n)
    return result
```

With this modification, your code should work correctly for both `permute_recursive` and `permute_backtrack`.

### Additional information

_No response_


Discussion:
def generate_permutations(nums):
    def backtrack(start):
        if start == len(nums):
            result.append(nums[:])
            return
        for i in range(start, len(nums)):
            nums[start], nums[i] = nums[i], nums[start]  # Swap elements
            backtrack(start + 1) 
 # Recurse
            nums[start], nums[i] = nums[i], nums[start]  # Backtrack
            
    result = []
    backtrack(0)
    return result

# Example usage
input_nums = [1, 2, 3]
permutations = generate_permutations(input_nums)
print(permutations)

I think it's more readable to make the list copy using `nums.copy()`. Feel free to open a PR to make this fix.
Hey. I have added a PR #9115 fixing this issue. As you mentioned, I have used nums.copy() to pass a copy of the nums list. Please review it. Thanks.

Resolving patch:
diff --git a/data_structures/arrays/permutations.py b/data_structures/arrays/permutations.py
--- a/data_structures/arrays/permutations.py
+++ b/data_structures/arrays/permutations.py
@@ -10,7 +10,7 @@ def permute_recursive(nums: list[int]) -> list[list[int]]:
         return [[]]
     for _ in range(len(nums)):
         n = nums.pop(0)
-        permutations = permute_recursive(nums)
+        permutations = permute_recursive(nums.copy())
         for perm in permutations:
             perm.append(n)
         result.extend(permutations)
@@ -43,6 +43,6 @@ def backtrack(start: int) -> None:
 if __name__ == "__main__":
     import doctest
 
-    res = permute_backtrack([1, 2, 3])
-    print(res)
+    result = permute_backtrack([1, 2, 3])
+    print(result)
     doctest.testmod()


Test patch:
Repository: TheAlgorithms/Python

Issue:
sorts/random_normal_distribution_quicksort.py has no tests
### Repository commit

3

### Python version (python --version)

Python 3.11.5

### Dependencies version (pip freeze)

Numpy

### Expected behavior

Tests.

### Actual behavior

No tests.


Discussion:
@prateekiiest
Explain a bit more about this problem. Maybe I can help.
If its regarding coming up with viable test cases and ensure running of the algortihm, I can help out!

Please read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md) to understand what this repo requires for tests.
Hey, Im'ma take this problem up.
As discussed in [CONTRIBUTING.md](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md), we do NOT assign issues.  We review pull requests.
@cclauss I think this file should be deleted entirely. It's just an implementation of quicksort with a random pivot (which we already have), and the only difference is that the _array elements_ themselves follow a normal distribution. For all intents and purposes, it's a duplicate of [sorts/random_pivot_quick_sort.py](https://github.com/TheAlgorithms/Python/blob/dec96438be1a165eaa300a4d6df33e338b4e44c6/sorts/random_pivot_quick_sort.py).
@tianyizheng02 hi, I am a beginner in open source and it is my first time contributing in a big repo like this. So I deleted the file random_normal_distribution_quicksort.py which you said is a copy of the random_pivot_quicksort.py . If I have made any mistakes please feel free to inform me, Thank you.

Resolving patch:
diff --git a/sorts/random_pivot_quick_sort.py b/sorts/random_pivot_quick_sort.py
deleted file mode 100644
--- a/sorts/random_pivot_quick_sort.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-Picks the random index as the pivot
-"""
-import random
-
-
-def partition(a, left_index, right_index):
-    pivot = a[left_index]
-    i = left_index + 1
-    for j in range(left_index + 1, right_index):
-        if a[j] < pivot:
-            a[j], a[i] = a[i], a[j]
-            i += 1
-    a[left_index], a[i - 1] = a[i - 1], a[left_index]
-    return i - 1
-
-
-def quick_sort_random(a, left, right):
-    if left < right:
-        pivot = random.randint(left, right - 1)
-        a[pivot], a[left] = (
-            a[left],
-            a[pivot],
-        )  # switches the pivot with the left most bound
-        pivot_index = partition(a, left, right)
-        quick_sort_random(
-            a, left, pivot_index
-        )  # recursive quicksort to the left of the pivot point
-        quick_sort_random(
-            a, pivot_index + 1, right
-        )  # recursive quicksort to the right of the pivot point
-
-
-def main():
-    user_input = input("Enter numbers separated by a comma:\n").strip()
-    arr = [int(item) for item in user_input.split(",")]
-
-    quick_sort_random(arr, 0, len(arr))
-
-    print(arr)
-
-
-if __name__ == "__main__":
-    main()


Test patch:
Repository: TheAlgorithms/Python

Issue:
Concatenate/consolidate all algorithms with different implementations
### Feature description

There are lots of algorithms with the same concept but different implementations/methods in different files. All these should be moved into one file


Discussion:
hello sir
Can I take this issue.

@CaedenPH Please assign this task to me.
@digital-dev-07 Read the [contributing guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md#contribution).
> If you are interested in resolving an [open issue](https://github.com/TheAlgorithms/Python/issues), simply make a pull request with your proposed fix. We do not assign issues in this repo so please do not ask for permission to work on an issue.

Resolving patch:
diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py
deleted file mode 100644
--- a/maths/miller_rabin.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import random
-
-from .binary_exp_mod import bin_exp_mod
-
-
-# This is a probabilistic check to test primality, useful for big numbers!
-# if it's a prime, it will return true
-# if it's not a prime, the chance of it returning true is at most 1/4**prec
-def is_prime_big(n, prec=1000):
-    """
-    >>> from maths.prime_check import is_prime
-    >>> # all(is_prime_big(i) == is_prime(i) for i in range(1000))  # 3.45s
-    >>> all(is_prime_big(i) == is_prime(i) for i in range(256))
-    True
-    """
-    if n < 2:
-        return False
-
-    if n % 2 == 0:
-        return n == 2
-
-    # this means n is odd
-    d = n - 1
-    exp = 0
-    while d % 2 == 0:
-        d /= 2
-        exp += 1
-
-    # n - 1=d*(2**exp)
-    count = 0
-    while count < prec:
-        a = random.randint(2, n - 1)
-        b = bin_exp_mod(a, d, n)
-        if b != 1:
-            flag = True
-            for _ in range(exp):
-                if b == n - 1:
-                    flag = False
-                    break
-                b = b * b
-                b %= n
-            if flag:
-                return False
-            count += 1
-    return True
-
-
-if __name__ == "__main__":
-    n = abs(int(input("Enter bound : ").strip()))
-    print("Here's the list of primes:")
-    print(", ".join(str(i) for i in range(n + 1) if is_prime_big(i)))


Test patch:
Repository: TheAlgorithms/Python

Issue:
Longest Palindromic subsequence problem
### Feature description

Add longest palindromic subsequence problem algorithm in python.


Discussion:

Resolving patch:
diff --git a/dynamic_programming/longest_palindromic_subsequence.py b/dynamic_programming/longest_palindromic_subsequence.py
new file mode 100644
--- /dev/null
+++ b/dynamic_programming/longest_palindromic_subsequence.py
@@ -0,0 +1,44 @@
+"""
+author: Sanket Kittad
+Given a string s, find the longest palindromic subsequence's length in s.
+Input: s = "bbbab"
+Output: 4
+Explanation: One possible longest palindromic subsequence is "bbbb".
+Leetcode link: https://leetcode.com/problems/longest-palindromic-subsequence/description/
+"""
+
+
+def longest_palindromic_subsequence(input_string: str) -> int:
+    """
+    This function returns the longest palindromic subsequence in a string
+    >>> longest_palindromic_subsequence("bbbab")
+    4
+    >>> longest_palindromic_subsequence("bbabcbcab")
+    7
+    """
+    n = len(input_string)
+    rev = input_string[::-1]
+    m = len(rev)
+    dp = [[-1] * (m + 1) for i in range(n + 1)]
+    for i in range(n + 1):
+        dp[i][0] = 0
+    for i in range(m + 1):
+        dp[0][i] = 0
+
+    # create and initialise dp array
+    for i in range(1, n + 1):
+        for j in range(1, m + 1):
+            # If characters at i and j are the same
+            # include them in the palindromic subsequence
+            if input_string[i - 1] == rev[j - 1]:
+                dp[i][j] = 1 + dp[i - 1][j - 1]
+            else:
+                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
+
+    return dp[n][m]
+
+
+if __name__ == "__main__":
+    import doctest
+
+    doctest.testmod()


Test patch: