S3Q1 · Railway Ticket Booking Analysis¶
⚡ Quick Reference
Function: analyze_bookings(bookings: dict, task: str)
berth_types = ["UB", "MB", "LB", "SU", "SL", None]
def analyze_bookings(bookings, task):
if task == "ticket_prices":
return {pnr: b["ticket_rate"] * len(b["passengers"])
for pnr, b in bookings.items()}
if task == "total_revenue":
return sum(b["ticket_rate"] * len(b["passengers"])
for b in bookings.values())
if task == "berth_preference_count":
counts = {bt: 0 for bt in berth_types}
for b in bookings.values():
for _, pref in b["passengers"]:
counts[pref] += 1
return counts
if task == "coach_type_count":
counts = {}
for b in bookings.values():
ct = b["coach_type"]
counts[ct] = counts.get(ct, 0) + len(b["passengers"])
return counts
Key rules:
- Ticket price per PNR = ticket_rate × number_of_passengers
- berth_preference_count includes all 6 berth types (even with 0 count), including None
- coach_type_count only includes coach types present in the data
Problem Statement¶
Problem
Implement analyze_bookings(bookings, task) - four analytics operations on nested booking data.
Sample data:
bookings = {
"PNR112": {"coach_type": "3AC", "ticket_rate": 900,
"passengers": [("Rahul","UB"), ("Baskar",None)]},
"PNR123": {"coach_type": "2AC", "ticket_rate": 1500,
"passengers": [("Amit","LB"), ("Ravi","UB")]},
"PNR456": {"coach_type": "3AC", "ticket_rate": 800,
"passengers": [("Priya","MB"), ("Neha",None)]},
"PNR789": {"coach_type": "SL", "ticket_rate": 500,
"passengers": [("Vikram","UB"),("Kiran","MB"),("Surya","SU")]},
}
Operation 1 - ticket_prices¶
Total price per PNR = ticket_rate × number of passengers:
| PNR | rate | passengers | total |
|---|---|---|---|
| PNR112 | 900 | 2 | 1800 |
| PNR123 | 1500 | 2 | 3000 |
| PNR456 | 800 | 2 | 1600 |
| PNR789 | 500 | 3 | 1500 |
→ {'PNR112': 1800, 'PNR123': 3000, 'PNR456': 1600, 'PNR789': 1500} ✓
Operation 2 - total_revenue¶
Sum all PNR totals:
1800 + 3000 + 1600 + 1500 = 7900 ✓
Operation 3 - berth_preference_count¶
Count passengers per berth preference. All 6 types must appear in output (zero if absent):
counts = {bt: 0 for bt in berth_types}
for b in bookings.values():
for _, pref in b["passengers"]:
counts[pref] += 1
return counts
| Berth | Passengers | Count |
|---|---|---|
UB |
Rahul, Ravi, Vikram | 3 |
MB |
Priya, Kiran | 2 |
LB |
Amit | 1 |
SU |
Surya | 1 |
SL |
- | 0 |
None |
Baskar, Neha | 2 |
→ {'UB':3, 'MB':2, 'LB':1, 'SU':1, 'SL':0, None:2} ✓
Operation 4 - coach_type_count¶
Count total passengers per coach type (only types present in data):
counts = {}
for b in bookings.values():
ct = b["coach_type"]
counts[ct] = counts.get(ct, 0) + len(b["passengers"])
return counts
| Coach | PNRs | Passengers |
|---|---|---|
3AC |
PNR112(2), PNR456(2) | 4 |
2AC |
PNR123(2) | 2 |
SL |
PNR789(3) | 3 |
→ {'3AC': 4, '2AC': 2, 'SL': 3} ✓
Complete solution approaches¶
berth_types = ["UB", "MB", "LB", "SU", "SL", None]
def analyze_bookings(bookings, task):
if task == "ticket_prices":
return {pnr: b["ticket_rate"] * len(b["passengers"])
for pnr, b in bookings.items()}
if task == "total_revenue":
return sum(b["ticket_rate"] * len(b["passengers"])
for b in bookings.values())
if task == "berth_preference_count":
counts = {bt: 0 for bt in berth_types}
for b in bookings.values():
for _, pref in b["passengers"]:
counts[pref] += 1
return counts
if task == "coach_type_count":
counts = {}
for b in bookings.values():
ct = b["coach_type"]
counts[ct] = counts.get(ct, 0) + len(b["passengers"])
return counts
berth_types = ["UB", "MB", "LB", "SU", "SL", None]
def analyze_bookings(bookings, task):
if task == "ticket_prices":
result = {}
for pnr, b in bookings.items():
result[pnr] = b["ticket_rate"] * len(b["passengers"])
return result
if task == "total_revenue":
total = 0
for b in bookings.values():
total += b["ticket_rate"] * len(b["passengers"])
return total
if task == "berth_preference_count":
counts = {bt: 0 for bt in berth_types}
for b in bookings.values():
for passenger in b["passengers"]:
pref = passenger[1]
counts[pref] += 1
return counts
if task == "coach_type_count":
counts = {}
for b in bookings.values():
ct = b["coach_type"]
n = len(b["passengers"])
if ct in counts:
counts[ct] += n
else:
counts[ct] = n
return counts
from collections import defaultdict
berth_types = ["UB", "MB", "LB", "SU", "SL", None]
def analyze_bookings(bookings, task):
all_passengers = [(pnr, b["coach_type"], b["ticket_rate"], p, pref)
for pnr, b in bookings.items()
for p, pref in b["passengers"]]
if task == "ticket_prices":
prices = defaultdict(int)
for pnr, _, rate, _, _ in all_passengers:
prices[pnr] += rate
return dict(prices)
if task == "total_revenue":
return sum(rate for _, _, rate, _, _ in all_passengers)
if task == "berth_preference_count":
counts = {bt: 0 for bt in berth_types}
for _, _, _, _, pref in all_passengers:
counts[pref] += 1
return counts
if task == "coach_type_count":
counts = defaultdict(int)
for _, ct, _, _, _ in all_passengers:
counts[ct] += 1
return dict(counts)
Key takeaways¶
Pre-initialise berth_preference_count with zeros
{bt: 0 for bt in berth_types} ensures all 6 berth types appear in the result, even those with no passengers. Without this, absent berth types would simply not appear as keys.
None is a valid dictionary key
Passengers with no berth preference have None as their second tuple element. Python dicts accept None as a key - counts[None] += 1 works correctly.
ticket_rate × len(passengers) - rate is per person
ticket_rate is the price for one passenger. Multiply by len(passengers) to get the total for the entire PNR booking.