You say you want all permutations without any city to appearing twice, yet your example has the starting city (cityA) listed again at the end:
I want for example: cityA-cityB + cityB-cityC + cityC-cityA
So, assuming the first city appearing again at the end is actually what you meant, I think the following shows how you could generate the permutations of cities you want — if that assumption is wrong, simply remove the one line where the first city is duplicated.
In order to get differing total distances (with three it's always the same), I added a fourth city and changed the output format so it's more compact to better accommodate more cities.
Barcelona;Belgrade;Berlin;Brussels0;1528.13;1497.61;1346.01528.13;0;999.25;1723.01497.61;999.25;0;764.01346.0;1723.0;764.0;0
Here's the code:
from __future__ import print_functionimport csvimport functoolstry: from itertools import izip, imapexcept ImportError: # Python 3 izip = zip imap = mapfrom itertools import permutations, repeat# Create a distance dictionary from csv data file with entries like this:# (city_a, city_b): float(distance-between-city_a-and-city_b)# for all pairs of city names in the file.data_filename = 'european_cities.csv'dist_dict = {}with open(data_filename, 'r') as file: reader = csv.reader(file, delimiter=';') cities = next(reader) # header row num_cities = len(cities) for city in cities: # should be a row of distances for each city from_city_iter = repeat(city, num_cities) dist_dict.update((pair for pair in izip(izip(from_city_iter, cities), imap(float, next(reader))) if pair[1])) # skip 0 distances (city_a == city_b)def pairwise(iterable):"s -> (s0,s1), (s1,s2), (s2,s3), ..." a, b = iter(iterable), iter(iterable) next(b) # advance second iterator one iteration return izip(a, b)for tour in permutations(cities, len(cities)): tour += (tour[0],) # make round trip by appending starting city route = '->'.join(tour) dist = sum(dist_dict[city_a, city_b] for city_a, city_b in pairwise(tour)) print('{:^49}: {:,}'.format(route, dist))
Output:
Barcelona->Belgrade->Berlin->Brussels->Barcelona : 4,637.38Barcelona->Belgrade->Brussels->Berlin->Barcelona : 5,512.74Barcelona->Berlin->Belgrade->Brussels->Barcelona : 5,565.86Barcelona->Berlin->Brussels->Belgrade->Barcelona : 5,512.74Barcelona->Brussels->Belgrade->Berlin->Barcelona : 5,565.86Barcelona->Brussels->Berlin->Belgrade->Barcelona : 4,637.38 Belgrade->Barcelona->Berlin->Brussels->Belgrade : 5,512.74 Belgrade->Barcelona->Brussels->Berlin->Belgrade : 4,637.38 Belgrade->Berlin->Barcelona->Brussels->Belgrade : 5,565.86 Belgrade->Berlin->Brussels->Barcelona->Belgrade : 4,637.38 Belgrade->Brussels->Barcelona->Berlin->Belgrade : 5,565.86 Belgrade->Brussels->Berlin->Barcelona->Belgrade : 5,512.74 Berlin->Barcelona->Belgrade->Brussels->Berlin : 5,512.74 Berlin->Barcelona->Brussels->Belgrade->Berlin : 5,565.86 Berlin->Belgrade->Barcelona->Brussels->Berlin : 4,637.38 Berlin->Belgrade->Brussels->Barcelona->Berlin : 5,565.86 Berlin->Brussels->Barcelona->Belgrade->Berlin : 4,637.38 Berlin->Brussels->Belgrade->Barcelona->Berlin : 5,512.74 Brussels->Barcelona->Belgrade->Berlin->Brussels : 4,637.38 Brussels->Barcelona->Berlin->Belgrade->Brussels : 5,565.86 Brussels->Belgrade->Barcelona->Berlin->Brussels : 5,512.74 Brussels->Belgrade->Berlin->Barcelona->Brussels : 5,565.86 Brussels->Berlin->Barcelona->Belgrade->Brussels : 5,512.74 Brussels->Berlin->Belgrade->Barcelona->Brussels : 4,637.38