|
| 1 | +#!/usr/bin/env python3 |
| 2 | +"""Road Trip Route Planner - Plan optimal routes between cities""" |
| 3 | + |
| 4 | +import heapq |
| 5 | +from typing import Dict, List, Tuple, Optional |
| 6 | + |
| 7 | +# Static map of cities with distances (km) and travel times (hours) |
| 8 | +CITY_MAP = { |
| 9 | + 'New York': [('Boston', 215, 3.5), ('Philadelphia', 95, 1.8), ('Washington', 225, 3.8)], |
| 10 | + 'Boston': [('New York', 215, 3.5), ('Portland', 105, 2.0)], |
| 11 | + 'Philadelphia': [('New York', 95, 1.8), ('Washington', 140, 2.3), ('Pittsburgh', 305, 5.0)], |
| 12 | + 'Washington': [('New York', 225, 3.8), ('Philadelphia', 140, 2.3), ('Richmond', 110, 1.8)], |
| 13 | + 'Pittsburgh': [('Philadelphia', 305, 5.0), ('Cleveland', 135, 2.2), ('Columbus', 185, 3.0)], |
| 14 | + 'Cleveland': [('Pittsburgh', 135, 2.2), ('Detroit', 170, 2.8), ('Columbus', 145, 2.4)], |
| 15 | + 'Detroit': [('Cleveland', 170, 2.8), ('Chicago', 280, 4.5)], |
| 16 | + 'Chicago': [('Detroit', 280, 4.5), ('Milwaukee', 90, 1.5), ('St Louis', 300, 4.8)], |
| 17 | + 'Columbus': [('Pittsburgh', 185, 3.0), ('Cleveland', 145, 2.4), ('Cincinnati', 110, 1.8)], |
| 18 | + 'Cincinnati': [('Columbus', 110, 1.8), ('Louisville', 100, 1.6), ('Indianapolis', 110, 1.8)], |
| 19 | + 'Indianapolis': [('Cincinnati', 110, 1.8), ('Chicago', 185, 3.0), ('Louisville', 115, 1.9)], |
| 20 | + 'Louisville': [('Cincinnati', 100, 1.6), ('Indianapolis', 115, 1.9), ('Nashville', 175, 2.8)], |
| 21 | + 'Nashville': [('Louisville', 175, 2.8), ('Memphis', 210, 3.3), ('Atlanta', 250, 4.0)], |
| 22 | + 'Atlanta': [('Nashville', 250, 4.0), ('Charlotte', 245, 3.9), ('Jacksonville', 345, 5.5)], |
| 23 | + 'Charlotte': [('Atlanta', 245, 3.9), ('Richmond', 300, 4.8)], |
| 24 | + 'Richmond': [('Washington', 110, 1.8), ('Charlotte', 300, 4.8)], |
| 25 | + 'Milwaukee': [('Chicago', 90, 1.5)], |
| 26 | + 'St Louis': [('Chicago', 300, 4.8), ('Memphis', 285, 4.5)], |
| 27 | + 'Memphis': [('St Louis', 285, 4.5), ('Nashville', 210, 3.3)], |
| 28 | + 'Portland': [('Boston', 105, 2.0)], |
| 29 | + 'Jacksonville': [('Atlanta', 345, 5.5)] |
| 30 | +} |
| 31 | + |
| 32 | +def dijkstra(start: str, end: str, optimize: str = 'distance') -> Optional[Tuple[List[str], float]]: |
| 33 | + """Find optimal route using Dijkstra's algorithm""" |
| 34 | + if start not in CITY_MAP or end not in CITY_MAP: |
| 35 | + return None |
| 36 | + |
| 37 | + idx = 1 if optimize == 'distance' else 2 |
| 38 | + pq = [(0, start, [start])] |
| 39 | + visited = set() |
| 40 | + |
| 41 | + while pq: |
| 42 | + cost, city, path = heapq.heappop(pq) |
| 43 | + if city in visited: |
| 44 | + continue |
| 45 | + if city == end: |
| 46 | + return path, cost |
| 47 | + visited.add(city) |
| 48 | + for neighbor, dist, time in CITY_MAP.get(city, []): |
| 49 | + if neighbor not in visited: |
| 50 | + heapq.heappush(pq, (cost + (dist if idx == 1 else time), neighbor, path + [neighbor])) |
| 51 | + return None |
| 52 | + |
| 53 | +def display_route(route: List[str], cost: float, optimize: str): |
| 54 | + """Display route information""" |
| 55 | + print(f"\n{'='*60}") |
| 56 | + print(f"Route ({optimize.upper()} optimized):") |
| 57 | + for i, city in enumerate(route): |
| 58 | + print(f" {i+1}. {city}") |
| 59 | + if i < len(route) - 1: |
| 60 | + print(" ↓") |
| 61 | + unit = 'km' if optimize == 'distance' else 'hours' |
| 62 | + print(f"\nTotal {optimize}: {cost:.1f} {unit}") |
| 63 | + print(f"{'='*60}") |
| 64 | + |
| 65 | +def main(): |
| 66 | + print("\n🚗 ROAD TRIP ROUTE PLANNER 🗺️") |
| 67 | + print("Available cities:") |
| 68 | + cities = sorted(CITY_MAP.keys()) |
| 69 | + for i in range(0, len(cities), 3): |
| 70 | + print(" " + ", ".join(cities[i:i+3])) |
| 71 | + |
| 72 | + try: |
| 73 | + start = input("\nEnter starting city: ").strip() |
| 74 | + end = input("Enter destination city: ").strip() |
| 75 | + print("\nOptimization options:") |
| 76 | + print(" 1. Shortest distance") |
| 77 | + print(" 2. Fastest time") |
| 78 | + choice = input("Choose option (1/2): ").strip() |
| 79 | + |
| 80 | + optimize = 'distance' if choice == '1' else 'time' |
| 81 | + result = dijkstra(start, end, optimize) |
| 82 | + |
| 83 | + if result: |
| 84 | + route, cost = result |
| 85 | + display_route(route, cost, optimize) |
| 86 | + else: |
| 87 | + print(f"\n❌ No route found between {start} and {end}") |
| 88 | + except KeyboardInterrupt: |
| 89 | + print("\n\nExiting...") |
| 90 | + |
| 91 | +if __name__ == "__main__": |
| 92 | + main() |
0 commit comments