Problem p00808 - Generation 2

Orig Description

Problem F: Young, Poor and Busy
Ken and Keiko are young, poor and busy. Short explanation: they are students, and ridden with part-time jobs. To make things worse, Ken lives in Hakodate and Keiko in Tokyo. They want to meet, but since they have neither time nor money, they have to go back to their respective jobs immediately after, and must be careful about transportation costs. Help them find the most economical meeting point.
Ken starts from Hakodate, Keiko from Tokyo. They know schedules and fares for all trains, and can choose to meet anywhere including their hometowns, but they cannot leave before 8am and must be back by 6pm in their respective towns. Train changes take no time (one can leave the same minute he/she arrives), but they want to meet for at least 30 minutes in the same city. 
There can be up to 100 cities and 2000 direct connections, so you should devise an algorithm clever enough for the task. 
Input
The input is a sequence of data sets.
The first line of a data set contains a single integer, the number of connections in the timetable. It is not greater than 2000.
Connections are given one on a line, in the following format.
     Start_city HH:MM Arrival_city HH:MM price
Start_city and Arrival_city are composed of up to 16 alphabetical characters, with only the first one in upper case. Departure and arrival times are given in hours and minutes (two digits each, separated by ":") from 00:00 to 23:59. Arrival time is strictly after departure time. The price for one connection is an integer between 1 and 10000, inclusive. Fields are separated by spaces.
The end of the input is marked by a line containing a zero. 
Output
The output should contain one integer for each data set, the lowest cost possible. This is the total fare of all connections they use.
If there is no solution to a data set, you should output a zero.
The solution to each data set should be given in a separate line. 
Sample Input
5
Hakodate 08:15 Morioka 12:30 2500
Morioka 14:05 Hakodate 17:30 2500
Morioka 15:30 Hakodate 18:00 3000
Morioka 14:30 Tokyo 17:50 3000
Tokyo 08:30 Morioka 13:35 3000
4
Hakodate 08:15 Morioka 12:30 2500
Morioka 14:04 Hakodate 17:30 2500
Morioka 14:30 Tokyo 17:50 3000
Tokyo 08:30 Morioka 13:35 3000
18
Hakodate 09:55 Akita 10:53 3840
Hakodate 14:14 Akita 16:09 1920
Hakodate 18:36 Akita 19:33 3840
Hakodate 08:00 Morioka 08:53 3550
Hakodate 22:40 Morioka 23:34 3550
Akita 14:23 Tokyo 14:53 2010
Akita 20:36 Tokyo 21:06 2010
Akita 08:20 Hakodate 09:18 3840
Akita 13:56 Hakodate 14:54 3840
Akita 21:37 Hakodate 22:35 3840
Morioka 09:51 Tokyo 10:31 2660
Morioka 14:49 Tokyo 15:29 2660
Morioka 19:42 Tokyo 20:22 2660
Morioka 15:11 Hakodate 16:04 3550
Morioka 23:03 Hakodate 23:56 3550
Tokyo 09:44 Morioka 11:04 1330
Tokyo 21:54 Morioka 22:34 2660
Tokyo 11:34 Akita 12:04 2010
0
Output for the Sample Input
11000
0
11090

Extracted Specification

An integer M (1 ≤ M ≤ 2000), representing the number of connections.
M lines follow, each containing:
- A string S1, the name of a starting location (1 to 16 alphabetical characters, first character uppercase).
- A time T1 in the format HH:MM, representing the departure time (00:00 ≤ HH:MM ≤ 23:59).
- A string S2, the name of an arrival location (1 to 16 alphabetical characters, first character uppercase).
- A time T2 in the format HH:MM, representing the arrival time (00:00 ≤ HH:MM ≤ 23:59).
- An integer P (1 ≤ P ≤ 10000), representing a price.
The input ends with a line containing a single zero.

### Example Input:

```
5
Hakodate 08:15 Morioka 12:30 2500
Morioka 14:05 Hakodate 17:30 2500
Morioka 15:30 Hakodate 18:00 3000
Morioka 14:30 Tokyo 17:50 3000
Tokyo 08:30 Morioka 13:35 3000
0
```

### Function Signature:
Write a function f(inputs) that takes in the input. 
def f(inputs: List[Tuple[int, List[Tuple[str, str, str, str, int]]]]):
    ''' 
    inputs: a list of tuples where each tuple contains:
        - an integer M
        - a list of M tuples, each containing:
            - a string S1
            - a string T1
            - a string S2
            - a string T2
            - an integer P
    '''

Test Case Generator

Sure, here is a test case generator for the problem "Young, Poor and Busy":

```python
import random
import string

def random_city():
    # Generates a random city name with the first letter uppercase and the rest lowercase
    return ''.join(random.choices(string.ascii_uppercase, k=1) + random.choices(string.ascii_lowercase, k=random.randint(1, 15)))

def random_time():
    # Generates a random time in the format HH:MM
    return f"{random.randint(0, 23):02d}:{random.randint(0, 59):02d}"

def time_greater_than(t1, t2):
    # Converts time strings HH:MM to minutes since 00:00 and compares them
    h1, m1 = map(int, t1.split(':'))
    h2, m2 = map(int, t2.split(':'))
    return (h1 * 60 + m1) > (h2 * 60 + m2)

def random_price():
    # Generates a random price between 1 and 10000
    return random.randint(1, 10000)

def generate_connection():
    while True:
        start_city = random_city()
        end_city = random_city()
        dep_time = random_time()
        arr_time = random_time()
        if time_greater_than(arr_time, dep_time):
            price = random_price()
            return f"{start_city} {dep_time} {end_city} {arr_time} {price}"

def tcgen():
    num_datasets = random.randint(1, 10)  # Number of datasets
    datasets = []
    
    for _ in range(num_datasets):
        num_connections = random.randint(1, 2000)
        connections = "\n".join(generate_connection() for _ in range(num_connections))
        datasets.append(f"{num_connections}\n{connections}")
    
    return "\n".join(datasets) + "\n0"

print(tcgen())
```

This generator creates a random number of datasets, each containing a random number of connections between cities, with times and prices generated according to the specified constraints. The end of input marker ("0") is appended at the end.

Explanation of the functions:
- `random_city()`: Generates a city name with the first letter uppercase and up to 15 lowercase letters.
- `random_time()`: Generates a time string in the format "HH:MM".
- `time_greater_than(t1, t2)`: Compares two times to ensure the arrival time is strictly after the departure time.
- `random_price()`: Generates a random price between 1 and 10000.
- `generate_connection()`: Creates a valid connection string by ensuring the arrival time is after the departure time.
- `tcgen()`: Generates random datasets with connections and combines them into a single test case output.

Extract Arguments

def extract_arguments(fh):
    data = []
    while True:
        connections = int(fh.readline().strip())
        if connections == 0:
            break
        dataset = []
        for _ in range(connections):
            line = fh.readline().strip().split()
            start_city = line[0]
            departure_time = line[1]
            arrival_city = line[2]
            arrival_time = line[3]
            price = int(line[4])
            dataset.append((start_city, departure_time, arrival_city, arrival_time, price))
        data.append(dataset)
    return data

# if __name__ == "__main__":
#     input_path = sys.argv[1]
#     with open(input_path, 'r') as fh: 
#         inputs = extract_arguments(fh)
#         f(inputs)