-
Notifications
You must be signed in to change notification settings - Fork 1
/
rails.pl
104 lines (92 loc) · 3.01 KB
/
rails.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
:- include('utils.pl').
:- include('ubahn.pl').
speed(9). % m/s
transfer_time(220). % seconds
station_wait_time(20). % seconds
% Case: direct route (A) --> (B).
route(A, B, Trains, Acc, R) :-
train(Train, Stations),
\+ member(Train, Trains),
member([A, _], Stations),
member([B, _], Stations),
append(Acc, [[A, Train, B]], R).
% Case: intermediary station/s (I) between
% departure (A) and destination (B).
route(A, B, Trains, Acc0, R) :-
train(Train, Stations),
\+ member(Train, Trains),
member([A, _], Stations),
member([I, _], Stations),
A \= I,
I \= B,
length(Acc0, L),
L < 3, % do not find routes where more than 2 changes are needed
append(Acc0, [[A, Train, I]], Acc1),
route(I, B, [Train|Trains], Acc1, R).
% Calculate distance between stops and
% get nr of stations and last stop of the line.
distance_and_last_stop([], R, R).
distance_and_last_stop([[A, Train, B]|T], Acc0, R) :-
train(Train, Stations),
member([A, D1], Stations),
member([B, D2], Stations),
D is D1 - D2,
AbsD is abs(D),
( D < 0
-> last(Stations, [End, _])
; nth1(1, Stations, [End, _])
),
indexof(Stations, [A,_], IndexA),
indexof(Stations, [B,_], IndexB),
Stops is abs(IndexA - IndexB),
append(Acc0, [[A, Train, B, End, Stops, AbsD]], Acc1),
distance_and_last_stop(T, Acc1, R).
route_with_distance(X, Y, R) :-
route(X, Y, [], [], L),
distance_and_last_stop(L, [], R).
% route with total distance and time
% time calculated based on distance, train speed and transfer
route_with_totals([], R, Distance, Time, [R, Distance, Time]).
route_with_totals([H|T], Acc, Distance, Time, Rt) :-
( Distance = 0
-> Transfer = 0
; transfer_time(Transfer),!
),
H = [A, Train, B, Dir, Stops, D],
speed(Speed),!,
station_wait_time(WaitTime),!,
TotalDistance is Distance + D,
TotalTime is D / Speed + Time + Transfer + Stops * WaitTime,
append(Acc, [[A, Train, B, Dir, Stops]], Acc1),
route_with_totals(T, Acc1, TotalDistance, TotalTime, Rt).
route_with_totals(X, Y, R) :-
route_with_distance(X, Y, L),
route_with_totals(L, [], 0, 0, R).
all_routes(A, B, All) :-
setof(L, route_with_totals(A, B, L), All).
% routes sorted by shortest time
sort_fastest(A, B, Result) :-
all_routes(A, B, All),
predsort(nthcompare(3), All, Sorted),!,
member(Result, Sorted).
print_intermediary([A, Train, B, Direction, Stops]) :-
ansi_format(fg(cyan), '~w', [A]),
ansi_format([fg(magenta)], ' ~w', [Train]),
ansi_format(fg(yellow), '~w', [' -> ']),
ansi_format(fg(cyan), '~w', [B]),
format(' ❯ ~w (~w)~n', [Direction, Stops]).
print_all([[]|[Distance, Time]]) :-
Minutes is Time / 60,
Km is Distance / 1000,
ansi_format(
fg(green),
'~1f minutes / ~1f km',
[Minutes, Km]
).
print_all([[[A, T, B, D, S]|Tail]|DistTime]) :-
print_intermediary([A, T, B, D, S]),
print_all([Tail|DistTime]).
route(A, B) :-
format('~n'),
sort_fastest(A, B, R),
print_all(R).