Quick Overview

Render bordered and filled rectangles onto a fixed ASCII canvas, clipping safely and honoring input-order overwrites. Handle negative coordinates, fully hidden shapes, one-cell dimensions, trailing spaces, overlap behavior, and a canvas of up to one million cells.

Render Overlapping Rectangles on an ASCII Canvas

Company: Amperity

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Onsite

# Render Overlapping Rectangles on an ASCII Canvas Implement `render_canvas(width, height, rectangles)`. The canvas initially contains spaces and is returned as a list of `height` strings, each of length `width`. Each rectangle is `(x, y, w, h, border_char, fill_char)`, where `(x, y)` is its upper-left corner, `w` is its width, and `h` is its height. Draw the outermost cells with `border_char` and interior cells with `fill_char`. Coordinates may place part or all of a rectangle outside the canvas; clip safely. Rectangles are drawn in input order, so later rectangles overwrite earlier pixels wherever they overlap. ## Constraints - `0 <= width, height <= 1000` - `1 <= w, h <= 1000` - `x` and `y` may be negative. - `border_char` and `fill_char` are single printable characters. - The total canvas area is at most `10^6` cells. ## Example For a `5` by `4` canvas and rectangle `(1, 1, 3, 2, '#', '.')`, return: ```text ### ### ``` A one-cell-wide or one-cell-high rectangle consists entirely of border cells. ## Clarifications Canvas coordinates use zero-based columns and rows. Preserve trailing spaces in every returned row. Explain how clipping prevents invalid indexing without changing whether a visible cell is a border or interior cell of the original rectangle. ## Hints Intersect each rectangle's coordinate range with the canvas before visiting pixels, but compute border status in the rectangle's original coordinates. ## Extensions - Return only changed regions for a very large sparse canvas. - Support transparency or z-indexes. - Add tests for total clipping, corner clipping, thin rectangles, and overwrite order.

Overview: Render bordered and filled rectangles onto a fixed ASCII canvas, clipping safely and honoring input-order overwrites. Handle negative coordinates, fully hidden shapes, one-cell dimensions, trailing spaces, overlap behavior, and a canvas of up to one million cells.

Read the full Amperity Software Engineer interview experience this question came from

Implement render_canvas(width, height, rectangles). Create a blank canvas and return it as a list of height strings, each containing exactly width cells. Each rectangle is (x, y, w, h, border_char, fill_char), with (x, y) as its upper-left corner. Draw cells on the rectangle's original outer edge with border_char and its interior with fill_char. Clip any portion outside the canvas safely, but determine border versus interior from the original rectangle coordinates. Process rectangles in input order so every later rectangle overwrites earlier pixels where they overlap. A one-cell-wide or one-cell-high rectangle consists entirely of border cells, and trailing spaces in every returned row must be preserved.

Constraints

  • 0 <= width, height <= 1000.
  • The total canvas area width * height is at most 10^6 cells.
  • Each rectangle is (x, y, w, h, border_char, fill_char), where 1 <= w, h <= 1000 and x and y may be negative.
  • border_char and fill_char are each one printable character.
  • Rectangles are drawn in input order, and later rectangles overwrite earlier pixels wherever they overlap.

Examples

Input: (5, 4, [(1, 1, 3, 2, "#", ".")])

Expected Output: [" "," ### "," ### "," "]

Explanation: The source example is preserved exactly; height two leaves no interior row, and all trailing spaces remain in the returned strings.

Input: (7, 5, [(0, 0, 7, 5, "#", "."), (2, 1, 3, 3, "@", "+")])

Expected Output: ["#######","#.@@@.#","#.@+@.#","#.@@@.#","#######"]

Explanation: The later three-by-three rectangle overwrites both border and fill cells of the earlier full-canvas rectangle.

Hints

  1. Intersect each rectangle's coordinate range with the canvas before visiting pixels, but compute border status in the rectangle's original coordinates.

Loading coding console...

Show the approach

Approach

Allocate the height-by-width canvas with one space per cell. For each rectangle, intersect its half-open column range [x, x + w) and row range [y, y + h) with the canvas ranges. If either intersection is empty, the rectangle performs no writes. Visit only cells in the intersection. A visited cell is on the rectangle's border exactly when its column is x or x + w - 1, or its row is y or y + h - 1; these comparisons deliberately use the original rectangle bounds rather than the clipped bounds. Write border_char for those cells and fill_char otherwise. Because rectangles are processed sequentially and each write replaces the current cell, later rectangles have the required overwrite priority. Finally join each row's cells without trimming, which preserves both leading and trailing spaces. The clipping intersection guarantees every visited row and column is a valid canvas index, while the original-boundary test guarantees clipping cannot turn an interior cell into a false border.

Time complexity:
O(width * height + sum of the visible intersection areas of all rectangles)
Space complexity:
O(width * height)