Advertisement
Guest User

Untitled

a guest
Nov 20th, 2017
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Block :: {top, left, width, height}
  2.  
  3. BlockTree :: {block: Block, children: [BlockTree]}
  4.  
  5. blockTreeOfBlocks :: [Block] -> BlockTree
  6.  
  7. size block = block.height * block.width
  8.  
  9. -- Predicate: checks if one block is within another
  10. within block1 block2 =
  11.     let beginX = block2.left
  12.         beginY = block2.top
  13.         endX   = beginX + block2.width
  14.         endY   = beginY + block2.height
  15.     in block1.top > beginY && (block1.top + block1.height) < endY
  16.     && block1.left > beginX && (block1.left + block1.width) < endX
  17.  
  18. -- Gets all blocks within a given block fom a list
  19. blocksWithin blocks block = filter (\b -> b `within` block) blocks
  20.  
  21. -- Predicate: checks if a block is a child of any of its siblings.
  22. -- Complexity: O(n)
  23. isIndependentFrom child siblings =
  24.     and (map (\sibling -> not (child `within` sibling)) siblings)
  25.  
  26. -- Splits a list of blocks (all assumed to be children of a parent)
  27. -- into immedate and non-indirect children of their parent.
  28. -- The input list of blocks must be sorted by size. The two output lists will be sorted by size
  29. -- (they are built in opposite order and we reverse them at the end).
  30. -- Complexity: O(n^2). The worst case is when all children are immediate children of the parent,
  31. -- as comparisons are done only against immediate children (since every non-immediate children is a child
  32. -- of an immediate child).
  33. let partitionChildren children =
  34.     let partitionR children (immediates, nonImmediates) =
  35.         case children of
  36.             child :: rest -> if (child `isIndependentFrom` immediates)
  37.                              then partitionR rest (child :: immediates, nonImmediates)
  38.                              else partitionR rest (immediates, child :: nonImmediates)
  39.             []            -> (reverse immediates, reverse nonImmediates)
  40.     in partitionR children ([], [])
  41.  
  42.  
  43. {-
  44.  Takes a block, its immediate children, its non-immediate children, (both lists sorted by size) and builds a tree.
  45.  The process used is as follows: For each child, we find the children of that child from
  46.  the non-immediate children. This costs O(m), where m is the number of non-immediate children.
  47.  Since the `blocksWithin` operation preserves sorting, we still have a sorted list.
  48.  
  49.  We then split the children of the child into its immediate and non-immediate children. As stated about
  50.  the operation above, this also preserves sorting. This costs O(m^2).
  51.  
  52.  We are then able to do a recursive call for the child with its immediate and non-immediate children.
  53.  The amount of recursive calls done further down will depend on how many immediate and non-immediate children
  54.  there were. The more immediate children we find, the more expensive it becomes to split the immediate from
  55.  the non-immediate children (the cost approaches O(m^2)) But if we have few immediate children, the
  56.  cost approaches m. The number of levels in the recursion tree here will be greater the fewer immediate children
  57.  we have, as the tree will have lower effective branching factor. When we have a lower branching factor,
  58.  the complexity approaches n log n, where n is the number of immediate children plus the number of non-immediate
  59.  children. If the branching factor is higher, the complexity becomes closer to the cost of partitioning the children,
  60.  which in the worst case, where all blocks are children of a single parent, is (m^2) = (n^2).
  61.  
  62.  Therefore, the worst-case time complexity of this operation is O(n^2).
  63. -}
  64. blockTreeNode parent immediateChildrenBlocks nonImmediateChildrenBlocks =
  65.     let childrenTrees = map (\child ->
  66.             let childrenOfChild = (nonImmediateChildrenBlocks `blocksWithin` child)
  67.                 (immediateChildrenOfChild, nonImmediateChildrenOfChild) = partitionChildren childrenOfChild
  68.             in blockTreeNode child immediateChildrenOfChild nonImmediateChildrenOfChild
  69.         ) immediateChildrenBlocks
  70.     in BlockTree parent childrenTrees
  71.  
  72. -- We start off by sorting the input list, taking the tree's root node and starting the recursive process.
  73. -- This costs n log n + n^2 = O(n^2).
  74. blockTreeOfBlocks blocks =
  75.     let (root :: children) = blocks `sortBy` size
  76.         (immediateChildren, nonImmediateChildren) = partitionChildren children
  77.     in blockTreeNode root immediateChildren nonImmediateChildren
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement