Design a Train Fare Calculator with Dynamic Stations and a Weekend Fare Cap

Read the full interview experience this question came from →

Quick 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.

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

|Home/Software Engineering Fundamentals/Amazon
Amazon logo
Amazon
Aug 29, 2026
mediumSoftware EngineerOnsiteSoftware Engineering Fundamentals
0
0

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 Guidance

  • 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 Guidance

  • 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 Guidance

  • 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 Guidance

  • 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 Guidance

  • 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 Guidance

  • 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 Guidance

  • 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 Guidance

  • 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?
Loading comments...