Skip to content

Instantly share code, notes, and snippets.

@mchav
Created June 17, 2016 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mchav/2571d91194421d4ea3677c4f4f45dbe8 to your computer and use it in GitHub Desktop.
Save mchav/2571d91194421d4ea3677c4f4f45dbe8 to your computer and use it in GitHub Desktop.
Counting inversions Haskell.
import Control.Monad
inversions :: [Int] -> Int
inversions = snd . countInversions
countInversions :: [Int] -> ([Int], Int)
countInversions [] = ([] , 0)
countInversions [x] = ([x], 0)
countInversions arr = let mid = (length arr) `div` 2
left = take mid arr
right = drop mid arr
(left' , l) = countInversions $! left
(right' , r) = countInversions $! right
(whole , w) = id $! countSplit left' right'
in (whole, l + r + w)
countSplit :: [Int] -> [Int] -> ([Int], Int)
countSplit [] y = (y, 0)
countSplit x [] = (x, 0)
countSplit (x:xs) (y:ys)
| x <= y = ((x: left ), 0 + l)
| otherwise = ((y: right), 0 + r)
where leftSplit = countSplit xs (y:ys)
rightSplit = countSplit (x:xs) ys
left = fst leftSplit
right = fst rightSplit
l = snd leftSplit
r = (snd rightSplit) + length((x: xs))
main = do
nums <- liftM (map (read :: String -> Int) . lines) getContents
print $ inversions nums
@3noch
Copy link

3noch commented Jun 17, 2016

left  = take mid arr
right = drop mid arr

can be done in half the time with Data.List.splitAt. But it can be done in O(1) with Data.Vector.Generic.splitAt if you use Vector instead of [].

@3noch
Copy link

3noch commented Jun 17, 2016

Curiosity: why 0 + ...?

@mchav
Copy link
Author

mchav commented Jun 17, 2016

I was being sloppy. Let me add the formatted code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment