Implement bitmap font render/compress/invert
Company: Stripe
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Take-home Project
Quick Answer: This question evaluates proficiency in bitmap and matrix manipulation, lossless compression/decompression techniques, and modular code reuse for transformations such as inversion, targeting skills in data representation, algorithmic correctness, and space-time trade-offs.
Part 1: Render a bitmap character
Constraints
- 0 <= number of rows in the chosen bitmap <= 200
- 0 <= number of columns in each row <= 200
- Each cell is either 0 or 1
- The chosen bitmap is rectangular
Examples
Input: ({'J': [[0, 1, 0], [0, 1, 0], [1, 0, 0]]}, 'J')
Expected Output: '0 1 0\n0 1 0\n1 0 0'
Explanation: A normal multi-row bitmap should be rendered exactly row by row.
Input: ({'A': [[1, 0], [0, 1]], 'B': [[1, 1], [1, 0]]}, 'B')
Expected Output: '1 1\n1 0'
Explanation: The function should select the requested character from a lookup table containing multiple entries.
Input: ({'E': []}, 'E')
Expected Output: ''
Explanation: Edge case: an empty bitmap has no rows, so the result is an empty string.
Input: ({'I': [[1, 1, 1, 1]]}, 'I')
Expected Output: '1 1 1 1'
Explanation: A single-row bitmap should not add extra newlines.
Hints
- Process the bitmap one row at a time.
- Build each row as a string first, then join all row strings with a newline.
Part 2: Lossless bitmap compression with row-wise RLE
Constraints
- 0 <= rows <= 200
- 0 <= cols <= 200
- Each cell is either 0 or 1
- The bitmap is rectangular
- Your compression must be lossless when decompressed
Examples
Input: [[1, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 1]]
Expected Output: [[[3, 4]], [[1, 2], [0, 2]], [[0, 3], [1, 1]], [[1, 1], [0, 2], [1, 1]]]
Explanation: Each row is independently encoded into runs.
Input: [[0, 0, 0, 0]]
Expected Output: [[[1, 4]], [[0, 4]]]
Explanation: A row with one repeated value becomes a single run.
Input: [[1, 0, 1, 0, 1]]
Expected Output: [[[1, 5]], [[1, 1], [0, 1], [1, 1], [0, 1], [1, 1]]]
Explanation: Alternating bits produce many short runs.
Input: []
Expected Output: [[[0, 0]]]
Explanation: Edge case: an empty bitmap stores only its dimensions.
Hints
- Scan each row from left to right and group consecutive equal values into runs.
- Store the original dimensions so decompression knows how many rows and columns to rebuild.
Part 3: Invert a compressed bitmap
Constraints
- 0 <= rows <= 200
- 0 <= cols <= 200
- The compressed input follows the exact Part 2 format
- All values are 0 or 1
- The decompressed bitmap is rectangular
Examples
Input: [[[2, 3]], [[0, 1], [1, 2]], [[1, 1], [0, 2]]]
Expected Output: [[1, 0, 0], [0, 1, 1]]
Explanation: Decompress to [[0, 1, 1], [1, 0, 0]] and invert every bit.
Input: [[[1, 1]], [[0, 1]]]
Expected Output: [[1]]
Explanation: Edge case: a single pixel flips from 0 to 1.
Input: [[[2, 2]], [[1, 2]], [[1, 2]]]
Expected Output: [[0, 0], [0, 0]]
Explanation: All foreground pixels become background pixels.
Input: [[[0, 0]]]
Expected Output: []
Explanation: Edge case: an empty compressed bitmap decompresses to an empty matrix.
Hints
- First rebuild the original bitmap row by row from the [value, count] runs.
- After decompression, each bit can be inverted with 1 - bit.