module EditDistance(naive, basic, better, script) where import Data.Array((!), listArray, range) import Data.List(minimumBy) import Data.Ord(comparing) data Action = Nop | Insert | Delete | Mutate deriving (Show) data Distance = Int deriving (Eq, Ord, Show) naive a b = d (length a) (length b) where d i 0 = i d 0 j = j d i j | a !! (i - 1) == b !! (j - 1) = d (i - 1) (j - 1) | otherwise = minimum [ d (i - 1) j + 1 , d i (j - 1) + 1 , d (i - 1) (j - 1) + 1 ] basic :: String -> String -> Int basic a b = d m n where (m, n) = (length a, length b) d i 0 = i d 0 j = j d i j | a !! (i - 1) == b !! (j - 1) = ds ! (i - 1, j - 1) | otherwise = minimum [ ds ! (i - 1, j) + 1 , ds ! (i, j - 1) + 1 , ds ! (i - 1, j - 1) + 1 ] ds = listArray bounds [d i j | (i, j) <- range bounds] bounds = ((0, 0), (m, n)) better a b = d m n where (m, n) = (length a, length b) a' = listArray (1, m) a b' = listArray (1, n) b d i 0 = i d 0 j = j d i j | a' ! i == b' ! j = ds ! (i - 1, j - 1) | otherwise = minimum [ ds ! (i - 1, j) + 1 , ds ! (i, j - 1) + 1 , ds ! (i - 1, j - 1) + 1 ] ds = listArray bounds [d i j | (i, j) <- range bounds] bounds = ((0, 0), (m, n)) cost :: Action -> Int cost Nop = 0 cost Mutate = 2 cost _ = 1 script :: Eq a => (Action -> Int) -> [a] -> [a] -> (Int, [Action]) script cost a b = (fst $ d m n, reverse . snd $ d m n) where (m, n) = (length a, length b) a' = listArray (1, m) a b' = listArray (1, n) b d 0 0 = (0, []) d i 0 = go (i - 1) 0 Delete d 0 j = go 0 (j - 1) Insert d i j | a' ! i == b' ! j = go (i - 1) (j - 1) Nop | otherwise = minimum' [ go (i - 1) j Delete , go i (j - 1) Insert , go (i - 1) (j - 1) Mutate ] minimum' = minimumBy (comparing fst) go i j action = let (score, actions) = ds ! (i, j) in (score + cost action, action : actions) ds = listArray bounds [d i j | (i, j) <- range bounds] bounds = ((0, 0), (m, n)) main :: IO () main = do a <- getLine b <- getLine let distance = fst $ script cost a b ops = snd $ script cost a b print distance print ops