Day 5: Cafeteria

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 2 points 11 months ago

There's an alternative approach to merging ranges. Put starting and ending points into a heap then scan it, keeping track of the number of open ranges present. Something like this:

mergeRanges rs =
    let
        -- We put in this order so we count openings before closings
        starts = map (\(a, b) -> (a, -1)) rs
        ends = map (\(a, b) -> (b, 1)) rs
        heap = H.fromList (starts ++ ends) :: H.MinHeap (Int, Int)
     in
        mergeNo heap
  where
    -- not in a range currently
    mergeNo :: H.MinHeap (Int, Int) -> [R]
    mergeNo h =
        case H.view h of
            Nothing -> []
            Just ((a, -1), h') -> mergeYes a 1 h'
    -- in a range
    mergeYes :: Int -> Int -> H.MinHeap (Int, Int) -> [R]
    mergeYes start height h =
        let Just ((v, delta), h') = H.view h
            newHeight = height - delta
         in if newHeight == 0
                then (start, v) : mergeNo h'
                else mergeYes start newHeight h'
  • source