[Haskell-cafe] Open Kattis Problem Srednji: Hints to improve my algorithm

Brent Yorgey byorgey at gmail.com
Wed Sep 23 10:15:23 UTC 2020


Viktor is right.  Here's a small hint towards one way of solving it: start
by replacing every number smaller than B by -1, and every number larger
than B by 1 (and B itself by 0).

-Brent

On Wed, Sep 23, 2020 at 2:17 AM Dominik Bollmann <dominikbollmann at gmail.com>
wrote:

>
> Hi Haskell-Cafe,
>
> I've been trying to solve the Open Kattis Problem called Srednji
> recently, unfortunately without success.
>
> Given a sequence A and a number B within that sequence this problem asks
> to find all odd sub-sequences of A that, when sorted, have B as their
> median in the middle. That is, from A we may remove some prefix and/or
> suffix and if the resulting sub-sequence -- when sorted -- contains B in
> the middle, then this sub-sequence is a solution. The problem asks to
> find the number of all solutions. Check out
> https://open.kattis.com/problems/srednji for the details.
>
> My Haskell solution below tries to find the number of odd sub-sequences
> by first locating the median and then repeatedly moving left and right
> from that median to find larger and larger sub-sequence candidates. Each
> found candidate is checked to have B in the middle when sorted in order
> to become a solution. Moreover, I also extend each such candidate
> further to the left (and to the right, respectively) to determine
> whether these leftward or rightward extensions are solutions, too.
>
> I think with this approach I systematically enumerate all solutions.
> Unfortunately, though, this approach is too slow and times out on the
> 11th hidden test cases.
>
> I'd therefore be thankful for hints about different approaches to
> solving this problem more efficiently.
>
>
> Thanks!
>
> Dominik.
>
> ====================================================================
>
> My current, slow Haskell code is this:
>
> import Data.Maybe
> import Data.Sequence (Seq, (<|), (|>))
> import qualified Data.Sequence as Seq
> import qualified Data.Vector.Unboxed as Vec
>
> data SubSeq = SubSeq
>   { getBalance :: {-# UNPACK #-} !Int
>   , getSubSeq  :: Seq Int
>   , from       :: {-# UNPACK #-} !Int
>   , to         :: {-# UNPACK #-} !Int
>   }
>
> balancedSubSeqs :: [Int] -> Int -> [SubSeq]
> balancedSubSeqs seq med = do
>   candidate <- leftRight [val0]
>   let lefts  = leftLeft candidate []
>       rights = rightRight candidate []
>   candidate ?: lefts ++ rights
>   where
>     medidx = fromJust (Vec.findIndex (== med) arr)
>     val0   = SubSeq 0 (Seq.singleton med) medidx medidx
>     arr    = Vec.fromList seq
>
>     leftRight cands@(SubSeq balance seq i j : _)
>       | i-1 < 0 || j+1 >= Vec.length arr = cands
>       | otherwise =
>         let v1       = arr Vec.! (i-1)
>             v2       = arr Vec.! (j+1)
>             balance' = newBalance balance v1 v2
>             seq'     = (v1 <| seq) |> v2
>         in leftRight (SubSeq balance' seq' (i-1) (j+1) : cands)
>
>     leftLeft cand@(SubSeq balance seq i j) sols
>       | i-2 < 0   = sols
>       | otherwise =
>         let v1 = arr Vec.! (i-2)
>             v2 = arr Vec.! (i-1)
>             balance' = newBalance balance v1 v2
>             seq'     = v1 <| v2 <| seq
>             newCand  = SubSeq balance' seq' (i-2) j
>         in leftLeft newCand (newCand ?: sols)
>
>     rightRight cand@(SubSeq balance seq i j) sols
>       | j+2 >= Vec.length arr = sols
>       | otherwise =
>         let v1 = arr Vec.! (j+1)
>             v2 = arr Vec.! (j+2)
>             balance' = newBalance balance v1 v2
>             seq'     = seq |> v1 |> v2
>             newCand  = SubSeq balance' seq' i (j+2)
>         in rightRight newCand (newCand ?: sols)
>
>     newBalance old n1 n2
>       | n1 < med, n2 < med = old - 2
>       | n1 > med, n2 > med = old + 2
>       | otherwise          = old
>
> infixr 5 ?:
> --(?:) :: SubSeq -> [SubSeq] -> [SubSeq]
> x@(SubSeq b _ _ _) ?: xs
>   | b == 0    = x : xs
>   | otherwise = xs
>
> main :: IO ()
> main = do
>   [len, median] <- fmap read . words <$> getLine
>   seq <- fmap read . words <$> getLine
>   let solutions = balancedSubSeqs seq median
>   print (length solutions)
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20200923/37f092bd/attachment.html>


More information about the Haskell-Cafe mailing list