import Data.List import Data.Maybe orderBySecond :: Ord a => (a, a) -> (a, a) -> Ordering orderBySecond (_, x1) (_, x2) = compare x1 x2 -- Gets the position in xs of elements in the second list (ys) indices :: Eq a => [a] -> [a] -> [(Int, Int)] indices xs ys = zip (map (\x -> fromJust $ x `elemIndex` xs) ys) [0 ..] getSwapsfromIndices :: [(Int, Int)] -> [(Int, Int)] getSwapsfromIndices xs = getSwapsfromIndices' xs [] -- The second argument for this is an accumulator used for tail recursion getSwapsfromIndices' :: [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)] getSwapsfromIndices' [] ys = ys getSwapsfromIndices' xs ys = getSwapsfromIndices' xs' (ys ++ new_swap) where (l1, l2) = minimumBy orderBySecond xs -- remove minimum from the list unordered = [ (x, y) | (x, y) <- xs, y /= l2] -- swap xs' = [ (if x == l2 then l1 else x, y) | (x, y) <- unordered] -- if no swap is needed, do not append anything new_swap = if l1 == l2 then [] else [(l1, l2)] swaps :: Eq a => [a] -> [a] -> [(Int, Int)] swaps xs ys = getSwapsfromIndices $ indices xs ys
By running the code with the above example:
*Main> swap [2,3,4,1,7] [7,1,2,4,3] [(4,0),(3,1),(4,2),(4,3)]
Please note that the only difference in the results is in the order of the indices in the swaps (which is conditional) and in the fact that I start to count elements from 0.
This implementation uses the idea of โโsuperimposing full order on elements in the first list, depending on where they are in the second list. Then it uses selection sorting to get swaps. This is probably not the most effective solution, but it is helpful to give you a start.