Skip to content

Instantly share code, notes, and snippets.

@parsonsmatt
Created August 8, 2017 04:12
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 parsonsmatt/1f83f8b8499af60c19a00d730d52f948 to your computer and use it in GitHub Desktop.
Save parsonsmatt/1f83f8b8499af60c19a00d730d52f948 to your computer and use it in GitHub Desktop.
Waterfall in ST
module Waterfall.Base where
import Control.Monad.ST
import Data.Foldable (for_)
import Data.STRef
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as MU
rainfallBase :: [Int] -> Int
rainfallBase xs = sum (zipWith (-) mins xs)
where
mins = zipWith min maxl maxr
maxl = scanl1 max xs
maxr = scanr1 max xs
rainfallUnboxedVector :: U.Vector Int -> Int
rainfallUnboxedVector xs = U.sum (U.zipWith (-) mins xs)
where
mins = U.zipWith min maxl maxr
maxl = U.scanl1' max xs
maxr = U.scanr1' max xs
rainfallST :: U.Vector Int -> Int
rainfallST xs = runST $ do
let len = U.length xs
towers <- MU.new len
mx <- newSTRef 0
sum' <- newSTRef 0
for_ [0..len] $ \i -> do
let t = U.unsafeIndex xs i
modifySTRef' mx (max t)
x <- readSTRef mx
MU.unsafeWrite towers i x
writeSTRef mx 0
for_ [len-1, len-2 .. 0] $ \i -> do
let t = U.unsafeIndex xs i
modifySTRef' mx (max t)
x <- readSTRef mx
m <- MU.read towers i
modifySTRef' sum' (\s -> s + (min x m - t))
readSTRef sum'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment