Advertisement
Guest User

Untitled

a guest
Nov 20th, 2017
69
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. within block1 block2 =
  10.     let beginX = block2.left
  11.         beginY = block2.top
  12.         endX   = beginX + block2.width
  13.         endY   = beginY + block2.height
  14.     in block1.top > beginY && (block1.top + block1.height) < endY
  15.     && block1.left > beginX && (block1.left + block1.width) < endX
  16.  
  17. blocksWithin blocks block = filter (\b -> b `within` block) blocks
  18.  
  19. -- determina se um bloco é filho de algum irmão.
  20. -- complexidade: O(n)
  21. let immediateChild child siblings =
  22.     and (map (\sibling -> not (child `within` sibling)) siblings)
  23.  
  24. -- divide uma lista de blocos em filhos diretos (aqueles que não são filhos de nenhum irmão)
  25. -- e filhos indiretos (aqueles que são). Esta função espera receber os blocos ordenados por tamanho
  26. -- por questão de otimização (um bloco não pode ser filho de um bloco menor do que ele)
  27. -- complexidade: O(n^2). O pior caso ocorre quando todos os blocos são filhos diretos.
  28. let partitionChildren children =
  29.     let partitionR children (immediates, nonImmediates) =
  30.         case children of
  31.             child :: rest -> if (child `immediateChild` immediates)
  32.                              then partitionR rest (child :: immediates, nonImmediates)
  33.                              else partitionR rest (immediates, child :: nonImmediates)
  34.             []            -> (immediates, nonImmediates)
  35.     in partitionR children ([], [])
  36.  
  37.  
  38. {-
  39.  recebe uma lista de blocos, uma lista de filhos diretos, e uma lista de filhos indiretos e monta
  40.  uma árvore. Para cada um dos filhos diretos, são determinados quais estão ou não contidos naquele filho,
  41.  e são divididos em filhos diretos e filhos indiretos para a nova chamada recursiva.
  42.  
  43.  A princípio, isso seria uma operação de custo N * M^2 sem contar a recursão,
  44.  onde N é o número de filhos diretos
  45.  e M o de filhos indiretos, mas quando o custo da operação de partição se aproxima de M^2 não há
  46.  chamada recursiva (porque todos os filhos são diretos). Ou seja, se o número de filhos da árvore é
  47.  alto, o custo em cada nível fica baixo e vice-versa. No caso de uma árvore binária, o custo fica
  48.  N em cada nível * log N níveis, ou seja N log N, e no caso de uma árvore com apenas um nível,
  49.  o custo tende a N^2. Nos casos intermediários, o custo fica entre N log N e N^2.
  50.  Portanto, podemos concluir que a complexidade desta operação é O(N^2).
  51. -}
  52. let blockTreeNode parent immediateChildrenBlocks nonImmediateChildrenBlocks =
  53.     let childrenTrees = map (\child ->
  54.             let childrenOfChild = (nonImmediateChildrenBlocks `blocksWithin` child) `sortBy` size
  55.                 (immediateChildrenOfChild, nonImmediateChildrenOfChild) = partitionChildren childrenOfChild
  56.             in blockTreeNode child immediateChildrenOfChild nonImmediateChildrenOfChild
  57.         ) immediateChildrenBlocks
  58.     in BlockTree parent childrenTrees
  59.  
  60. -- A função principal só inicia a recursão adicionando uma operação em tempo constante.
  61. -- Portanto, a complexidade total é O(N^2)
  62. let blockTreeOfBlocks blocks =
  63.     let (parent :: children) = blocks `sortBy` size
  64.         (immediateChildren, nonImmediateChildren) = partitionChildren children
  65.     in blockTreeNode parent immediateChildren nonImmediateChildren
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement