Program to minimize hamming distance after swap operations in Python

Suppose we have two integer arrays, src and tgt, both are of same length. We also have an array allowedSwaps where allowedSwaps[i] contains a pair (ai, bi) indicates that we can swap the elements at index ai with element index bi of the array src. (We can swap elements at a specific pair of indices as many times as we want in any order). As we know the Hamming distance of two arrays of the same length, src and tgt, is the number of positions where the elements are different. We have to find the minimum Hamming distance of src and tgt after performing any amount of swap operations on array src.

So, if the input is like src = [2,3,4,5], tgt = [3,2,5,6], allowedSwaps = [[0,1],[2,3]], then the output will be 1 because src can be converted in the following way: Swap indices 0 and 1, so source = [3,2,4,5], swap indices 2 and 3, so source = [3,2,5,4]. Here hamming distance of src and tgt is 1 as they differ in 1 position: index 3.

To solve this, we will follow these steps −

  • graph := a list of size same as src and fill with n
  • Define a function find() . This will take x
  • while graph[x] is not same as x, do
    • graph[x] := graph[graph[x]]
    • x := graph[x]
  • return x
  • Define a function union() . This will take x, y
  • x1 := find(x), y1 := find(y)
  • graph[x1] := y1
  • From the main method, do the following
  • for each pair (x, y) in allowedSwaps, do
    • union(x, y)
  • groups := a map where values are lists, by default lists are empty
  • for i in range 0 to size of src - 1, do
    • i1 := find(i)
    • insert i at the end of groups[i1]
  • ans := 0
  • for each ids in list of all values of groups, do
    • counter := an empty map to hold count values
    • for each idx in ids, do
      • counter[src[idx]] := counter[src[idx]] + 1
      • counter[tgt[idx]] := counter[tgt[idx]] - 1
      • ans := ans + (sum of all absolute value of val, for all var in the list of values of counter)/2
  • return ans


Let us see the following implementation to get better understanding −

from collections import defaultdict, Counter
def solve(src, tgt, allowedSwaps):
   graph = [ n for n in range(len(src)) ]

   def find(x):
      while graph[x] != x:
         graph[x] = graph[graph[x]]
         x = graph[x]
      return x

   def union(x, y):
      x1, y1 = find(x), find(y)
      graph[x1] = y1

   for x, y in allowedSwaps:

   groups = defaultdict(list)
   for i in range(len(src)):
      i1 = find(i)

   ans = 0
   for ids in groups.values():
      counter = Counter()
      for idx in ids:
         counter[src[idx]] += 1
         counter[tgt[idx]] -= 1
      ans += sum( abs(val) for val in counter.values())/2
   return ans

src = [2,3,4,5]
tgt = [3,2,5,6]
allowedSwaps = [[0,1],[2,3]]
print(solve(src, tgt, allowedSwaps))


[2,3,4,5], [3,2,5,6], [[0,1],[2,3]]