計算將港鐵車程拆開以減低車費的車程組合
本人並不確保本文的準確性,對任何損失或傷害概不負責,亦非鼓吹這樣做,只為作出簡單的計算供參考。本文提及的車費於本文刊登日有效。
眾所周知,如果在某些港鐵站前往羅湖或落馬洲,在上水出閘再原站入閘,總車費有可能會減少。我嘗試利用以下的小程式,計算出成人車票,包括八達通及單程車票,在港鐵系統內有可能因中途出閘再入閘而便宜了的組合。
先到政府資料一線通網站下載最新的港鐵車費表 mtr_lines_fares.csv(不包括輕鐵)。
再執行以下程式:
#!/usr/bin/env python import csv from math import ceil octopusFareList = {} ticketFareList = {} stationList = {} """ field available "SRC_STATION_NAME", "SRC_STATION_ID", "DEST_STATION_NAME", "DEST_STATION_ID", "OCT_ADT_FARE", "OCT_STD_FARE", "SINGLE_ADT_FARE", "OCT_CON_CHILD_FARE", "OCT_CON_ELDERLY_FARE", "OCT_CON_PWD_FARE", "SINGLE_CON_CHILD_FARE", "SINGLE_CON_ELDERLY_FARE" """ with open('mtr_lines_fares.csv', 'rb') as csvfile: reader = csv.DictReader(csvfile, delimiter=',') for row in reader: if (row['SRC_STATION_ID'] == row['DEST_STATION_ID']): continue srcId = int(row['SRC_STATION_ID']) destId = int(row['DEST_STATION_ID']) octopusFareList[srcId,destId] = float(row['OCT_ADT_FARE']) ticketFareList[srcId,destId] = float(row['SINGLE_ADT_FARE']) stationList[srcId] = row["SRC_STATION_NAME"] # print octopusFareList[100,22] # 1 = Central, 39 = Hong Kong , 3 = TST ,80 = ETST ,exclude these cases centralStdId = 1 hongKongStdId = 39 tstStdId = 3 etstStdId = 80 print '"TYPE","START","OUT_AND_IN","END","OLD","NEW","SAVE"' for i in range(1,121): for j in range(1,121): if i == j or (i == centralStdId and j == hongKongStdId) or (i == hongKongStdId and j == centralStdId) or (i == etstStdId and j == tstStdId)or (i == tstStdId and j == etstStdId): continue if (i,j) not in octopusFareList.keys(): continue for x in range(1,121): if x == i or x == j or (i == centralStdId and x == hongKongStdId) or (i == hongKongStdId and x == centralStdId) or (i == etstStdId and x == tstStdId)or (i == tstStdId and x == etstStdId) or (j == centralStdId and x == hongKongStdId) or (j == hongKongStdId and x == centralStdId) or (j == etstStdId and x == tstStdId)or (j == tstStdId and x == etstStdId): continue if (i,x) not in octopusFareList.keys(): continue if (x,j) not in octopusFareList.keys(): continue # normal octopus case newOctupusFare = octopusFareList[i,x] + octopusFareList[x,j] if newOctupusFare <= octopusFareList[i,j] - 0.01: print '"OCTOPUS","' + stationList[i] + '","' + stationList[x] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare) # 2nd trip discount newOctupusFare = octopusFareList[i,x] + ceil(octopusFareList[x,j] * 0.9*10.0)/10.0 if newOctupusFare <= octopusFareList[i,j] - 0.01: print '"OCTOPUS(2nd trip)","' + stationList[i] + '","' + stationList[x] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare) # single trip ticket newTicketFare = ticketFareList[i,x] + ticketFareList[x,j] if newTicketFare <= ticketFareList[i,j] - 0.01: print '"TICKET","' + stationList[i] + '","' + stationList[x] + '","' + stationList[j] + '",'+ str(ticketFareList[i,j]) + "," + str(newTicketFare) + "," + str(ticketFareList[i,j] - newTicketFare) # Handle TST and ETST if (i != tstStdId) and (j != etstStdId) and (i != etstStdId) and (j != tstStdId): # normal octopus case newOctupusFare = octopusFareList[i,tstStdId] + octopusFareList[etstStdId,j] if newOctupusFare <= octopusFareList[i,j] - 0.01: print '"OCTOPUS","' + stationList[i] + '","' + stationList[tstStdId] + "->" + stationList[etstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare) # 2nd trip discount newOctupusFare = octopusFareList[i,tstStdId] + ceil(octopusFareList[etstStdId,j] * 0.9*10.0)/10.0 if newOctupusFare <= octopusFareList[i,j] - 0.01: print '"OCTOPUS(2nd trip)","' + stationList[i] + '","' + stationList[tstStdId] + "->" + stationList[etstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare) # single trip ticket newTicketFare = ticketFareList[i,tstStdId] + ticketFareList[etstStdId,j] if newTicketFare <= ticketFareList[i,j] - 0.01: print '"TICKET","' + stationList[i] + '","' + stationList[tstStdId] + "->" + stationList[etstStdId] + '","' + stationList[j] + '",'+ str(ticketFareList[i,j]) + "," + str(newTicketFare) + "," + str(ticketFareList[i,j] - newTicketFare) # normal octopus case newOctupusFare = octopusFareList[i,etstStdId] + octopusFareList[tstStdId,j] if newOctupusFare <= octopusFareList[i,j] - 0.01: print '"OCTOPUS","' + stationList[i] + '","' + stationList[etstStdId] + "->" + stationList[tstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare) # 2nd trip discount newOctupusFare = octopusFareList[i,etstStdId] + ceil(octopusFareList[tstStdId,j] * 0.9*10.0)/10.0 if newOctupusFare <= octopusFareList[i,j] - 0.01: print '"OCTOPUS(2nd trip)","' + stationList[i] + '","' + stationList[etstStdId] + "->" + stationList[tstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare) # single trip ticket newTicketFare = ticketFareList[i,etstStdId] + ticketFareList[tstStdId,j] if newTicketFare <= ticketFareList[i,j] - 0.01: print '"TICKET","' + stationList[i] + '","' + stationList[etstStdId] + "->" + stationList[tstStdId] + '","' + stationList[j] + '",'+ str(ticketFareList[i,j]) + "," + str(newTicketFare) + "," + str(ticketFareList[i,j] - newTicketFare)
執行後,可得出一萬多項結果。我將結果輸出到一個 csv file,可到此下載。
以下為部分結果:
第一列為車票種類,有八達通、第二程八達通可享九折的車程(詳情)和單程車票。
第二列為起點車站,本例選取了大埔墟作為起點。
第三列為中途出閘再入閘(單程車票需重新購票)的車站。
第四列為終點車站。
第五及第六列分別為原來車費及新車費。
第七列為可節省的車費。
本文連結