You are building a text rendering system that displays characters using bitmap fonts. In a bitmap font, each character is represented as a grid of pixels, where each pixel is either "on" (filled) or "off" (empty).
The problem is divided into three progressive parts:
Single Character Rendering: Convert a binary grid (0s and 1s) into a visual representation using . for empty pixels and # for filled pixels
Word Rendering: Render multiple characters side by side to display a word or sentence
Run-Length Encoded Fonts: Support fonts that use run-length encoding (RLE) for compact storage
There are multiple parts to this problem -- ask the interviewer how many parts there are to better manage your time
Start with the simplest approach and extend it as parts get more complex
Write your own test cases and ensure your code compiles and runs correctly
Implement a function render_character(grid) that takes a binary grid (list of strings containing 0s and 1s) and returns the rendered output where:
0 is replaced with (empty pixel)Each character is represented as a list of strings, where each string is a row of the character grid containing only 0 and 1.
`
letter_j = [ "0000000", "0001000", "0001000", "0101000", "0010000" ] `
` grid = [ "0000000", "0001000", "0001000", "0101000", "0010000" ]
render_character(grid)
`
Extend your solution to implement render_word(text, font) that renders multiple characters side by side to form a word or sentence. Each character's columns should be concatenated horizontally.
The font is a dictionary with a "face" name and a "chars" mapping from character to its bitmap representation:
font = { "face": "Simple Font", "chars": { "H": ["10001", "10001", "11111", "10001", "10001"], "I": ["111", "010", "010", "010", "111"] } }
` font = { "face": "Simple Font", "chars": { "H": ["10001", "10001", "11111", "10001", "10001"], "I": ["111", "010", "010", "010", "111"] } }
render_word("HI", font)
`
#...#### #...#.#. #####.#. #...#.#. #...####
Characters are placed side by side horizontally (no spacing between characters)
All characters in a font have the same height (number of rows)
Character widths may vary within the same font
Handle empty strings by returning an empty list
The conversion from binary to visual representation should happen after concatenation
Some fonts use run-length encoding (RLE) for compact storage. Instead of storing each pixel individually, RLE stores the length of consecutive runs of the same value.
Implement decode_rle(encoded_rows) that decodes RLE-encoded character data.
Each row is encoded as a string of characters representing run lengths
Runs alternate between "off" (0) and "on" (1) pixels, starting with "off"
Digits 0-9 represent run lengths 0-9
Letters a-z represent run lengths 10-35 (where a=10, b=11, ..., z=35)
Once decode_rle is implemented, you can combine it with the earlier functions to render words from RLE-encoded fonts:
Runs always start with "off" (0) pixels
Runs alternate: off, on, off, on, ...
Digits 0-9 represent their numeric value
Letters a-z represent values 10-35
All rows should decode to the same width (the font is monospaced after decoding)
After decoding, apply the same rendering logic from Part 1