Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Cat and Mouse II

Updated
4 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "1728" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.

Problem Statement

A game is played by a cat and a mouse named Cat and Mouse. The environment is represented by a grid of size rows x cols, where each element is a wall, floor, player (Cat, Mouse), or food. Players are represented by the characters 'C'(Cat),'M'(Mouse). Floors are represented by the character '.' and can be walked on. Walls are represented by the character '#' and cannot be walked on. Food is represented by the character 'F' and can be walked on. There is only one of each character 'C', 'M', and 'F' in grid. Mouse and Cat play according to the following rules: Mouse moves first, then they take turns to move. During each turn, Cat and Mouse can jump in one of the four directions (left, right, up, down). They cannot jump over the wall nor outside of the grid. catJump, mouseJump are the maximum lengths Cat and Mouse can jump at a time, respectively. Cat and Mouse can jump less than the maximum length. Staying in the same position is allowed. Mouse can jump over Cat. The game can end in 4 ways: If Cat occupies the same position as Mouse, Cat wins. If Cat reaches the food first, Cat wins. If Mouse reaches the food first, Mouse wins. If Mouse cannot get to the food within 1000 turns, Cat wins. Given a rows x cols matrix grid and two integers catJump and mouseJump, return true if Mouse can win the game if both Cat and Mouse play optimally, otherwise return false. Example 1: Input: grid = ["####F","#C...","M...."], catJump = 1, mouseJump = 2 Output: true Explanation: Cat cannot catch Mouse on its turn nor can it get the food before Mouse. Example 2: Input: grid = ["M.C...F"], catJump = 1, mouseJump = 4 Output: true Example 3: Input: grid = ["M.C...F"], catJump = 1, mouseJump = 3 Output: false Constraints: rows == grid.length cols = grid[i].length 1 <= rows, cols <= 8 grid[i][j] consist only of characters 'C', 'M', 'F', '.', and '#'. There is only one of each character 'C', 'M', and 'F' in grid. 1 <= catJump, mouseJump <= 8

Explanation

Here's a breakdown of the solution approach, followed by the Python code:

  • Minimax with Memoization: Employ a minimax algorithm to explore the game tree, determining the optimal moves for both Mouse and Cat. Use memoization to avoid redundant computations by storing the results of previously evaluated game states.
  • Game State Representation: Define a game state as a tuple containing the mouse's coordinates, the cat's coordinates, and the current turn number.
  • Early Termination: Implement the game's termination conditions (Cat captures Mouse, Mouse reaches food, Cat reaches food, turn limit exceeded) to efficiently prune the search space.

  • Runtime Complexity: O(rows * cols * rows * cols * 1000), Storage Complexity: O(rows * cols * rows * cols * 1000)

Code

    def canMouseWin(grid, catJump, mouseJump):
    rows, cols = len(grid), len(grid[0])
    mouse_start, cat_start, food = None, None, None
    for r in range(rows):
        for c in range(cols):
            if grid[r][c] == 'M':
                mouse_start = (r, c)
            elif grid[r][c] == 'C':
                cat_start = (r, c)
            elif grid[r][c] == 'F':
                food = (r, c)

    memo = {}

    def get_neighbors(r, c, jump):
        neighbors = []
        for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            for i in range(1, jump + 1):
                nr, nc = r + dr * i, c + dc * i
                if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] != '#':
                    neighbors.append((nr, nc))
                else:
                    break
        neighbors.append((r, c)) # staying in same position allowed
        return neighbors

    def minimax(mouse_pos, cat_pos, turn):
        if turn > 1000:
            return False

        state = (mouse_pos[0], mouse_pos[1], cat_pos[0], cat_pos[1], turn)
        if state in memo:
            return memo[state]

        if mouse_pos == cat_pos:
            memo[state] = False
            return False
        if mouse_pos == food:
            memo[state] = True
            return True
        if cat_pos == food:
            memo[state] = False
            return False

        if turn % 2 == 0:  # Mouse's turn
            neighbors = get_neighbors(mouse_pos[0], mouse_pos[1], mouseJump)
            can_win = False
            for next_mouse_pos in neighbors:
                if minimax(next_mouse_pos, cat_pos, turn + 1):
                    can_win = True
                    break
            memo[state] = can_win
            return can_win
        else:  # Cat's turn
            neighbors = get_neighbors(cat_pos[0], cat_pos[1], catJump)
            can_win = True
            for next_cat_pos in neighbors:
                if not minimax(mouse_pos, next_cat_pos, turn + 1):
                    can_win = False
                    break
            memo[state] = can_win
            return can_win

    return minimax(mouse_start, cat_start, 0)

More from this blog

C

Chatmagic blog

2894 posts