~/problems / Pools & pipelines / Thread pool / concurrent crawler

Image transformation pipeline with processes

medium 3 levels ~60 min Anthropic

Level 1 Apply a list of transformations

In the interview you'd use an imaging library such as Pillow. Here the images are plain Python data so everything runs with the standard library: an image is a non-empty list of rows, each row a list of pixels, each pixel a list [r, g, b] of ints in 0..255. All rows have the same length. image[y][x] is the pixel in row y, column x.

A transformation is a dict with a "type" key and maybe one parameter. Implement

apply_transformations(image, transformations: list[dict]) -> image

which applies the transformations in order and returns a new image. Never modify the input image (like image-library calls, each step returns a new object; keep reassigning the result).

type parameter effect
grayscale none every pixel becomes [v, v, v] with v = (299*r + 587*g + 114*b) // 1000
flip_horizontal (also spelled flip_horizontally) none mirror left to right: each row reversed
flip_vertical (also spelled flip_vertically) none mirror top to bottom: row order reversed
scale factor (float > 0) nearest-neighbour resize to width max(1, int(w * factor)) and height max(1, int(h * factor)); output pixel (x, y) copies source pixel (x * w // new_w, y * h // new_h)
blur radius (int ≥ 0) box blur: each channel becomes the floor of the mean of that channel over the (2r+1) x (2r+1) square around the pixel, counting only pixels inside the image; every output pixel is computed from the input of this step
rotate angle (degrees, always a multiple of 90, may be negative or ≥ 360) rotate counter-clockwise by angle; a 90° turn of a w x h image gives an h x w image

Any other type raises ValueError.

img = [[[255, 0, 0], [0, 0, 255]]]            # 1 row, 2 pixels: red, blue
apply_transformations(img, [{"type": "grayscale"}])
# [[[76, 76, 76], [29, 29, 29]]]
apply_transformations(img, [{"type": "rotate", "angle": 90}])
# [[[0, 0, 255]], [[255, 0, 0]]]   blue ends up on top
apply_transformations(img, [{"type": "scale", "factor": 1.5}])
# [[[255, 0, 0], [255, 0, 0], [0, 0, 255]]]   width 3, height int(1.5) = 1
apply_transformations(img, [])                 # an equal copy

Level 2 unlocks when level 1 passes.

Level 3 unlocks when level 2 passes.

Topic: Thread pool / concurrent crawler. ThreadPoolExecutor, asyncio, thread-safe visited set.

0:00
Ctrl ' run · Ctrl ↵ submit
esc