I came up with the following ugly code. The idea is similar to swap based sorting technique. Suppose you have two lists
[7,1,2,4,3] and [2,3,4,1,7]
Now you can obtain swaps one item at a time. First get the first element correct, I have mentioned the swaps as pair of indexes to swap in the list followed by the list obtained after applying the swap
(1,5) => [7,3,4,1,2]
(2,4) => [7,1,4,3,2]
(3,5) => [7,1,2,3,4]
(4,5) => [7,1,2,4,3]
So the swaps are
[(1,5),(2,4),(3,5),(4,5)]
import qualified Data.Map as M
import Data.Maybe
-- It will totally break if lists don't contain same items.
swaps :: Ord a => [a] -> [a] -> [(Int,Int)]
swaps xs ys = reverse . getFirst $ foldl f ([],xsm,mxs,1) ys
where
getFirst (a,_,_,_) = a
xsm = M.fromList $ zip xs ([1..]) -- Construct map for O(logn) lookups
mxs = M.fromList $ zip ([1..]) xs -- Map for Reverse lookup
f (swps,xm,mx,i) y = if i==a then (swps,newxm,newmx,i+1)
else ((i,a):swps,newxm,newmx,i+1)
where
a = fromJust $ M.lookup y xm -- Not very safe to use fromJust
b = fromJust $ M.lookup i mx
newxm = M.insert b a $ M.insert y i xm
newmx = M.insert a b $ M.insert i y mx
In ghci
*Main> swaps [2,3,4,1,7] [7,1,2,4,3]
[(1,5),(2,4),(3,5),(4,5)]