title: Available Captures for Rook
slug: available-captures-for-rook
difficulty: easy
leetcode_id: 999
leetcode_url: https://leetcode.com/problems/available-captures-for-rook/
categories:
  - arrays
patterns:
  - slug: matrix-traversal
    is_optimal: true

function_signature: "def num_rook_captures(board: list[list[str]]) -> int:"

test_cases:
  visible:
    - input: { board: [[".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", "p", ".", ".", ".", "."], [".", ".", ".", "R", ".", ".", ".", "p"], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", "p", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."]] }
      expected: 3
    - input: { board: [[".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", "R", ".", ".", "."]] }
      expected: 0
    - input: { board: [[".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", "p", ".", ".", ".", "."], [".", ".", ".", "p", ".", ".", ".", "."], ["p", "p", ".", "R", ".", "p", "B", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", "B", ".", ".", ".", "."], [".", ".", ".", "p", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."]] }
      expected: 3
  hidden:
    - input: { board: [["R", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."]] }
      expected: 0
    - input: { board: [["p", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], ["R", ".", ".", ".", ".", ".", ".", "p"], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."]] }
      expected: 2
    - input: { board: [[".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", "B", ".", "R", ".", "B", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."]] }
      expected: 0
    - input: { board: [[".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], ["p", ".", ".", "R", ".", ".", ".", "p"], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."]] }
      expected: 2
    - input: { board: [[".", ".", ".", "p", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", "R", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", "p", ".", ".", ".", "."]] }
      expected: 2

description: |
  You are given an `8 x 8` **matrix** representing a chessboard. There is **exactly one** white rook represented by `'R'`, some number of white bishops `'B'`, and some number of black pawns `'p'`. Empty squares are represented by `'.'`.

  A rook can move any number of squares horizontally or vertically (up, down, left, right) until it reaches another piece *or* the edge of the board. A rook is **attacking** a pawn if it can move to the pawn's square in one move.

  Note: A rook cannot move through other pieces, such as bishops or pawns. This means a rook cannot attack a pawn if there is another piece blocking the path.

  Return *the number of pawns the white rook is attacking*.

constraints: |
  - `board.length == 8`
  - `board[i].length == 8`
  - `board[i][j]` is either `'R'`, `'.'`, `'B'`, or `'p'`
  - There is exactly one cell with `board[i][j] == 'R'`

examples:
  - input: 'board = [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]'
    output: "3"
    explanation: "The rook is attacking all three pawns since there are no pieces blocking the path in any direction."
  - input: 'board = [[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".","R",".",".","."]]'
    output: "0"
    explanation: "There are no pawns on the board, so the rook cannot capture any."
  - input: 'board = [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","p",".",".",".","."],["p","p",".","R",".","p","B","."],[".",".",".",".",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."]]'
    output: "3"
    explanation: "The rook attacks the pawn to its left, above (first pawn only, second is blocked), and to its right (bishop blocks the pawn beyond it). The pawn below is blocked by a bishop."

explanation:
  intuition: |
    Think of this problem like shining a flashlight from the rook's position in four directions: up, down, left, and right.

    The light travels until it hits something. If it hits a pawn (`'p'`), that's a capture! If it hits a bishop (`'B'`) or the edge of the board, the light stops and we move on to the next direction.

    The key insight is that **order matters** — the rook can only capture the *first* piece it encounters in each direction. Any pieces beyond that are blocked from view, just like how a flashlight beam stops at the first obstacle.

    Since a rook moves in exactly four directions and we need to check each one until we hit something, this is a straightforward simulation problem.

  approach: |
    We solve this using a **Direction Traversal** approach:

    **Step 1: Find the rook's position**

    - Iterate through the 8x8 board to locate the cell containing `'R'`
    - Store its row and column coordinates

    &nbsp;

    **Step 2: Define the four directions**

    - Use direction vectors: `(-1, 0)` for up, `(1, 0)` for down, `(0, -1)` for left, `(0, 1)` for right
    - Each vector represents how row and column change as we move

    &nbsp;

    **Step 3: Traverse each direction**

    - For each direction, start from the rook's position
    - Move one square at a time in that direction
    - Stop when we hit: a pawn (count it), a bishop (don't count), or the board edge

    &nbsp;

    **Step 4: Return the total count**

    - Sum up all pawns encountered across the four directions

  common_pitfalls:
    - title: Counting All Pawns in a Direction
      description: |
        A common mistake is to count *all* pawns in a direction rather than just the first piece encountered.

        For example, if there are two pawns stacked vertically above the rook, only the closest one can be captured — the second is blocked by the first.

        Always `break` out of the direction loop as soon as you hit any piece (pawn or bishop).
      wrong_approach: "Continue traversing after finding a pawn"
      correct_approach: "Stop traversal immediately upon hitting any piece"

    - title: Forgetting to Check Board Boundaries
      description: |
        When traversing in a direction, you must check that the new position is within the 8x8 board before accessing the cell.

        Accessing `board[-1][3]` or `board[8][3]` will either cause an error or give incorrect results depending on the language.
      wrong_approach: "Traverse without boundary checks"
      correct_approach: "Check 0 <= row < 8 and 0 <= col < 8 before accessing"

    - title: Treating Bishops as Transparent
      description: |
        Bishops block the rook's path just like pawns do — the only difference is bishops don't count as captures.

        If you only check for pawns and ignore bishops, you'll incorrectly count pawns that are actually blocked.
      wrong_approach: "Only stop traversal for pawns"
      correct_approach: "Stop traversal for any piece (pawn or bishop)"

  key_takeaways:
    - "**Direction vectors** simplify grid traversal — define `(dr, dc)` pairs and loop through them"
    - "**First-hit termination**: In line-of-sight problems, always stop at the first obstacle"
    - "**Fixed-size boards** (like 8x8) mean O(1) complexity, but the technique scales to larger grids"
    - "This pattern applies to many chess and grid simulation problems"

  time_complexity: "O(1). The board is always 8x8, and we traverse at most 8 cells in each of 4 directions (32 cells total)."
  space_complexity: "O(1). We only use a few variables for position tracking and counting."

solutions:
  - approach_name: Direction Traversal
    is_optimal: true
    code: |
      def num_rook_captures(board: list[list[str]]) -> int:
          # Find the rook's position
          rook_row, rook_col = 0, 0
          for r in range(8):
              for c in range(8):
                  if board[r][c] == 'R':
                      rook_row, rook_col = r, c
                      break

          # Four directions: up, down, left, right
          directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
          captures = 0

          for dr, dc in directions:
              # Start from rook's position and move in this direction
              r, c = rook_row + dr, rook_col + dc

              # Keep moving until we hit the edge or a piece
              while 0 <= r < 8 and 0 <= c < 8:
                  if board[r][c] == 'p':
                      # Found a pawn — count it and stop
                      captures += 1
                      break
                  elif board[r][c] == 'B':
                      # Bishop blocks the path — stop without counting
                      break
                  # Empty square — keep moving
                  r += dr
                  c += dc

          return captures
    explanation: |
      **Time Complexity:** O(1) — Fixed 8x8 board with at most 32 cells traversed.

      **Space Complexity:** O(1) — Only a few integer variables used.

      We locate the rook, then traverse in each of the four cardinal directions. For each direction, we move step-by-step until we either find a pawn (increment count), hit a bishop (stop), or reach the board edge (stop).
