<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def build_route_timetable( feed: "Feed", route_id: str, dates: List[str] ) -> DataFrame: """ Return a timetable for the given route and dates. Parameters feed : Feed route_id : string ID of a route in ``feed.routes`` dates : string or list A YYYYMMDD date string or list thereof Returns ------- DataFrame The columns are all those in ``feed.trips`` plus those in ``feed.stop_times`` plus ``'date'``, and the trip IDs are restricted to the given route ID. The result is sorted first by date and then by grouping by trip ID and sorting the groups by their first departure time. Skip dates outside of the Feed's dates. If there is no route activity on the given dates, then return an empty DataFrame. Notes ----- Assume the following feed attributes are not ``None``: - ``feed.stop_times`` - Those used in :func:`.trips.get_trips` """

    dates = feed.restrict_dates(dates)
    if not dates:
        return pd.DataFrame()

    t = pd.merge(feed.trips, feed.stop_times)
    t = t[t["route_id"] == route_id].copy()
    a = feed.compute_trip_activity(dates)

    frames = []
    for date in dates:
        # Slice to trips active on date
        ids = a.loc[a[date] == 1, "trip_id"]
        f = t[t["trip_id"].isin(ids)].copy()
        f["date"] = date
        # Groupby trip ID and sort groups by their minimum departure time.
        # For some reason NaN departure times mess up the transform below.
        # So temporarily fill NaN departure times as a workaround.
        f["dt"] = f["departure_time"].fillna(method="ffill")
        f["min_dt"] = f.groupby("trip_id")["dt"].transform(min)
        frames.append(f)

    f = pd.concat(frames)
    return f.sort_values(["date", "min_dt", "stop_sequence"]).drop(
        ["min_dt", "dt"], axis=1
    )