John is writing a program that finds the best route from A to B using public transport. For a given pair of origin and destination the program calculates a set of routes with departure time and arrival time, such as this:

10:12 11:45
10:15 11:50
10:22 12:05
10:25 12:00

As you see, the output may include a few routes that are superfluous in the sense that there is another route that starts later and ends earlier. Such routes are certainly never wanted by the user since he cat get out later to arrive sooner.

Your task, if you choose to accept it, is to write a program that prunes a set of routes such that all superfluous rules are eliminated.

Input

The input is a list of newline separated pairs of whitespace separated departure and arrival time in military format (hh:mm). Such a pair is called a route.

You may assume that all times are in the same day and that the arrival time is always later than the departure time. You may also assume that the list is orderer by departure times.

Output

The output is the same list as the input without redundant routes. A redundant route is a route for which another route exists in the list that has a later departure and an earlier arrival time. There must exist an order to remove all redundant routes such that in each step you can show the route that makes the removed route redundant. You don't have to output that order.

Extra credit

Prove or disprove that for each list of input routes there exists exactly one set of output routes.

Restriction

Usual codegolf rules apply

Scoring

To score, apply the function that gives an upper bound to your solutions complexity with your solution's total number of characters. Normalize your bounding function such that a solution length of two character yields a score of two.

For example, if your solution has 24 characters and a complexity of O(2n), your score is 4194304. If your solution has 123 characters and a complexity of O(n2) your score is 7564. If your solution has 200 characters and a complexity of O(n*logn), your score is 734.

I use this scoring method in order to encourage people to implement efficient solutions.

@FUZxxl Not sure if it's just me who was confused then :) - I'm of the opinion that a route that starts later and ends earlier gives a wholly shorter journey time overall, and is therefore more desirable to the traveller. Your wording indicates (possibly just to me...) that these shorter routes are the superfluous ones. Possibly a bit of ambiguity around the "Such routes", perhaps.
–
LeighDec 11 '12 at 14:51

1

How about: " As you see, the train schedule may include superfluous departure-arrival options. A departure-arrival Option A is superfluous if there exists another option, B, that departs after A yet arrives before A. Your task is to identify and remove superfluous options from the train schedule."
–
David CarraherDec 11 '12 at 15:30

4 Answers
4

GolfScript, 26 characters, 26 score

The solution assumes a list sorted on departure time on input (as noted in the problem description) and also prints a sorted list (if this restriction can be dropped we may save 3 chars).

The code traverses the list backwards and removes any connection where the arrival time is larger than the minimum arrival time processed so far.

n% # split input at newlines
-1% # reverse list
{ # filter list...
6> # take arrival time of current item
[0$m] # make an array consisting of that arrival time and the minimum
# up to now, contained in variable m. Note since m is not initialized
# the array will consist of a single item in the first iteration
$ # sort that array (consisting of one or two items)
0= # take first item, i.e. minimum arrival time
:m # save to variable m
= # compare current item to m and select if both are equal
}, # ... end of filter list
-1% # reverse list again
n* # join items with newline

Lemma:
If a route is invalidated by some other route where , and no other route between and invalidates , then invalidates all routes from to .

Because the routes are sorted by departure time, and , must necessarily have a later departure time than . Then, in order to invalidate , needs only to have an earlier arrival time. If there were a route between and which was not invalidated by , it would have an earlier arival time than , and hence, would have already invalidated .

Therefore, a linear time algorithm, which only checks if the current route invalidates the previous route is sufficient to solve the problem. When an invalidation is found, the route before the invalidated route must also be checked, until a route is not invalidated (or no valid routes remain). Because a route can only be invalidated once, no more than routes will be invalidated in this manner.

Note that it is important that the invalid routes actually be removed from the list. If they are simply marked invalid (or set to null, etc.), this will result in complexity, in the case that each new route invalidates all previous routes.

Proof that only one solution exists follows directly from the law of transitivity. If a route is invalidated by , and is invalidated by , is also invalidated by . In order for multiple solutions to exist, it must be possible to invalidate without invalidating , but any route that invalidates will also invalidate , and will lead to the same solution.

APL 10757 52 . O(n) = 52

The input m variable could be simply typed in as follows for the first example below:

m←4 11⍴'10:12 11:4510:15 11:5010:22 12:0510:25 12:00'

or it could be read in programatically from a number of sources eg text file.

The line before the start of the loop converts the character input (m) of arrival times to 4 digit numbers. The loop is then using sequential ≤ on those times to do the pruning. Tested on the following:

I don't speak APL, but judging by the English that's O(n squared), giving a score of 11449.
–
histocratDec 11 '12 at 17:28

@histocrat If you accept primo's explanation of the solution then it is O(n).
–
GrahamDec 11 '12 at 18:27

I'm curious how to test this solution. I've tried running this code (assuming that m is the variable that needs to be assigned to the input?), but running it on this online apl interpreter produces the runtime error Symbol 'T' referenced before assignment. Have I missed something?
–
primoDec 13 '12 at 7:31

@primo That interpreter does not implement the full set of APL functions. It is failing on the third line of code with error: Function ⍎ Execute is not implemented. In your example the result of that line is effectively m←1145 1150 1205 1200
–
GrahamDec 13 '12 at 10:33

@Graham what would be your recommendation for testing this solution (or any other APL solution, for that matter)?
–
primoDec 13 '12 at 10:42