Compute Roller Coaster Scores
Company: Zoox
Role: Machine Learning Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates proficiency in string parsing, floating-point arithmetic, conditional logic, and designing extensible rule-based scoring systems.
Part 1: Compute Roller Coaster Overall Scores
Constraints
- 0 <= len(descriptions) <= 10^4
- Each description is well-formed and contains exactly 4 space-separated tokens.
- Numeric fields can be parsed as floats.
- Any denominator used by the relevant formula is nonzero.
Examples
Input: ['Wooden 4 2 Chain', 'Steel 20 0 Cable', 'Suspended 2 0.5 Cable']
Expected Output: ['Overall: 2.0', 'Overall: 10.0', 'Overall: 1.5']
Explanation: Wooden -> 1.0 * min(1, 1/2) * 4 = 2.0; Steel -> 2.0 * min(1, 5/20) * 20 = 10.0; Suspended -> 0.5 * (min(1, 1/0.5) + 0.5) * 2 = 1.5.
Input: ['Suspended 10 4 Launched']
Expected Output: ['Overall: 1.8']
Explanation: Comfort = min(1, 1/4) + 0.1 = 0.35, so score = 0.5 * 0.35 * 10 = 1.75, which rounds to 1.8.
Input: []
Expected Output: []
Explanation: Edge case: an empty input list should return an empty output list.
Input: ['Wooden 7.5 0.25 Chain', 'Steel 3 99 Cable']
Expected Output: ['Overall: 7.5', 'Overall: 6.0']
Explanation: For both coasters, the comfort score is capped at 1.0 by the min operation.
Hints
- Parse each description into four pieces, then branch on coaster type to choose the correct comfort formula.
- Use formatting like f'Overall: {score:.1f}' so the result is rounded to one decimal place.
Part 2: Build an Extensible Roller Coaster Scoring Engine
Constraints
- 0 <= len(descriptions) <= 10^4
- Every coaster type appearing in descriptions exists in rules.
- Supported comfort_model values are 'inverse_bumps', 'inverse_speed', 'inverse_bumps_plus_lift_bonus', and 'constant'.
- Descriptions are well-formed and numeric fields can be parsed as floats.
- Any denominator used by the relevant formula is nonzero.
Examples
Input: (['Wooden 4 2 Chain', 'Steel 20 0 Cable', 'Suspended 2 0.5 Cable'], {'Wooden': {'scale': 1.0, 'comfort_model': 'inverse_bumps', 'base': 1.0}, 'Steel': {'scale': 2.0, 'comfort_model': 'inverse_speed', 'base': 5.0}, 'Suspended': {'scale': 0.5, 'comfort_model': 'inverse_bumps_plus_lift_bonus', 'base': 1.0, 'lift_bonus': {'Cable': 0.5, 'Launched': 0.1}}})
Expected Output: ['Overall: 2.0', 'Overall: 10.0', 'Overall: 1.5']
Explanation: These rules reproduce the original three coaster types using a data-driven configuration.
Input: (['Hybrid 12 8 Magnetic'], {'Hybrid': {'scale': 1.5, 'comfort_model': 'constant', 'value': 0.8}})
Expected Output: ['Overall: 14.4']
Explanation: A brand new type is added only by changing the rules data: 1.5 * 0.8 * 12 = 14.4.
Input: (['Wooden 10 4 Chain'], {'Wooden': {'scale': 2.0, 'comfort_model': 'inverse_bumps', 'base': 2.0}})
Expected Output: ['Overall: 10.0']
Explanation: Changing the scale and base values in the rule changes the score without any change to the loop logic.
Input: ([], {'Wooden': {'scale': 1.0, 'comfort_model': 'inverse_bumps', 'base': 1.0}})
Expected Output: []
Explanation: Edge case: no coasters means no output strings.
Input: (['Suspended 6 2 Chain'], {'Suspended': {'scale': 0.5, 'comfort_model': 'inverse_bumps_plus_lift_bonus', 'base': 1.0, 'lift_bonus': {'Cable': 0.5, 'Launched': 0.1}}})
Expected Output: ['Overall: 1.5']
Explanation: Chain is not present in lift_bonus, so the bonus defaults to 0.0.
Hints
- Keep the parsing loop generic, and move each comfort formula into a handler selected by comfort_model.
- A dispatch table from comfort_model to function is a clean way to make the design extensible.