我们如何在Haskell中的列表中计算反演?
例如。 [1, 2, 3, 1]
,xi > xj
其中i < j
是反转的条件。在给定的例子中,它将是3。
我尝试了以下代码:
module Inversion where
inv :: Ord a => [a] -> [(a, a)]
inv [] = []
inv xs = [(a, b) | a <- xs, b <- tail xs, a > b]
我甚至尝试用尾巴压缩它然后得到它们。
答案 0 :(得分:4)
import Data.List
inv :: Ord a => [a] -> [(a, a)]
inv xs = [(a,b) | (a:bs) <- tails xs, b <- bs, a > b]
答案 1 :(得分:1)
这是一个接近你已经得到的天真实现:
inv :: Ord a => [a] -> [(a, a)]
inv [] = []
inv xs = [(a, b) | b <- xs', a > b] ++ inv xs'
where xs' = tail xs
a = head xs
首先想到的是:将第一个元素与列表中的其他元素进行比较,然后对列表的其余部分进行相同的操作。
你的例子:
*Main> inv [1,2,3,1]
[(2,1),(3,1)]
答案 2 :(得分:0)
这似乎对我有用:
inv lst = filter nonOrdPair $ zip lst (tail lst)
where nonOrdPair (a,b) = a > b
你的例子中的给出了
Prelude> inv [1, 2, 3, 1]
[(3,1)]
如果您只需要第一个元素,则可以使用map fst
获取它。
答案 3 :(得分:0)
在这种情况下,您无法使用zip
和tail
。这将导致仅比较连续对,您需要所有对。因此,如果列出了(x:xs)
,则需要检查xs
是否小于x
:
import Data.Maybe (mapMaybe)
checkInv :: Ord a => a -> a -> Maybe (a,a)
checkInv x y = if x <= y then Nothing
else Just (x, y)
inv :: Ord a => [a] -> [(a,a)]
inv [] = []
inv (x:xs) = mapMaybe (checkInv x) xs ++ inv xs
> inv [1,2,3,1]
[(2,1), (3,1)]
答案 4 :(得分:0)
只是为了解决这个问题:
inv :: Ord a => [a] -> [(a,a)]
inv [x] = [] :: [(x,x)]
inv xs = foldl (\acc x -> if (head xs) > x then (head xs, x) : acc else acc) [] xs
压缩然后过滤这些对并不是一个坏主意,但你必须考虑所有这些对才能起作用:
inv xs = filter (\(a, b) -> a > b) $ allPairs xs
where
allPairs xs = allPairsHelp xs (tail xs)
where
allPairsHelp xs [] = []
allPairsHelp xs ys = zip xs ys ++ allPairsHelp xs (tail ys)