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

  • gedhrel@lemmy.world
    link
    fedilink
    arrow-up
    2
    ·
    3 days 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'