Design a Train Fare Calculator with Dynamic Stations and a Weekend Fare Cap
Company: Amazon
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
A train line serves five stations in this order:
```text
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.
```hint 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.
```
#### 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.
```hint 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 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.
```
#### 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.
```hint 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.
```
#### 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
### What a Strong Answer Covers
- Clarifies direction, invalid input, insertion semantics and the scope of the cap before coding
- A constant-time fare lookup backed by a position index that stays consistent as stations are added
- A clean separation between route data, route structure and pricing rules
- A weekend cap implemented as a pluggable rule with the travel date passed in, not read from a hard-coded clock
- Tests covering the example, reverse trips, same-station trips, unknown stations, added stations and the weekend boundary
### 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?
Overview: 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.
Read the full Amazon Software Engineer interview experience this question came from