n = 5
size = n * n

#-----JUST SOME TEST DATA--------------------------------------
import string, itertools, random
original = [''.join(t) for t in itertools.product(string.letters[:n], repeat=2)]
#random.shuffle(original)

current = list(original)
random.shuffle(current)

def printMatrix(matrix):
	for i in range(n):
		print(matrix[i * n : (i + 1) * n])

print("original:")
printMatrix(original)
print("current:")
printMatrix(current)
#---------------------------------------------------------------------
	
# cache orignal matrix token indices in dictionary
# this dictionary is used by evaluate function
indexInOriginal = {}
for index, value in enumerate(original):
	indexInOriginal[value] = index
	
#---------------------------------------------------------------------

def indexOf(row, column):
	return row * n + column

def coordinatesOf(index):
	return (index / n, index % n)

def distanceModuloN(a, b):
	diff = abs(a - b)
	return min(diff, n - diff)

def cyclicDistanceSquared(indexA, indexB):
	ax, ay = coordinatesOf(indexA)
	bx, by = coordinatesOf(indexB)
	dx = distanceModuloN(ax, bx)
	dy = distanceModuloN(ay, by)
	return dx * dx + dy * dy


def evaluate(original, current):
	result = 0
	print('-' * 68)
	print("{0:^20}|{1:^31}|{2:^15}".format("token pair", "distance squared", "product"))
	print("{0:^20}|{1:^15}|{2:^15}|".format("", "current", "original"))
	print('-' * 68)
	for i in range(size):
		for j in range(i + 1, size):
			distanceSquaredInCurrent = cyclicDistanceSquared(i, j)
			distanceSquaredInOriginal = cyclicDistanceSquared(indexInOriginal[current[i]], indexInOriginal[current[j]])
			product = distanceSquaredInCurrent * distanceSquaredInOriginal
			result += product
			print("{0:^20}|{1:^15}|{2:^15}|{3:^15}".format(
				(current[i], current[j]),
				distanceSquaredInCurrent,
				distanceSquaredInOriginal,
				product))
	print('-' * 68)
	print("{0:52}|{1:^15}".format("", result))
	# result -= lowerBound[n]
	return result
	
evaluate(original, current)