You are given an integer array `arr`.

In one move, you can select a **palindromic** subarray `arr[i], arr[i + 1], ..., arr[j]` where `i <= j`, and remove that subarray from the given array. Note that after removing a subarray, the elements on the left and on the right of that subarray move to fill the gap left by the removal.

Return _the minimum number of moves needed to remove all numbers from the array_.

**Example 1:**

**Input:** arr = \[1,2\]
**Output:** 2

**Example 2:**

**Input:** arr = \[1,3,4,1,5\]
**Output:** 3
**Explanation:** Remove \[4\] then remove \[1,3,1\] then remove \[5\].

**Constraints:**

*   `1 <= arr.length <= 100`
*   `1 <= arr[i] <= 20`


def minimumMoves(arr):
    def minRemovals(i, j):
        if i > j:
            return 0
        if i == j:
            return 1
        if dp[i][j] != -1:
            return dp[i][j]

        ans = minRemovals(i + 1, j) + 1
        for k in range(i + 1, j + 1):
            if arr[i] == arr[k]:
                ans = min(ans, minRemovals(i + 1, k - 1) + minRemovals(k + 1, j))
        dp[i][j] = ans
        return ans

    dp = [[-1] * len(arr) for _ in range(len(arr))]
    return minRemovals(0, len(arr) - 1)
