Design a Train Fare Calculator with Dynamic Stations and a Weekend Fare Cap
AmazonSoftware Engineer · OnsiteLast updated
An object-oriented design and coding exercise for a train line where each segment between adjacent stations costs one unit. It asks for a fare function between two stations, a route class that loads route data and supports adding stations at runtime, and a weekend rule that caps the total fare.
A train line serves five stations in this order:
G → U → H → K → I
Riding between two adjacent stations costs 1, and a trip costs the sum of the segments it covers. For example, a trip from G to I covers four segments and costs 4.
The exercise builds up in three steps: a fare function, an object-oriented design for the route, and a weekend pricing rule.
Clarifying Questions
- Is the fare the same in both directions (I to G as G to I)?
- What should happen for a trip from a station to itself, or for a station name that is not on the line?
- Will every segment always cost 1, or might segments be priced differently later?
- Is this a single line, or will there be several lines with transfers?
Part 1 — Calculate a fare
Implement calculateFare(start, stop), which returns the fare between two stations on the line.
What This Part Should Cover
- A correct fare in both directions, including the example G to I = 4
- Handling a trip to the same station and an unknown station name
- Time and space complexity of the lookup and of any preprocessing
Part 2 — Route data and a class with dynamic stations
Think about where the route data comes from. Design and implement a class that holds the route and supports adding (pushing) stations to it dynamically, with fares still correct after a station is added.
Clarifying Questions for this Part
- Are new stations only appended at the end of the line, or can they be inserted between existing stations?
- Where does the route live: a configuration file, a database, or another service? Can it change while the system is running?
What This Part Should Cover
- Class responsibilities and interfaces, including an abstraction for the route data source
- The add-station operation: validation (such as duplicate names) and its cost
- How fares behave after the route changes, and safety when fare queries and updates happen at the same time
Part 3 — Weekend fare cap
On weekends, the total fare is capped at a maximum amount. Implement this rule.
Clarifying Questions for this Part
- What is the maximum amount, and should it be configurable?
- Does the cap apply to each trip, or to the total a rider pays across all trips in a day?
- How is "weekend" decided: by the trip's departure date, and in which time zone? Do public holidays count?
What This Part Should Cover
- Where the cap lives in the design and how the calculator learns the travel date
- Correct behavior when the base fare is below, equal to and above the cap
- How the rule combines with future pricing rules, and the tests that pin it down
Hints
Hint 1
Avoid walking the line: Precompute something for each station so that a fare becomes a constant-time calculation rather than a walk from one station to the other.
Hint 2
Separate data, structure and pricing: Decide which object owns the order of stations, which object turns a trip into a fare, and how the route gets loaded, so that any one of them can change without rewriting the others.
Hint 3
Keep lookups fast after an update: Work out exactly what must be updated when a station is pushed, so that fare queries stay as cheap as in Part 1.
Hint 4
Keep the rule outside the distance: Find a place where pricing rules can be applied to a fare without changing how the distance between stations is computed.
Follow-up questions
- A second line crosses this one at a shared station. How do you compute the fare for a trip that changes lines?
- Segments start to have different prices. What changes in your route class, and what stays the same?
- The cap becomes a daily cap across all of a rider's weekend trips. What new state do you need, and where does it live?
- A station is inserted between two existing stations instead of appended. What breaks, and what happens to tickets already sold?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.