module Subsequences(suffixes, prefixes, subsequences, permutations, subsequence, isPrefixOf, isSuffixOf, isSubsequenceOf, isPermutationOf, isPrefixOfBy, isSuffixOfBy, isSubsequenceOfBy, isPermutationOfBy, locateSubsequences) where
suffixes :: [a] -> [[a]]
suffixes [] = []
suffixes xxs@(_:xs) = xxs : suffixes xs
prefixes :: [a] -> [[a]]
prefixes [] = []
prefixes xs = xs : prefixes (init xs)
subsequences :: [a] -> [[a]]
subsequences = concatMap prefixes . suffixes
permutations :: [a] -> [[a]]
permutations [] = [[]]
permutations (x:xs) = [ zs | ys <- permutations xs, zs <- insertAll x ys ]
where insertAll x [] = [[x]]
insertAll x yys@(y:ys) = (x:yys) : map (y:) (insertAll x ys)
subsequence :: Int -> Int -> [a] -> [a]
subsequence start end xs = take (end - start) (drop start xs)
isPrefixOf, isSuffixOf :: Eq a => [a] -> [a] -> Bool
isSubsequenceOf, isPermutationOf :: Eq a => [a] -> [a] -> Bool
isPrefixOf = isPrefixOfBy (==)
isSuffixOf = isSuffixOfBy (==)
isSubsequenceOf = isSubsequenceOfBy (==)
isPermutationOf = isPermutationOfBy (==)
isPrefixOfBy, isSuffixOfBy :: (a -> a -> Bool) -> [a] -> [a] -> Bool
isSubsequenceOfBy, isPermutationOfBy :: (a -> a -> Bool) -> [a] -> [a] -> Bool
isPrefixOfBy eq [] ys = True
isPrefixOfBy eq (x:xs) (y:ys) | eq x y = isPrefixOfBy eq xs ys
isPrefixOfBy eq _ _ = False
isSuffixOfBy eq xs ys = isPrefixOfBy eq (reverse xs) (reverse ys)
isSubsequenceOfBy eq xs ys = any (isPrefixOfBy eq xs) (suffixes ys)
isPermutationOfBy eq [] [] = True
isPermutationOfBy eq (x:xs) ys = del x ys []
where del x [] _ = False
del x (y:ys) r = if eq x y then isPermutationOfBy eq xs (reverse r ++ ys)
else del x ys (y:r)
locateSubsequences :: Eq a => [a] -> [a] -> [Int]
locateSubsequences xs ys = locateSubsequencesBy (==) xs ys
locateSubsequencesBy :: (a -> a -> Bool) -> [a] -> [a] -> [Int]
locateSubsequencesBy eq xs ys =
map fst (filter (isPrefixOfBy eq xs . snd) (zip [0..] (suffixes ys)))