I'm a Haskell beginner and trying to hone my skill by solving algorithmic problems. Here's what I got for maxheapify
from Introduction to Algorithms
ixParent :: Int -> Int
ixParent = floor . flip (/) 2 . fromIntegral
ixLeft :: Int -> Int
ixLeft = (*) 2
ixRight :: Int -> Int
ixRight = (+) 1 . (*) 2
maxHeapify :: (Show a, Num a, Ord a) => Int -> [a] -> [a]
maxHeapify i h = if m == i then h else maxHeapify m h' where
s = length h
l = ixLeft i
r = ixRight i
m = snd $ maximumBy (\e1 e2-> compare (fst e1) (fst e2)) [(h!!(n-1), n)|n <- [i,l,r], n <= s]
h' = h & ix (i-1) .~ (h!!(m-1)) & ix (m-1) .~ (h!!(i-1))
Any suggestions on the improvements or correction are highly appreciated. I'm looking for more idiomatic way of doing Haskell
Version 0.1:
import Control.Lens
import Data.List
ixP :: Int -> Int
ixP = floor . flip (/) 2 . fromIntegral
idxL :: Int -> Int
idxL = (*) 2
idxR :: Int -> Int
idxR = (+) 1 . (*) 2
maxHeapify ::(Ord a, Show a) => Int -> [a] -> [a]
maxHeapify _ [] = []
maxHeapify i h = if l == i then h else maxHeapify l h'
where
l = snd . maximumBy (\(i1,_) (i2,_) -> compare i1 i2)
$ [(h!!(n-1), n) | n<- [i, idxL i, idxR i], n <= length h]
h' = h
& ix (i-1) .~ h!!(l-1)
& ix (l-1) .~ h!!(i-1)
buildMaxHeap :: (Ord a, Show a) => [a] -> [a]
buildMaxHeap xs = go (ixP (length xs)) xs
where
go 0 xs = xs
go i xs = go (i - 1) (maxHeapify i xs)
heapSort :: (Ord a, Show a) => [a] -> [a]
heapSort [] = []
heapSort h = heapSort (maxHeapify 1 xs) ++ [x]
where
mx = buildMaxHeap h
x = head mx
xs = tail mx
Update 1:
Added heapIncreaseKey
heapIncreaseKey :: (Ord a, Show a) => Int -> a -> [a] -> [a]
heapIncreaseKey i k h =
if k < h!!(i-1)
then fail "New Key is smaller than current one"
else go i k h
where
go i k h = if i > 1 && h!!(p - 1) < k
then go p k (h & ix (i-1) .~ h!!(p -1))
else h & ix (i-1) .~ k
where
p = ixP i
Here my question is related to variable naming. I am using the same names for variables in the go
function and the outer function. Is there a better way?