Tue, 20 Jun 2017 09:39:42 +0300
optimointia
#!/usr/bin/env python3 def supista_reitti(reitti, ajomatka, kokonainen = False): length = ((ajomatka / 600) + len(reitti)) / 2 def abstract_sign(sign): abstractions = { 'Moikoinen': 'Hirvensalo', 'Maanpää': 'Hirvensalo', 'Papinsaari': 'Hirvensalo', 'Häppilä': 'Hirvensalo', 'Friskala': 'Hirvensalo', 'Kukola': 'Hirvensalo', 'Oriniemi': 'Hirvensalo', 'Haarla': 'Hirvensalo', 'Lauttasaari': 'Hirvensalo', 'Pikisaari': 'Hirvensalo', 'Pernon telakka': 'Perno', } try: start = sign.index('Kauppatori') except ValueError: return sign result = [] for i, place in enumerate(sign): if i >= start: abstract_place = abstractions.get(place, place) if abstract_place not in result: result.append(abstract_place) else: result.append(place) return result if not reitti: return '' eksoalueet = { 'Turku', 'Naantali', 'Lieto', 'Aura', 'Kaarina', 'Pargas', 'Marttila', 'Somero', 'Koski Tl', 'Tarvasjoki', 'Kaivopuisto', } replacements = { "Ylioppilaskylä-Itä": "Ylioppilaskylä", "Ylioppilaskylä-Länsi": "Ylioppilaskylä", "Caribia": "Ylioppilaskylä", "Jokila": "Lieto", "Piispala": "Lieto", 'Saaro': 'Ruissalo', 'Silvola': 'Vahto', 'Hemmola': 'Vahto', 'Paasniittu': 'Ruskon keskusta', 'Kahari': 'Ruskon keskusta', 'Kemiö': 'Kemiönsaari', 'Kasnäs': 'Kemiönsaari', } have_already = set() i = 0 while i < len(reitti): if reitti[i] in replacements: reitti[i] = replacements[reitti[i]] if reitti[i] in have_already: del reitti[i] else: have_already.add(reitti[i]) i += 1 prioriteetit = { 'Ihala': 150, 'Kauppakeskus Mylly': 200, 'Kuninkoja': 80, 'Moikoinen': 35, 'Raision keskusta': 100, 'Friskala': 20, 'Kukola': 50, 'Kaistarniemi': 50, 'Papinsaari': 50, 'Oriniemi': 50, 'Pikisaari': 50, 'Häppilä': 50, 'Haarla': 50, 'Ylioppilaskylä': 50, 'Halinen': 70, 'Kakskerta': 200, 'Pansio': 50, 'Räntämäki': 10, 'Verkahovi': 20, 'Skanssi': 200, 'Vaala': 20, 'Varissuo': 60, 'Kohmo': 80, 'Kupittaa': 70, 'Kauppatori': 1e15, 'Lentoasema': 50, 'Runosmäki': 50, 'Lieto': 100, 'Lieto as': 200, 'Ilmarinen': 50, 'Vahto': 50, 'Ruskon keskusta': 200, 'Oriketo': 30, 'Harittu': 40, 'Jäkärlä': 50, 'Paattinen': 100, 'Kaarinan keskusta': 200, 'Naantalin keskusta': 200, 'Uittamo': 50, 'Piikkiö': 100, 'Paimio': 100, 'Pargas': 50, 'Yli-Maaria': 50, 'Saramäki': 50, 'Tarvasjoki': 100, 'Marttila': 100, 'Koski Tl': 100, 'Katariina': 50, 'Länsikeskus': 50, 'Kaanaa': 100, 'Satava': 50, 'Suikkila': 50, 'Raunistula': 50, 'Räntämäki': 50, 'Moisio': 25, 'Pääskyvuori': 100, 'Rautatieasema': 50, 'Rymättylä': 50, "Sauvo": 500, "Kemiönsaari": 500, } if 'Kauppatori' not in reitti: prioriteetit['Länsikeskus'] = prioriteetit['Skanssi'] = prioriteetit['Kauppatori'] # nimiä joista voidaan joustaa tarvittaessa helpot_supistukset = { 'Raision keskusta': 'Raisio', 'Ruskon keskusta': 'Rusko', 'Naantalin keskusta': 'Naantali', 'Kaarinan keskusta': 'Kaarina', 'Kauppakeskus Mylly': 'Mylly', } # jos ei nyt millään vaan mahdu muuten... vakavat_supistukset = { 'Kauppatori': 'Tori', 'Ylioppilaskylä': 'Yo-kylä', } lähtö = reitti[0] määränpää = reitti[-1] reitti_arvot = {} f = lambda i: i**-0.3 jakaja = max(f(i + 1) for i in range(len(reitti))) for i, pysäkki in enumerate(reitti): # muunna indeksi siten että myöhemmät alueet korostuvat i = f(i + 1) / jakaja # ota prioriteetti huomioon, jotkin alueet ovat tärkeämpiä kyltissä kuin toiset i *= prioriteetit.get(pysäkki, 1) reitti_arvot[pysäkki] = i # nollaa lähtöpaikan arvo ettei se mitenkään tule kylttiin if lähtö in reitti_arvot: reitti_arvot[lähtö] = 0 # varmista että määränpää tulee kylttiin reitti_arvot[määränpää] = 1e10 # muodosta kyltti-tiedot järjestettynä reittiarvon mukaan painot = sorted([ (pysäkki, reitti_arvot[pysäkki], i) \ for i, pysäkki in enumerate(reitti) \ if reitti_arvot[pysäkki] >= 1 ], key = lambda pysäkki: -pysäkki[1]) # enintään neljä tulee kylttiin painot = painot[:3] # jos kolmas kylttiarvo ei ole tarpeeksi merkittävä suhteessa reitin pituuteen niin otetaan se pois try: if painot[2][0] != määränpää and painot[2][1] < (1000 / length ** 1.15): del painot[2] except IndexError: pass try: if painot[1][0] != määränpää and painot[1][1] < (500 / length ** 1.15): del painot[1] except IndexError: pass # lajitellaan painoarvot uudestaan reittijärjestykseen jotta kyltti tulee oikeinpäin painot = sorted(painot, key = lambda paino: paino[2]) # muodostetaan kyltti.. kyltti = [paino[0] for paino in painot] #kyltti = abstract_sign(kyltti) # supista nimet jos mahdollista def viimeistele(kyltti, supistus_taso = 0): if supistus_taso > 0: kyltti = [helpot_supistukset.get(paikka, paikka) for paikka in kyltti] if supistus_taso > 1: kyltti = [vakavat_supistukset.get(paikka, paikka) for paikka in kyltti] return kyltti tulos = viimeistele(kyltti) for i in range(len(kyltti) - 1): if kyltti[i + 1].startswith(kyltti[i]): del kyltti[i] if len(' - '.join(kyltti)) > 20: tulos = viimeistele(kyltti, supistus_taso = 1) if len(' - '.join(kyltti)) > 70: tulos = viimeistele(kyltti, supistus_taso = 2) if kokonainen: tulos = [lähtö] + tulos lyhyt_lähtö = replacements.get(lähtö, lähtö) if lyhyt_lähtö != tulos[-1] and helpot_supistukset.get(lyhyt_lähtö, lyhyt_lähtö) in eksoalueet | {'Kauppatori'} and tulos[-1] in eksoalueet | {'Kauppatori'}: tulos = ['Turku' if k == 'Kauppatori' else k for k in tulos] return tulos