Implement composition and mixin utilities
Company: Point72
Role: Data Scientist
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Take-home Project
Quick Answer: This question evaluates functional programming concepts (function composition and variable-argument handling) and object-oriented serialization patterns (mixins, public-attribute filtering, and JSON encoding), testing competence in Python implementation and robustness to edge cases; it is commonly asked to evaluate reasoning about data flow through composed functions and correct modeling of object-to-JSON transformations in the Coding & Algorithms domain. The level of abstraction is primarily practical application with applied conceptual understanding, focusing on implementation-level skills such as argument routing, type-aware behavior, attribute selection, and JSON serialization error signalling.
Part 1: Left-to-Right Function Composition
Constraints
- 1 <= len(funcs) <= 15
- funcs[0] == 'add'
- Each later function name is one of: 'square', 'splitter', 'my_max', 'my_min'
- 1 <= len(args) <= 100
- -10^9 <= args[i] <= 10^9
Examples
Input: (['add', 'splitter'], [2, 3])
Expected Output: [2, 3]
Explanation: add(2, 3) = 5, then splitter(5) = [2, 3].
Input: (['add', 'square', 'splitter'], [2, 4])
Expected Output: [18, 18]
Explanation: add(2, 4) = 6, square(6) = 36, splitter(36) = [18, 18].
Input: (['add', 'splitter', 'my_max', 'square'], [5, 2, 1])
Expected Output: 16
Explanation: add = 8, splitter(8) = [4, 4], my_max([4, 4]) = 4, square(4) = 16.
Input: (['add'], [7])
Expected Output: 7
Explanation: Edge case: only one function. Return add(7).
Input: (['add', 'splitter'], [-3])
Expected Output: [-2, -1]
Explanation: Edge case with floor division: floor(-3 / 2) = -2, so splitter(-3) = [-2, -1].
Hints
- Build a mapping from function name to the actual helper implementation.
- Only the first function consumes all values from `args`; every later function should take the previous result as a single argument.
Part 2: Public Attribute Serialization Utilities
Constraints
- 0 <= len(attributes) <= 100
- All keys in `attributes` are strings
- Attributes whose names start with '_' must be excluded
- Official tests use insertion-ordered dictionaries (Python 3.7+ behavior)
- Your code must raise `TypeError('Object is not JSON serializable')` for unsupported JSON values
Examples
Input: ({'name': 'Alice', '_token': 'abc', 'age': 30},)
Expected Output: ({'name': 'Alice', 'age': 30}, '{"name": "Alice", "age": 30}')
Explanation: Only public attributes are kept. `_token` is excluded.
Input: ({'_private': 1, '_cache': [1, 2]},)
Expected Output: ({}, '{}')
Explanation: Edge case: all attributes are private, so both outputs represent an empty object.
Input: ({},)
Expected Output: ({}, '{}')
Explanation: Edge case: no attributes at all.
Input: ({'title': 'Book', 'pages': 200, 'tags': ['python', 'oop'], 'meta': {'edition': 2}, '_debug': True},)
Expected Output: ({'title': 'Book', 'pages': 200, 'tags': ['python', 'oop'], 'meta': {'edition': 2}}, '{"title": "Book", "pages": 200, "tags": ["python", "oop"], "meta": {"edition": 2}}')
Explanation: Nested lists and dictionaries are valid JSON, and `_debug` is excluded.
Input: ({'active': True, 'count': None, '_skip': 'x'},)
Expected Output: ({'active': True, 'count': None}, '{"active": true, "count": null}')
Explanation: JSON converts Python `True` to `true` and `None` to `null`.
Hints
- Filter the dictionary first; both representations should be built from exactly the same public data.
- Use `json.dumps(...)` and catch `TypeError` so you can raise the required message.